Skip to content

MCP Reference ​

McpAdapter(options) ​

ts
McpAdapter({
  name: 'billing', // required
  path: '/mcp',
  stateless: true,
  auth: { type: 'bearer', authenticate: verify },
  protectedResource: { authorizationServers: ['https://auth.example.com'] },
  toolFilter: (tool, call) => true,
})

Server ​

OptionDefaultNotes
namerequiredserver name advertised to clients
version'0.0.0'server version advertised to clients
description—shown in client UIs
transport'http''http' (Streamable HTTP), 'stdio', or 'sse' (a deprecated alias of http). KICK_MCP_STDIO=1 forces stdio

Which routes are tools ​

OptionDefaultNotes
mode'explicit''explicit': only marked routes. 'auto': every route, filtered by include / exclude
include—auto mode: HTTP methods to expose
exclude—auto mode: path patterns to skip; '/admin/*' also skips /api/v1/admin/users
exposeWhen—routes carrying these route flags are tools; an object flag value supplies tool options
hideWhen—routes carrying these flags are never tools — wins over everything

Endpoint ​

OptionDefaultNotes
path`${basePath}/messages`the full endpoint path
basePath'/_mcp'used when path isn't set
statelessfalsea fresh server per request, no sessions; GET / DELETE answer 405
maxSessions1000session mode: open sessions beyond it get 503
sessionIdleTimeoutMs30 minutessession mode: close a session with nothing in progress after this long
allowedOrigins[]browser origins allowed ('*' for any); requests without Origin are always allowed
allowedHostsanyhosts served (a list or a function); others get 403
trustProxyfalseread the request's scheme and host from X-Forwarded-Proto / -Host

Auth ​

OptionNotes
auth.type'bearer': the credential is the bearer token. 'custom': the raw Authorization value
auth.validate(credential)return true to allow
auth.authenticate(credential, request)return an McpPrincipal, or null to refuse. Use instead of validate
auth.resourceMetadataUrlresource_metadata in the 401 challenge (string or function); defaults to the protectedResource route
auth.scopesscopes named in the 401 challenge
protectedResourceserve RFC 9728 metadata: authorizationServers (list or function), scopesSupported, resource

Calls ​

OptionDefaultNotes
toolFilter—(tool, call) => boolean: which tools a caller sees, for list and call
forwardHeaders['authorization', 'cookie', 'x-request-id', 'traceparent', 'tracestate']headers copied from the MCP request onto route tool calls
toolTimeoutMsno limitend a call that runs longer, with a timeout error
resourceFilter—(resource, call) => boolean: which resources a caller sees and reads
requestStateKeya random key per processsigns ctx.elicit answers between rounds; share it across instances

@McpTool(options) ​

OptionDefaultNotes
descriptionrequiredwhat the tool does, for the model
nameController.methodunique across the server; [A-Za-z0-9_.-]{1,128}
title—a display name
inputSchemathe route's params, query, bodyreplaces the query/body input; path params are still added
outputSchema—advertised in tools/list; a JSON object answer is sent as structuredContent
annotations—readOnlyHint, destructiveHint, idempotentHint, openWorldHint
scopes—scopes the principal must hold; otherwise 403 insufficient_scope
examples—example arguments and results
hiddenfalseleave out of auto mode

A route flag's object value takes the same fields.

Custom tools ​

registerProvider({ name, tools }) mounts custom tools; registering a provider with the same name replaces it.

Tool fieldNotes
nameunique across the server
descriptionfor the model
inputSchemaany schema library; arguments are validated before the handler runs
outputSchemaan object result is sent as structuredContent
title, annotations, scopesas on @McpTool
handler(args, ctx)its return value is the result; throw McpToolError for a typed error

ctx has principal, origin, headers, signal, fetch(request) and elicit(key, { message, schema }).

Resources ​

registerResourceProvider({ name, resources?, templates? }) mounts resources (Resources).

FieldNotes
uri / uriTemplatea fixed URI, or an RFC 6570 template such as invoices://{id}
name, title, description, mimeTypeshown to clients; mimeType defaults by what read returns
scopesscopes the principal must hold; otherwise 403 insufficient_scope
read(ctx) / read(params, ctx)string → text, Uint8Array → binary, other values → JSON
list(ctx) (templates)concrete resources to show in resources/list

Types ​

TypeShape
McpPrincipal{ subject, clientId?, scopes?, audience?, [key]: unknown }
McpRequestInfo{ headers, host, origin, resource }
McpCallContextMcpRequestInfo & { principal? } — what toolFilter gets
McpToolSummary{ name, description, kind: 'route' | 'custom', scopes?, annotations?, route?, provider? }
McpToolDefinitiona discovered route tool: name, description, inputSchema, outputSchema?, httpMethod, mountPath, annotations?, title?, scopes?
McpToolErrornew McpToolError(code, message, data?)
McpResourceSummary{ kind: 'resource' | 'template', name, uri?, uriTemplate?, scopes?, provider } — what resourceFilter gets

The adapter instance ​

Resolve it with container.resolve(MCP_ADAPTER) (typed McpAdapterInstance), or keep the value McpAdapter() returned:

MethodDoes
getTools()the route tools discovered at startup
registerProvider(p)mount custom tools; connected clients get tools/list_changed (session mode)
unregisterProvider(name)unmount them; false when no such provider
registerResourceProvider(p)mount resources; connected clients get resources/list_changed
unregisterResourceProvider(name)unmount them; false when no such provider

Exports ​

ts
import {
  McpAdapter,
  McpTool,
  McpToolError,
  MCP_ADAPTER,
  getMcpToolMeta,
  isMcpTool,
  MCP_TOOL_METADATA,
} from '@forinda/kickjs-mcp'

import type {
  McpAdapterOptions,
  McpAdapterInstance,
  McpToolOptions,
  McpToolDefinition,
  McpCustomTool,
  McpToolContext,
  McpToolProvider,
  McpPrincipal,
  McpRequestInfo,
  McpCallContext,
  McpProtectedResourceOptions,
  McpToolAnnotations,
  McpToolSummary,
  McpAuthOptions,
  McpExposureMode,
  McpTransport,
  McpToolExample,
} from '@forinda/kickjs-mcp'

Released under the MIT License. Built with TypeScript — runs on Express, Fastify, or h3.