CC-301j · Module 2
Error Handling in MCP Tools
3 min read
When an MCP tool fails, Claude needs to understand why. A tool that throws an unhandled exception returns a generic error message that Claude cannot act on. A tool that catches the error and returns a structured error message gives Claude the context to recover — retry with different parameters, try an alternative approach, or explain the failure to the user.
The error handling pattern: wrap your handler in a try-catch. In the catch block, classify the error (authentication failure, invalid input, resource not found, rate limit, server error) and return a structured message. "Authentication failed — the API token may have expired. Ask the user to re-authenticate." gives Claude a recovery action. "Error: 500 Internal Server Error" gives Claude nothing to work with.
server.tool('query_db', 'Query the database', schema, async (params) => {
try {
const result = await db.query(params.sql);
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
} catch (error) {
// Classify and return actionable error
if (error.code === 'ECONNREFUSED') {
return {
content: [{ type: 'text',
text: 'Database connection refused. The database server may be down. ' +
'Ask the user to verify the database is running.' }],
isError: true,
};
}
return {
content: [{ type: 'text', text: `Query failed: ${error.message}` }],
isError: true,
};
}
});