Skip to content

Commit a8aa403

Browse files
committed
docs: add tool error sanitization section to migration-SKILL.md
1 parent 6fb53de commit a8aa403

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

docs/migration-SKILL.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,36 @@ Type changes in handler context:
454454

455455
> These task APIs are `@experimental` and may change without notice.
456456
457+
## 12b. Tool Error Sanitization (Breaking Change)
458+
459+
Tool handlers that `throw new Error('message')` now return `"Internal error"` to clients instead of the raw error message. This prevents accidental leakage of server internals (hostnames, connection strings, stack traces) through tool error responses.
460+
461+
To send a user-visible error message, use the new `ToolError` class:
462+
463+
```typescript
464+
import { ToolError } from '@modelcontextprotocol/server';
465+
466+
// Generic errors are sanitized -- client sees: "Internal error"
467+
server.registerTool('db-query', {
468+
description: 'Query the database',
469+
inputSchema: z.object({ sql: z.string() })
470+
}, async ({ sql }) => {
471+
throw new Error('Connection refused to 10.0.0.5:5432');
472+
});
473+
474+
// ToolError messages pass through -- client sees: "Invalid query syntax"
475+
server.registerTool('safe-query', {
476+
description: 'Query with validated input',
477+
inputSchema: z.object({ sql: z.string() })
478+
}, async ({ sql }) => {
479+
throw new ToolError('Invalid query syntax');
480+
});
481+
```
482+
483+
`ProtocolError` messages (SDK validation errors) are still passed through unchanged.
484+
485+
**Migration action:** If your v1 tool handlers rely on `throw new Error('user-visible message')` to communicate errors to clients, switch those throws to `throw new ToolError('user-visible message')`. No changes needed for tools that only throw errors for genuinely unexpected failures.
486+
457487
## 13. Client Behavioral Changes
458488

459489
`Client.listPrompts()`, `listResources()`, `listResourceTemplates()`, `listTools()` now return empty results when the server lacks the corresponding capability (instead of sending the request). Set `enforceStrictCapabilities: true` in `ClientOptions` to throw an error instead.

0 commit comments

Comments
 (0)