h3-mcp logoh3-mcp

Handler Options

Every field of McpHandlerOptions.

defineMcpHandler takes this object, or a function returning it:

defineMcpHandler(options: McpHandlerOptions | ((event: H3Event) => McpHandlerOptions));

#Identity

OptionTypeDefaultNotes
namestringRequired. Machine name of the server
versionstringRequired. Server version
titlestringHuman-friendly display name
descriptionstringShort description
iconsMcpIcon[]{ src, mimeType?, sizes?, theme? }
websiteUrlstringServer homepage
instructionsstringGuidance passed to the model — worth writing well

#Definitions

OptionTypeNotes
toolsMaybeLazy<McpToolDefinition>[]Tools
resourcesMaybeLazy<McpResourceDefinition>[]Resources
resourceTemplatesMaybeLazy<McpResourceTemplateDefinition>[]Templates
promptsMaybeLazy<McpPromptDefinition>[]Prompts

MaybeLazy<T> is T | (() => T | Promise<T>), so any entry may be a function resolved once on first use.

Read more in Lazy definitions.

#Era

OptionTypeDefaultNotes
era"dual" \| "modern" \| "legacy""dual"Ignored on the h3-mcp/modern and h3-mcp/legacy entrypoints
Read more in Protocol eras.

#Modern Era

OptionTypeDefaultNotes
cacheMcpCacheOptions{ ttlMs: 0, cacheScope: "private" }Per-method keys: discover, tools, prompts, resources, resourceTemplates, resourceRead
extensionsRecord<string, object>Advertised in capabilities.extensions
loggingbooleanfalseAdvertise logging on server/discover
echoServerInfobooleantrueInclude _meta server info on modern results
subscriptions{ max?, keepAliveMs? }{ max: 100, keepAliveMs: 15000 }subscriptions/listen limits
onListen(subscription, event) => voidCalled when a listen stream opens
Read more in Caching.

#Legacy Era

OptionTypeDefaultNotes
sessionboolean \| McpSessionOptionsfalse{ enabled?, generateId?, maxSessions? }
onStream(stream, event) => voidEnables the GET/SSE stream
onSubscribe(uri, event) => voidresources/subscribe
onUnsubscribe(uri, event) => voidresources/unsubscribe
onLogLevelSet(level, event) => voidlogging/setLevel
onCancelled(notification, event) => voidnotifications/cancelled
onProgress(notification, event) => voidnotifications/progress

All of these are @deprecated in the sense that 2026-07-28 removed the feature — they remain fully functional on the legacy path.

Read more in Legacy era.

#Security

OptionTypeDefaultNotes
authfalse \| McpAuthOptionsfalse (disabled){ enabled?, schemes?, tokens?, header?, validate? }
originfalse \| McpOriginOptionsenabled: { allow: [], allowMissing: true }{ allow?, allowMissing?, validate? }
limitsfalse \| McpLimitsOptions{ maxBodySize: 4 MiB, contentType: ["application/json"] }Applied to POST before parsing

Auth defaults, once enabled: schemes: ["bearer", "api-key"], header: "x-api-key". Enabling auth requires at least one of tokens or validate.

Read more in Security.

#Dynamic Resolution

Every option above can be computed per request:

defineMcpHandler((event) => ({
  name: "my-server",
  version: "1.0.0",
  tools: getToolsForUser(event),
  auth: { tokens: tokensForTenant(event) },
}));

The function runs at most once per event and the result is cached in a WeakMap.

Read more in Dynamic options.
h3-mcp logo

h3-mcp  MCP servers, built on H3.