Tool handlers catch errors and return isError: true
Why it matters
MCP tools that let exceptions propagate unhandled either crash the server process or produce an opaque JSON-RPC internal error (-32603) with no actionable detail. CWE-703 (improper check of exceptional conditions) is the root; CWE-209 (generation of error messages with sensitive information) is the follow-on risk when raw stack traces leak internal file paths and dependency versions into tool output. The correct MCP pattern is to catch exceptions inside the handler and return isError: true with a descriptive, scrubbed message — keeping the server alive and giving the AI something useful to act on.
Severity rationale
High because unhandled exceptions crash the server or surface raw stack traces, taking down all tools simultaneously and potentially exposing internal implementation details.
Remediation
Wrap every tool handler body in a try/catch. Return isError: true with a clean error message — never rethrow.
// src/tools/query.ts
server.tool('query_db', ..., async ({ sql }) => {
try {
const result = await db.query(sql)
return { content: [{ type: 'text', text: JSON.stringify(result) }] }
} catch (error) {
// Return error as content — do not rethrow
return {
content: [{ type: 'text', text: `Query failed: ${(error as Error).message}` }],
isError: true,
}
}
})
Strip stack traces before including error messages in the response. Expose the error type and message, not the stack or internal paths.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the MCP Server Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-703 — Improper Check or Handling of Exceptional Conditions
- cwe · CWE-209 — Generation of Error Message Containing Sensitive Information
- external · mcp-spec-tool-iserror — MCP Specification — Tool result isError field
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mcp-server·automated