diff --git a/src/lib/mcp/responses.ts b/src/lib/mcp/responses.ts index c97f76c..b0a3cfd 100644 --- a/src/lib/mcp/responses.ts +++ b/src/lib/mcp/responses.ts @@ -1,3 +1,5 @@ +import { APIError } from "@onkernel/sdk"; + type PaginatedPage = { getPaginatedItems(): T[]; has_more?: boolean | null; @@ -64,12 +66,38 @@ function errorMessage(error: unknown) { return error instanceof Error ? error.message : String(error); } -export function toolErrorResponse( +// Named after what the API said, so a stale session id (404) is distinguishable from an +// org hitting its limits (429) or a fault on our side (5xx). Status codes only; the +// message stays out. +class ToolCallError extends Error { + constructor(name: string, message: string) { + super(message); + this.name = name; + } +} + +function errorName(error: unknown) { + if (error instanceof APIError && typeof error.status === "number") { + return `KernelApiError${error.status}`; + } + return error instanceof Error ? error.constructor.name : "Error"; +} + +/** + * Fails a tool call that a Kernel API request rejected. + * + * Throws rather than returning an isError result: analytics reads the error category + * from a thrown error's name, while a returned result only ever coerces to a generic + * "Error". The MCP SDK turns the throw back into the same isError text result the client + * saw before, so agents see no difference. + */ +export function throwToolError( toolName: string, action: string, error: unknown, -) { - return errorResponse( +): never { + throw new ToolCallError( + errorName(error), `Error in ${toolName} (${action}): ${errorMessage(error)}`, ); } diff --git a/src/lib/mcp/tools/api-keys.ts b/src/lib/mcp/tools/api-keys.ts index 9c34f2a..8690a03 100644 --- a/src/lib/mcp/tools/api-keys.ts +++ b/src/lib/mcp/tools/api-keys.ts @@ -6,7 +6,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -107,7 +107,7 @@ export function registerAPIKeyCapabilities(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_api_keys", params.action, error); + throwToolError("manage_api_keys", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/apps.ts b/src/lib/mcp/tools/apps.ts index 8c969a1..e395fc7 100644 --- a/src/lib/mcp/tools/apps.ts +++ b/src/lib/mcp/tools/apps.ts @@ -7,7 +7,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -206,7 +206,7 @@ export function registerAppCapabilities(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_apps", params.action, error); + throwToolError("manage_apps", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/auth-connections.ts b/src/lib/mcp/tools/auth-connections.ts index 73206f1..70e8bee 100644 --- a/src/lib/mcp/tools/auth-connections.ts +++ b/src/lib/mcp/tools/auth-connections.ts @@ -6,7 +6,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -255,11 +255,7 @@ export function registerAuthConnectionTools(server: McpServer) { } } } catch (error) { - return toolErrorResponse( - "manage_auth_connections", - params.action, - error, - ); + throwToolError("manage_auth_connections", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/browser-curl.ts b/src/lib/mcp/tools/browser-curl.ts index c7a2687..eb297cf 100644 --- a/src/lib/mcp/tools/browser-curl.ts +++ b/src/lib/mcp/tools/browser-curl.ts @@ -4,7 +4,7 @@ import { createKernelClient, type KernelClient } from "@/lib/mcp/kernel-client"; import { errorResponse, jsonResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; type BrowserCurlParams = Parameters[1]; @@ -74,7 +74,7 @@ export function registerBrowserCurlTool(server: McpServer) { const response = await client.browsers.curl(session_id, curlParams); return jsonResponse(response); } catch (error) { - return toolErrorResponse("browser_curl", "request", error); + throwToolError("browser_curl", "request", error); } }, ); diff --git a/src/lib/mcp/tools/browser-pools.ts b/src/lib/mcp/tools/browser-pools.ts index 20ced89..ae6072f 100644 --- a/src/lib/mcp/tools/browser-pools.ts +++ b/src/lib/mcp/tools/browser-pools.ts @@ -12,7 +12,7 @@ import { errorResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -474,7 +474,7 @@ export function registerBrowserPoolCapabilities(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_browser_pools", params.action, error); + throwToolError("manage_browser_pools", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/browsers.ts b/src/lib/mcp/tools/browsers.ts index 6865fe2..3fe0781 100644 --- a/src/lib/mcp/tools/browsers.ts +++ b/src/lib/mcp/tools/browsers.ts @@ -13,7 +13,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; import { @@ -695,7 +695,7 @@ export function registerBrowserCapabilities(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_browsers", params.action, error); + throwToolError("manage_browsers", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/computer-action.ts b/src/lib/mcp/tools/computer-action.ts index 58291da..9a2100b 100644 --- a/src/lib/mcp/tools/computer-action.ts +++ b/src/lib/mcp/tools/computer-action.ts @@ -5,7 +5,7 @@ import { errorResponse, jsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; type ComputerClient = KernelClient["browsers"]["computer"]; @@ -353,7 +353,7 @@ export function registerComputerActionTool(server: McpServer) { `Executed ${executedActionCount} action(s) successfully`, ); } catch (error) { - return toolErrorResponse("computer_action", "actions", error); + throwToolError("computer_action", "actions", error); } }, ); diff --git a/src/lib/mcp/tools/credential-providers.ts b/src/lib/mcp/tools/credential-providers.ts index e13f05e..9a7b744 100644 --- a/src/lib/mcp/tools/credential-providers.ts +++ b/src/lib/mcp/tools/credential-providers.ts @@ -6,7 +6,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -164,11 +164,7 @@ export function registerCredentialProviderTools(server: McpServer) { } } } catch (error) { - return toolErrorResponse( - "manage_credential_providers", - params.action, - error, - ); + throwToolError("manage_credential_providers", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/credentials.ts b/src/lib/mcp/tools/credentials.ts index cb7f2c3..04a865d 100644 --- a/src/lib/mcp/tools/credentials.ts +++ b/src/lib/mcp/tools/credentials.ts @@ -6,7 +6,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -152,7 +152,7 @@ export function registerCredentialTools(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_credentials", params.action, error); + throwToolError("manage_credentials", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/extensions.ts b/src/lib/mcp/tools/extensions.ts index f20d831..320472d 100644 --- a/src/lib/mcp/tools/extensions.ts +++ b/src/lib/mcp/tools/extensions.ts @@ -5,7 +5,7 @@ import { errorResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -53,7 +53,7 @@ export function registerExtensionTools(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_extensions", params.action, error); + throwToolError("manage_extensions", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/profiles.ts b/src/lib/mcp/tools/profiles.ts index f0b30a4..c444a3e 100644 --- a/src/lib/mcp/tools/profiles.ts +++ b/src/lib/mcp/tools/profiles.ts @@ -8,7 +8,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -214,7 +214,7 @@ export function registerProfileCapabilities(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_profiles", params.action, error); + throwToolError("manage_profiles", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/projects.ts b/src/lib/mcp/tools/projects.ts index 5bb7239..f8af0e0 100644 --- a/src/lib/mcp/tools/projects.ts +++ b/src/lib/mcp/tools/projects.ts @@ -6,7 +6,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -175,7 +175,7 @@ export function registerProjectCapabilities(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_projects", params.action, error); + throwToolError("manage_projects", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/proxies.ts b/src/lib/mcp/tools/proxies.ts index 632ed10..974503f 100644 --- a/src/lib/mcp/tools/proxies.ts +++ b/src/lib/mcp/tools/proxies.ts @@ -6,7 +6,7 @@ import { jsonResponse, paginatedJsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; import { paginationParams } from "@/lib/mcp/schemas"; @@ -169,7 +169,7 @@ export function registerProxyTools(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_proxies", params.action, error); + throwToolError("manage_proxies", params.action, error); } }, ); diff --git a/src/lib/mcp/tools/replays.ts b/src/lib/mcp/tools/replays.ts index d754a16..12c728a 100644 --- a/src/lib/mcp/tools/replays.ts +++ b/src/lib/mcp/tools/replays.ts @@ -6,7 +6,7 @@ import { itemsJsonResponse, jsonResponse, textResponse, - toolErrorResponse, + throwToolError, } from "@/lib/mcp/responses"; export function registerReplayTools(server: McpServer) { @@ -90,7 +90,7 @@ export function registerReplayTools(server: McpServer) { } } } catch (error) { - return toolErrorResponse("manage_replays", params.action, error); + throwToolError("manage_replays", params.action, error); } }, );