Build a local TypeScript server

Keep errors useful

Design validation, not-found, backend, and unexpected failures so callers can recover without receiving sensitive internals.

8 minute lesson

~~~

MCP exposes failures at two levels.

Protocol errors mean the request cannot be dispatched, such as an unknown method or malformed request. Tool execution errors mean the tool was called but could not complete its job.

The SDK validates our Zod input before the handler runs. The handler still owns domain failures such as a missing note or unavailable database.

Return an actionable tool error:

return {
  content: [{
    type: 'text',
    text: 'The notes backend is temporarily unavailable. Try again later.'
  }],
  isError: true
}

Do not return a stack trace, SQL statement, environment value, or upstream response body. Those details belong in a protected diagnostic channel.

For unexpected failures, create a request-safe incident ID. Log the ID with the internal error, then return only the ID and a generic message. The caller can report it without receiving secrets.

Build a small failure table in TESTING.md:

CaseHandler runs?Expected result
Empty queryNoInput validation error
Limit above tenNoInput validation error
Unknown note IDYesisError: true
Existing note IDYesStructured success

Useful errors reveal the safe next step. They do not reveal the server internals.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →