From 42a6adc8d9ab32d689ba196dc165a0dc0262c5f8 Mon Sep 17 00:00:00 2001 From: John Collier Date: Fri, 21 Nov 2025 17:56:21 -0500 Subject: [PATCH] chore(mcp): clarify error handling in mcp-actions-backend readme Signed-off-by: John Collier --- plugins/mcp-actions-backend/README.md | 25 +++++++++++++++++++ .../src/services/handleErrors.ts | 1 + 2 files changed, 26 insertions(+) diff --git a/plugins/mcp-actions-backend/README.md b/plugins/mcp-actions-backend/README.md index d81d0207c5..820542c0c9 100644 --- a/plugins/mcp-actions-backend/README.md +++ b/plugins/mcp-actions-backend/README.md @@ -71,6 +71,31 @@ export const myPlugin = createBackendPlugin({ }); ``` +### Error Handling + +When errors are thrown from MCP actions, the backend will handle and surface error message for any error from `@backstage/errors`. Unknown errors will be handled by `@modelcontextprotocol/sdk`'s default error handling, which may result in a generic `500 Server Error` being returned. As a result, we recommend usign errors from `@backstage/errors` when applicable. + +See https://backstage.io/docs/reference/errors/ for a full list of supported errors. + +When writing MCP tools, use the appropriate error from `@backstage/errors` when applicable: + +```ts +action: async ({ input }) => { + // ... get current user and some resource + + if (!resource) { + throw new NotFoundError(`Resource ${input.id} not found`); + } + + // Check if the user has permissions to access/use the resource + if (!hasPermission(user, resource)) { + throw new NotAllowedError( + `user does not have sufficient permissions for ${resource}`, + ); + } +}; +``` + ### Authentication Configuration By default, the Backstage backend requires authentication for all requests. diff --git a/plugins/mcp-actions-backend/src/services/handleErrors.ts b/plugins/mcp-actions-backend/src/services/handleErrors.ts index 67d92664eb..5266c80e75 100644 --- a/plugins/mcp-actions-backend/src/services/handleErrors.ts +++ b/plugins/mcp-actions-backend/src/services/handleErrors.ts @@ -32,6 +32,7 @@ const knownErrors = new Set([ 'NotModifiedError', 'NotImplementedError', 'ResponseError', + 'ServiceUnavailableError', ]); // Extracts the cause error, if the provided error is `ResponseError` or