Exports
Everything h3-mcp exports at runtime.
The runtime surface is deliberately small: one handler factory, four identity helpers for type inference, and one error class. Everything else is types.
#defineMcpHandler(handlerOpts)
Define an H3 event handler that implements the Model Context Protocol (MCP) over HTTP using JSON-RPC 2.0 as the wire format.
The handler is dual-era: a POST whose params._meta["io.modelcontextprotocol/protocolVersion"] is set is served statelessly per 2026-07-28; anything else (including initialize and MCP-Session-Id traffic) takes the legacy ≤2025-11-25 path. Use era: "modern" or era: "legacy" to serve only one.
To also drop the unused era from your bundle, import from h3-mcp/modern or h3-mcp/legacy instead — those entrypoints never reference the other era's implementation.
Example:
app.all(
"/mcp",
defineMcpHandler({
name: "my-server",
version: "1.0.0",
tools: [echoTool],
resources: [readmeResource],
prompts: [greetPrompt],
}),
);Example:
// Dynamic options based on request context
app.all(
"/mcp",
defineMcpHandler((event) => ({
name: "my-server",
version: "1.0.0",
tools: getToolsForUser(event),
})),
);#defineMcpPrompt(definition)
Define an MCP prompt with optional arguments and a handler that returns messages.
Example:
// Prompt with arguments
const greetPrompt = defineMcpPrompt({
name: "greet",
description: "Generate a greeting",
args: [{ name: "name", required: true }],
handler: async (args, event) => ({
messages: [
{ role: "user", content: { type: "text", text: `Hello ${args.name}!` } },
],
}),
});Example:
// Prompt without arguments
const helpPrompt = defineMcpPrompt({
name: "help",
description: "Show help information",
handler: async (event) => ({
messages: [
{ role: "user", content: { type: "text", text: "How can I help?" } },
],
}),
});#defineMcpResource(definition)
Define an MCP resource with a static URI and a handler that returns its contents.
Example:
const readmeResource = defineMcpResource({
name: "readme",
uri: "file:///readme",
description: "Project README",
mimeType: "text/markdown",
handler: async (uri, event) => ({
contents: [{ uri: uri.toString(), text: "# My Project" }],
}),
});#defineMcpResourceTemplate(definition)
Define an MCP resource template with a URI template (RFC 6570) and a handler.
Resource templates expose parameterized resources. Clients fill in template parameters and call resources/read with the expanded URI.
Example:
const fileTemplate = defineMcpResourceTemplate({
name: "file",
uriTemplate: "file:///{path}",
description: "Read a file by path",
mimeType: "text/plain",
handler: async (uri, event) => ({
contents: [{ uri: uri.toString(), text: `Contents of ${uri.pathname}` }],
}),
});#defineMcpTool(definition)
Define an MCP tool with a name, optional JSON Schema input, and a handler function.
Example:
// Tool with input parameters
const echoTool = defineMcpTool({
name: "echo",
description: "Echo back a message",
inputSchema: {
type: "object",
properties: { message: { type: "string" } },
required: ["message"],
},
handler: async (args, event) => ({
content: [{ type: "text", text: args.message as string }],
}),
});Example:
// Tool without input parameters
const pingTool = defineMcpTool({
name: "ping",
description: "Returns pong",
handler: async (event) => ({
content: [{ type: "text", text: "pong" }],
}),
});#McpJsonRpcError()
#McpJsonRpcError
A JSON-RPC error with an explicit code and HTTP status — the one error class whose message reaches the client verbatim on the modern era.
import { McpJsonRpcError } from "h3-mcp";
throw new McpJsonRpcError(-32602, "Widget id must be a UUID", { status: 400 });new McpJsonRpcError(code, message, { status?, data? }). When status is omitted it defaults per code: -32601 → 404, -32603 → 500, otherwise 400. McpJsonRpcError.isMcpJsonRpcError(value) is a type guard.
#Era Entrypoints
h3-mcp/modern and h3-mcp/legacy export the same helpers and error class, plus a single-era defineMcpHandler and the version it serves:
| Export | h3-mcp | h3-mcp/modern | h3-mcp/legacy |
|---|---|---|---|
defineMcpHandler | ✅ dual | ✅ modern-only | ✅ legacy-only |
defineMcpTool | ✅ | ✅ | ✅ |
defineMcpResource | ✅ | ✅ | ✅ |
defineMcpResourceTemplate | ✅ | ✅ | ✅ |
defineMcpPrompt | ✅ | ✅ | ✅ |
McpJsonRpcError | ✅ | ✅ | ✅ |
MCP_PROTOCOL_VERSION | — | ✅ 2026-07-28 | — |
MCP_LEGACY_PROTOCOL_VERSION | — | — | ✅ 2025-11-25 |
| all types | ✅ | ✅ | ✅ |
Each entrypoint is self-contained — never import from two of them in the same file, or you defeat the bundle split.
#Types
Every type is exported from each entrypoint. The ones you are most likely to name explicitly:
| Type | Use |
|---|---|
McpHandlerOptions | The options object |
McpToolDefinition · McpResourceDefinition · McpResourceTemplateDefinition · McpPromptDefinition | Definition shapes |
McpCallToolResult · McpReadResourceResult · McpGetPromptResult | Handler return values |
McpContentBlock · McpIcon | Content and icons |
McpRequestContext | event.context.mcp |
McpInputRequiredResult · McpInputRequests · McpInputResponses | MRTR |
McpSubscription · McpSubscriptionFilter · McpSubscriptionOptions | Subscriptions |
McpCacheOptions · McpCacheHints · McpCacheScope | Caching |
McpAuthOptions · McpOriginOptions · McpLimitsOptions · McpSessionOptions | Security |
McpEra · McpImplementation · McpClientCapabilities · McpExtensions | Era and identity |
StandardSchemaV1 · StandardJSONSchemaV1 · StandardTypedV1 | Standard Schema (vendored) |
h3-mcp also augments h3's H3EventContext with mcp?: McpRequestContext, so event.context.mcp is typed everywhere once the package is imported.
#Deprecated but Functional
These are legacy-era features removed in 2026-07-28. They still work and are not going away — the JSDoc @deprecated marks are there to point you at the modern replacement:
| Deprecated | Modern replacement |
|---|---|
session | stateless requests; explicit handles in tool arguments |
onStream | onListen (subscriptions) |
onSubscribe / onUnsubscribe | onListen |
onLogLevelSet | _meta log level + mcp.log() |