Skip to main content
A tool is a typed function exposed by your MCP server that an LLM can invoke. Each tool has a name, a description the model uses to decide when to call it, an input schema validated at runtime, and a handler that produces the result. Use defineTool to create tools, then pass them to createMCPServer.

Defining a tool

Register your tools when creating the server:

Tool definition fields

Handler return values

Handlers can return either a plain object or a full ToolResult. Plain objects are automatically wrapped into structured content — you don’t need to construct the content array yourself in the common case.
A ToolResult has the following shape:

Authenticated tools

Set requiresAuth: true to have the framework automatically reject calls that arrive without a valid provider token. Inside the handler, use context.resolvedHeaders to forward authentication to external APIs without constructing the header yourself.
When you need to narrow the TypeScript type and guarantee providerToken is present, use assertProviderToken:

Tool context

Every handler receives a context object as its second argument:

Annotations

Annotations are behavioral hints for MCP clients. They are not enforced by the framework — they help clients display accurate UI and make safe decisions about when to invoke a tool automatically.

Error responses with toolFail

Use toolFail to create a typed error factory that merges a message into a preset shape. This keeps error responses structurally consistent with success responses.
The factory signature is:

Tool versioning with meta

Supply a meta object to have tool_version and tool_last_update automatically injected into every handler result, including error paths.

Built-in tools

@phake/mcp ships two built-in tools you can use for testing and diagnostics.

echo

Echoes a message back, optionally uppercased. Useful for verifying connectivity.Input: { message: string, uppercase?: boolean }Output: { echoed: string, length: number }

health

Reports server status, runtime, and optional uptime details.Input: { verbose?: boolean }Output: { status: string, timestamp: number, runtime: string, uptime?: number }
Import and register them the same way as any other tool: