feat: structured errors with hint, ToolResult, cursor pagination
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
+84
-13
@@ -7,33 +7,104 @@ namespace LIT\MCP\Abilities;
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Factory for the error objects abilities return. The MCP adapter turns them
|
||||
* into tool results with isError: true.
|
||||
* Factory for the error objects abilities return.
|
||||
*
|
||||
* mcp-adapter 0.5 turns a WP_Error into a tool result with isError: true but
|
||||
* forwards only the message text. The message therefore carries the whole
|
||||
* structured error as JSON: {code, message, hint, fields?, usages?, …} (spec §8.2).
|
||||
*/
|
||||
final class Errors
|
||||
{
|
||||
public static function forbidden(string $message): WP_Error
|
||||
/**
|
||||
* @param array<string, mixed> $details Extra keys for the client, e.g. fields or usages.
|
||||
*/
|
||||
public static function make(string $code, string $message, string $hint, int $status, array $details = []): WP_Error
|
||||
{
|
||||
return new WP_Error('lit_forbidden', $message, ['status' => 403]);
|
||||
$payload = array_merge(['code' => $code, 'message' => $message, 'hint' => $hint], $details);
|
||||
$json = wp_json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
return new WP_Error(
|
||||
'lit_' . $code,
|
||||
is_string($json) ? $json : $message,
|
||||
array_merge(['status' => $status, 'hint' => $hint], $details)
|
||||
);
|
||||
}
|
||||
|
||||
/** @param array<string, string> $fields */
|
||||
public static function invalidInput(string $message, array $fields = []): WP_Error
|
||||
{
|
||||
return new WP_Error('lit_validation_failed', $message, ['status' => 400, 'fields' => $fields]);
|
||||
public static function forbidden(
|
||||
string $message,
|
||||
string $hint = 'Mit den Rechten des verbundenen WordPress-Kontos nicht erlaubt; ggf. Administrator fragen.'
|
||||
): WP_Error {
|
||||
return self::make('forbidden', $message, $hint, 403);
|
||||
}
|
||||
|
||||
public static function notFound(string $message): WP_Error
|
||||
/**
|
||||
* @param array<string, string> $fields Input path => problem.
|
||||
*/
|
||||
public static function invalidInput(
|
||||
string $message,
|
||||
array $fields = [],
|
||||
string $hint = 'Die unter fields genannten Eingaben korrigieren und erneut senden.'
|
||||
): WP_Error {
|
||||
return self::make('validation_failed', $message, $hint, 400, $fields === [] ? [] : ['fields' => $fields]);
|
||||
}
|
||||
|
||||
public static function notFound(
|
||||
string $message,
|
||||
string $hint = 'ID prüfen, z. B. über lit-content-query oder lit-media-search suchen.'
|
||||
): WP_Error {
|
||||
return self::make('not_found', $message, $hint, 404);
|
||||
}
|
||||
|
||||
public static function revMismatch(): WP_Error
|
||||
{
|
||||
return new WP_Error('lit_not_found', $message, ['status' => 404]);
|
||||
return self::make(
|
||||
'rev_mismatch',
|
||||
'Der Inhalt wurde seit dem letzten Lesen geändert; nichts wurde geschrieben.',
|
||||
'Neu lesen (z. B. lit-content-get) und die Änderung auf dem aktuellen Stand wiederholen.',
|
||||
409
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array<string, mixed>> $usages
|
||||
*/
|
||||
public static function inUse(string $message, array $usages): WP_Error
|
||||
{
|
||||
return self::make(
|
||||
'in_use',
|
||||
$message,
|
||||
'Verwendungen prüfen; nur mit force: true trotzdem ausführen.',
|
||||
409,
|
||||
['usages' => $usages]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $details
|
||||
*/
|
||||
public static function confirmRequired(string $message, array $details = []): WP_Error
|
||||
{
|
||||
return self::make(
|
||||
'confirm_required',
|
||||
$message,
|
||||
'Beim Nutzer nachfragen und dann mit confirm: true erneut aufrufen.',
|
||||
409,
|
||||
$details
|
||||
);
|
||||
}
|
||||
|
||||
public static function unsupported(string $message, string $hint): WP_Error
|
||||
{
|
||||
return self::make('unsupported', $message, $hint, 400);
|
||||
}
|
||||
|
||||
public static function internal(): WP_Error
|
||||
{
|
||||
return new WP_Error(
|
||||
'lit_internal_error',
|
||||
return self::make(
|
||||
'internal_error',
|
||||
'Interner Fehler bei der Ausführung. Details stehen im PHP-Error-Log der Website.',
|
||||
['status' => 500]
|
||||
'Später erneut versuchen oder den Administrator der Website informieren.',
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user