@webpieces/mcp-server 0.4.790 → 0.4.792

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.
@@ -27,7 +27,7 @@ export declare class WpMcpServer<TGrant, TMintRequest> {
27
27
  */
28
28
  private readonly logApiCall;
29
29
  private readonly responseWriter;
30
- /** tools/call gives the app's translators first refusal; every other reply stays framework-owned. */
30
+ /** tools/call reads `McpRegistry`; every other reply stays framework-owned. See McpErrorTranslator. */
31
31
  private readonly translator;
32
32
  private registry?;
33
33
  private handler?;
@@ -12,6 +12,7 @@ const McpAuth_1 = require("./McpAuth");
12
12
  const McpApiDispatcher_1 = require("./McpApiDispatcher");
13
13
  const McpInvocationContext_1 = require("./McpInvocationContext");
14
14
  const McpToolRegistry_1 = require("./McpToolRegistry");
15
+ const McpToolCallRendering_1 = require("./McpToolCallRendering");
15
16
  const WpMcpErrorTranslator_1 = require("./WpMcpErrorTranslator");
16
17
  const log = core_util_1.LogManager.getLogger('WpMcpServer');
17
18
  /**
@@ -81,7 +82,7 @@ class WpMcpServer {
81
82
  */
82
83
  logApiCall = new core_util_1.LogApiCallImpl(new core_context_1.RequestContextApiCallContext());
83
84
  responseWriter = new http_server_1.ExpressResponseWriter();
84
- /** tools/call gives the app's translators first refusal; every other reply stays framework-owned. */
85
+ /** tools/call reads `McpRegistry`; every other reply stays framework-owned. See McpErrorTranslator. */
85
86
  translator;
86
87
  registry;
87
88
  handler;
@@ -91,7 +92,7 @@ class WpMcpServer {
91
92
  revision;
92
93
  constructor(config) {
93
94
  this.config = config;
94
- this.translator = new WpMcpErrorTranslator_1.WpMcpErrorTranslator(() => this.challenge(), config.errorTranslator);
95
+ this.translator = new WpMcpErrorTranslator_1.WpMcpErrorTranslator(() => this.challenge());
95
96
  }
96
97
  /**
97
98
  * Mounts this MCP endpoint on `app`: POST at `options.endpointPath`, plus a 405 (`Allow: POST`)
@@ -177,7 +178,7 @@ class WpMcpServer {
177
178
  res.setHeader('X-Accel-Buffering', 'no');
178
179
  await core_context_1.RequestContext.run(async () => {
179
180
  new core_context_1.RequestContextHeaders().fillFromRequest(this.toHttpRequest(req));
180
- WpMcpErrorTranslator_1.McpCorrelation.stamp(this.correlationOf(req));
181
+ McpToolCallRendering_1.McpCorrelation.stamp(this.correlationOf(req));
181
182
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP HTTP entry point; delegates only to WpMcpErrorTranslator
182
183
  try {
183
184
  await this.logEdge('serve', () => this.serveExpress(req, res, options));
@@ -192,7 +193,7 @@ class WpMcpServer {
192
193
  async handleBodyFailure(cause, req, res) {
193
194
  await core_context_1.RequestContext.run(async () => {
194
195
  new core_context_1.RequestContextHeaders().fillFromRequest(this.toHttpRequest(req));
195
- WpMcpErrorTranslator_1.McpCorrelation.stamp(this.correlationOf(req));
196
+ McpToolCallRendering_1.McpCorrelation.stamp(this.correlationOf(req));
196
197
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP body entry point; delegates only to WpMcpErrorTranslator
197
198
  try {
198
199
  await this.logEdge('body', () => this.rejectBody(cause));
@@ -319,14 +320,14 @@ class WpMcpServer {
319
320
  */
320
321
  async handleCallTool(server, request, authentication, sdkContext) {
321
322
  const name = request.params.name;
322
- WpMcpErrorTranslator_1.McpCorrelation.stamp(new WpMcpErrorTranslator_1.McpCorrelation(sdkContext.mcpReq.id, name));
323
+ McpToolCallRendering_1.McpCorrelation.stamp(new McpToolCallRendering_1.McpCorrelation(sdkContext.mcpReq.id, name));
323
324
  const tool = this.requireRegistry().find(name);
324
325
  if (!tool)
325
326
  throw this.translator.unknownTool(name);
326
327
  // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP tools/call entry point; delegates only to WpMcpErrorTranslator
327
328
  try {
328
329
  const result = await this.callTool(tool, request, authentication, sdkContext);
329
- result._meta = this.translator.resultMeta(WpMcpErrorTranslator_1.McpCorrelation.requestId());
330
+ result._meta = this.translator.resultMeta(McpToolCallRendering_1.McpCorrelation.requestId());
330
331
  return server.server.projectCallToolResult(result, tool.outputSchema);
331
332
  }
332
333
  catch (err) {
@@ -437,7 +438,7 @@ class WpMcpServer {
437
438
  const id = body?.['id'];
438
439
  const params = this.bodyObject(body?.['params']);
439
440
  const name = params?.['name'];
440
- return new WpMcpErrorTranslator_1.McpCorrelation(typeof id === 'string' || typeof id === 'number' ? id : null, typeof name === 'string' ? name : undefined);
441
+ return new McpToolCallRendering_1.McpCorrelation(typeof id === 'string' || typeof id === 'number' ? id : null, typeof name === 'string' ? name : undefined);
441
442
  }
442
443
  challenge() {
443
444
  return `Bearer resource_metadata="${this.config.resourceMetadataUrl}"`;
@@ -1 +1 @@
1
- {"version":3,"file":"WpMcpServer.js","sourceRoot":"","sources":["../../../../../packages/http/mcp-server/src/WpMcpServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto';\nimport {\n AuthInfo,\n CallToolRequest,\n CallToolResult,\n createMcpHandler,\n ListToolsResult,\n McpHttpHandler,\n McpRequestContext,\n McpServer,\n ProgressToken,\n ServerContext,\n ServerOptions,\n Tool,\n Implementation,\n} from '@modelcontextprotocol/server';\nimport { NodeMcpRequestHandler, toNodeHandler } from '@modelcontextprotocol/node';\nimport { Express, json, NextFunction, Request, Response } from 'express';\nimport {\n ApiBadRequestError,\n ApiForbiddenError,\n ApiImplementationError,\n ApiMethodInfo,\n ApiUnauthorizedError,\n DtoValue,\n LogApiCallImpl,\n LogManager,\n toError,\n} from '@webpieces/core-util';\nimport {\n HttpRequest,\n RequestContext,\n RequestContextApiCallContext,\n RequestContextHeaders,\n} from '@webpieces/core-context';\nimport { ExpressResponseWriter } from '@webpieces/http-server';\nimport { MintedJwt } from '@webpieces/http-routing';\nimport {\n MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS,\n McpEndpointDescriptor,\n McpProtectedResourceMetadata,\n VerifiedMcpCredential,\n WpMcpServerConfig,\n} from './McpAuth';\nimport { McpApiDispatcher } from './McpApiDispatcher';\nimport { McpBindOptions } from './McpBindOptions';\nimport { McpInvocationContext, McpProgressReporter } from './McpInvocationContext';\nimport { McpToolRegistry, RegisteredMcpTool } from './McpToolRegistry';\nimport { McpCorrelation, WpMcpErrorTranslator } from './WpMcpErrorTranslator';\n\nconst log = LogManager.getLogger('WpMcpServer');\n\ntype AuthenticatedExpressRequest = Request & { auth?: AuthInfo };\n\n/**\n * The request DTO the edge `LogApiCall` lines report. These boundaries run BEFORE (or outside) any\n * API dispatch, so there is no contract DTO to log; the step name is the fact worth having.\n */\nclass McpEdgeRequest {\n constructor(public readonly step: string) {}\n}\n\n/** Body of the 405 answered for every non-POST method at the bound MCP endpoint path. */\nclass McpMethodNotAllowedBody {\n readonly error = 'method_not_allowed';\n}\n\n/** Facts established once per POST at the bind boundary and handed to the SDK handlers. */\nclass McpPostAuthentication {\n constructor(\n public readonly accessToken: string,\n public readonly credential: VerifiedMcpCredential,\n public readonly disconnectSignal: AbortSignal,\n ) {}\n}\n\n/**\n * The official SDK server with Webpieces-owned tools/list and tools/call handlers. It answers\n * `toolInputSchemaJson` from the Webpieces registry so the SDK's pre-dispatch SEP-2243\n * `Mcp-Param-*` header validation still runs without registering SDK-side tool callbacks.\n */\nclass WpSdkMcpServer extends McpServer {\n constructor(\n info: Implementation,\n options: ServerOptions,\n private readonly registry: McpToolRegistry,\n ) {\n super(info, options);\n }\n\n // webpieces-disable no-any-unknown -- signature is fixed by the SDK's JSON Schema record type\n override toolInputSchemaJson(name: string): Record<string, unknown> | undefined {\n return this.registry.find(name)?.inputSchema as Record<string, DtoValue> | undefined;\n }\n}\n\n/**\n * MCP adapter around the official SDK's request-scoped HTTP handler, serving BOTH wire eras from\n * one tool registry: modern (2026-07-28, per-request `_meta` envelope) and legacy (the 2025-11-25\n * family, negotiated by `initialize`). The SDK routes each request to the leg its shape selects and\n * negotiates the revision; only a revision no era knows is refused. Pinning one era instead made\n * every shipping client unreachable (issue #969), and the MCP lifecycle spec is explicit that a\n * server answers with a revision it supports rather than erroring.\n *\n * Error boundary: every failure is mapped by the one `WpMcpErrorTranslator`, and each entry point\n * has exactly one catch that only delegates to it: the bind HTTP handler\n * (`toBearerBoundaryResponse`), tools/list (`toListError`) and tools/call (`toToolCallResult`).\n * `subscriptions/listen` is served entirely by the SDK's listen router, so Webpieces has no handler\n * (and no catch) there. The external bearer is verified exactly once per POST, at the HTTP\n * boundary, before the SDK is involved.\n */\nexport class WpMcpServer<TGrant, TMintRequest> {\n private readonly dispatcher = new McpApiDispatcher();\n /**\n * These edges have NO filter chain above them — `LogApiFilter` never sees a rejected bearer, a\n * bad `Origin`, a body express could not parse, or a `tools/list` the SDK renders itself.\n * Wrapping each in `LogApiCall` is this repo's one line on logging, and it is why\n * `ApiErrorBoundary` no longer writes a second, barer line of its own.\n */\n private readonly logApiCall = new LogApiCallImpl(new RequestContextApiCallContext());\n private readonly responseWriter = new ExpressResponseWriter();\n /** tools/call gives the app's translators first refusal; every other reply stays framework-owned. */\n private readonly translator: WpMcpErrorTranslator;\n private registry?: McpToolRegistry;\n private handler?: McpHttpHandler;\n private streamingHandler?: McpHttpHandler;\n private nodeHandler?: NodeMcpRequestHandler;\n private streamingNodeHandler?: NodeMcpRequestHandler;\n private revision?: string;\n\n constructor(private readonly config: WpMcpServerConfig<TGrant, TMintRequest>) {\n this.translator = new WpMcpErrorTranslator(\n (): string => this.challenge(),\n config.errorTranslator,\n );\n }\n\n /**\n * Mounts this MCP endpoint on `app`: POST at `options.endpointPath`, plus a 405 (`Allow: POST`)\n * for every other method there.\n *\n * SINGLE CANONICAL ORIGIN: one server serves exactly one protected resource, so this may be\n * called only once and `WpMcpServerConfig.setResource(...)`'s path must equal `endpointPath`.\n * That resource URI is fixed for the lifetime of the process and is never derived from the\n * request `Host` — a host-derived audience would make the boundary's own audience check compare\n * two caller-controlled values, which is the confused deputy this check exists to prevent.\n * Serving a second hostname is a second deployment, not a second audience.\n *\n * The OAuth/discovery half stays app-owned: publish `protectedResourceMetadata()` at\n * `WpMcpServerConfig.resourceMetadataUrl`, which is where the 401 challenge sends clients.\n */\n bind(app: Express, options: McpBindOptions): void {\n if (this.handler) {\n throw new Error(\n 'WpMcpServer.bind(...) may be called only once; an MCP resource has exactly one ' +\n 'canonical URI, fixed for the lifetime of the process.',\n );\n }\n // Fail at boot naming the forgotten setter, never on the first request with a 401 the client\n // answers by re-authenticating (see WpMcpServerConfig).\n this.config.validate();\n const resourcePath = new URL(this.config.resource).pathname;\n if (resourcePath !== options.endpointPath) {\n throw new Error(\n `MCP resource path '${resourcePath}' must equal endpointPath ` +\n `'${options.endpointPath}'; the canonical resource URI ` +\n `'${this.config.resource}' and the bound route are the same endpoint.`,\n );\n }\n this.registry = new McpToolRegistry(options.bindings);\n this.revision = this.calculateRegistryRevision(this.registry);\n this.handler = this.createHandler(options, 'auto');\n this.streamingHandler = this.createHandler(options, 'sse');\n this.nodeHandler = toNodeHandler(this.handler, {\n onerror: (error: Error) => log.error('MCP Node transport failed', error),\n });\n this.streamingNodeHandler = toNodeHandler(this.streamingHandler, {\n onerror: (error: Error) => log.error('MCP streaming Node transport failed', error),\n });\n app.post(\n options.endpointPath,\n json(),\n async (req: Request, res: Response): Promise<void> =>\n this.handleHttp(req, res, options),\n // Express routes body-parser failures (bad JSON, body too large) to an error handler.\n (bodyError: Error, req: Request, res: Response, _next: NextFunction): void => {\n void this.handleBodyFailure(bodyError, req, res);\n },\n );\n // Registered AFTER the POST route so POST still wins. NEITHER era served here has a session\n // GET: 2026-07-28 has none at all (`subscriptions/listen` is a POST method), and the legacy\n // leg is the SDK's STATELESS fallback, which answers the 2025 session GET/DELETE with the\n // same 405. So every other method is a method error — and a discovery probe gets that\n // instead of Express' bare 404.\n app.all(options.endpointPath, (_req: Request, res: Response): void => {\n res.setHeader('Allow', 'POST');\n res.status(405).json(new McpMethodNotAllowedBody());\n });\n }\n\n protectedResourceMetadata(): McpProtectedResourceMetadata {\n return this.config.protectedResourceMetadata();\n }\n\n /** Gracefully closes active listen/request streams; clients must reconnect and refresh lists. */\n async close(): Promise<void> {\n await Promise.all([this.handler?.close(), this.streamingHandler?.close()]);\n }\n\n /** Level-triggered invalidation; the authoritative list is always fetched again by clients. */\n toolsChanged(): void {\n this.handler?.notify.toolsChanged();\n }\n\n get registryRevision(): string | undefined {\n return this.revision;\n }\n\n private createHandler(options: McpBindOptions, responseMode: 'auto' | 'sse'): McpHttpHandler {\n return createMcpHandler(\n (context: McpRequestContext) => this.buildSdkServer(context, options),\n {\n // Both eras, one factory: `stateless` serves 2025-era traffic through a fresh\n // instance of the SAME McpServerFactory, so the two eras can never drift apart.\n legacy: 'stateless',\n responseMode,\n bus: options.deployment.bus,\n maxSubscriptions: options.maxSubscriptions,\n keepAliveMs: options.keepAliveMs,\n onerror: (error: Error) => log.warn('MCP protocol request rejected', error),\n },\n );\n }\n\n /** Entry point #1: the one catch for everything before and around the SDK exchange. */\n private async handleHttp(req: Request, res: Response, options: McpBindOptions): Promise<void> {\n res.setHeader('X-Accel-Buffering', 'no');\n await RequestContext.run(async () => {\n new RequestContextHeaders().fillFromRequest(this.toHttpRequest(req));\n McpCorrelation.stamp(this.correlationOf(req));\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP HTTP entry point; delegates only to WpMcpErrorTranslator\n try {\n await this.logEdge('serve', () => this.serveExpress(req, res, options));\n } catch (err: unknown) {\n const error = toError(err);\n this.writeBoundaryError(res, error);\n }\n });\n }\n\n /** Express hands body-parser failures (bad JSON, body too large) here, outside every filter. */\n private async handleBodyFailure(cause: Error, req: Request, res: Response): Promise<void> {\n await RequestContext.run(async () => {\n new RequestContextHeaders().fillFromRequest(this.toHttpRequest(req));\n McpCorrelation.stamp(this.correlationOf(req));\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP body entry point; delegates only to WpMcpErrorTranslator\n try {\n await this.logEdge('body', () => this.rejectBody(cause));\n } catch (err: unknown) {\n const error = toError(err);\n this.writeBoundaryError(res, error);\n }\n });\n }\n\n /** A body express could not parse is a caller input error, reported through the same edge. */\n private async rejectBody(cause: Error): Promise<never> {\n throw new ApiBadRequestError(\n `MCP request body rejected: ${cause.message}`,\n undefined,\n undefined,\n cause,\n );\n }\n\n /**\n * The pre-SDK boundary owns the socket, so it produces a VALUE and writes it through the SAME\n * express writer `ExpressWrapper` uses. A failure after headers were sent can only end the\n * stream.\n */\n private writeBoundaryError(res: Response, error: Error): void {\n if (res.headersSent) {\n res.end();\n return;\n }\n this.responseWriter.write(res, this.translator.toBearerBoundaryResponse(error));\n }\n\n /** Run one un-filtered edge step under `LogApiCall`, so its failure gets exactly one log line. */\n private async logEdge<R>(step: string, work: () => Promise<R>): Promise<R> {\n return this.logApiCall.execute(\n new ApiMethodInfo('server', 'McpEndpoint', step),\n new McpEdgeRequest(step),\n work,\n );\n }\n\n private async serveExpress(\n req: Request,\n res: Response,\n options: McpBindOptions,\n ): Promise<void> {\n const origin = req.header('origin');\n if (origin && !options.allowedOrigins.includes(origin)) {\n throw new ApiForbiddenError(`MCP request Origin '${origin}' is not allowed.`);\n }\n const authentication = await this.authenticate(req);\n const request = req as AuthenticatedExpressRequest;\n request.auth = this.authInfo(authentication);\n const serve = this.hasProgressToken(req.body)\n ? this.streamingNodeHandler\n : this.nodeHandler;\n if (!serve) throw new ApiImplementationError('MCP Node handlers are not initialized.');\n await serve(request, res, req.body);\n }\n\n /** Verifies the external bearer once for this POST. Handlers never re-verify it. */\n private async authenticate(req: Request): Promise<McpPostAuthentication> {\n const match = req.header('authorization')?.match(/^Bearer ([^\\s]+)$/i);\n const token = match?.[1];\n if (!token) throw new ApiUnauthorizedError('MCP request has no bearer access token.');\n const credential = await this.config.accessTokenAuthority.verifyAccessToken(\n token,\n this.config.resource,\n );\n this.validateCredential(credential);\n return new McpPostAuthentication(token, credential, this.disconnectSignal(req));\n }\n\n private disconnectSignal(req: Request): AbortSignal {\n const disconnected = new AbortController();\n const res = req.res;\n const cancel = (): void => disconnected.abort();\n req.once('aborted', cancel);\n req.socket.once('close', cancel);\n res?.once('close', cancel);\n res?.once('finish', (): void => {\n req.off('aborted', cancel);\n req.socket.off('close', cancel);\n res.off('close', cancel);\n });\n return disconnected.signal;\n }\n\n private buildSdkServer(context: McpRequestContext, options: McpBindOptions): McpServer {\n // The era is the SDK's to decide and BOTH are served; what is not negotiable is that the\n // request came through `bind`'s HTTP boundary, which is where the external bearer is\n // verified. A factory call without it is a wiring mistake, never a client's doing.\n const authentication = context.authInfo?.extra?.['webpiecesAuthentication'];\n if (!(authentication instanceof McpPostAuthentication)) {\n throw new ApiImplementationError(\n 'WpMcpServer serves only MCP requests authenticated by its bind boundary.',\n );\n }\n const registry = this.requireRegistry();\n const server = new WpSdkMcpServer(\n { name: this.config.name, version: `${this.config.version}+${this.revision}` },\n {\n capabilities: { tools: { listChanged: true } },\n cacheHints: {\n 'tools/list': { ttlMs: options.deployment.ttlMs, cacheScope: 'private' },\n 'server/discover': { ttlMs: options.deployment.ttlMs, cacheScope: 'private' },\n },\n },\n registry,\n );\n server.server.removeRequestHandler('tools/list');\n server.server.removeRequestHandler('tools/call');\n server.server.setRequestHandler(\n 'tools/list',\n async (_request: object): Promise<ListToolsResult> =>\n this.handleListTools(authentication),\n );\n server.server.setRequestHandler(\n 'tools/call',\n async (request: CallToolRequest, sdkContext: ServerContext): Promise<CallToolResult> =>\n this.handleCallTool(server, request, authentication, sdkContext),\n );\n return server;\n }\n\n /** Entry point #2: tools/list has no tool-result channel, so failures are JSON-RPC errors. */\n private async handleListTools(authentication: McpPostAuthentication): Promise<ListToolsResult> {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP tools/list entry point; delegates only to WpMcpErrorTranslator\n try {\n return await this.logEdge('tools/list', async () =>\n this.listTools(authentication.credential),\n );\n } catch (err: unknown) {\n const error = toError(err);\n this.translator.toListError(error);\n }\n }\n\n private listTools(credential: VerifiedMcpCredential): ListToolsResult {\n const tools: Tool[] = [];\n for (const tool of this.requireRegistry().tools) {\n if (tool.isVisibleTo(credential.listingRoles)) tools.push(this.toolDefinition(tool));\n }\n return { tools };\n }\n\n private toolDefinition(tool: RegisteredMcpTool): Tool {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema as Tool['inputSchema'],\n outputSchema: tool.outputSchema as Tool['outputSchema'],\n annotations: tool.annotations,\n _meta: { webpiecesRegistryRevision: this.revision },\n };\n }\n\n /**\n * Entry point #3: an unknown tool is a JSON-RPC -32602; every failure after the tool is found\n * is an `isError: true` result, identically for local and remote bindings.\n */\n private async handleCallTool(\n server: WpSdkMcpServer,\n request: CallToolRequest,\n authentication: McpPostAuthentication,\n sdkContext: ServerContext,\n ): Promise<CallToolResult> {\n const name = request.params.name;\n McpCorrelation.stamp(new McpCorrelation(sdkContext.mcpReq.id, name));\n const tool = this.requireRegistry().find(name);\n if (!tool) throw this.translator.unknownTool(name);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP tools/call entry point; delegates only to WpMcpErrorTranslator\n try {\n const result = await this.callTool(tool, request, authentication, sdkContext);\n result._meta = this.translator.resultMeta(McpCorrelation.requestId());\n return server.server.projectCallToolResult(\n result,\n tool.outputSchema as Record<string, DtoValue>,\n );\n } catch (err: unknown) {\n const error = toError(err);\n return this.translator.toToolCallResult(error);\n }\n }\n\n /** Everything a tool call does. No catch in here: failures propagate to handleCallTool. */\n private async callTool(\n tool: RegisteredMcpTool,\n request: CallToolRequest,\n authentication: McpPostAuthentication,\n sdkContext: ServerContext,\n ): Promise<CallToolResult> {\n const credential = authentication.credential;\n const endpointJwt =\n tool.binding.topology === 'local'\n ? await this.mintEndpointJwt(tool, authentication)\n : undefined;\n const invocation = new McpInvocationContext(\n sdkContext.mcpReq.id,\n tool.name,\n credential.subject,\n credential.listingRoles,\n AbortSignal.any([sdkContext.mcpReq.signal, authentication.disconnectSignal]),\n this.progressReporter(sdkContext),\n );\n const args = (request.params.arguments ?? {}) as DtoValue;\n const value = await this.dispatcher.call(\n tool,\n args,\n credential,\n invocation,\n endpointJwt?.token,\n );\n const outputFailure = this.requireRegistry().schemaBuilder.validate(\n tool.responseClass,\n value,\n );\n if (outputFailure) {\n throw new ApiImplementationError(\n `MCP output schema violation for ${tool.apiClass.name}.${tool.methodName}: ${outputFailure.message}`,\n );\n }\n const structured = this.record(value);\n return {\n content: [{ type: 'text', text: JSON.stringify(structured) }],\n structuredContent: structured,\n };\n }\n\n private async mintEndpointJwt(\n tool: RegisteredMcpTool,\n authentication: McpPostAuthentication,\n ): Promise<MintedJwt> {\n const descriptor = new McpEndpointDescriptor(\n tool.name,\n tool.apiClass.name,\n tool.methodName,\n );\n const minted = await this.config.endpointJwtAuthority.mint(\n this.config.endpointMintRequest(authentication.credential, descriptor),\n );\n const now = Math.floor(Date.now() / 1000);\n if (minted.token === authentication.accessToken) {\n throw new ApiImplementationError(\n `MCP access-token passthrough is forbidden (endpoint JWT for ${tool.name}).`,\n );\n }\n if (\n minted.expiresAtEpochSeconds <= now ||\n minted.expiresAtEpochSeconds - now > this.config.maxEndpointJwtLifetimeSeconds\n ) {\n throw new ApiImplementationError(\n `MCP endpoint JWT lifetime is invalid for ${tool.name}.`,\n );\n }\n return minted;\n }\n\n private validateCredential(credential: VerifiedMcpCredential): void {\n const now = Math.floor(Date.now() / 1000);\n const reject = (reason: string): never => {\n throw new ApiUnauthorizedError(`MCP access token rejected: ${reason}`);\n };\n if (credential.subject.trim() === '') reject('no subject');\n const stamps = [\n credential.issuedAtEpochSeconds,\n credential.expiresAtEpochSeconds,\n credential.accountValidatedAtEpochSeconds,\n ];\n if (!stamps.every(Number.isFinite)) reject('security timestamps must be finite');\n if (credential.resource !== this.config.resource) reject('resource mismatch');\n if (!this.config.authorizationServers.includes(credential.issuer)) {\n reject('issuer is not trusted');\n }\n if (credential.issuedAtEpochSeconds > now || credential.expiresAtEpochSeconds <= now) {\n reject('outside its valid time window');\n }\n const lifetime = credential.expiresAtEpochSeconds - credential.issuedAtEpochSeconds;\n if (lifetime > MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS) reject('lifetime exceeds 30 days');\n for (const scope of this.config.requiredScopes) {\n if (!credential.scopes.includes(scope)) reject(`missing required scope '${scope}'`);\n }\n const validatedAge = now - credential.accountValidatedAtEpochSeconds;\n if (\n credential.accountValidatedAtEpochSeconds > now ||\n validatedAge > this.config.maxAccountValidationAgeSeconds\n ) {\n reject('account authorization state is not fresh enough for dispatch');\n }\n }\n\n private authInfo(authentication: McpPostAuthentication): AuthInfo {\n const credential = authentication.credential;\n return {\n token: authentication.accessToken,\n clientId: credential.subject,\n scopes: [...credential.scopes],\n expiresAt: credential.expiresAtEpochSeconds,\n resource: new URL(credential.resource),\n extra: { webpiecesAuthentication: authentication },\n };\n }\n\n private progressReporter(context: ServerContext): McpProgressReporter | undefined {\n const token = context.mcpReq._meta?.progressToken;\n if (token === undefined) return undefined;\n return async (progress: number, total?: number, message?: string): Promise<void> => {\n await context.mcpReq.notify({\n method: 'notifications/progress',\n params: this.progressParams(token, progress, total, message),\n });\n };\n }\n\n private progressParams(\n progressToken: ProgressToken,\n progress: number,\n total?: number,\n message?: string,\n ): Record<string, DtoValue> {\n const params: Record<string, DtoValue> = { progressToken, progress };\n if (total !== undefined) params['total'] = total;\n if (message !== undefined) params['message'] = message;\n return params;\n }\n\n /** What the raw POST body tells us before the SDK has parsed anything: the id, and the tool. */\n private correlationOf(req: Request): McpCorrelation {\n const body = this.bodyObject(req.body);\n const id = body?.['id'];\n const params = this.bodyObject(body?.['params']);\n const name = params?.['name'];\n return new McpCorrelation(\n typeof id === 'string' || typeof id === 'number' ? id : null,\n typeof name === 'string' ? name : undefined,\n );\n }\n\n private challenge(): string {\n return `Bearer resource_metadata=\"${this.config.resourceMetadataUrl}\"`;\n }\n\n private bodyObject(value: DtoValue | undefined): Record<string, DtoValue> | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n return value as Record<string, DtoValue>;\n }\n\n private hasProgressToken(body: DtoValue): boolean {\n const params = this.bodyObject(this.bodyObject(body)?.['params']);\n return this.bodyObject(params?.['_meta'])?.['progressToken'] !== undefined;\n }\n\n private toHttpRequest(req: Request): HttpRequest {\n const headers = new Map<string, string[]>();\n for (const [name, value] of Object.entries(req.headers)) {\n if (typeof value === 'string') headers.set(name, [value]);\n else if (Array.isArray(value)) headers.set(name, value);\n }\n return new HttpRequest(req.method, req.originalUrl || req.path, headers);\n }\n\n private calculateRegistryRevision(registry: McpToolRegistry): string {\n const surface = registry.tools.map((tool: RegisteredMcpTool) => [\n tool.name,\n tool.description,\n tool.inputSchema,\n tool.outputSchema,\n tool.annotations,\n ]);\n return createHash('sha256').update(JSON.stringify(surface)).digest('hex').slice(0, 12);\n }\n\n private requireRegistry(): McpToolRegistry {\n if (!this.registry) throw new Error('Call WpMcpServer.bind(...) before serving requests.');\n return this.registry;\n }\n\n private record(value: DtoValue): Record<string, DtoValue> {\n const jsonValue = JSON.stringify(value);\n if (jsonValue === undefined) {\n throw new ApiImplementationError('MCP structured content is not JSON serializable.');\n }\n const parsed = JSON.parse(jsonValue) as DtoValue;\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return { value: parsed };\n }\n return parsed as Record<string, DtoValue>;\n }\n}\n"]}
1
+ {"version":3,"file":"WpMcpServer.js","sourceRoot":"","sources":["../../../../../packages/http/mcp-server/src/WpMcpServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto';\nimport {\n AuthInfo,\n CallToolRequest,\n CallToolResult,\n createMcpHandler,\n ListToolsResult,\n McpHttpHandler,\n McpRequestContext,\n McpServer,\n ProgressToken,\n ServerContext,\n ServerOptions,\n Tool,\n Implementation,\n} from '@modelcontextprotocol/server';\nimport { NodeMcpRequestHandler, toNodeHandler } from '@modelcontextprotocol/node';\nimport { Express, json, NextFunction, Request, Response } from 'express';\nimport {\n ApiBadRequestError,\n ApiForbiddenError,\n ApiImplementationError,\n ApiMethodInfo,\n ApiUnauthorizedError,\n DtoValue,\n LogApiCallImpl,\n LogManager,\n toError,\n} from '@webpieces/core-util';\nimport {\n HttpRequest,\n RequestContext,\n RequestContextApiCallContext,\n RequestContextHeaders,\n} from '@webpieces/core-context';\nimport { ExpressResponseWriter } from '@webpieces/http-server';\nimport { MintedJwt } from '@webpieces/http-routing';\nimport {\n MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS,\n McpEndpointDescriptor,\n McpProtectedResourceMetadata,\n VerifiedMcpCredential,\n WpMcpServerConfig,\n} from './McpAuth';\nimport { McpApiDispatcher } from './McpApiDispatcher';\nimport { McpBindOptions } from './McpBindOptions';\nimport { McpInvocationContext, McpProgressReporter } from './McpInvocationContext';\nimport { McpToolRegistry, RegisteredMcpTool } from './McpToolRegistry';\nimport { McpCorrelation } from './McpToolCallRendering';\nimport { WpMcpErrorTranslator } from './WpMcpErrorTranslator';\n\nconst log = LogManager.getLogger('WpMcpServer');\n\ntype AuthenticatedExpressRequest = Request & { auth?: AuthInfo };\n\n/**\n * The request DTO the edge `LogApiCall` lines report. These boundaries run BEFORE (or outside) any\n * API dispatch, so there is no contract DTO to log; the step name is the fact worth having.\n */\nclass McpEdgeRequest {\n constructor(public readonly step: string) {}\n}\n\n/** Body of the 405 answered for every non-POST method at the bound MCP endpoint path. */\nclass McpMethodNotAllowedBody {\n readonly error = 'method_not_allowed';\n}\n\n/** Facts established once per POST at the bind boundary and handed to the SDK handlers. */\nclass McpPostAuthentication {\n constructor(\n public readonly accessToken: string,\n public readonly credential: VerifiedMcpCredential,\n public readonly disconnectSignal: AbortSignal,\n ) {}\n}\n\n/**\n * The official SDK server with Webpieces-owned tools/list and tools/call handlers. It answers\n * `toolInputSchemaJson` from the Webpieces registry so the SDK's pre-dispatch SEP-2243\n * `Mcp-Param-*` header validation still runs without registering SDK-side tool callbacks.\n */\nclass WpSdkMcpServer extends McpServer {\n constructor(\n info: Implementation,\n options: ServerOptions,\n private readonly registry: McpToolRegistry,\n ) {\n super(info, options);\n }\n\n // webpieces-disable no-any-unknown -- signature is fixed by the SDK's JSON Schema record type\n override toolInputSchemaJson(name: string): Record<string, unknown> | undefined {\n return this.registry.find(name)?.inputSchema as Record<string, DtoValue> | undefined;\n }\n}\n\n/**\n * MCP adapter around the official SDK's request-scoped HTTP handler, serving BOTH wire eras from\n * one tool registry: modern (2026-07-28, per-request `_meta` envelope) and legacy (the 2025-11-25\n * family, negotiated by `initialize`). The SDK routes each request to the leg its shape selects and\n * negotiates the revision; only a revision no era knows is refused. Pinning one era instead made\n * every shipping client unreachable (issue #969), and the MCP lifecycle spec is explicit that a\n * server answers with a revision it supports rather than erroring.\n *\n * Error boundary: every failure is mapped by the one `WpMcpErrorTranslator`, and each entry point\n * has exactly one catch that only delegates to it: the bind HTTP handler\n * (`toBearerBoundaryResponse`), tools/list (`toListError`) and tools/call (`toToolCallResult`).\n * `subscriptions/listen` is served entirely by the SDK's listen router, so Webpieces has no handler\n * (and no catch) there. The external bearer is verified exactly once per POST, at the HTTP\n * boundary, before the SDK is involved.\n */\nexport class WpMcpServer<TGrant, TMintRequest> {\n private readonly dispatcher = new McpApiDispatcher();\n /**\n * These edges have NO filter chain above them — `LogApiFilter` never sees a rejected bearer, a\n * bad `Origin`, a body express could not parse, or a `tools/list` the SDK renders itself.\n * Wrapping each in `LogApiCall` is this repo's one line on logging, and it is why\n * `ApiErrorBoundary` no longer writes a second, barer line of its own.\n */\n private readonly logApiCall = new LogApiCallImpl(new RequestContextApiCallContext());\n private readonly responseWriter = new ExpressResponseWriter();\n /** tools/call reads `McpRegistry`; every other reply stays framework-owned. See McpErrorTranslator. */\n private readonly translator: WpMcpErrorTranslator;\n private registry?: McpToolRegistry;\n private handler?: McpHttpHandler;\n private streamingHandler?: McpHttpHandler;\n private nodeHandler?: NodeMcpRequestHandler;\n private streamingNodeHandler?: NodeMcpRequestHandler;\n private revision?: string;\n\n constructor(private readonly config: WpMcpServerConfig<TGrant, TMintRequest>) {\n this.translator = new WpMcpErrorTranslator((): string => this.challenge());\n }\n\n /**\n * Mounts this MCP endpoint on `app`: POST at `options.endpointPath`, plus a 405 (`Allow: POST`)\n * for every other method there.\n *\n * SINGLE CANONICAL ORIGIN: one server serves exactly one protected resource, so this may be\n * called only once and `WpMcpServerConfig.setResource(...)`'s path must equal `endpointPath`.\n * That resource URI is fixed for the lifetime of the process and is never derived from the\n * request `Host` — a host-derived audience would make the boundary's own audience check compare\n * two caller-controlled values, which is the confused deputy this check exists to prevent.\n * Serving a second hostname is a second deployment, not a second audience.\n *\n * The OAuth/discovery half stays app-owned: publish `protectedResourceMetadata()` at\n * `WpMcpServerConfig.resourceMetadataUrl`, which is where the 401 challenge sends clients.\n */\n bind(app: Express, options: McpBindOptions): void {\n if (this.handler) {\n throw new Error(\n 'WpMcpServer.bind(...) may be called only once; an MCP resource has exactly one ' +\n 'canonical URI, fixed for the lifetime of the process.',\n );\n }\n // Fail at boot naming the forgotten setter, never on the first request with a 401 the client\n // answers by re-authenticating (see WpMcpServerConfig).\n this.config.validate();\n const resourcePath = new URL(this.config.resource).pathname;\n if (resourcePath !== options.endpointPath) {\n throw new Error(\n `MCP resource path '${resourcePath}' must equal endpointPath ` +\n `'${options.endpointPath}'; the canonical resource URI ` +\n `'${this.config.resource}' and the bound route are the same endpoint.`,\n );\n }\n this.registry = new McpToolRegistry(options.bindings);\n this.revision = this.calculateRegistryRevision(this.registry);\n this.handler = this.createHandler(options, 'auto');\n this.streamingHandler = this.createHandler(options, 'sse');\n this.nodeHandler = toNodeHandler(this.handler, {\n onerror: (error: Error) => log.error('MCP Node transport failed', error),\n });\n this.streamingNodeHandler = toNodeHandler(this.streamingHandler, {\n onerror: (error: Error) => log.error('MCP streaming Node transport failed', error),\n });\n app.post(\n options.endpointPath,\n json(),\n async (req: Request, res: Response): Promise<void> =>\n this.handleHttp(req, res, options),\n // Express routes body-parser failures (bad JSON, body too large) to an error handler.\n (bodyError: Error, req: Request, res: Response, _next: NextFunction): void => {\n void this.handleBodyFailure(bodyError, req, res);\n },\n );\n // Registered AFTER the POST route so POST still wins. NEITHER era served here has a session\n // GET: 2026-07-28 has none at all (`subscriptions/listen` is a POST method), and the legacy\n // leg is the SDK's STATELESS fallback, which answers the 2025 session GET/DELETE with the\n // same 405. So every other method is a method error — and a discovery probe gets that\n // instead of Express' bare 404.\n app.all(options.endpointPath, (_req: Request, res: Response): void => {\n res.setHeader('Allow', 'POST');\n res.status(405).json(new McpMethodNotAllowedBody());\n });\n }\n\n protectedResourceMetadata(): McpProtectedResourceMetadata {\n return this.config.protectedResourceMetadata();\n }\n\n /** Gracefully closes active listen/request streams; clients must reconnect and refresh lists. */\n async close(): Promise<void> {\n await Promise.all([this.handler?.close(), this.streamingHandler?.close()]);\n }\n\n /** Level-triggered invalidation; the authoritative list is always fetched again by clients. */\n toolsChanged(): void {\n this.handler?.notify.toolsChanged();\n }\n\n get registryRevision(): string | undefined {\n return this.revision;\n }\n\n private createHandler(options: McpBindOptions, responseMode: 'auto' | 'sse'): McpHttpHandler {\n return createMcpHandler(\n (context: McpRequestContext) => this.buildSdkServer(context, options),\n {\n // Both eras, one factory: `stateless` serves 2025-era traffic through a fresh\n // instance of the SAME McpServerFactory, so the two eras can never drift apart.\n legacy: 'stateless',\n responseMode,\n bus: options.deployment.bus,\n maxSubscriptions: options.maxSubscriptions,\n keepAliveMs: options.keepAliveMs,\n onerror: (error: Error) => log.warn('MCP protocol request rejected', error),\n },\n );\n }\n\n /** Entry point #1: the one catch for everything before and around the SDK exchange. */\n private async handleHttp(req: Request, res: Response, options: McpBindOptions): Promise<void> {\n res.setHeader('X-Accel-Buffering', 'no');\n await RequestContext.run(async () => {\n new RequestContextHeaders().fillFromRequest(this.toHttpRequest(req));\n McpCorrelation.stamp(this.correlationOf(req));\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP HTTP entry point; delegates only to WpMcpErrorTranslator\n try {\n await this.logEdge('serve', () => this.serveExpress(req, res, options));\n } catch (err: unknown) {\n const error = toError(err);\n this.writeBoundaryError(res, error);\n }\n });\n }\n\n /** Express hands body-parser failures (bad JSON, body too large) here, outside every filter. */\n private async handleBodyFailure(cause: Error, req: Request, res: Response): Promise<void> {\n await RequestContext.run(async () => {\n new RequestContextHeaders().fillFromRequest(this.toHttpRequest(req));\n McpCorrelation.stamp(this.correlationOf(req));\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP body entry point; delegates only to WpMcpErrorTranslator\n try {\n await this.logEdge('body', () => this.rejectBody(cause));\n } catch (err: unknown) {\n const error = toError(err);\n this.writeBoundaryError(res, error);\n }\n });\n }\n\n /** A body express could not parse is a caller input error, reported through the same edge. */\n private async rejectBody(cause: Error): Promise<never> {\n throw new ApiBadRequestError(\n `MCP request body rejected: ${cause.message}`,\n undefined,\n undefined,\n cause,\n );\n }\n\n /**\n * The pre-SDK boundary owns the socket, so it produces a VALUE and writes it through the SAME\n * express writer `ExpressWrapper` uses. A failure after headers were sent can only end the\n * stream.\n */\n private writeBoundaryError(res: Response, error: Error): void {\n if (res.headersSent) {\n res.end();\n return;\n }\n this.responseWriter.write(res, this.translator.toBearerBoundaryResponse(error));\n }\n\n /** Run one un-filtered edge step under `LogApiCall`, so its failure gets exactly one log line. */\n private async logEdge<R>(step: string, work: () => Promise<R>): Promise<R> {\n return this.logApiCall.execute(\n new ApiMethodInfo('server', 'McpEndpoint', step),\n new McpEdgeRequest(step),\n work,\n );\n }\n\n private async serveExpress(\n req: Request,\n res: Response,\n options: McpBindOptions,\n ): Promise<void> {\n const origin = req.header('origin');\n if (origin && !options.allowedOrigins.includes(origin)) {\n throw new ApiForbiddenError(`MCP request Origin '${origin}' is not allowed.`);\n }\n const authentication = await this.authenticate(req);\n const request = req as AuthenticatedExpressRequest;\n request.auth = this.authInfo(authentication);\n const serve = this.hasProgressToken(req.body)\n ? this.streamingNodeHandler\n : this.nodeHandler;\n if (!serve) throw new ApiImplementationError('MCP Node handlers are not initialized.');\n await serve(request, res, req.body);\n }\n\n /** Verifies the external bearer once for this POST. Handlers never re-verify it. */\n private async authenticate(req: Request): Promise<McpPostAuthentication> {\n const match = req.header('authorization')?.match(/^Bearer ([^\\s]+)$/i);\n const token = match?.[1];\n if (!token) throw new ApiUnauthorizedError('MCP request has no bearer access token.');\n const credential = await this.config.accessTokenAuthority.verifyAccessToken(\n token,\n this.config.resource,\n );\n this.validateCredential(credential);\n return new McpPostAuthentication(token, credential, this.disconnectSignal(req));\n }\n\n private disconnectSignal(req: Request): AbortSignal {\n const disconnected = new AbortController();\n const res = req.res;\n const cancel = (): void => disconnected.abort();\n req.once('aborted', cancel);\n req.socket.once('close', cancel);\n res?.once('close', cancel);\n res?.once('finish', (): void => {\n req.off('aborted', cancel);\n req.socket.off('close', cancel);\n res.off('close', cancel);\n });\n return disconnected.signal;\n }\n\n private buildSdkServer(context: McpRequestContext, options: McpBindOptions): McpServer {\n // The era is the SDK's to decide and BOTH are served; what is not negotiable is that the\n // request came through `bind`'s HTTP boundary, which is where the external bearer is\n // verified. A factory call without it is a wiring mistake, never a client's doing.\n const authentication = context.authInfo?.extra?.['webpiecesAuthentication'];\n if (!(authentication instanceof McpPostAuthentication)) {\n throw new ApiImplementationError(\n 'WpMcpServer serves only MCP requests authenticated by its bind boundary.',\n );\n }\n const registry = this.requireRegistry();\n const server = new WpSdkMcpServer(\n { name: this.config.name, version: `${this.config.version}+${this.revision}` },\n {\n capabilities: { tools: { listChanged: true } },\n cacheHints: {\n 'tools/list': { ttlMs: options.deployment.ttlMs, cacheScope: 'private' },\n 'server/discover': { ttlMs: options.deployment.ttlMs, cacheScope: 'private' },\n },\n },\n registry,\n );\n server.server.removeRequestHandler('tools/list');\n server.server.removeRequestHandler('tools/call');\n server.server.setRequestHandler(\n 'tools/list',\n async (_request: object): Promise<ListToolsResult> =>\n this.handleListTools(authentication),\n );\n server.server.setRequestHandler(\n 'tools/call',\n async (request: CallToolRequest, sdkContext: ServerContext): Promise<CallToolResult> =>\n this.handleCallTool(server, request, authentication, sdkContext),\n );\n return server;\n }\n\n /** Entry point #2: tools/list has no tool-result channel, so failures are JSON-RPC errors. */\n private async handleListTools(authentication: McpPostAuthentication): Promise<ListToolsResult> {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP tools/list entry point; delegates only to WpMcpErrorTranslator\n try {\n return await this.logEdge('tools/list', async () =>\n this.listTools(authentication.credential),\n );\n } catch (err: unknown) {\n const error = toError(err);\n this.translator.toListError(error);\n }\n }\n\n private listTools(credential: VerifiedMcpCredential): ListToolsResult {\n const tools: Tool[] = [];\n for (const tool of this.requireRegistry().tools) {\n if (tool.isVisibleTo(credential.listingRoles)) tools.push(this.toolDefinition(tool));\n }\n return { tools };\n }\n\n private toolDefinition(tool: RegisteredMcpTool): Tool {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema as Tool['inputSchema'],\n outputSchema: tool.outputSchema as Tool['outputSchema'],\n annotations: tool.annotations,\n _meta: { webpiecesRegistryRevision: this.revision },\n };\n }\n\n /**\n * Entry point #3: an unknown tool is a JSON-RPC -32602; every failure after the tool is found\n * is an `isError: true` result, identically for local and remote bindings.\n */\n private async handleCallTool(\n server: WpSdkMcpServer,\n request: CallToolRequest,\n authentication: McpPostAuthentication,\n sdkContext: ServerContext,\n ): Promise<CallToolResult> {\n const name = request.params.name;\n McpCorrelation.stamp(new McpCorrelation(sdkContext.mcpReq.id, name));\n const tool = this.requireRegistry().find(name);\n if (!tool) throw this.translator.unknownTool(name);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- MCP tools/call entry point; delegates only to WpMcpErrorTranslator\n try {\n const result = await this.callTool(tool, request, authentication, sdkContext);\n result._meta = this.translator.resultMeta(McpCorrelation.requestId());\n return server.server.projectCallToolResult(\n result,\n tool.outputSchema as Record<string, DtoValue>,\n );\n } catch (err: unknown) {\n const error = toError(err);\n return this.translator.toToolCallResult(error);\n }\n }\n\n /** Everything a tool call does. No catch in here: failures propagate to handleCallTool. */\n private async callTool(\n tool: RegisteredMcpTool,\n request: CallToolRequest,\n authentication: McpPostAuthentication,\n sdkContext: ServerContext,\n ): Promise<CallToolResult> {\n const credential = authentication.credential;\n const endpointJwt =\n tool.binding.topology === 'local'\n ? await this.mintEndpointJwt(tool, authentication)\n : undefined;\n const invocation = new McpInvocationContext(\n sdkContext.mcpReq.id,\n tool.name,\n credential.subject,\n credential.listingRoles,\n AbortSignal.any([sdkContext.mcpReq.signal, authentication.disconnectSignal]),\n this.progressReporter(sdkContext),\n );\n const args = (request.params.arguments ?? {}) as DtoValue;\n const value = await this.dispatcher.call(\n tool,\n args,\n credential,\n invocation,\n endpointJwt?.token,\n );\n const outputFailure = this.requireRegistry().schemaBuilder.validate(\n tool.responseClass,\n value,\n );\n if (outputFailure) {\n throw new ApiImplementationError(\n `MCP output schema violation for ${tool.apiClass.name}.${tool.methodName}: ${outputFailure.message}`,\n );\n }\n const structured = this.record(value);\n return {\n content: [{ type: 'text', text: JSON.stringify(structured) }],\n structuredContent: structured,\n };\n }\n\n private async mintEndpointJwt(\n tool: RegisteredMcpTool,\n authentication: McpPostAuthentication,\n ): Promise<MintedJwt> {\n const descriptor = new McpEndpointDescriptor(\n tool.name,\n tool.apiClass.name,\n tool.methodName,\n );\n const minted = await this.config.endpointJwtAuthority.mint(\n this.config.endpointMintRequest(authentication.credential, descriptor),\n );\n const now = Math.floor(Date.now() / 1000);\n if (minted.token === authentication.accessToken) {\n throw new ApiImplementationError(\n `MCP access-token passthrough is forbidden (endpoint JWT for ${tool.name}).`,\n );\n }\n if (\n minted.expiresAtEpochSeconds <= now ||\n minted.expiresAtEpochSeconds - now > this.config.maxEndpointJwtLifetimeSeconds\n ) {\n throw new ApiImplementationError(\n `MCP endpoint JWT lifetime is invalid for ${tool.name}.`,\n );\n }\n return minted;\n }\n\n private validateCredential(credential: VerifiedMcpCredential): void {\n const now = Math.floor(Date.now() / 1000);\n const reject = (reason: string): never => {\n throw new ApiUnauthorizedError(`MCP access token rejected: ${reason}`);\n };\n if (credential.subject.trim() === '') reject('no subject');\n const stamps = [\n credential.issuedAtEpochSeconds,\n credential.expiresAtEpochSeconds,\n credential.accountValidatedAtEpochSeconds,\n ];\n if (!stamps.every(Number.isFinite)) reject('security timestamps must be finite');\n if (credential.resource !== this.config.resource) reject('resource mismatch');\n if (!this.config.authorizationServers.includes(credential.issuer)) {\n reject('issuer is not trusted');\n }\n if (credential.issuedAtEpochSeconds > now || credential.expiresAtEpochSeconds <= now) {\n reject('outside its valid time window');\n }\n const lifetime = credential.expiresAtEpochSeconds - credential.issuedAtEpochSeconds;\n if (lifetime > MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS) reject('lifetime exceeds 30 days');\n for (const scope of this.config.requiredScopes) {\n if (!credential.scopes.includes(scope)) reject(`missing required scope '${scope}'`);\n }\n const validatedAge = now - credential.accountValidatedAtEpochSeconds;\n if (\n credential.accountValidatedAtEpochSeconds > now ||\n validatedAge > this.config.maxAccountValidationAgeSeconds\n ) {\n reject('account authorization state is not fresh enough for dispatch');\n }\n }\n\n private authInfo(authentication: McpPostAuthentication): AuthInfo {\n const credential = authentication.credential;\n return {\n token: authentication.accessToken,\n clientId: credential.subject,\n scopes: [...credential.scopes],\n expiresAt: credential.expiresAtEpochSeconds,\n resource: new URL(credential.resource),\n extra: { webpiecesAuthentication: authentication },\n };\n }\n\n private progressReporter(context: ServerContext): McpProgressReporter | undefined {\n const token = context.mcpReq._meta?.progressToken;\n if (token === undefined) return undefined;\n return async (progress: number, total?: number, message?: string): Promise<void> => {\n await context.mcpReq.notify({\n method: 'notifications/progress',\n params: this.progressParams(token, progress, total, message),\n });\n };\n }\n\n private progressParams(\n progressToken: ProgressToken,\n progress: number,\n total?: number,\n message?: string,\n ): Record<string, DtoValue> {\n const params: Record<string, DtoValue> = { progressToken, progress };\n if (total !== undefined) params['total'] = total;\n if (message !== undefined) params['message'] = message;\n return params;\n }\n\n /** What the raw POST body tells us before the SDK has parsed anything: the id, and the tool. */\n private correlationOf(req: Request): McpCorrelation {\n const body = this.bodyObject(req.body);\n const id = body?.['id'];\n const params = this.bodyObject(body?.['params']);\n const name = params?.['name'];\n return new McpCorrelation(\n typeof id === 'string' || typeof id === 'number' ? id : null,\n typeof name === 'string' ? name : undefined,\n );\n }\n\n private challenge(): string {\n return `Bearer resource_metadata=\"${this.config.resourceMetadataUrl}\"`;\n }\n\n private bodyObject(value: DtoValue | undefined): Record<string, DtoValue> | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n return value as Record<string, DtoValue>;\n }\n\n private hasProgressToken(body: DtoValue): boolean {\n const params = this.bodyObject(this.bodyObject(body)?.['params']);\n return this.bodyObject(params?.['_meta'])?.['progressToken'] !== undefined;\n }\n\n private toHttpRequest(req: Request): HttpRequest {\n const headers = new Map<string, string[]>();\n for (const [name, value] of Object.entries(req.headers)) {\n if (typeof value === 'string') headers.set(name, [value]);\n else if (Array.isArray(value)) headers.set(name, value);\n }\n return new HttpRequest(req.method, req.originalUrl || req.path, headers);\n }\n\n private calculateRegistryRevision(registry: McpToolRegistry): string {\n const surface = registry.tools.map((tool: RegisteredMcpTool) => [\n tool.name,\n tool.description,\n tool.inputSchema,\n tool.outputSchema,\n tool.annotations,\n ]);\n return createHash('sha256').update(JSON.stringify(surface)).digest('hex').slice(0, 12);\n }\n\n private requireRegistry(): McpToolRegistry {\n if (!this.registry) throw new Error('Call WpMcpServer.bind(...) before serving requests.');\n return this.registry;\n }\n\n private record(value: DtoValue): Record<string, DtoValue> {\n const jsonValue = JSON.stringify(value);\n if (jsonValue === undefined) {\n throw new ApiImplementationError('MCP structured content is not JSON serializable.');\n }\n const parsed = JSON.parse(jsonValue) as DtoValue;\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return { value: parsed };\n }\n return parsed as Record<string, DtoValue>;\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import 'reflect-metadata';
2
- import { ContextKey, ErrorTranslators, Filter, HttpResponseDto, LogLevel, Service } from '@webpieces/core-util';
2
+ import { ContextKey, ErrorTranslator, Filter, HttpResponseDto, LogLevel, Service } from '@webpieces/core-util';
3
3
  import { MethodMeta, OidcHook, WpResponse } from '@webpieces/http-routing';
4
4
  /** Contracts, controllers and test doubles for McpRemoteBinding.integration.spec.ts. */
5
5
  export declare const REMOTE_USER: ContextKey<string, "trusted">;
@@ -93,8 +93,9 @@ export declare class BoundaryProbeFilter extends Filter<MethodMeta, WpResponse<u
93
93
  * an MCP gateway relays a Webpieces peer's typed failure so the model sees the same kind it would see
94
94
  * for a local binding. `relay = false` answers "not mine", which is the framework default.
95
95
  */
96
- export declare class RelayWebpiecesPeerErrors implements ErrorTranslators {
96
+ export declare class RelayWebpiecesPeerErrors implements ErrorTranslator {
97
97
  relay: boolean;
98
+ private readonly fallback;
98
99
  toWire(error: Error): HttpResponseDto;
99
- fromWire(response: HttpResponseDto): Error | undefined;
100
+ fromWire(response: HttpResponseDto): void;
100
101
  }
@@ -8,7 +8,6 @@ const inversify_1 = require("inversify");
8
8
  const core_util_1 = require("@webpieces/core-util");
9
9
  const core_context_1 = require("@webpieces/core-context");
10
10
  const http_routing_1 = require("@webpieces/http-routing");
11
- const http_server_1 = require("@webpieces/http-server");
12
11
  /** Contracts, controllers and test doubles for McpRemoteBinding.integration.spec.ts. */
13
12
  exports.REMOTE_USER = core_util_1.ContextKey.trusted('mcpRemoteUser', 'verified by the MCP access-token authority before delegation', 'x-mcp-remote-user');
14
13
  exports.REMOTE_ROLES = core_util_1.ContextKey.trusted('mcpRemoteRoles', 'verified by the MCP access-token authority before delegation', 'x-mcp-remote-roles');
@@ -422,19 +421,20 @@ exports.BoundaryProbeFilter = BoundaryProbeFilter = tslib_1.__decorate([
422
421
  */
423
422
  class RelayWebpiecesPeerErrors {
424
423
  relay = true;
424
+ fallback = new core_util_1.WebpiecesDefaultErrorTranslator();
425
425
  toWire(error) {
426
- return new http_server_1.ApiErrorHttpMapper('gui').toResponse(error);
426
+ return this.fallback.toWire(error);
427
427
  }
428
428
  fromWire(response) {
429
- if (!this.relay || !core_util_1.ApiErrorCodec.isPayload(response.body))
430
- return undefined;
431
- const decoded = core_util_1.ApiErrorCodec.decode(response.body);
432
- if (!core_util_1.ApiErrorHttpStatus.hasCode(decoded))
433
- return undefined;
434
- const statusCode = decoded instanceof core_util_1.ApiCodedError ? decoded.statusCode : undefined;
435
- return core_util_1.ApiErrorHttpStatus.codeFor(decoded.kind, statusCode) === response.status.code
436
- ? decoded
437
- : undefined;
429
+ if (this.relay && core_util_1.ApiErrorCodec.isPayload(response.body)) {
430
+ const decoded = core_util_1.ApiErrorCodec.decode(response.body);
431
+ const statusCode = decoded instanceof core_util_1.ApiCodedError ? decoded.statusCode : undefined;
432
+ if (core_util_1.ApiErrorHttpStatus.hasCode(decoded) &&
433
+ core_util_1.ApiErrorHttpStatus.codeFor(decoded.kind, statusCode) === response.status.code) {
434
+ throw decoded;
435
+ }
436
+ }
437
+ this.fallback.fromWire(response);
438
438
  }
439
439
  }
440
440
  exports.RelayWebpiecesPeerErrors = RelayWebpiecesPeerErrors;
@@ -1 +1 @@
1
- {"version":3,"file":"McpRemoteFixtures.js","sourceRoot":"","sources":["../../../../../../packages/http/mcp-server/src/__tests__/McpRemoteFixtures.ts"],"names":[],"mappings":"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","sourcesContent":["import 'reflect-metadata';\nimport { injectable } from 'inversify';\nimport {\n ApiBadRequestError,\n ApiCodedError,\n ApiConflictError,\n ApiConnectionError,\n ApiDependencyBackoffError,\n ApiDependencyError,\n ApiDependencyTimeoutError,\n ApiEndpointNotFoundError,\n ApiEndUserError,\n ApiErrorCodec,\n ApiErrorHttpStatus,\n ApiForbiddenError,\n ApiImplementationError,\n ApiNotFoundError,\n ApiNotImplementedError,\n ApiPath,\n ApiPreconditionFailedError,\n ApiRateLimitedError,\n ApiRequestTimeoutError,\n ApiUnauthorizedError,\n ApiUnavailableError,\n ApiUnprocessableError,\n ApiUnsupportedMediaTypeError,\n ContextKey,\n Endpoint,\n ErrorTranslators,\n Filter,\n HttpResponseDto,\n LogLevel,\n Service,\n WebpiecesCoreHeaders,\n WpAuthJwt,\n WpAuthOidc,\n WpDto,\n WpDtoField,\n WpDtoFieldOptions,\n WpMcpAuthJwt,\n WpMcpTool,\n WpResponseDto,\n} from '@webpieces/core-util';\nimport { RequestContext } from '@webpieces/core-context';\nimport { MethodMeta, OidcHook, WpResponse } from '@webpieces/http-routing';\nimport { ApiErrorHttpMapper } from '@webpieces/http-server';\n\n/** Contracts, controllers and test doubles for McpRemoteBinding.integration.spec.ts. */\n\nexport const REMOTE_USER = ContextKey.trusted<string>(\n 'mcpRemoteUser',\n 'verified by the MCP access-token authority before delegation',\n 'x-mcp-remote-user',\n);\nexport const REMOTE_ROLES = ContextKey.trusted<string>(\n 'mcpRemoteRoles',\n 'verified by the MCP access-token authority before delegation',\n 'x-mcp-remote-roles',\n);\nexport const REMOTE_SERVICE = 'mcp-remote-integration';\nexport const REFUSED_SERVICE = 'mcp-remote-refused';\nexport const GARBAGE_SERVICE = 'mcp-remote-garbage';\nexport const OIDC_TOKEN = 'oidc-for-mcp-remote-integration';\nexport const EXTERNAL_MCP_BEARER = 'external-mcp-access-token';\nexport const LOCAL_ENDPOINT_JWT = 'local-endpoint-jwt-that-must-not-cross-the-remote-hop';\nexport const GATEWAY_PATH = '/gateway/mcp';\n\n@WpDto()\nexport class RemoteRequest {\n @WpDtoField(new WpDtoFieldOptions('Search text', true))\n query!: string;\n\n constructor(query?: string) {\n if (query !== undefined) this.query = query;\n }\n}\n\n@WpDto()\nexport class RemoteResponse {\n @WpDtoField(new WpDtoFieldOptions('Delegated user', true))\n user!: string;\n\n @WpDtoField(new WpDtoFieldOptions('Delegated roles', true))\n roles!: string;\n\n @WpDtoField(new WpDtoFieldOptions('Result', true))\n result!: string;\n\n constructor(user?: string, roles?: string, result?: string) {\n if (user !== undefined) this.user = user;\n if (roles !== undefined) this.roles = roles;\n if (result !== undefined) this.result = result;\n }\n}\n\n@ApiPath('/remote-mcp')\nexport abstract class RemoteMcpApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'remote_integration_search',\n description: 'Calls a remote Webpieces API.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/missing-remote-mcp')\nexport abstract class MissingRemoteMcpApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'missing_remote_integration_search',\n description: 'Intentionally absent route.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/refused-remote-mcp')\nexport abstract class RefusedRemoteApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'refused_remote',\n description: 'Nothing listens on this port.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/garbage-remote-mcp')\nexport abstract class GarbageRemoteApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'garbage_remote',\n description: 'Answers an undecodable body.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/oidc-fail-remote-mcp')\nexport abstract class OidcFailRemoteApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'oidc_fail_remote',\n description: 'Its OIDC token cannot be minted.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/local-throw')\nexport abstract class LocalThrowApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthJwt({ allRolesAllowed: true })\n @Endpoint('/throw', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'local_throw',\n description: 'Throws the requested failure in-process.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n fail(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/remote-throw')\nexport abstract class RemoteThrowApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/throw', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'remote_throw',\n description: 'Throws the requested failure remotely.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n fail(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n/**\n * One named throw, run identically behind the local and the remote binding.\n *\n * `expectedServerLevel` is the level of the ONE operator line the failure now produces on the server\n * that raised it — `LogApiCall`'s, at `warn` for `[API-server-resp-OTHER]` (a healthy rejection of\n * the caller's mistake) and `error` for `[API-server-resp-FAIL]`. `ApiErrorBoundary` no longer\n * writes a second line of its own (#961).\n */\nexport class ThrowCase {\n constructor(\n public readonly name: string,\n public readonly expectedKind: string,\n public readonly expectedServerLevel: LogLevel,\n public readonly raise: () => never,\n ) {}\n}\n\nexport const THROW_CASES: readonly ThrowCase[] = [\n new ThrowCase('end-user', 'end-user', 'warn', () => {\n throw new ApiEndUserError('The two passwords you entered do not match.', 'PW_MISMATCH');\n }),\n new ThrowCase('bad-request', 'bad-request', 'warn', () => {\n throw new ApiBadRequestError('internal column name', '$.query', 'query must be a word');\n }),\n new ThrowCase('unauthorized', 'unauthorized', 'warn', () => {\n throw new ApiUnauthorizedError('session internals');\n }),\n new ThrowCase('forbidden', 'forbidden', 'warn', () => {\n throw new ApiForbiddenError('acl internals');\n }),\n new ThrowCase('not-found', 'not-found', 'warn', () => {\n throw new ApiNotFoundError('row 7 missing');\n }),\n new ThrowCase('endpoint-not-found', 'endpoint-not-found', 'warn', () => {\n throw new ApiEndpointNotFoundError('route internals');\n }),\n new ThrowCase('request-timeout', 'request-timeout', 'error', () => {\n throw new ApiRequestTimeoutError('slow internals');\n }),\n new ThrowCase('rate-limited', 'rate-limited', 'error', () => {\n throw new ApiRateLimitedError('quota internals');\n }),\n new ThrowCase('conflict', 'conflict', 'warn', () => {\n throw new ApiConflictError('version internals');\n }),\n new ThrowCase('unprocessable', 'unprocessable', 'warn', () => {\n throw new ApiUnprocessableError('rule internals');\n }),\n new ThrowCase('precondition-failed', 'precondition-failed', 'warn', () => {\n throw new ApiPreconditionFailedError('etag internals');\n }),\n new ThrowCase('unsupported-media-type', 'unsupported-media-type', 'warn', () => {\n throw new ApiUnsupportedMediaTypeError('parser internals');\n }),\n new ThrowCase('not-implemented', 'not-implemented', 'error', () => {\n throw new ApiNotImplementedError('feature internals');\n }),\n new ThrowCase('coded-4xx', 'coded', 'warn', () => {\n throw new ApiCodedError('quota internals', 460, 'QUOTA');\n }),\n new ThrowCase('coded-5xx', 'coded', 'error', () => {\n throw new ApiCodedError('disk internals', 507);\n }),\n new ThrowCase('implementation', 'implementation', 'error', () => {\n throw new ApiImplementationError('bug internals');\n }),\n new ThrowCase('dependency', 'dependency', 'error', () => {\n throw new ApiDependencyError('upstream internals');\n }),\n new ThrowCase('unavailable', 'unavailable', 'error', () => {\n throw new ApiUnavailableError('maintenance internals');\n }),\n new ThrowCase('dependency-timeout', 'dependency-timeout', 'error', () => {\n throw new ApiDependencyTimeoutError('upstream slow internals');\n }),\n new ThrowCase('dependency-backoff', 'dependency-backoff', 'error', () => {\n throw new ApiDependencyBackoffError('backoff internals', 42);\n }),\n new ThrowCase('connection', 'implementation', 'error', () => {\n throw new ApiConnectionError('ECONNRESET internals');\n }),\n new ThrowCase('raw-error', 'implementation', 'error', () => {\n throw new Error('SECRET-raw-internals');\n }),\n new ThrowCase('thrown-string', 'implementation', 'error', () => {\n throw 'SECRET-string-internals';\n }),\n];\n\nexport function raiseFor(query: string): never {\n const found = THROW_CASES.find((candidate: ThrowCase) => candidate.name === query);\n if (!found) throw new Error(`unknown throw case ${query}`);\n return found.raise();\n}\n\n@injectable()\nexport class RemoteMcpController extends RemoteMcpApi {\n calls = 0;\n authorization?: string;\n\n override search(request: RemoteRequest): Promise<RemoteResponse> {\n this.calls += 1;\n this.authorization = RequestContext.getRequest()?.getHeader('authorization');\n return Promise.resolve(\n new RemoteResponse(\n RequestContext.getTrusted(REMOTE_USER) ?? 'missing-user',\n RequestContext.getTrusted(REMOTE_ROLES) ?? 'missing-roles',\n `remote:${request.query}`,\n ),\n );\n }\n}\n\n@injectable()\nexport class LocalThrowController extends LocalThrowApi {\n override async fail(request: RemoteRequest): Promise<RemoteResponse> {\n return raiseFor(request.query);\n }\n}\n\n@injectable()\nexport class RemoteThrowController extends RemoteThrowApi {\n override async fail(request: RemoteRequest): Promise<RemoteResponse> {\n return raiseFor(request.query);\n }\n}\n\nexport class RecordingOidcMinter {\n readonly audiences: string[] = [];\n\n constructor(\n private readonly failure?: Error,\n private readonly token = OIDC_TOKEN,\n ) {}\n\n mintIdToken(audience: string): Promise<string> {\n this.audiences.push(audience);\n if (this.failure) return Promise.reject(this.failure);\n return Promise.resolve(this.token);\n }\n}\n\nexport class RecordingOidcVerifier extends OidcHook {\n readonly tokens: string[] = [];\n readonly callerLists: string[][] = [];\n\n override verifyOidc(token: string, callers: string[]): Promise<void> {\n this.tokens.push(token);\n this.callerLists.push(callers);\n if (token !== OIDC_TOKEN) throw new Error(`unexpected OIDC token '${token}'`);\n return Promise.resolve();\n }\n}\n\n@injectable()\nexport class BoundaryProbeFilter extends Filter<MethodMeta, WpResponse<unknown>> {\n calls = 0;\n sawLogIdentity = false;\n sawTrustedUser?: string;\n\n override filter(\n meta: MethodMeta,\n next: Service<MethodMeta, WpResponse<unknown>>,\n ): Promise<WpResponse<unknown>> {\n this.calls += 1;\n this.sawLogIdentity =\n RequestContext.getUntrusted(WebpiecesCoreHeaders.CONTROLLER) ===\n 'RemoteMcpController' &&\n RequestContext.getUntrusted(WebpiecesCoreHeaders.METHOD) === 'search';\n this.sawTrustedUser = RequestContext.getTrusted(REMOTE_USER);\n return next.invoke(meta);\n }\n}\n\n/**\n * The documented gateway opt-out from http-client-node's \"a dependency's 4xx is OUR 500\" invariant:\n * an MCP gateway relays a Webpieces peer's typed failure so the model sees the same kind it would see\n * for a local binding. `relay = false` answers \"not mine\", which is the framework default.\n */\nexport class RelayWebpiecesPeerErrors implements ErrorTranslators {\n relay = true;\n\n toWire(error: Error): HttpResponseDto {\n return new ApiErrorHttpMapper('gui').toResponse(error);\n }\n\n fromWire(response: HttpResponseDto): Error | undefined {\n if (!this.relay || !ApiErrorCodec.isPayload(response.body)) return undefined;\n const decoded = ApiErrorCodec.decode(response.body);\n if (!ApiErrorHttpStatus.hasCode(decoded)) return undefined;\n const statusCode = decoded instanceof ApiCodedError ? decoded.statusCode : undefined;\n return ApiErrorHttpStatus.codeFor(decoded.kind, statusCode) === response.status.code\n ? decoded\n : undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"McpRemoteFixtures.js","sourceRoot":"","sources":["../../../../../../packages/http/mcp-server/src/__tests__/McpRemoteFixtures.ts"],"names":[],"mappings":"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","sourcesContent":["import 'reflect-metadata';\nimport { injectable } from 'inversify';\nimport {\n ApiBadRequestError,\n ApiCodedError,\n ApiConflictError,\n ApiConnectionError,\n ApiDependencyBackoffError,\n ApiDependencyError,\n ApiDependencyTimeoutError,\n ApiEndpointNotFoundError,\n ApiEndUserError,\n ApiErrorCodec,\n ApiErrorHttpStatus,\n ApiForbiddenError,\n ApiImplementationError,\n ApiNotFoundError,\n ApiNotImplementedError,\n ApiPath,\n ApiPreconditionFailedError,\n ApiRateLimitedError,\n ApiRequestTimeoutError,\n ApiUnauthorizedError,\n ApiUnavailableError,\n ApiUnprocessableError,\n ApiUnsupportedMediaTypeError,\n ContextKey,\n Endpoint,\n ErrorTranslator,\n Filter,\n WebpiecesDefaultErrorTranslator,\n HttpResponseDto,\n LogLevel,\n Service,\n WebpiecesCoreHeaders,\n WpAuthJwt,\n WpAuthOidc,\n WpDto,\n WpDtoField,\n WpDtoFieldOptions,\n WpMcpAuthJwt,\n WpMcpTool,\n WpResponseDto,\n} from '@webpieces/core-util';\nimport { RequestContext } from '@webpieces/core-context';\nimport { MethodMeta, OidcHook, WpResponse } from '@webpieces/http-routing';\n\n\n/** Contracts, controllers and test doubles for McpRemoteBinding.integration.spec.ts. */\n\nexport const REMOTE_USER = ContextKey.trusted<string>(\n 'mcpRemoteUser',\n 'verified by the MCP access-token authority before delegation',\n 'x-mcp-remote-user',\n);\nexport const REMOTE_ROLES = ContextKey.trusted<string>(\n 'mcpRemoteRoles',\n 'verified by the MCP access-token authority before delegation',\n 'x-mcp-remote-roles',\n);\nexport const REMOTE_SERVICE = 'mcp-remote-integration';\nexport const REFUSED_SERVICE = 'mcp-remote-refused';\nexport const GARBAGE_SERVICE = 'mcp-remote-garbage';\nexport const OIDC_TOKEN = 'oidc-for-mcp-remote-integration';\nexport const EXTERNAL_MCP_BEARER = 'external-mcp-access-token';\nexport const LOCAL_ENDPOINT_JWT = 'local-endpoint-jwt-that-must-not-cross-the-remote-hop';\nexport const GATEWAY_PATH = '/gateway/mcp';\n\n@WpDto()\nexport class RemoteRequest {\n @WpDtoField(new WpDtoFieldOptions('Search text', true))\n query!: string;\n\n constructor(query?: string) {\n if (query !== undefined) this.query = query;\n }\n}\n\n@WpDto()\nexport class RemoteResponse {\n @WpDtoField(new WpDtoFieldOptions('Delegated user', true))\n user!: string;\n\n @WpDtoField(new WpDtoFieldOptions('Delegated roles', true))\n roles!: string;\n\n @WpDtoField(new WpDtoFieldOptions('Result', true))\n result!: string;\n\n constructor(user?: string, roles?: string, result?: string) {\n if (user !== undefined) this.user = user;\n if (roles !== undefined) this.roles = roles;\n if (result !== undefined) this.result = result;\n }\n}\n\n@ApiPath('/remote-mcp')\nexport abstract class RemoteMcpApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'remote_integration_search',\n description: 'Calls a remote Webpieces API.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/missing-remote-mcp')\nexport abstract class MissingRemoteMcpApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'missing_remote_integration_search',\n description: 'Intentionally absent route.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/refused-remote-mcp')\nexport abstract class RefusedRemoteApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'refused_remote',\n description: 'Nothing listens on this port.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/garbage-remote-mcp')\nexport abstract class GarbageRemoteApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'garbage_remote',\n description: 'Answers an undecodable body.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/oidc-fail-remote-mcp')\nexport abstract class OidcFailRemoteApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/search', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'oidc_fail_remote',\n description: 'Its OIDC token cannot be minted.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n search(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/local-throw')\nexport abstract class LocalThrowApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthJwt({ allRolesAllowed: true })\n @Endpoint('/throw', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'local_throw',\n description: 'Throws the requested failure in-process.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n fail(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n@ApiPath('/remote-throw')\nexport abstract class RemoteThrowApi {\n @WpMcpAuthJwt({ allRolesAllowed: true })\n @WpAuthOidc('mcp-gateway')\n @Endpoint('/throw', 'rpc')\n @WpResponseDto(() => RemoteResponse)\n @WpMcpTool({\n name: 'remote_throw',\n description: 'Throws the requested failure remotely.',\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n })\n fail(_request: RemoteRequest): Promise<RemoteResponse> {\n throw new Error('contract only');\n }\n}\n\n/**\n * One named throw, run identically behind the local and the remote binding.\n *\n * `expectedServerLevel` is the level of the ONE operator line the failure now produces on the server\n * that raised it — `LogApiCall`'s, at `warn` for `[API-server-resp-OTHER]` (a healthy rejection of\n * the caller's mistake) and `error` for `[API-server-resp-FAIL]`. `ApiErrorBoundary` no longer\n * writes a second line of its own (#961).\n */\nexport class ThrowCase {\n constructor(\n public readonly name: string,\n public readonly expectedKind: string,\n public readonly expectedServerLevel: LogLevel,\n public readonly raise: () => never,\n ) {}\n}\n\nexport const THROW_CASES: readonly ThrowCase[] = [\n new ThrowCase('end-user', 'end-user', 'warn', () => {\n throw new ApiEndUserError('The two passwords you entered do not match.', 'PW_MISMATCH');\n }),\n new ThrowCase('bad-request', 'bad-request', 'warn', () => {\n throw new ApiBadRequestError('internal column name', '$.query', 'query must be a word');\n }),\n new ThrowCase('unauthorized', 'unauthorized', 'warn', () => {\n throw new ApiUnauthorizedError('session internals');\n }),\n new ThrowCase('forbidden', 'forbidden', 'warn', () => {\n throw new ApiForbiddenError('acl internals');\n }),\n new ThrowCase('not-found', 'not-found', 'warn', () => {\n throw new ApiNotFoundError('row 7 missing');\n }),\n new ThrowCase('endpoint-not-found', 'endpoint-not-found', 'warn', () => {\n throw new ApiEndpointNotFoundError('route internals');\n }),\n new ThrowCase('request-timeout', 'request-timeout', 'error', () => {\n throw new ApiRequestTimeoutError('slow internals');\n }),\n new ThrowCase('rate-limited', 'rate-limited', 'error', () => {\n throw new ApiRateLimitedError('quota internals');\n }),\n new ThrowCase('conflict', 'conflict', 'warn', () => {\n throw new ApiConflictError('version internals');\n }),\n new ThrowCase('unprocessable', 'unprocessable', 'warn', () => {\n throw new ApiUnprocessableError('rule internals');\n }),\n new ThrowCase('precondition-failed', 'precondition-failed', 'warn', () => {\n throw new ApiPreconditionFailedError('etag internals');\n }),\n new ThrowCase('unsupported-media-type', 'unsupported-media-type', 'warn', () => {\n throw new ApiUnsupportedMediaTypeError('parser internals');\n }),\n new ThrowCase('not-implemented', 'not-implemented', 'error', () => {\n throw new ApiNotImplementedError('feature internals');\n }),\n new ThrowCase('coded-4xx', 'coded', 'warn', () => {\n throw new ApiCodedError('quota internals', 460, 'QUOTA');\n }),\n new ThrowCase('coded-5xx', 'coded', 'error', () => {\n throw new ApiCodedError('disk internals', 507);\n }),\n new ThrowCase('implementation', 'implementation', 'error', () => {\n throw new ApiImplementationError('bug internals');\n }),\n new ThrowCase('dependency', 'dependency', 'error', () => {\n throw new ApiDependencyError('upstream internals');\n }),\n new ThrowCase('unavailable', 'unavailable', 'error', () => {\n throw new ApiUnavailableError('maintenance internals');\n }),\n new ThrowCase('dependency-timeout', 'dependency-timeout', 'error', () => {\n throw new ApiDependencyTimeoutError('upstream slow internals');\n }),\n new ThrowCase('dependency-backoff', 'dependency-backoff', 'error', () => {\n throw new ApiDependencyBackoffError('backoff internals', 42);\n }),\n new ThrowCase('connection', 'implementation', 'error', () => {\n throw new ApiConnectionError('ECONNRESET internals');\n }),\n new ThrowCase('raw-error', 'implementation', 'error', () => {\n throw new Error('SECRET-raw-internals');\n }),\n new ThrowCase('thrown-string', 'implementation', 'error', () => {\n throw 'SECRET-string-internals';\n }),\n];\n\nexport function raiseFor(query: string): never {\n const found = THROW_CASES.find((candidate: ThrowCase) => candidate.name === query);\n if (!found) throw new Error(`unknown throw case ${query}`);\n return found.raise();\n}\n\n@injectable()\nexport class RemoteMcpController extends RemoteMcpApi {\n calls = 0;\n authorization?: string;\n\n override search(request: RemoteRequest): Promise<RemoteResponse> {\n this.calls += 1;\n this.authorization = RequestContext.getRequest()?.getHeader('authorization');\n return Promise.resolve(\n new RemoteResponse(\n RequestContext.getTrusted(REMOTE_USER) ?? 'missing-user',\n RequestContext.getTrusted(REMOTE_ROLES) ?? 'missing-roles',\n `remote:${request.query}`,\n ),\n );\n }\n}\n\n@injectable()\nexport class LocalThrowController extends LocalThrowApi {\n override async fail(request: RemoteRequest): Promise<RemoteResponse> {\n return raiseFor(request.query);\n }\n}\n\n@injectable()\nexport class RemoteThrowController extends RemoteThrowApi {\n override async fail(request: RemoteRequest): Promise<RemoteResponse> {\n return raiseFor(request.query);\n }\n}\n\nexport class RecordingOidcMinter {\n readonly audiences: string[] = [];\n\n constructor(\n private readonly failure?: Error,\n private readonly token = OIDC_TOKEN,\n ) {}\n\n mintIdToken(audience: string): Promise<string> {\n this.audiences.push(audience);\n if (this.failure) return Promise.reject(this.failure);\n return Promise.resolve(this.token);\n }\n}\n\nexport class RecordingOidcVerifier extends OidcHook {\n readonly tokens: string[] = [];\n readonly callerLists: string[][] = [];\n\n override verifyOidc(token: string, callers: string[]): Promise<void> {\n this.tokens.push(token);\n this.callerLists.push(callers);\n if (token !== OIDC_TOKEN) throw new Error(`unexpected OIDC token '${token}'`);\n return Promise.resolve();\n }\n}\n\n@injectable()\nexport class BoundaryProbeFilter extends Filter<MethodMeta, WpResponse<unknown>> {\n calls = 0;\n sawLogIdentity = false;\n sawTrustedUser?: string;\n\n override filter(\n meta: MethodMeta,\n next: Service<MethodMeta, WpResponse<unknown>>,\n ): Promise<WpResponse<unknown>> {\n this.calls += 1;\n this.sawLogIdentity =\n RequestContext.getUntrusted(WebpiecesCoreHeaders.CONTROLLER) ===\n 'RemoteMcpController' &&\n RequestContext.getUntrusted(WebpiecesCoreHeaders.METHOD) === 'search';\n this.sawTrustedUser = RequestContext.getTrusted(REMOTE_USER);\n return next.invoke(meta);\n }\n}\n\n/**\n * The documented gateway opt-out from http-client-node's \"a dependency's 4xx is OUR 500\" invariant:\n * an MCP gateway relays a Webpieces peer's typed failure so the model sees the same kind it would see\n * for a local binding. `relay = false` answers \"not mine\", which is the framework default.\n */\nexport class RelayWebpiecesPeerErrors implements ErrorTranslator {\n relay = true;\n\n private readonly fallback = new WebpiecesDefaultErrorTranslator();\n\n toWire(error: Error): HttpResponseDto {\n return this.fallback.toWire(error);\n }\n\n fromWire(response: HttpResponseDto): void {\n if (this.relay && ApiErrorCodec.isPayload(response.body)) {\n const decoded = ApiErrorCodec.decode(response.body);\n const statusCode = decoded instanceof ApiCodedError ? decoded.statusCode : undefined;\n if (\n ApiErrorHttpStatus.hasCode(decoded) &&\n ApiErrorHttpStatus.codeFor(decoded.kind, statusCode) === response.status.code\n ) {\n throw decoded;\n }\n }\n this.fallback.fromWire(response);\n }\n}\n"]}
package/src/index.d.ts CHANGED
@@ -10,5 +10,7 @@ export { McpDeployment } from './McpDeployment';
10
10
  export type { McpDeploymentMode } from './McpDeployment';
11
11
  export { McpApiDispatcher } from './McpApiDispatcher';
12
12
  export { WpMcpServer } from './WpMcpServer';
13
- export { MCP_REQUEST_ID_META_KEY, McpCorrelation, McpDefaultToolCallRenderer, McpErrorData, McpHttpErrorBody, McpHttpErrorDetail, ModelVisibleToolError, WpMcpErrorTranslator, } from './WpMcpErrorTranslator';
14
- export type { McpErrorTranslators } from './WpMcpErrorTranslator';
13
+ export { MCP_REQUEST_ID_META_KEY, McpCorrelation, McpDefaultToolCallRenderer, McpErrorData, McpHttpErrorBody, McpHttpErrorDetail, ModelVisibleToolError, } from './McpToolCallRendering';
14
+ export { WpMcpErrorTranslator } from './WpMcpErrorTranslator';
15
+ export type { McpErrorTranslator } from './McpToolCallRendering';
16
+ export { McpRegistry } from './McpRegistry';
package/src/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WpMcpErrorTranslator = exports.ModelVisibleToolError = exports.McpHttpErrorDetail = exports.McpHttpErrorBody = exports.McpErrorData = exports.McpDefaultToolCallRenderer = exports.McpCorrelation = exports.MCP_REQUEST_ID_META_KEY = exports.WpMcpServer = exports.McpApiDispatcher = exports.McpDeployment = exports.McpBindOptions = exports.McpInvocationContext = exports.MCP_INVOCATION_CONTEXT = exports.McpApiBinding = exports.RegisteredMcpTool = exports.McpToolRegistry = exports.WpMcpServerConfig = exports.VerifiedMcpCredential = exports.McpProtectedResourceMetadata = exports.MintedMcpAccessToken = exports.McpEndpointDescriptor = exports.MAX_MCP_ENDPOINT_JWT_LIFETIME_SECONDS = exports.MAX_MCP_ACCOUNT_VALIDATION_AGE_SECONDS = exports.MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS = void 0;
3
+ exports.McpRegistry = exports.WpMcpErrorTranslator = exports.ModelVisibleToolError = exports.McpHttpErrorDetail = exports.McpHttpErrorBody = exports.McpErrorData = exports.McpDefaultToolCallRenderer = exports.McpCorrelation = exports.MCP_REQUEST_ID_META_KEY = exports.WpMcpServer = exports.McpApiDispatcher = exports.McpDeployment = exports.McpBindOptions = exports.McpInvocationContext = exports.MCP_INVOCATION_CONTEXT = exports.McpApiBinding = exports.RegisteredMcpTool = exports.McpToolRegistry = exports.WpMcpServerConfig = exports.VerifiedMcpCredential = exports.McpProtectedResourceMetadata = exports.MintedMcpAccessToken = exports.McpEndpointDescriptor = exports.MAX_MCP_ENDPOINT_JWT_LIFETIME_SECONDS = exports.MAX_MCP_ACCOUNT_VALIDATION_AGE_SECONDS = exports.MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS = void 0;
4
4
  var McpAuth_1 = require("./McpAuth");
5
5
  Object.defineProperty(exports, "MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS", { enumerable: true, get: function () { return McpAuth_1.MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS; } });
6
6
  Object.defineProperty(exports, "MAX_MCP_ACCOUNT_VALIDATION_AGE_SECONDS", { enumerable: true, get: function () { return McpAuth_1.MAX_MCP_ACCOUNT_VALIDATION_AGE_SECONDS; } });
@@ -26,13 +26,17 @@ var McpApiDispatcher_1 = require("./McpApiDispatcher");
26
26
  Object.defineProperty(exports, "McpApiDispatcher", { enumerable: true, get: function () { return McpApiDispatcher_1.McpApiDispatcher; } });
27
27
  var WpMcpServer_1 = require("./WpMcpServer");
28
28
  Object.defineProperty(exports, "WpMcpServer", { enumerable: true, get: function () { return WpMcpServer_1.WpMcpServer; } });
29
+ var McpToolCallRendering_1 = require("./McpToolCallRendering");
30
+ Object.defineProperty(exports, "MCP_REQUEST_ID_META_KEY", { enumerable: true, get: function () { return McpToolCallRendering_1.MCP_REQUEST_ID_META_KEY; } });
31
+ Object.defineProperty(exports, "McpCorrelation", { enumerable: true, get: function () { return McpToolCallRendering_1.McpCorrelation; } });
32
+ Object.defineProperty(exports, "McpDefaultToolCallRenderer", { enumerable: true, get: function () { return McpToolCallRendering_1.McpDefaultToolCallRenderer; } });
33
+ Object.defineProperty(exports, "McpErrorData", { enumerable: true, get: function () { return McpToolCallRendering_1.McpErrorData; } });
34
+ Object.defineProperty(exports, "McpHttpErrorBody", { enumerable: true, get: function () { return McpToolCallRendering_1.McpHttpErrorBody; } });
35
+ Object.defineProperty(exports, "McpHttpErrorDetail", { enumerable: true, get: function () { return McpToolCallRendering_1.McpHttpErrorDetail; } });
36
+ Object.defineProperty(exports, "ModelVisibleToolError", { enumerable: true, get: function () { return McpToolCallRendering_1.ModelVisibleToolError; } });
29
37
  var WpMcpErrorTranslator_1 = require("./WpMcpErrorTranslator");
30
- Object.defineProperty(exports, "MCP_REQUEST_ID_META_KEY", { enumerable: true, get: function () { return WpMcpErrorTranslator_1.MCP_REQUEST_ID_META_KEY; } });
31
- Object.defineProperty(exports, "McpCorrelation", { enumerable: true, get: function () { return WpMcpErrorTranslator_1.McpCorrelation; } });
32
- Object.defineProperty(exports, "McpDefaultToolCallRenderer", { enumerable: true, get: function () { return WpMcpErrorTranslator_1.McpDefaultToolCallRenderer; } });
33
- Object.defineProperty(exports, "McpErrorData", { enumerable: true, get: function () { return WpMcpErrorTranslator_1.McpErrorData; } });
34
- Object.defineProperty(exports, "McpHttpErrorBody", { enumerable: true, get: function () { return WpMcpErrorTranslator_1.McpHttpErrorBody; } });
35
- Object.defineProperty(exports, "McpHttpErrorDetail", { enumerable: true, get: function () { return WpMcpErrorTranslator_1.McpHttpErrorDetail; } });
36
- Object.defineProperty(exports, "ModelVisibleToolError", { enumerable: true, get: function () { return WpMcpErrorTranslator_1.ModelVisibleToolError; } });
37
38
  Object.defineProperty(exports, "WpMcpErrorTranslator", { enumerable: true, get: function () { return WpMcpErrorTranslator_1.WpMcpErrorTranslator; } });
39
+ // The process-global home of the ONE MCP translator, mirroring ClientRegistry / IpcRegistry.
40
+ var McpRegistry_1 = require("./McpRegistry");
41
+ Object.defineProperty(exports, "McpRegistry", { enumerable: true, get: function () { return McpRegistry_1.McpRegistry; } });
38
42
  //# sourceMappingURL=index.js.map
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/mcp-server/src/index.ts"],"names":[],"mappings":";;;AAAA,qCASmB;AARf,gIAAA,qCAAqC,OAAA;AACrC,iIAAA,sCAAsC,OAAA;AACtC,gIAAA,qCAAqC,OAAA;AACrC,gHAAA,qBAAqB,OAAA;AACrB,+GAAA,oBAAoB,OAAA;AACpB,uHAAA,4BAA4B,OAAA;AAC5B,gHAAA,qBAAqB,OAAA;AACrB,4GAAA,iBAAiB,OAAA;AAGrB,qDAAuE;AAA9D,kHAAA,eAAe,OAAA;AAAE,oHAAA,iBAAiB,OAAA;AAC3C,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AAEtB,+DAAsF;AAA7E,8HAAA,sBAAsB,OAAA;AAAE,4HAAA,oBAAoB,OAAA;AAErD,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AAEtB,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AACpB,+DASgC;AAR5B,+HAAA,uBAAuB,OAAA;AACvB,sHAAA,cAAc,OAAA;AACd,kIAAA,0BAA0B,OAAA;AAC1B,oHAAA,YAAY,OAAA;AACZ,wHAAA,gBAAgB,OAAA;AAChB,0HAAA,kBAAkB,OAAA;AAClB,6HAAA,qBAAqB,OAAA;AACrB,4HAAA,oBAAoB,OAAA","sourcesContent":["export {\n MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS,\n MAX_MCP_ACCOUNT_VALIDATION_AGE_SECONDS,\n MAX_MCP_ENDPOINT_JWT_LIFETIME_SECONDS,\n McpEndpointDescriptor,\n MintedMcpAccessToken,\n McpProtectedResourceMetadata,\n VerifiedMcpCredential,\n WpMcpServerConfig,\n} from './McpAuth';\nexport type { McpAccessTokenAuthority, McpEndpointMintRequestFactory } from './McpAuth';\nexport { McpToolRegistry, RegisteredMcpTool } from './McpToolRegistry';\nexport { McpApiBinding } from './McpApiBinding';\nexport type { McpBindingTopology } from './McpApiBinding';\nexport { MCP_INVOCATION_CONTEXT, McpInvocationContext } from './McpInvocationContext';\nexport type { McpProgressReporter } from './McpInvocationContext';\nexport { McpBindOptions } from './McpBindOptions';\nexport { McpDeployment } from './McpDeployment';\nexport type { McpDeploymentMode } from './McpDeployment';\nexport { McpApiDispatcher } from './McpApiDispatcher';\nexport { WpMcpServer } from './WpMcpServer';\nexport {\n MCP_REQUEST_ID_META_KEY,\n McpCorrelation,\n McpDefaultToolCallRenderer,\n McpErrorData,\n McpHttpErrorBody,\n McpHttpErrorDetail,\n ModelVisibleToolError,\n WpMcpErrorTranslator,\n} from './WpMcpErrorTranslator';\nexport type { McpErrorTranslators } from './WpMcpErrorTranslator';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/mcp-server/src/index.ts"],"names":[],"mappings":";;;AAAA,qCASmB;AARf,gIAAA,qCAAqC,OAAA;AACrC,iIAAA,sCAAsC,OAAA;AACtC,gIAAA,qCAAqC,OAAA;AACrC,gHAAA,qBAAqB,OAAA;AACrB,+GAAA,oBAAoB,OAAA;AACpB,uHAAA,4BAA4B,OAAA;AAC5B,gHAAA,qBAAqB,OAAA;AACrB,4GAAA,iBAAiB,OAAA;AAGrB,qDAAuE;AAA9D,kHAAA,eAAe,OAAA;AAAE,oHAAA,iBAAiB,OAAA;AAC3C,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AAEtB,+DAAsF;AAA7E,8HAAA,sBAAsB,OAAA;AAAE,4HAAA,oBAAoB,OAAA;AAErD,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AAEtB,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AACpB,+DAQgC;AAP5B,+HAAA,uBAAuB,OAAA;AACvB,sHAAA,cAAc,OAAA;AACd,kIAAA,0BAA0B,OAAA;AAC1B,oHAAA,YAAY,OAAA;AACZ,wHAAA,gBAAgB,OAAA;AAChB,0HAAA,kBAAkB,OAAA;AAClB,6HAAA,qBAAqB,OAAA;AAEzB,+DAA8D;AAArD,4HAAA,oBAAoB,OAAA;AAE7B,6FAA6F;AAC7F,6CAA4C;AAAnC,0GAAA,WAAW,OAAA","sourcesContent":["export {\n MAX_MCP_ACCESS_TOKEN_LIFETIME_SECONDS,\n MAX_MCP_ACCOUNT_VALIDATION_AGE_SECONDS,\n MAX_MCP_ENDPOINT_JWT_LIFETIME_SECONDS,\n McpEndpointDescriptor,\n MintedMcpAccessToken,\n McpProtectedResourceMetadata,\n VerifiedMcpCredential,\n WpMcpServerConfig,\n} from './McpAuth';\nexport type { McpAccessTokenAuthority, McpEndpointMintRequestFactory } from './McpAuth';\nexport { McpToolRegistry, RegisteredMcpTool } from './McpToolRegistry';\nexport { McpApiBinding } from './McpApiBinding';\nexport type { McpBindingTopology } from './McpApiBinding';\nexport { MCP_INVOCATION_CONTEXT, McpInvocationContext } from './McpInvocationContext';\nexport type { McpProgressReporter } from './McpInvocationContext';\nexport { McpBindOptions } from './McpBindOptions';\nexport { McpDeployment } from './McpDeployment';\nexport type { McpDeploymentMode } from './McpDeployment';\nexport { McpApiDispatcher } from './McpApiDispatcher';\nexport { WpMcpServer } from './WpMcpServer';\nexport {\n MCP_REQUEST_ID_META_KEY,\n McpCorrelation,\n McpDefaultToolCallRenderer,\n McpErrorData,\n McpHttpErrorBody,\n McpHttpErrorDetail,\n ModelVisibleToolError,\n} from './McpToolCallRendering';\nexport { WpMcpErrorTranslator } from './WpMcpErrorTranslator';\nexport type { McpErrorTranslator } from './McpToolCallRendering';\n// The process-global home of the ONE MCP translator, mirroring ClientRegistry / IpcRegistry.\nexport { McpRegistry } from './McpRegistry';\n"]}