mcp-expose 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/LICENSE +21 -0
- package/README.md +708 -0
- package/dist/adonisjs/index.cjs +708 -0
- package/dist/adonisjs/index.cjs.map +1 -0
- package/dist/adonisjs/index.d.cts +68 -0
- package/dist/adonisjs/index.d.ts +68 -0
- package/dist/adonisjs/index.js +684 -0
- package/dist/adonisjs/index.js.map +1 -0
- package/dist/express/index.cjs +789 -0
- package/dist/express/index.cjs.map +1 -0
- package/dist/express/index.d.cts +61 -0
- package/dist/express/index.d.ts +61 -0
- package/dist/express/index.js +763 -0
- package/dist/express/index.js.map +1 -0
- package/dist/fastify/index.cjs +660 -0
- package/dist/fastify/index.cjs.map +1 -0
- package/dist/fastify/index.d.cts +42 -0
- package/dist/fastify/index.d.ts +42 -0
- package/dist/fastify/index.js +635 -0
- package/dist/fastify/index.js.map +1 -0
- package/dist/hono/index.cjs +656 -0
- package/dist/hono/index.cjs.map +1 -0
- package/dist/hono/index.d.cts +44 -0
- package/dist/hono/index.d.ts +44 -0
- package/dist/hono/index.js +630 -0
- package/dist/hono/index.js.map +1 -0
- package/dist/index.cjs +720 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +81 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +686 -0
- package/dist/index.js.map +1 -0
- package/dist/koa/index.cjs +739 -0
- package/dist/koa/index.cjs.map +1 -0
- package/dist/koa/index.d.cts +68 -0
- package/dist/koa/index.d.ts +68 -0
- package/dist/koa/index.js +709 -0
- package/dist/koa/index.js.map +1 -0
- package/dist/nestjs/index.cjs +1117 -0
- package/dist/nestjs/index.cjs.map +1 -0
- package/dist/nestjs/index.d.cts +104 -0
- package/dist/nestjs/index.d.ts +104 -0
- package/dist/nestjs/index.js +1079 -0
- package/dist/nestjs/index.js.map +1 -0
- package/dist/server-fzkb-wJo.d.cts +194 -0
- package/dist/server-fzkb-wJo.d.ts +194 -0
- package/package.json +225 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/express/index.ts","../../src/core/dispatch.ts","../../src/core/marker.ts","../../src/core/node.ts","../../src/core/schema.ts","../../src/core/route-tool.ts","../../src/core/server.ts","../../src/express/discover.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { createFetchDispatcher } from '../core/dispatch.js';\nimport { mark } from '../core/marker.js';\nimport { loopbackBaseUrl, normalizeHeaders, readRawBody, writeNodeResponse } from '../core/node.js';\nimport { createRouteTool } from '../core/route-tool.js';\nimport { McpServer } from '../core/server.js';\nimport type { McpServerOptions, McpToolDefinition, RouteToolOptions, ToolContext } from '../core/types.js';\nimport { discoverExpressRoutes, type ExpressAppLike } from './discover.js';\n\nexport type { ExpressAppLike } from './discover.js';\n\ntype Req = IncomingMessage & { body?: unknown; ip?: string };\ntype Next = (err?: unknown) => void;\ntype Middleware = (req: Req, res: ServerResponse, next: Next) => void;\n\n/**\n * Mark an Express route as an MCP tool. Put it first in the route's handler list:\n *\n * app.get('/users/:id', mcpTool({ description: 'Get a user' }), auth, getUser)\n *\n * It is a no-op at request time; it only carries metadata.\n */\nexport function mcpTool(options: RouteToolOptions = {}): Middleware {\n return mark<Middleware>((_req, _res, next) => next(), options);\n}\n\nexport interface ExpressMcpOptions extends McpServerOptions {\n /** Path of the MCP endpoint. @default '/mcp' */\n path?: string;\n /**\n * Base URL for internal calls. Defaults to the address/port the MCP request\n * arrived on (loopback), so no configuration is needed in most setups.\n */\n baseUrl?: string;\n /**\n * Prefixes of mounted routers, e.g. `{ '/api': apiRouter }`. Express 5 does\n * not keep mount paths, so routers mounted with a path must be listed here.\n * (Express 4 mount paths are detected automatically.)\n */\n routers?: Record<string, unknown>;\n /** Routes to expose without touching the route definitions. */\n routes?: (RouteToolOptions & { method: string; path: string })[];\n /** Extra hand-written tools (see `defineTool`). */\n tools?: McpToolDefinition[];\n /**\n * Middleware run before the MCP endpoint, e.g. your auth middleware, to\n * protect tools/list as well as tools/call.\n */\n middleware?: Middleware[];\n}\n\n/**\n * Add an MCP endpoint (default `POST /mcp`) to an Express app. Tools are\n * discovered lazily on the first MCP request, so call this before or after\n * defining routes. Returns the underlying McpServer.\n */\nexport function mountMcp(app: ExpressAppLike, options: ExpressMcpOptions): McpServer {\n const path = options.path ?? '/mcp';\n const server = new McpServer(options);\n const dispatch = createFetchDispatcher({\n baseUrl: options.baseUrl ?? ((ctx) => loopbackBaseUrl(ctx.raw as IncomingMessage)),\n });\n\n for (const t of options.tools ?? []) server.addTool(t);\n server.onLoad(() => {\n const found = discoverExpressRoutes(app, options.routers);\n for (const r of options.routes ?? []) found.push({ method: r.method, path: r.path, options: r });\n for (const f of found)\n server.addTool(createRouteTool({ method: f.method, path: f.path }, f.options, dispatch, options));\n });\n\n const handler: Middleware = (req, res, next) => {\n (async () => {\n const body = req.method === 'POST' && req.body === undefined ? await readRawBody(req) : req.body;\n const ctx: ToolContext = {\n headers: normalizeHeaders(req.headers),\n clientIp: req.ip ?? req.socket.remoteAddress,\n raw: req,\n };\n const out = await server.handleHttp({ method: req.method ?? 'POST', headers: ctx.headers, body }, ctx);\n writeNodeResponse(res, out);\n })().catch(next);\n };\n (app.all as (path: string, ...h: Middleware[]) => void).call(app, path, ...(options.middleware ?? []), handler);\n return server;\n}\n","import type { Dispatcher, RouteRequest, ToolContext } from './types.js';\n\nexport function buildUrl(base: string, req: Pick<RouteRequest, 'path' | 'query'>): string {\n const url = new URL(base.replace(/\\/+$/, '') + req.path);\n for (const [k, v] of Object.entries(req.query)) {\n for (const item of Array.isArray(v) ? v : [v]) url.searchParams.append(k, item);\n }\n return url.toString();\n}\n\nexport interface FetchDispatcherOptions {\n /**\n * Base URL of the API, e.g. `http://127.0.0.1:3000` or `https://api.example.com/v1`.\n * A function lets adapters resolve it per call (e.g. from the local port).\n */\n baseUrl: string | ((ctx: ToolContext) => string);\n /** Custom fetch implementation. Defaults to the global `fetch`. */\n fetch?: typeof fetch;\n /** Per-request timeout in ms. @default 30_000 */\n timeoutMs?: number;\n}\n\n/**\n * Dispatches tool calls as real HTTP requests. Used for loopback calls into the\n * host app (Express, Koa, NestJS) and for standalone gateways in front of any API.\n */\nexport function createFetchDispatcher(opts: FetchDispatcherOptions): Dispatcher {\n const doFetch = opts.fetch ?? fetch;\n return async (req, ctx) => {\n const base = typeof opts.baseUrl === 'function' ? opts.baseUrl(ctx) : opts.baseUrl;\n const res = await doFetch(buildUrl(base, req), {\n method: req.method,\n headers: req.headers,\n body:\n req.body === undefined || req.method === 'GET' || req.method === 'HEAD' ? undefined : JSON.stringify(req.body),\n signal: AbortSignal.timeout(opts.timeoutMs ?? 30_000),\n });\n const headers: Record<string, string> = {};\n res.headers.forEach((v, k) => (headers[k] = v));\n return { status: res.status, headers, body: await res.text() };\n };\n}\n","import type { RouteToolOptions } from './types.js';\n\n/** Symbol under which marker middleware carries its tool options. */\nexport const MCP_TOOL = Symbol.for('mcp-expose.tool');\n\nexport type Marked<T> = T & { [MCP_TOOL]: RouteToolOptions };\n\nexport function markerOf(fn: unknown): RouteToolOptions | undefined {\n return typeof fn === 'function' ? (fn as Partial<Marked<object>>)[MCP_TOOL] : undefined;\n}\n\nexport function mark<T extends object>(fn: T, opts: RouteToolOptions): Marked<T> {\n Object.defineProperty(fn, MCP_TOOL, { value: opts, enumerable: false });\n return fn as Marked<T>;\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { McpHttpResponse } from './server.js';\n\n/** Flatten Node's IncomingHttpHeaders into lower-cased single strings. */\nexport function normalizeHeaders(headers: Record<string, string | string[] | undefined>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (v === undefined) continue;\n out[k.toLowerCase()] = Array.isArray(v) ? v.join(', ') : String(v);\n }\n return out;\n}\n\n/** Read and return the raw body of a Node request (for frameworks without a JSON body parser). */\nexport function readRawBody(req: IncomingMessage, limit = 4 * 1024 * 1024): Promise<string> {\n return new Promise((resolve, reject) => {\n let size = 0;\n const chunks: Buffer[] = [];\n req.on('data', (c: Buffer) => {\n size += c.length;\n if (size > limit) {\n reject(new Error('Request body too large'));\n req.destroy();\n } else chunks.push(c);\n });\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));\n req.on('error', reject);\n });\n}\n\n/** Base URL that reaches the same server the MCP request arrived on. */\nexport function loopbackBaseUrl(req: IncomingMessage): string {\n const socket = req.socket as IncomingMessage['socket'] & {\n encrypted?: boolean;\n server?: { address(): { address: string } | string | null };\n };\n const port = socket.localPort;\n const encrypted = socket.encrypted;\n // Prefer the address the server is bound to: when it listens on all\n // interfaces this yields 127.0.0.1, so internal calls come from loopback\n // (which `trust proxy: 'loopback'` style settings rely on).\n const bound = socket.server?.address();\n let host = (typeof bound === 'object' && bound?.address) || socket.localAddress || '127.0.0.1';\n if (host.startsWith('::ffff:')) host = host.slice(7);\n if (host === '::' || host === '0.0.0.0') host = '127.0.0.1';\n if (host.includes(':')) host = `[${host}]`;\n return `${encrypted ? 'https' : 'http'}://${host}:${port}`;\n}\n\nexport function writeNodeResponse(res: ServerResponse, out: McpHttpResponse): void {\n res.statusCode = out.status;\n for (const [k, v] of Object.entries(out.headers)) res.setHeader(k, v);\n res.end(out.body);\n}\n","import type { JsonSchema, McpToolDefinition, SchemaLike } from './types.js';\n\ninterface StandardSchemaV1 {\n '~standard': {\n validate?: (value: unknown) => unknown;\n jsonSchema?: { input?: (opts: { target: string }) => unknown };\n };\n}\n\nfunction isStandard(s: unknown): s is StandardSchemaV1 {\n return typeof s === 'object' && s !== null && '~standard' in s;\n}\n\n/** Convert any supported schema flavour into a plain JSON Schema object. */\nexport function toJsonSchema(schema: SchemaLike | undefined): JsonSchema | undefined {\n if (schema === undefined || schema === null) return undefined;\n let out: unknown;\n if (isStandard(schema) && typeof schema['~standard'].jsonSchema?.input === 'function') {\n out = schema['~standard'].jsonSchema.input({ target: 'draft-2020-12' });\n } else if (typeof (schema as { toJSONSchema?: unknown }).toJSONSchema === 'function') {\n out = (schema as { toJSONSchema(): unknown }).toJSONSchema();\n } else if (isStandard(schema)) {\n throw new Error(\n 'mcp-expose: this schema library does not support JSON Schema export. Pass a plain JSON Schema instead.',\n );\n } else {\n out = schema;\n }\n const { $schema: _ignored, ...rest } = out as JsonSchema;\n return rest;\n}\n\n/** Build a validator from a Standard Schema, if the input is one. */\nexport function toValidator(schema: SchemaLike | undefined): McpToolDefinition['validate'] {\n if (!isStandard(schema) || typeof schema['~standard'].validate !== 'function') return undefined;\n const validate = schema['~standard'].validate;\n return async (value) => {\n const result = (await validate(value)) as {\n value?: unknown;\n issues?: { message: string; path?: (PropertyKey | { key: PropertyKey })[] }[];\n };\n if (!result.issues) return { ok: true, value: result.value };\n const message = result.issues\n .map((i) => {\n const path = (i.path ?? []).map((p) => (typeof p === 'object' ? String(p.key) : String(p))).join('.');\n return path ? `${path}: ${i.message}` : i.message;\n })\n .join('; ');\n return { ok: false, message };\n };\n}\n\n/** Very small structural check used when no Standard Schema validator exists. */\nexport function checkRequired(schema: JsonSchema, args: Record<string, unknown>): string | undefined {\n const missing = (schema.required ?? []).filter((k) => args[k] === undefined);\n return missing.length ? `Missing required argument(s): ${missing.join(', ')}` : undefined;\n}\n","import { checkRequired, toJsonSchema, toValidator } from './schema.js';\nimport type {\n Dispatcher,\n JsonSchema,\n McpServerOptions,\n McpToolDefinition,\n RouteResponse,\n RouteSpec,\n RouteToolOptions,\n ToolAnnotations,\n ToolContext,\n ToolResult,\n} from './types.js';\n\nexport const DEFAULT_FORWARD_HEADERS = ['authorization', 'cookie', 'x-api-key', 'accept-language'];\nconst BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);\nconst PARAM_RE = /:([A-Za-z0-9_]+)\\??|\\{([A-Za-z0-9_]+)\\}/g;\n\n/** Names of the path parameters in a route path (`/a/:id/{slug}` -> ['id', 'slug']). */\nexport function pathParams(path: string): string[] {\n return [...path.matchAll(PARAM_RE)].map((m) => (m[1] ?? m[2]) as string);\n}\n\n/**\n * Encode one path-parameter value. Rejects empty, `.` and `..` values: after URL\n * normalisation they would change which route is called (e.g. `/orders/../admin`),\n * letting an agent reach routes that were never exposed as tools.\n */\nfunction encodeSegment(name: string, value: unknown): string {\n const raw = String(value);\n if (raw === '' || raw === '.' || raw === '..') {\n throw new Error(`Invalid value for path parameter \"${name}\": ${JSON.stringify(raw)}`);\n }\n return encodeURIComponent(raw);\n}\n\n/** Replace path placeholders with URL-encoded values. Missing optional params drop their segment. */\nexport function interpolatePath(path: string, values: Record<string, unknown>): string {\n return path\n .replace(/\\/:([A-Za-z0-9_]+)\\?/g, (_, k: string) =>\n values[k] === undefined ? '' : `/${encodeSegment(k, values[k])}`,\n )\n .replace(PARAM_RE, (_, a?: string, b?: string) => {\n const k = (a ?? b) as string;\n return encodeSegment(k, values[k]);\n });\n}\n\n/** Join path segments, normalising slashes. */\nexport function joinPaths(...parts: (string | undefined)[]): string {\n const joined = parts\n .filter((p): p is string => !!p && p !== '/')\n .map((p) => p.replace(/^\\/+|\\/+$/g, ''))\n .filter(Boolean)\n .join('/');\n return `/${joined}`;\n}\n\n/** `GET /users/:id/orders` -> `get_users_by_id_orders` */\nexport function toolNameFromRoute(method: string, path: string): string {\n const segments = path\n .split('/')\n .filter(Boolean)\n .map((s) => {\n const m = /^(?::([A-Za-z0-9_]+)\\??|\\{([A-Za-z0-9_]+)\\})$/.exec(s);\n return m ? `by_${m[1] ?? m[2]}` : s;\n });\n return sanitizeToolName([method.toLowerCase(), ...segments].join('_'));\n}\n\nexport function sanitizeToolName(name: string): string {\n return name\n .replace(/[^A-Za-z0-9_-]+/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '')\n .slice(0, 64);\n}\n\nfunction defaultAnnotations(method: string): ToolAnnotations {\n switch (method) {\n case 'GET':\n case 'HEAD':\n return { readOnlyHint: true, openWorldHint: false };\n case 'DELETE':\n return { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };\n case 'PUT':\n return { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };\n default:\n return { readOnlyHint: false, destructiveHint: false, openWorldHint: false };\n }\n}\n\ninterface ArgMapping {\n params: string[];\n query: Set<string>;\n body: Set<string>;\n /** Body schema is not an object: the whole body is passed under the `body` key. */\n wholeBody: boolean;\n bodyMethod: boolean;\n}\n\n/**\n * Build the flat input schema an agent sees, and remember which argument goes\n * to the path, query string or body when the tool is called.\n */\nexport function buildInputSchema(\n route: RouteSpec,\n opts: RouteToolOptions,\n): { schema: JsonSchema; mapping: ArgMapping } {\n const method = route.method.toUpperCase();\n const params = pathParams(route.path);\n const mapping: ArgMapping = {\n params,\n query: new Set(),\n body: new Set(),\n wholeBody: false,\n bodyMethod: BODY_METHODS.has(method),\n };\n\n if (opts.input) {\n const schema = toJsonSchema(opts.input) as JsonSchema;\n return { schema: { type: 'object', ...schema }, mapping };\n }\n\n const properties: Record<string, JsonSchema> = {};\n const required = new Set<string>();\n\n const paramSchema = toJsonSchema(opts.params);\n for (const p of params) {\n properties[p] = paramSchema?.properties?.[p] ?? { type: 'string', description: `Path parameter \"${p}\"` };\n if (!route.path.includes(`:${p}?`)) required.add(p);\n }\n\n const querySchema = toJsonSchema(opts.query);\n for (const [k, v] of Object.entries(querySchema?.properties ?? {})) {\n properties[k] = v;\n mapping.query.add(k);\n }\n for (const k of querySchema?.required ?? []) required.add(k);\n\n const bodySchema = toJsonSchema(opts.body);\n if (bodySchema) {\n if (bodySchema.properties && (bodySchema.type === undefined || bodySchema.type === 'object')) {\n for (const [k, v] of Object.entries(bodySchema.properties)) {\n properties[k] = v;\n mapping.body.add(k);\n }\n for (const k of bodySchema.required ?? []) required.add(k);\n } else {\n properties.body = bodySchema;\n required.add('body');\n mapping.wholeBody = true;\n }\n }\n\n const schema: JsonSchema = { type: 'object', properties };\n if (required.size) schema.required = [...required];\n return { schema, mapping };\n}\n\nfunction splitArgs(args: Record<string, unknown>, mapping: ArgMapping) {\n const pathValues: Record<string, unknown> = {};\n const query: Record<string, string | string[]> = {};\n let body: Record<string, unknown> | unknown | undefined;\n\n for (const [k, v] of Object.entries(args)) {\n if (v === undefined) continue;\n if (mapping.params.includes(k)) {\n pathValues[k] = v;\n } else if (mapping.wholeBody && k === 'body') {\n body = v;\n } else if (mapping.query.has(k) || (!mapping.body.has(k) && !mapping.bodyMethod)) {\n query[k] = Array.isArray(v) ? v.map(String) : typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v);\n } else {\n body = { ...((body as Record<string, unknown>) ?? {}), [k]: v };\n }\n }\n if (body === undefined && mapping.bodyMethod) body = {};\n return { pathValues, query, body };\n}\n\nexport function responseToResult(res: RouteResponse, maxChars: number): ToolResult {\n let text = res.body;\n if (text.length > maxChars) text = `${text.slice(0, maxChars)}\\n…[truncated ${text.length - maxChars} chars]`;\n const isError = res.status >= 400;\n const result: ToolResult = {\n content: [{ type: 'text', text: isError ? `HTTP ${res.status}\\n${text}` : text || `HTTP ${res.status}` }],\n };\n if (isError) {\n result.isError = true;\n return result;\n }\n if ((res.headers['content-type'] ?? '').includes('json') && text === res.body) {\n try {\n const parsed = JSON.parse(res.body);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) result.structuredContent = parsed;\n } catch {\n /* not JSON after all */\n }\n }\n return result;\n}\n\nexport function pickForwardHeaders(ctx: ToolContext, names: string[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const name of names) {\n const v = ctx.headers[name.toLowerCase()];\n if (v !== undefined) out[name.toLowerCase()] = v;\n }\n return out;\n}\n\n/**\n * Turn an HTTP route + options into an MCP tool whose handler calls the route\n * through `dispatch`, so auth guards, validation and rate limits all still apply.\n */\nexport function createRouteTool(\n route: RouteSpec,\n opts: RouteToolOptions,\n dispatch: Dispatcher,\n serverOpts: Pick<McpServerOptions, 'forwardHeaders' | 'maxResponseChars'> = {},\n): McpToolDefinition {\n const method = route.method.toUpperCase();\n const name = sanitizeToolName(opts.name ?? toolNameFromRoute(method, route.path));\n const { schema, mapping } = buildInputSchema(route, opts);\n const forward = serverOpts.forwardHeaders ?? DEFAULT_FORWARD_HEADERS;\n const maxChars = serverOpts.maxResponseChars ?? 100_000;\n\n return {\n name,\n title: opts.title,\n description: opts.description ?? `${method} ${route.path}`,\n inputSchema: schema,\n annotations: { ...defaultAnnotations(method), ...opts.annotations },\n validate: toValidator(opts.input),\n async handler(args, ctx) {\n const missing = opts.input ? undefined : checkRequired(schema, args);\n if (missing) return { isError: true, content: [{ type: 'text', text: missing }] };\n\n const { pathValues, query, body } = splitArgs(args, mapping);\n const headers: Record<string, string> = {\n accept: 'application/json',\n ...pickForwardHeaders(ctx, forward),\n ...opts.headers,\n 'x-mcp-tool': name,\n };\n if (ctx.clientIp) headers['x-forwarded-for'] = ctx.clientIp;\n if (body !== undefined) headers['content-type'] = 'application/json';\n\n let path: string;\n try {\n path = interpolatePath(route.path, pathValues);\n } catch (err) {\n return { isError: true, content: [{ type: 'text', text: (err as Error).message }] };\n }\n const res = await dispatch({ method, path, query, body, headers }, ctx);\n return responseToResult(res, maxChars);\n },\n };\n}\n","import type { McpServerOptions, McpToolDefinition, ToolContext, ToolResult } from './types.js';\n\nexport const SUPPORTED_PROTOCOL_VERSIONS = ['2025-11-25', '2025-06-18', '2025-03-26', '2024-11-05'];\nexport const LATEST_PROTOCOL_VERSION = SUPPORTED_PROTOCOL_VERSIONS[0] as string;\n\ntype JsonRpcId = string | number | null;\ninterface JsonRpcRequest {\n jsonrpc: '2.0';\n id?: JsonRpcId;\n method: string;\n params?: Record<string, unknown>;\n}\nexport interface JsonRpcResponse {\n jsonrpc: '2.0';\n id: JsonRpcId;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n}\n\nconst PARSE_ERROR = -32700;\nconst INVALID_REQUEST = -32600;\nconst METHOD_NOT_FOUND = -32601;\nconst INVALID_PARAMS = -32602;\n\nconst ok = (id: JsonRpcId, result: unknown): JsonRpcResponse => ({ jsonrpc: '2.0', id, result });\nconst fail = (id: JsonRpcId, code: number, message: string): JsonRpcResponse => ({\n jsonrpc: '2.0',\n id,\n error: { code, message },\n});\n\n/** Minimal HTTP request/response shapes, so each adapter can bridge its own framework. */\nexport interface McpHttpRequest {\n method: string;\n headers: Record<string, string>;\n /** Parsed JSON body, or the raw string. */\n body: unknown;\n}\nexport interface McpHttpResponse {\n status: number;\n headers: Record<string, string>;\n body?: string;\n}\n\n/**\n * A stateless MCP server speaking the Streamable HTTP transport (JSON responses).\n * Holds the tool registry and answers JSON-RPC messages.\n */\nexport class McpServer {\n private readonly tools = new Map<string, McpToolDefinition>();\n private loaders: (() => void | Promise<void>)[] = [];\n\n constructor(readonly options: McpServerOptions) {}\n\n /** Register a tool. Throws on duplicate names. */\n addTool(tool: McpToolDefinition): this {\n if (this.tools.has(tool.name)) {\n throw new Error(`mcp-expose: duplicate tool name \"${tool.name}\". Set an explicit \\`name\\`.`);\n }\n this.tools.set(tool.name, tool);\n return this;\n }\n\n /** Register a function that adds tools lazily, right before the first MCP request is served. */\n onLoad(loader: () => void | Promise<void>): this {\n this.loaders.push(loader);\n return this;\n }\n\n async listTools(): Promise<McpToolDefinition[]> {\n await this.load();\n return [...this.tools.values()];\n }\n\n private async load() {\n if (!this.loaders.length) return;\n const loaders = this.loaders;\n this.loaders = [];\n for (const l of loaders) await l();\n }\n\n /** Handle one JSON-RPC message (or a batch). Returns null when no response is due. */\n async handleMessage(message: unknown, ctx: ToolContext): Promise<JsonRpcResponse | JsonRpcResponse[] | null> {\n if (Array.isArray(message)) {\n const results = (await Promise.all(message.map((m) => this.handleOne(m, ctx)))).filter(\n (r): r is JsonRpcResponse => r !== null,\n );\n return results.length ? results : null;\n }\n return this.handleOne(message, ctx);\n }\n\n private async handleOne(message: unknown, ctx: ToolContext): Promise<JsonRpcResponse | null> {\n const msg = message as Partial<JsonRpcRequest>;\n if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') {\n return fail(null, INVALID_REQUEST, 'Invalid JSON-RPC message');\n }\n // Responses from the client or notifications: acknowledge, no reply.\n if (typeof msg.method !== 'string' || msg.id === undefined) return null;\n const id = msg.id;\n const params = msg.params ?? {};\n\n await this.load();\n switch (msg.method) {\n case 'initialize': {\n const requested = params.protocolVersion as string | undefined;\n const protocolVersion =\n requested && SUPPORTED_PROTOCOL_VERSIONS.includes(requested) ? requested : LATEST_PROTOCOL_VERSION;\n return ok(id, {\n protocolVersion,\n capabilities: { tools: { listChanged: false } },\n serverInfo: { name: this.options.name, version: this.options.version ?? '1.0.0' },\n ...(this.options.instructions ? { instructions: this.options.instructions } : {}),\n });\n }\n case 'ping':\n return ok(id, {});\n case 'tools/list':\n return ok(id, {\n tools: [...this.tools.values()].map((t) => ({\n name: t.name,\n ...(t.title ? { title: t.title } : {}),\n description: t.description,\n inputSchema: t.inputSchema,\n ...(t.annotations ? { annotations: t.annotations } : {}),\n })),\n });\n case 'tools/call': {\n const tool = this.tools.get(params.name as string);\n if (!tool) return fail(id, INVALID_PARAMS, `Unknown tool: ${String(params.name)}`);\n return ok(id, await this.callTool(tool, (params.arguments ?? {}) as Record<string, unknown>, ctx));\n }\n case 'resources/list':\n return ok(id, { resources: [] });\n case 'prompts/list':\n return ok(id, { prompts: [] });\n default:\n return fail(id, METHOD_NOT_FOUND, `Method not found: ${msg.method}`);\n }\n }\n\n private async callTool(\n tool: McpToolDefinition,\n args: Record<string, unknown>,\n ctx: ToolContext,\n ): Promise<ToolResult> {\n try {\n if (tool.validate) {\n const v = await tool.validate(args);\n if (!v.ok) return { isError: true, content: [{ type: 'text', text: `Invalid arguments: ${v.message}` }] };\n args = v.value as Record<string, unknown>;\n }\n return await tool.handler(args, ctx);\n } catch (err) {\n // Tool failures are reported in-band so the model can react to them.\n return { isError: true, content: [{ type: 'text', text: `Tool error: ${(err as Error).message}` }] };\n }\n }\n\n /** Check the Origin header (DNS rebinding protection). */\n isOriginAllowed(origin: string | undefined): boolean {\n if (!origin) return true;\n const allowed = this.options.allowedOrigins;\n if (allowed === '*') return true;\n return (allowed ?? []).includes(origin);\n }\n\n /**\n * Framework-neutral Streamable HTTP handler. Adapters convert their request\n * into McpHttpRequest, call this, and write the McpHttpResponse back.\n */\n async handleHttp(req: McpHttpRequest, ctx: ToolContext): Promise<McpHttpResponse> {\n const json = { 'content-type': 'application/json' };\n if (!this.isOriginAllowed(req.headers.origin)) {\n return { status: 403, headers: json, body: JSON.stringify(fail(null, INVALID_REQUEST, 'Origin not allowed')) };\n }\n if (req.method.toUpperCase() !== 'POST') {\n // Stateless server: no standalone SSE stream and no sessions to delete.\n return { status: 405, headers: { allow: 'POST' } };\n }\n let body = req.body;\n if (typeof body === 'string' || body instanceof Uint8Array) {\n try {\n body = JSON.parse(typeof body === 'string' ? body : new TextDecoder().decode(body));\n } catch {\n return { status: 400, headers: json, body: JSON.stringify(fail(null, PARSE_ERROR, 'Parse error')) };\n }\n }\n const response = await this.handleMessage(body, ctx);\n if (response === null) return { status: 202, headers: {} };\n return { status: 200, headers: json, body: JSON.stringify(response) };\n }\n}\n","// Internal: route discovery for Express 3, 4 and 5 (not part of the public API).\nimport { markerOf } from '../core/marker.js';\nimport { joinPaths } from '../core/route-tool.js';\nimport type { RouteToolOptions } from '../core/types.js';\n\ninterface ExpressLayer {\n route?: { path: string | string[]; methods: Record<string, boolean>; stack: { handle: unknown }[] };\n name?: string;\n handle?: { stack?: ExpressLayer[] };\n regexp?: RegExp & { fast_slash?: boolean };\n}\n\n/** Structural type for an Express 4/5 app (or Router). Kept loose on purpose. */\nexport interface ExpressAppLike {\n all: Function;\n router?: unknown;\n _router?: unknown;\n /** Express 3 route table: `{ get: [{ path, method, callbacks }], ... }`. */\n routes?: unknown;\n}\n\ntype Express3Routes = Record<string, { path: string | RegExp; method: string; callbacks: unknown[] }[]>;\n\n/** Express 3 keeps app-level routes in `app.routes`, keyed by method. */\nfunction collectExpress3(routes: Express3Routes, out: Found[]) {\n for (const list of Object.values(routes)) {\n for (const r of list) {\n const marker = r.callbacks.map(markerOf).find(Boolean);\n if (marker && typeof r.path === 'string')\n out.push({ method: r.method.toUpperCase(), path: r.path, options: marker });\n }\n }\n}\n\nfunction stackOf(app: ExpressAppLike): ExpressLayer[] {\n // Express 4 keeps the router on `_router`; its `app.router` getter throws.\n // Express 5 exposes `app.router`.\n let router = app._router as { stack?: ExpressLayer[] } | undefined;\n if (!router) {\n try {\n router = app.router as typeof router;\n } catch {\n router = undefined;\n }\n }\n return router?.stack ?? [];\n}\n\n/** Recover an Express 4 mount path from a layer regexp (best effort). */\nfunction express4Prefix(layer: ExpressLayer): string | undefined {\n const re = layer.regexp;\n if (!re) return undefined;\n if (re.fast_slash) return '';\n const m = /^\\/\\^((?:\\\\[.*+?^${}()|[\\]\\\\/]|[^.*+?^${}()|[\\]\\\\/])*)\\\\\\/\\?\\(\\?=\\\\\\/\\|\\$\\)\\/i?$/.exec(re.toString());\n return m ? (m[1] as string).replace(/\\\\(.)/g, '$1') : undefined;\n}\n\nexport interface Found {\n method: string;\n path: string;\n options: RouteToolOptions;\n}\n\nfunction collect(\n stack: ExpressLayer[],\n prefix: string,\n routers: Map<unknown, string>,\n out: Found[],\n unresolved: string[],\n) {\n for (const layer of stack) {\n if (layer.route) {\n const marker = layer.route.stack.map((l) => markerOf(l.handle)).find(Boolean);\n if (!marker) continue;\n const paths = Array.isArray(layer.route.path) ? layer.route.path : [layer.route.path];\n for (const method of Object.keys(layer.route.methods).filter((m) => m !== '_all')) {\n for (const p of paths) out.push({ method: method.toUpperCase(), path: joinPaths(prefix, p), options: marker });\n }\n } else if (layer.handle?.stack) {\n const known = routers.get(layer.handle);\n const sub = known ?? express4Prefix(layer);\n if (sub === undefined) {\n // Only complain if this router actually contains MCP tools.\n const inner: Found[] = [];\n collect(layer.handle.stack, '', routers, inner, unresolved);\n if (inner.length) unresolved.push(...inner.map((f) => `${f.method} ${f.path}`));\n continue;\n }\n collect(layer.handle.stack, joinPaths(prefix, sub), routers, out, unresolved);\n }\n }\n}\n\n/** Find every route marked with `mcpTool()` in an Express app. */\nexport function discoverExpressRoutes(app: ExpressAppLike, routers: Record<string, unknown> = {}): Found[] {\n const stack = stackOf(app);\n const byRouter = new Map(Object.entries(routers).map(([prefix, r]) => [r, prefix]));\n const out: Found[] = [];\n const unresolved: string[] = [];\n collect(stack, '', byRouter, out, unresolved);\n if (!stack.length && app.routes && typeof app.routes === 'object') collectExpress3(app.routes as Express3Routes, out);\n if (unresolved.length) {\n throw new Error(\n `mcp-expose: cannot determine the mount path of a router containing MCP tools (${unresolved.join(', ')}). ` +\n `Pass it via the \\`routers\\` option, e.g. mountMcp(app, { routers: { '/api': apiRouter } }).`,\n );\n }\n return out;\n}\n"],"mappings":"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","names":["buildUrl","base","req","url","URL","replace","path","k","v","Object","entries","query","item","Array","isArray","searchParams","append","toString","createFetchDispatcher","opts","doFetch","fetch","ctx","baseUrl","res","method","headers","body","undefined","JSON","stringify","signal","AbortSignal","timeout","timeoutMs","forEach","status","text","MCP_TOOL","Symbol","for","markerOf","fn","undefined","mark","opts","Object","defineProperty","value","enumerable","normalizeHeaders","headers","out","k","v","Object","entries","undefined","toLowerCase","Array","isArray","join","String","readRawBody","req","limit","Promise","resolve","reject","size","chunks","on","c","length","Error","destroy","push","Buffer","concat","toString","loopbackBaseUrl","socket","port","localPort","encrypted","bound","server","address","host","localAddress","startsWith","slice","includes","writeNodeResponse","res","statusCode","status","setHeader","end","body","isStandard","s","toJsonSchema","schema","undefined","out","jsonSchema","input","target","toJSONSchema","Error","$schema","_ignored","rest","toValidator","validate","value","result","issues","ok","message","map","i","path","p","String","key","join","checkRequired","args","missing","required","filter","k","length","DEFAULT_FORWARD_HEADERS","BODY_METHODS","Set","PARAM_RE","pathParams","path","matchAll","map","m","encodeSegment","name","value","raw","String","Error","JSON","stringify","encodeURIComponent","interpolatePath","values","replace","_","k","undefined","a","b","joinPaths","parts","joined","filter","p","Boolean","join","toolNameFromRoute","method","segments","split","s","exec","sanitizeToolName","toLowerCase","slice","defaultAnnotations","readOnlyHint","openWorldHint","destructiveHint","idempotentHint","buildInputSchema","route","opts","toUpperCase","params","mapping","query","body","wholeBody","bodyMethod","has","input","schema","toJsonSchema","type","properties","required","paramSchema","description","includes","add","querySchema","v","Object","entries","bodySchema","size","splitArgs","args","pathValues","Array","isArray","responseToResult","res","maxChars","text","length","isError","status","result","content","headers","parsed","parse","structuredContent","pickForwardHeaders","ctx","names","out","createRouteTool","dispatch","serverOpts","forward","forwardHeaders","maxResponseChars","title","inputSchema","annotations","validate","toValidator","handler","missing","checkRequired","accept","clientIp","err","message","SUPPORTED_PROTOCOL_VERSIONS","LATEST_PROTOCOL_VERSION","PARSE_ERROR","INVALID_REQUEST","METHOD_NOT_FOUND","INVALID_PARAMS","ok","id","result","jsonrpc","fail","code","message","error","McpServer","tools","Map","loaders","options","addTool","tool","has","name","Error","set","onLoad","loader","push","listTools","load","values","length","l","handleMessage","ctx","Array","isArray","results","Promise","all","map","m","handleOne","filter","r","msg","method","undefined","params","requested","protocolVersion","includes","capabilities","listChanged","serverInfo","version","instructions","t","title","description","inputSchema","annotations","get","String","callTool","arguments","resources","prompts","args","validate","v","isError","content","type","text","value","handler","err","isOriginAllowed","origin","allowed","allowedOrigins","handleHttp","req","json","headers","status","body","JSON","stringify","toUpperCase","allow","Uint8Array","parse","TextDecoder","decode","response","collectExpress3","routes","out","list","Object","values","r","marker","callbacks","map","markerOf","find","Boolean","path","push","method","toUpperCase","options","stackOf","app","router","_router","undefined","stack","express4Prefix","layer","re","regexp","fast_slash","m","exec","toString","replace","collect","prefix","routers","unresolved","route","l","handle","paths","Array","isArray","keys","methods","filter","p","joinPaths","known","get","sub","inner","length","f","discoverExpressRoutes","byRouter","Map","entries","Error","join","mcpTool","options","mark","_req","_res","next","mountMcp","app","path","server","McpServer","dispatch","createFetchDispatcher","baseUrl","ctx","loopbackBaseUrl","raw","t","tools","addTool","onLoad","found","discoverExpressRoutes","routers","r","routes","push","method","f","createRouteTool","handler","req","res","body","undefined","readRawBody","headers","normalizeHeaders","clientIp","ip","socket","remoteAddress","out","handleHttp","writeNodeResponse","catch","all","call","middleware"]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { M as McpServerOptions, R as RouteToolOptions, a as McpToolDefinition, b as McpServer } from '../server-fzkb-wJo.cjs';
|
|
3
|
+
|
|
4
|
+
/** Structural type for an Express 4/5 app (or Router). Kept loose on purpose. */
|
|
5
|
+
interface ExpressAppLike {
|
|
6
|
+
all: Function;
|
|
7
|
+
router?: unknown;
|
|
8
|
+
_router?: unknown;
|
|
9
|
+
/** Express 3 route table: `{ get: [{ path, method, callbacks }], ... }`. */
|
|
10
|
+
routes?: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type Req = IncomingMessage & {
|
|
14
|
+
body?: unknown;
|
|
15
|
+
ip?: string;
|
|
16
|
+
};
|
|
17
|
+
type Next = (err?: unknown) => void;
|
|
18
|
+
type Middleware = (req: Req, res: ServerResponse, next: Next) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Mark an Express route as an MCP tool. Put it first in the route's handler list:
|
|
21
|
+
*
|
|
22
|
+
* app.get('/users/:id', mcpTool({ description: 'Get a user' }), auth, getUser)
|
|
23
|
+
*
|
|
24
|
+
* It is a no-op at request time; it only carries metadata.
|
|
25
|
+
*/
|
|
26
|
+
declare function mcpTool(options?: RouteToolOptions): Middleware;
|
|
27
|
+
interface ExpressMcpOptions extends McpServerOptions {
|
|
28
|
+
/** Path of the MCP endpoint. @default '/mcp' */
|
|
29
|
+
path?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Base URL for internal calls. Defaults to the address/port the MCP request
|
|
32
|
+
* arrived on (loopback), so no configuration is needed in most setups.
|
|
33
|
+
*/
|
|
34
|
+
baseUrl?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Prefixes of mounted routers, e.g. `{ '/api': apiRouter }`. Express 5 does
|
|
37
|
+
* not keep mount paths, so routers mounted with a path must be listed here.
|
|
38
|
+
* (Express 4 mount paths are detected automatically.)
|
|
39
|
+
*/
|
|
40
|
+
routers?: Record<string, unknown>;
|
|
41
|
+
/** Routes to expose without touching the route definitions. */
|
|
42
|
+
routes?: (RouteToolOptions & {
|
|
43
|
+
method: string;
|
|
44
|
+
path: string;
|
|
45
|
+
})[];
|
|
46
|
+
/** Extra hand-written tools (see `defineTool`). */
|
|
47
|
+
tools?: McpToolDefinition[];
|
|
48
|
+
/**
|
|
49
|
+
* Middleware run before the MCP endpoint, e.g. your auth middleware, to
|
|
50
|
+
* protect tools/list as well as tools/call.
|
|
51
|
+
*/
|
|
52
|
+
middleware?: Middleware[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Add an MCP endpoint (default `POST /mcp`) to an Express app. Tools are
|
|
56
|
+
* discovered lazily on the first MCP request, so call this before or after
|
|
57
|
+
* defining routes. Returns the underlying McpServer.
|
|
58
|
+
*/
|
|
59
|
+
declare function mountMcp(app: ExpressAppLike, options: ExpressMcpOptions): McpServer;
|
|
60
|
+
|
|
61
|
+
export { type ExpressAppLike, type ExpressMcpOptions, mcpTool, mountMcp };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { M as McpServerOptions, R as RouteToolOptions, a as McpToolDefinition, b as McpServer } from '../server-fzkb-wJo.js';
|
|
3
|
+
|
|
4
|
+
/** Structural type for an Express 4/5 app (or Router). Kept loose on purpose. */
|
|
5
|
+
interface ExpressAppLike {
|
|
6
|
+
all: Function;
|
|
7
|
+
router?: unknown;
|
|
8
|
+
_router?: unknown;
|
|
9
|
+
/** Express 3 route table: `{ get: [{ path, method, callbacks }], ... }`. */
|
|
10
|
+
routes?: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type Req = IncomingMessage & {
|
|
14
|
+
body?: unknown;
|
|
15
|
+
ip?: string;
|
|
16
|
+
};
|
|
17
|
+
type Next = (err?: unknown) => void;
|
|
18
|
+
type Middleware = (req: Req, res: ServerResponse, next: Next) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Mark an Express route as an MCP tool. Put it first in the route's handler list:
|
|
21
|
+
*
|
|
22
|
+
* app.get('/users/:id', mcpTool({ description: 'Get a user' }), auth, getUser)
|
|
23
|
+
*
|
|
24
|
+
* It is a no-op at request time; it only carries metadata.
|
|
25
|
+
*/
|
|
26
|
+
declare function mcpTool(options?: RouteToolOptions): Middleware;
|
|
27
|
+
interface ExpressMcpOptions extends McpServerOptions {
|
|
28
|
+
/** Path of the MCP endpoint. @default '/mcp' */
|
|
29
|
+
path?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Base URL for internal calls. Defaults to the address/port the MCP request
|
|
32
|
+
* arrived on (loopback), so no configuration is needed in most setups.
|
|
33
|
+
*/
|
|
34
|
+
baseUrl?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Prefixes of mounted routers, e.g. `{ '/api': apiRouter }`. Express 5 does
|
|
37
|
+
* not keep mount paths, so routers mounted with a path must be listed here.
|
|
38
|
+
* (Express 4 mount paths are detected automatically.)
|
|
39
|
+
*/
|
|
40
|
+
routers?: Record<string, unknown>;
|
|
41
|
+
/** Routes to expose without touching the route definitions. */
|
|
42
|
+
routes?: (RouteToolOptions & {
|
|
43
|
+
method: string;
|
|
44
|
+
path: string;
|
|
45
|
+
})[];
|
|
46
|
+
/** Extra hand-written tools (see `defineTool`). */
|
|
47
|
+
tools?: McpToolDefinition[];
|
|
48
|
+
/**
|
|
49
|
+
* Middleware run before the MCP endpoint, e.g. your auth middleware, to
|
|
50
|
+
* protect tools/list as well as tools/call.
|
|
51
|
+
*/
|
|
52
|
+
middleware?: Middleware[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Add an MCP endpoint (default `POST /mcp`) to an Express app. Tools are
|
|
56
|
+
* discovered lazily on the first MCP request, so call this before or after
|
|
57
|
+
* defining routes. Returns the underlying McpServer.
|
|
58
|
+
*/
|
|
59
|
+
declare function mountMcp(app: ExpressAppLike, options: ExpressMcpOptions): McpServer;
|
|
60
|
+
|
|
61
|
+
export { type ExpressAppLike, type ExpressMcpOptions, mcpTool, mountMcp };
|