@routecraft/ai 0.5.0-canary.8 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/index.cjs +14 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1971 -389
- package/dist/index.d.ts +1971 -389
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/package.json +19 -12
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/brand.ts","../src/llm/providers/index.ts","../src/llm/structured-output.ts","../src/llm/types.ts","../src/llm/destination.ts","../src/llm/llm.ts","../src/llm/validate-options.ts","../src/llm/plugin.ts","../src/mcp/types.ts","../src/mcp/adapters/mcp/shared.ts","../src/mcp/adapters/mcp/source.ts","../src/mcp/extract-content.ts","../src/mcp/build-auth-headers.ts","../src/mcp/adapters/mcp/destination.ts","../src/mcp/adapters/mcp/index.ts","../src/mcp/oauth.ts","../src/mcp/server.ts","../src/mcp/validate-options.ts","../src/mcp/stdio-client-manager.ts","../src/mcp/tool-registry.ts","../src/mcp/plugin.ts","../src/agent/runner.ts","../src/agent/destination.ts","../src/agent/agent.ts","../src/embedding/providers/index.ts","../src/embedding/types.ts","../src/embedding/destination.ts","../src/embedding/embedding.ts","../src/embedding/plugin.ts"],"names":["BRAND","isBranded","obj","key","isMcpAdapter","throwProviderInstallError","pkg","provider","isModuleNotFoundFor","error","msg","PROVIDER_DEFAULTS","toLlmUsage","u","getStructuredOutput","result","assertLanguageModelShape","model","providerName","modelId","m","callLlm","params","config","options","systemPrompt","userPrompt","output","callOpenAI","callAnthropic","callGemini","callOpenRouter","callOllama","_","createOpenAI","generateText","openaiSettings","genParams","out","parsed","createAnthropic","createGoogleGenerativeAI","createOpenRouter","openrouter","resolvedId","rawModel","createOllama","ollama","name","toAiOutputSpec","schema","standard","jsonSchemaObj","validate","value","err","formatSchemaIssues","aiSchema","jsonSchema","Output","ADAPTER_LLM_PROVIDERS","ADAPTER_LLM_OPTIONS","parseStructuredTextFallback","text","DEFAULT_TEMPERATURE","DEFAULT_MAX_TOKENS","resolvePrompt","source","exchange","resolveUserPromptDefault","body","parseProviderModel","id","colon","resolveProviderAndModel","context","store","providerId","modelName","LlmDestinationAdapter","getExchangeContext","merged","opts","fallback","llmResult","metadata","llm","PROVIDERS","isProvider","s","validateLlmPluginOptions","PROVIDER_IDS","toModelConfig","llmPlugin","ctx","map","MCP_PLUGIN_REGISTERED","ADAPTER_MCP_CLIENT_SERVERS","MCP_TOOL_REGISTRY","MCP_STDIO_MANAGERS","McpHeadersKeys","isOAuthAuth","auth","BRAND_MCP_ADAPTER","McpSourceAdapter","endpoint","rcError","handler","abortController","onReady","direct","extractContent","response","content","item","rrIndexes","resolveToken","token","idx","buildAuthHeaders","headers","customHeaders","authorizationOverride","resolved","assertHttpUrl","url","trimmed","resolveServerConfig","resolveConnection","defaultArgs","McpDestinationAdapter","toolName","args","manager","serverConfig","serverUrl","clientModule","transportModule","Client","StreamableHTTPClientTransport","transportOptions","transport","clientInfo","client","clientCleanup","closeOrDisconnect","transportCleanup","closeOrDestroy","mcp","endpointOrOptions","clientOpts","entry","isClientColonOptions","colonIndex","serverId","tool","clientOptions","normaliseClientSupplier","input","clientId","staticClient","buildVerifier","verify","oauth","verifyAccessToken","getClient","principalStore","AsyncLocalStorage","MCP_SDK_INSTALL","McpServer","isRoutecraftError","Server","StdioServerTransport","ServerCtor","TransportClass","server","sessionId","tr","prevOnClose","sid","handleRequest","req","res","principal","createSessionFn","runWithPrincipal","fn","session","hr","port","host","createServer","oauthOptions","expressFn","mcpAuthRouter","requireBearerAuth","ProxyOAuthServerProvider","expressMod","wrappedVerifier","detail","app","authRouterOptions","bearerOptions","nodeReq","nodeRes","authInfo","successDetail","resolve","reject","boundPort","listenDetail","stashed","addr","authOptions","rawHeader","schemeMatch","typesModule","t","ListToolsRequestSchema","CallToolRequestSchema","srv","tools","request","names","exposedDetail","registry","ADAPTER_DIRECT_REGISTRY","toolsFilter","allowed","meta","channelStore","ADAPTER_DIRECT_STORE","channel","DefaultExchange","resultExchange","resultText","logMsg","userMsg","cause","validateMcpPluginOptions","validateWithSchema","StdioClientManager","logger","onEvent","onToolsUpdated","clientMod","stdioMod","command","env","cwd","data","_error","transportWithClose","maxRestarts","restartDelayMs","restartBackoffMultiplier","delay","stableMs","McpToolRegistry","sourceMap","isStdioConfig","mcpPlugin","stdioManagers","httpClients","httpRefreshTimers","toolRegistry","clientEntries","k","v","startStdioClient","httpConfig","listHttpClientTools","setupHttpToolRefresh","timer","managerOpts","event","details","_serverId","getOrCreateHttpClient","existing","rawClient","typed","interval","AgentRunner","_options","validateModelId","AgentDestinationAdapter","agent","pipelineCache","disposeEmbeddingPipelineCache","entries","cached","resolveHuggingFaceModel","HUGGINGFACE_INSTALL","getHuggingFacePipeline","pipelineFn","pipe","run","previewForError","toNumberArray","d","callEmbedding","vec","i","ADAPTER_EMBEDDING_PROVIDERS","ADAPTER_EMBEDDING_OPTIONS","buildText","using","EmbeddingDestinationAdapter","embedding","embeddingPlugin"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Cross-instance identity for @routecraft/ai: Symbol.for() keys and type guards.\n * Shared across all copies of @routecraft/ai (and multiple routecraft versions) in a process.\n */\n\nexport const BRAND = {\n McpAdapter: Symbol.for(\"routecraft.ai.McpAdapter\"),\n} as const;\n\nfunction isBranded(obj: unknown, key: symbol): boolean {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n (obj as Record<symbol, unknown>)[key] === true\n );\n}\n\nexport function isMcpAdapter(obj: unknown): boolean {\n return isBranded(obj, BRAND.McpAdapter);\n}\n","import type {\n LlmModelConfig,\n LlmOptionsMerged,\n LlmResult,\n LlmUsage,\n} from \"../types.ts\";\n\nfunction throwProviderInstallError(pkg: string, provider: string): never {\n throw new Error(\n `The ${provider} LLM provider requires the \"${pkg}\" package. Install it with: pnpm add ${pkg}`,\n );\n}\n\nfunction isModuleNotFoundFor(error: unknown, pkg: string): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message ?? \"\";\n return (\n (msg.includes(\"ERR_MODULE_NOT_FOUND\") ||\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Cannot find package\")) &&\n msg.includes(pkg)\n );\n}\n\n/** Provider-level defaults so users can register models with minimal config (e.g. { provider: \"ollama\" }). */\nconst PROVIDER_DEFAULTS = {\n ollama: {\n baseURL: \"http://localhost:11434/api\",\n },\n} as const;\n\n/** Pass through AI SDK usage so LlmUsage matches LanguageModelUsage (inputTokens/outputTokens). */\nfunction toLlmUsage(u: {\n inputTokens?: number | undefined;\n outputTokens?: number | undefined;\n totalTokens?: number | undefined;\n}): LlmUsage {\n return {\n ...(u.inputTokens !== undefined && { inputTokens: u.inputTokens }),\n ...(u.outputTokens !== undefined && { outputTokens: u.outputTokens }),\n ...(u.totalTokens !== undefined && { totalTokens: u.totalTokens }),\n };\n}\n\n/**\n * Safely read structured output from generateText result. The AI SDK's result.output\n * is a getter that throws AI_NoOutputGeneratedError when the model didn't produce\n * valid structured output (e.g. empty, blocked, or unparseable). Catching here\n * allows returning without output so the adapter can try parsing result.text.\n */\nfunction getStructuredOutput(result: { output?: unknown }): unknown {\n try {\n if (\"output\" in result && result.output !== undefined) return result.output;\n } catch {\n // SDK getter threw (e.g. AI_NoOutputGeneratedError); leave output undefined.\n }\n return undefined;\n}\n\n/**\n * Runtime check that a provider-returned value has the minimal LanguageModel shape\n * required by the AI SDK generateText (doGenerate, doStream). Throws a descriptive\n * error if validation fails so we avoid silent type assertions.\n */\nfunction assertLanguageModelShape(\n model: unknown,\n providerName: string,\n modelId: string,\n): void {\n if (model === null || typeof model !== \"object\") {\n throw new Error(\n `[${providerName}] Invalid model: expected an object, got ${typeof model}. Model id: ${modelId}`,\n );\n }\n const m = model as Record<string, unknown>;\n if (typeof m[\"doGenerate\"] !== \"function\") {\n throw new Error(\n `[${providerName}] Invalid model: missing or invalid doGenerate method. Model id: ${modelId}. ` +\n \"Ensure the provider returns an AI SDK-compatible language model.\",\n );\n }\n if (typeof m[\"doStream\"] !== \"function\") {\n throw new Error(\n `[${providerName}] Invalid model: missing or invalid doStream method. Model id: ${modelId}. ` +\n \"Ensure the provider returns an AI SDK-compatible language model.\",\n );\n }\n}\n\nexport interface CallLlmParams {\n config: LlmModelConfig;\n /** Model id to use for the request (for OpenRouter may be config.modelId ?? registeredId). */\n modelId: string;\n options: Pick<\n LlmOptionsMerged,\n | \"temperature\"\n | \"maxTokens\"\n | \"topP\"\n | \"frequencyPenalty\"\n | \"presencePenalty\"\n >;\n systemPrompt: string;\n userPrompt: string;\n /** Optional structured output spec (from toAiOutputSpec). Enables provider-level JSON schema. */\n output?: unknown;\n}\n\n/**\n * Dispatches to the appropriate provider and returns a normalized LlmResult.\n */\nexport async function callLlm(params: CallLlmParams): Promise<LlmResult> {\n const { config, modelId, options, systemPrompt, userPrompt, output } = params;\n switch (config.provider) {\n case \"openai\":\n return callOpenAI(\n config,\n modelId,\n options,\n systemPrompt,\n userPrompt,\n output,\n );\n case \"anthropic\":\n return callAnthropic(\n config,\n modelId,\n options,\n systemPrompt,\n userPrompt,\n output,\n );\n case \"gemini\":\n return callGemini(\n config,\n modelId,\n options,\n systemPrompt,\n userPrompt,\n output,\n );\n case \"openrouter\":\n return callOpenRouter(\n config,\n modelId,\n options,\n systemPrompt,\n userPrompt,\n output,\n );\n case \"ollama\":\n return callOllama(\n config,\n modelId,\n options,\n systemPrompt,\n userPrompt,\n output,\n );\n default: {\n const _: never = config;\n throw new Error(\n `LLM provider not implemented: ${(_ as LlmModelConfig).provider}`,\n );\n }\n }\n}\n\nasync function callOpenAI(\n config: import(\"../types.ts\").LlmModelConfigOpenAI,\n modelId: string,\n options: CallLlmParams[\"options\"],\n systemPrompt: string,\n userPrompt: string,\n output: CallLlmParams[\"output\"],\n): Promise<LlmResult> {\n let createOpenAI: (s: {\n apiKey: string;\n baseURL?: string;\n }) => (m: string) => unknown;\n try {\n const mod = await import(\"@ai-sdk/openai\");\n createOpenAI = mod.createOpenAI as typeof createOpenAI;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@ai-sdk/openai\")) {\n throwProviderInstallError(\"@ai-sdk/openai\", \"OpenAI\");\n }\n throw error;\n }\n const { generateText } = await import(\"ai\");\n const openaiSettings: { apiKey: string; baseURL?: string } = {\n apiKey: config.apiKey,\n };\n if (config.baseURL !== undefined) openaiSettings.baseURL = config.baseURL;\n const openai = createOpenAI(openaiSettings);\n const model = openai(modelId);\n const genParams: Parameters<typeof generateText>[0] = {\n model: model as Parameters<typeof generateText>[0][\"model\"],\n prompt: userPrompt,\n ...(options.maxTokens !== undefined && {\n maxOutputTokens: options.maxTokens,\n }),\n temperature: options.temperature,\n };\n if (systemPrompt) genParams.system = systemPrompt;\n if (options.topP !== undefined) genParams.topP = options.topP;\n if (options.frequencyPenalty !== undefined)\n genParams.frequencyPenalty = options.frequencyPenalty;\n if (options.presencePenalty !== undefined)\n genParams.presencePenalty = options.presencePenalty;\n const params = output !== undefined ? { ...genParams, output } : genParams;\n const result = await generateText(\n params as Parameters<typeof generateText>[0],\n );\n const out: LlmResult = { text: result.text ?? \"\", raw: result };\n if (result.usage) out.usage = toLlmUsage(result.usage);\n const parsed = getStructuredOutput(result as { output?: unknown });\n if (parsed !== undefined) out.output = parsed;\n return out;\n}\n\nasync function callAnthropic(\n config: import(\"../types.ts\").LlmModelConfigAnthropic,\n modelId: string,\n options: CallLlmParams[\"options\"],\n systemPrompt: string,\n userPrompt: string,\n output: CallLlmParams[\"output\"],\n): Promise<LlmResult> {\n let createAnthropic: (s: { apiKey: string }) => (m: string) => unknown;\n try {\n const mod = await import(\"@ai-sdk/anthropic\");\n createAnthropic = mod.createAnthropic as typeof createAnthropic;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@ai-sdk/anthropic\")) {\n throwProviderInstallError(\"@ai-sdk/anthropic\", \"Anthropic\");\n }\n throw error;\n }\n const { generateText } = await import(\"ai\");\n const anthropic = createAnthropic({ apiKey: config.apiKey });\n const model = anthropic(modelId);\n const genParams: Parameters<typeof generateText>[0] = {\n model: model as Parameters<typeof generateText>[0][\"model\"],\n prompt: userPrompt,\n ...(options.maxTokens !== undefined && {\n maxOutputTokens: options.maxTokens,\n }),\n temperature: options.temperature,\n };\n if (systemPrompt) genParams.system = systemPrompt;\n // Same option keys as callOpenAI; SDK passes through. Anthropic supports topP;\n // frequencyPenalty/presencePenalty may be unsupported (SDK may warn).\n if (options.topP !== undefined) genParams.topP = options.topP;\n if (options.frequencyPenalty !== undefined)\n genParams.frequencyPenalty = options.frequencyPenalty;\n if (options.presencePenalty !== undefined)\n genParams.presencePenalty = options.presencePenalty;\n const params = output !== undefined ? { ...genParams, output } : genParams;\n const result = await generateText(\n params as Parameters<typeof generateText>[0],\n );\n const out: LlmResult = { text: result.text ?? \"\", raw: result };\n if (result.usage) out.usage = toLlmUsage(result.usage);\n const parsed = getStructuredOutput(result as { output?: unknown });\n if (parsed !== undefined) out.output = parsed;\n return out;\n}\n\nasync function callGemini(\n config: import(\"../types.ts\").LlmModelConfigGemini,\n modelId: string,\n options: CallLlmParams[\"options\"],\n systemPrompt: string,\n userPrompt: string,\n output: CallLlmParams[\"output\"],\n): Promise<LlmResult> {\n let createGoogleGenerativeAI: (s: {\n apiKey: string;\n }) => (m: string) => unknown;\n try {\n const mod = await import(\"@ai-sdk/google\");\n createGoogleGenerativeAI =\n mod.createGoogleGenerativeAI as typeof createGoogleGenerativeAI;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@ai-sdk/google\")) {\n throwProviderInstallError(\"@ai-sdk/google\", \"Gemini\");\n }\n throw error;\n }\n const { generateText } = await import(\"ai\");\n const google = createGoogleGenerativeAI({ apiKey: config.apiKey });\n const model = google(modelId);\n const genParams: Parameters<typeof generateText>[0] = {\n model: model as Parameters<typeof generateText>[0][\"model\"],\n prompt: userPrompt,\n ...(options.maxTokens !== undefined && {\n maxOutputTokens: options.maxTokens,\n }),\n temperature: options.temperature,\n };\n if (systemPrompt) genParams.system = systemPrompt;\n // Same option keys as callOpenAI; SDK passes through. Gemini may not support\n // all (e.g. frequencyPenalty/presencePenalty); check result.warnings if needed.\n if (options.topP !== undefined) genParams.topP = options.topP;\n if (options.frequencyPenalty !== undefined)\n genParams.frequencyPenalty = options.frequencyPenalty;\n if (options.presencePenalty !== undefined)\n genParams.presencePenalty = options.presencePenalty;\n const params = output !== undefined ? { ...genParams, output } : genParams;\n const result = await generateText(\n params as Parameters<typeof generateText>[0],\n );\n const out: LlmResult = { text: result.text ?? \"\", raw: result };\n if (result.usage) out.usage = toLlmUsage(result.usage);\n const parsed = getStructuredOutput(result as { output?: unknown });\n if (parsed !== undefined) out.output = parsed;\n return out;\n}\n\nasync function callOpenRouter(\n config: import(\"../types.ts\").LlmModelConfigOpenRouter,\n modelId: string,\n options: CallLlmParams[\"options\"],\n systemPrompt: string,\n userPrompt: string,\n output: CallLlmParams[\"output\"],\n): Promise<LlmResult> {\n let createOpenRouter: (s: { apiKey: string }) => {\n chat: (id: string) => unknown;\n };\n try {\n const mod = await import(\"@openrouter/ai-sdk-provider\");\n createOpenRouter = mod.createOpenRouter as typeof createOpenRouter;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@openrouter/ai-sdk-provider\")) {\n throwProviderInstallError(\"@openrouter/ai-sdk-provider\", \"OpenRouter\");\n }\n throw error;\n }\n const { generateText } = await import(\"ai\");\n const openrouter = createOpenRouter({ apiKey: config.apiKey });\n const resolvedId = config.modelId ?? modelId;\n const rawModel = openrouter.chat(resolvedId);\n assertLanguageModelShape(rawModel, \"OpenRouter\", resolvedId);\n const model = rawModel as Parameters<typeof generateText>[0][\"model\"];\n const genParams: Parameters<typeof generateText>[0] = {\n model,\n prompt: userPrompt,\n ...(options.maxTokens !== undefined && {\n maxOutputTokens: options.maxTokens,\n }),\n temperature: options.temperature,\n };\n if (systemPrompt) genParams.system = systemPrompt;\n // Same option keys as callOpenAI. OpenRouter is OpenAI-compatible; typically supports all.\n if (options.topP !== undefined) genParams.topP = options.topP;\n if (options.frequencyPenalty !== undefined)\n genParams.frequencyPenalty = options.frequencyPenalty;\n if (options.presencePenalty !== undefined)\n genParams.presencePenalty = options.presencePenalty;\n const params = output !== undefined ? { ...genParams, output } : genParams;\n const result = await generateText(\n params as Parameters<typeof generateText>[0],\n );\n const out: LlmResult = { text: result.text ?? \"\", raw: result };\n if (result.usage) out.usage = toLlmUsage(result.usage);\n const parsed = getStructuredOutput(result as { output?: unknown });\n if (parsed !== undefined) out.output = parsed;\n return out;\n}\n\nasync function callOllama(\n config: import(\"../types.ts\").LlmModelConfigOllama,\n modelId: string,\n options: CallLlmParams[\"options\"],\n systemPrompt: string,\n userPrompt: string,\n output: CallLlmParams[\"output\"],\n): Promise<LlmResult> {\n let createOllama: (s: { baseURL?: string }) => (name: string) => unknown;\n try {\n const mod = await import(\"ollama-ai-provider-v2\");\n createOllama = mod.createOllama as typeof createOllama;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"ollama-ai-provider-v2\")) {\n throwProviderInstallError(\"ollama-ai-provider-v2\", \"Ollama\");\n }\n throw error;\n }\n const { generateText } = await import(\"ai\");\n const ollama = createOllama({\n baseURL: config.baseURL ?? PROVIDER_DEFAULTS.ollama.baseURL,\n });\n const name = config.modelId ?? modelId;\n const rawModel = ollama(name);\n assertLanguageModelShape(rawModel, \"Ollama\", name);\n const model = rawModel as Parameters<typeof generateText>[0][\"model\"];\n const genParams: Parameters<typeof generateText>[0] = {\n model,\n prompt: userPrompt,\n ...(options.maxTokens !== undefined && {\n maxOutputTokens: options.maxTokens,\n }),\n temperature: options.temperature,\n };\n if (systemPrompt) genParams.system = systemPrompt;\n // Same option keys as callOpenAI. Ollama supports top_p; frequencyPenalty/presencePenalty\n // may be unsupported (SDK may warn).\n if (options.topP !== undefined) genParams.topP = options.topP;\n if (options.frequencyPenalty !== undefined)\n genParams.frequencyPenalty = options.frequencyPenalty;\n if (options.presencePenalty !== undefined)\n genParams.presencePenalty = options.presencePenalty;\n const params = output !== undefined ? { ...genParams, output } : genParams;\n const result = await generateText(\n params as Parameters<typeof generateText>[0],\n );\n const out: LlmResult = { text: result.text ?? \"\", raw: result };\n if (result.usage) out.usage = toLlmUsage(result.usage);\n const parsed = getStructuredOutput(result as { output?: unknown });\n if (parsed !== undefined) out.output = parsed;\n return out;\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { formatSchemaIssues } from \"@routecraft/routecraft\";\nimport { Output, jsonSchema } from \"ai\";\n\n/**\n * Build an AI SDK output spec from a Standard Schema for provider-level\n * structured output (OpenAI response_format, Ollama format, etc.) and validation.\n *\n * The AI SDK accepts Zod directly in Output.object({ schema: z.object(...) }).\n * This package uses Standard Schema (per .standards/type-safety-and-schemas.md), so\n * it cannot depend on Zod. This helper bridges any Standard Schema (Zod, Valibot,\n * ArkType, etc.) by using the SDK’s lower-level jsonSchema(jsonSchemaObj, {\n * validate }): we get the JSON schema from ~standard.jsonSchema.output/.input\n * and use ~standard.validate as the validate callback. Callers can pass a Zod\n * schema (as Standard Schema), Valibot, or ArkType and get the same behavior.\n */\nexport function toAiOutputSpec(schema: StandardSchemaV1): unknown {\n const standard = (schema as unknown as Record<string, unknown>)[\n \"~standard\"\n ] as\n | {\n validate: (\n value: unknown,\n ) =>\n | { value?: unknown; issues?: unknown }\n | Promise<{ value?: unknown; issues?: unknown }>;\n jsonSchema?: {\n output?: (opts: { target: string }) => Record<string, unknown>;\n input?: (opts: { target: string }) => Record<string, unknown>;\n };\n }\n | undefined;\n\n if (!standard?.validate) {\n throw new Error(\n \"LLM outputSchema must be a StandardSchemaV1 with ~standard.validate\",\n );\n }\n\n const jsonSchemaObj =\n standard.jsonSchema?.output?.({ target: \"draft-2020-12\" }) ??\n standard.jsonSchema?.input?.({ target: \"draft-2020-12\" });\n\n if (!jsonSchemaObj || typeof jsonSchemaObj !== \"object\") {\n throw new Error(\n \"LLM outputSchema must expose ~standard.jsonSchema.output or .input for provider structured output\",\n );\n }\n\n function validate(\n value: unknown,\n ): { success: true; value: unknown } | { success: false; error: Error } {\n let result:\n | { value?: unknown; issues?: unknown }\n | Promise<{\n value?: unknown;\n issues?: unknown;\n }>;\n try {\n result = standard!.validate(value);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err : new Error(String(err)),\n };\n }\n if (result instanceof Promise) {\n return {\n success: false,\n error: new Error(\n \"Async output schema is not supported for LLM structured output\",\n ),\n };\n }\n const hasIssues =\n result.issues != null &&\n (Array.isArray(result.issues)\n ? result.issues.length > 0\n : typeof result.issues === \"object\" && result.issues !== null\n ? Object.keys(result.issues).length > 0\n : Boolean(result.issues));\n if (hasIssues) {\n return {\n success: false,\n error: new Error(formatSchemaIssues(result.issues)),\n };\n }\n return { success: true, value: result.value };\n }\n\n const aiSchema = jsonSchema(\n jsonSchemaObj as Parameters<typeof jsonSchema>[0],\n { validate },\n );\n return Output.object({ schema: aiSchema });\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { Exchange } from \"@routecraft/routecraft\";\n\n/**\n * Store key for plugin-registered providers (provider id -> LlmModelConfig).\n * @experimental\n */\nexport const ADAPTER_LLM_PROVIDERS = Symbol.for(\n \"routecraft.adapter.llm.providers\",\n);\n\n/**\n * Store key for context-level default LLM options.\n * @experimental\n */\nexport const ADAPTER_LLM_OPTIONS = Symbol.for(\"routecraft.adapter.llm.options\");\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [ADAPTER_LLM_PROVIDERS]: Map<string, LlmModelConfig>;\n [ADAPTER_LLM_OPTIONS]: Partial<LlmOptionsMerged>;\n }\n}\n\nexport type LlmProviderType =\n | \"openai\"\n | \"anthropic\"\n | \"openrouter\"\n | \"ollama\"\n | \"gemini\";\n\nexport interface LlmModelConfigOpenAI {\n provider: \"openai\";\n apiKey: string;\n baseURL?: string;\n}\n\nexport interface LlmModelConfigAnthropic {\n provider: \"anthropic\";\n apiKey: string;\n}\n\nexport interface LlmModelConfigOpenRouter {\n provider: \"openrouter\";\n apiKey: string;\n /** OpenRouter model id (e.g. anthropic/claude-3.5-sonnet). Defaults to the registered key. */\n modelId?: string;\n}\n\nexport interface LlmModelConfigOllama {\n provider: \"ollama\";\n /**\n * Ollama server URL. Optional: defaults to http://localhost:11434/api.\n * Only set when using a remote Ollama or custom port.\n */\n baseURL?: string;\n /**\n * Override model name sent to Ollama. Optional: defaults to the model\n * from the llm(\"provider:model\") call (the part after the colon).\n */\n modelId?: string;\n}\n\nexport interface LlmModelConfigGemini {\n provider: \"gemini\";\n apiKey: string;\n}\n\nexport type LlmModelConfig =\n | LlmModelConfigOpenAI\n | LlmModelConfigAnthropic\n | LlmModelConfigOpenRouter\n | LlmModelConfigOllama\n | LlmModelConfigGemini;\n\n/** Provider options for llmPlugin({ providers }). Key is the provider; no need to repeat provider in the value. */\nexport interface LlmOllamaProviderOptions {\n baseURL?: string;\n modelId?: string;\n}\nexport interface LlmOpenAIProviderOptions {\n apiKey: string;\n baseURL?: string;\n}\nexport interface LlmAnthropicProviderOptions {\n apiKey: string;\n}\nexport interface LlmOpenRouterProviderOptions {\n apiKey: string;\n modelId?: string;\n}\nexport interface LlmGeminiProviderOptions {\n apiKey: string;\n}\n\nexport interface LlmPluginProviders {\n ollama?: LlmOllamaProviderOptions;\n openai?: LlmOpenAIProviderOptions;\n anthropic?: LlmAnthropicProviderOptions;\n openrouter?: LlmOpenRouterProviderOptions;\n gemini?: LlmGeminiProviderOptions;\n}\n\n/** Map provider id → provider-specific options (for type-safe toModelConfig). */\nexport type LlmProviderOptionsMap = Required<LlmPluginProviders>;\n\n/** Resolve system or user prompt from exchange (string or function). */\nexport type LlmPromptSource =\n | string\n | ((exchange: Exchange<unknown>) => string);\n\nexport interface LlmOptions {\n systemPrompt?: LlmPromptSource;\n userPrompt?: LlmPromptSource;\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n frequencyPenalty?: number;\n presencePenalty?: number;\n /**\n * Optional output schema (Standard Schema). When set, the adapter requests\n * provider-level structured output and validates the result. Supported by\n * OpenAI (gpt-4o/mini) and Ollama; others may return JSON that is validated\n * after the call. On success, the parsed value is set on LlmResult.output.\n */\n outputSchema?: StandardSchemaV1;\n}\n\n/** Internal merged type for adapter and store. */\nexport type LlmOptionsMerged = Required<\n Pick<LlmOptions, \"temperature\" | \"maxTokens\">\n> &\n Omit<LlmOptions, \"temperature\" | \"maxTokens\">;\n\n/**\n * Token usage. Matches Vercel AI SDK LanguageModelUsage shape (inputTokens/outputTokens)\n * so result.usage can be used interchangeably with generateText() return value.\n */\nexport interface LlmUsage {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n}\n\n/**\n * LLM result shape aligned with Vercel AI SDK generateText() return value.\n * Same property names (text, output, usage) so code and docs transfer directly.\n */\nexport interface LlmResult {\n /** Generated text (raw string from the model). */\n text: string;\n /** Parsed structured output when outputSchema was set and validation succeeded. */\n output?: unknown;\n /** Token usage for the last step. Same shape as AI SDK usage. */\n usage?: LlmUsage;\n /** Full generateText() result for advanced use (debugging, response metadata). */\n raw?: unknown;\n}\n\n/**\n * When outputSchema S is provided to llm(), the result type narrows output to InferOutput<S>.\n * Used for type inference from llm(modelId, { outputSchema }) so body.output is typed downstream.\n */\nexport type LlmResultWithOutput<S extends StandardSchemaV1 | undefined> =\n S extends StandardSchemaV1\n ? Omit<LlmResult, \"output\"> & {\n output?: StandardSchemaV1.InferOutput<S>;\n }\n : LlmResult;\n\n/**\n * Recommended LLM model ids for autocomplete (chat/completion use cases).\n * Format: \"providerId:modelName\". Custom models are allowed via string.\n * Updated for 2026.\n */\nexport type LlmModelId =\n // OpenAI (2026: GPT-5.2, Codex, o1)\n | \"openai:gpt-5.2\"\n | \"openai:gpt-5.2-codex\"\n | \"openai:gpt-5\"\n | \"openai:gpt-5.1-chat-latest\"\n | \"openai:gpt-5-mini\"\n | \"openai:gpt-5-codex-mini\"\n | \"openai:gpt-4o\"\n | \"openai:gpt-4o-mini\"\n | \"openai:o1\"\n | \"openai:o1-mini\"\n // Anthropic (2026: Claude 4.6 / 4.5)\n | \"anthropic:claude-opus-4-6\"\n | \"anthropic:claude-sonnet-4-6\"\n | \"anthropic:claude-haiku-4-5\"\n // Ollama (common local models)\n | \"ollama:qwen3\"\n | \"ollama:llama3.2\"\n | \"ollama:llama3.3\"\n | \"ollama:mistral\"\n | \"ollama:gemma2\"\n | \"ollama:deepseek-r1\"\n | \"ollama:lfm2.5-thinking\"\n // OpenRouter (top open-weight / frontier: GLM, Kimi, Qwen, DeepSeek)\n | \"openrouter:z-ai/glm-5\"\n | \"openrouter:z-ai/glm-4.7\"\n | \"openrouter:moonshotai/kimi-k2-thinking\"\n | \"openrouter:qwen/qwen3.5-plus-02-15\"\n | \"openrouter:qwen/qwen3-next\"\n | \"openrouter:deepseek/deepseek-v3.2\"\n | \"openrouter:deepseek/deepseek-r1\"\n | \"openrouter:meta-llama/llama-3.3-70b-instruct\"\n // Gemini (2026: 2.5 + 3.x preview)\n | \"gemini:gemini-2.5-pro\"\n | \"gemini:gemini-2.5-flash\"\n | \"gemini:gemini-2.5-flash-lite\"\n | \"gemini:gemini-3.1-pro-preview\"\n | \"gemini:gemini-3-pro-preview\"\n | \"gemini:gemini-3-flash-preview\"\n // Other (custom models)\n | string;\n\nexport interface LlmPluginOptions {\n /**\n * Supported providers keyed by id. Only set options you need (defaults for url etc. apply).\n * Routes use llm(\"providerId:modelName\"), e.g. llm(\"ollama:lfm2.5-thinking\").\n */\n providers: LlmPluginProviders;\n /** Optional context-level default options (systemPrompt, temperature, etc.). */\n defaultOptions?: Partial<LlmOptionsMerged>;\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport {\n getExchangeContext,\n type CraftContext,\n type Destination,\n type Exchange,\n type MergedOptions,\n} from \"@routecraft/routecraft\";\nimport { callLlm } from \"./providers/index.ts\";\nimport { toAiOutputSpec } from \"./structured-output.ts\";\nimport type {\n LlmModelConfig,\n LlmOptions,\n LlmOptionsMerged,\n LlmPromptSource,\n LlmResultWithOutput,\n} from \"./types.ts\";\nimport { ADAPTER_LLM_OPTIONS, ADAPTER_LLM_PROVIDERS } from \"./types.ts\";\n\n/**\n * When the AI SDK doesn't set result.output (e.g. it threw on the getter), try to\n * parse result.text as JSON and validate with the output schema. Returns the\n * parsed value or undefined. Handles both sync and async Standard Schema validate().\n */\nasync function parseStructuredTextFallback(\n text: string,\n schema: StandardSchemaV1,\n): Promise<unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return undefined;\n }\n const standard = (schema as unknown as Record<string, unknown>)[\n \"~standard\"\n ] as\n | {\n validate: (\n value: unknown,\n ) =>\n | { value?: unknown; issues?: unknown }\n | Promise<{ value?: unknown; issues?: unknown }>;\n }\n | undefined;\n if (!standard?.validate) return undefined;\n let result = standard.validate(parsed);\n if (result instanceof Promise) result = await result;\n if (\n result &&\n typeof result === \"object\" &&\n \"issues\" in result &&\n result.issues\n )\n return undefined;\n return result && typeof result === \"object\" && \"value\" in result\n ? result.value\n : undefined;\n}\n\nconst DEFAULT_TEMPERATURE = 0;\nconst DEFAULT_MAX_TOKENS = 1024;\n\nfunction resolvePrompt(\n source: LlmPromptSource | undefined,\n exchange: Exchange<unknown>,\n): string {\n if (source === undefined || source === \"\") return \"\";\n if (typeof source === \"function\") return source(exchange);\n return source;\n}\n\nfunction resolveUserPromptDefault(exchange: Exchange<unknown>): string {\n const body = exchange.body;\n if (typeof body === \"string\") return body;\n if (body === null || body === undefined) return \"\";\n if (typeof body === \"object\") return JSON.stringify(body);\n return String(body);\n}\n\n/** Format: \"providerId:modelName\", e.g. \"ollama:lfm2.5-thinking\". */\nfunction parseProviderModel(id: string): {\n providerId: string;\n modelName: string;\n} {\n const colon = id.indexOf(\":\");\n if (colon < 1 || colon === id.length - 1) {\n throw new Error(\n `LLM adapter: model id must be \"providerId:modelName\" (e.g. ollama:lfm2.5-thinking). Got: \"${id}\"`,\n );\n }\n return {\n providerId: id.slice(0, colon),\n modelName: id.slice(colon + 1),\n };\n}\n\nfunction resolveProviderAndModel(\n modelId: string,\n context: CraftContext | undefined,\n): { config: LlmModelConfig; modelName: string } {\n if (!context) {\n throw new Error(\n `LLM adapter: model id \"${modelId}\" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store \"${ADAPTER_LLM_PROVIDERS.description}\" can be read.`,\n );\n }\n const store = context.getStore(\n ADAPTER_LLM_PROVIDERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, LlmModelConfig> | undefined;\n if (!store) {\n throw new Error(\n `LLM provider not found: no providers registered. Add llmPlugin({ providers: { ollama: { provider: \"ollama\" }, ... } }) to your config.`,\n );\n }\n const { providerId, modelName } = parseProviderModel(modelId);\n const config = store.get(providerId);\n if (!config) {\n throw new Error(\n `LLM provider \"${providerId}\" not found. Register it with llmPlugin({ providers: { \"${providerId}\": { provider, apiKey?, baseURL? } } }).`,\n );\n }\n return { config, modelName };\n}\n\n/**\n * LLM destination adapter. Expects model id as \"providerId:modelName\" (e.g. ollama:lfm2.5-thinking),\n * resolves the provider from the plugin store, merges options, and calls the provider with the model name.\n * Use with .enrich(llm(\"providerId:modelName\", options)) or .to(llm(...)).\n *\n * @experimental\n * @template S - Output schema type when outputSchema is provided; narrows result.output for downstream typing.\n */\nexport class LlmDestinationAdapter<\n S extends StandardSchemaV1 | undefined = undefined,\n>\n implements\n Destination<unknown, LlmResultWithOutput<S>>,\n MergedOptions<LlmOptionsMerged>\n{\n readonly adapterId = \"routecraft.adapter.llm\";\n\n constructor(\n private readonly modelId: string,\n options: Partial<LlmOptions> = {},\n ) {\n this.options = options as Partial<LlmOptionsMerged>;\n }\n\n public options: Partial<LlmOptionsMerged>;\n\n mergedOptions(context: CraftContext): LlmOptionsMerged {\n const store = context.getStore(\n ADAPTER_LLM_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Partial<LlmOptionsMerged> | undefined;\n return {\n temperature: DEFAULT_TEMPERATURE,\n maxTokens: DEFAULT_MAX_TOKENS,\n ...store,\n ...this.options,\n } as LlmOptionsMerged;\n }\n\n async send(exchange: Exchange<unknown>): Promise<LlmResultWithOutput<S>> {\n const context = getExchangeContext(exchange);\n const { config, modelName } = resolveProviderAndModel(\n this.modelId,\n context,\n );\n const merged = this.mergedOptions(context!);\n\n const systemPrompt = resolvePrompt(merged.systemPrompt, exchange);\n const userPrompt =\n resolvePrompt(merged.userPrompt, exchange) ||\n resolveUserPromptDefault(exchange);\n\n const opts: Parameters<typeof callLlm>[0][\"options\"] = {\n temperature: merged.temperature,\n maxTokens: merged.maxTokens,\n };\n if (merged.topP !== undefined) opts.topP = merged.topP;\n if (merged.frequencyPenalty !== undefined)\n opts.frequencyPenalty = merged.frequencyPenalty;\n if (merged.presencePenalty !== undefined)\n opts.presencePenalty = merged.presencePenalty;\n\n const output =\n merged.outputSchema !== undefined\n ? toAiOutputSpec(merged.outputSchema)\n : undefined;\n\n const result = await callLlm({\n config,\n modelId: modelName,\n options: opts,\n systemPrompt,\n userPrompt,\n output,\n });\n\n if (\n result.output === undefined &&\n result.text &&\n merged.outputSchema !== undefined\n ) {\n const fallback = await parseStructuredTextFallback(\n result.text,\n merged.outputSchema,\n );\n if (fallback !== undefined) result.output = fallback;\n }\n\n return result as LlmResultWithOutput<S>;\n }\n\n /**\n * Extract metadata from LLM result for observability.\n * Includes model, provider, and token usage.\n */\n getMetadata(result: unknown): Record<string, unknown> {\n const llmResult = result as LlmResultWithOutput<S>;\n const { providerId } = parseProviderModel(this.modelId);\n\n const metadata: Record<string, unknown> = {\n model: this.modelId,\n provider: providerId,\n };\n\n if (llmResult.usage) {\n if (llmResult.usage[\"inputTokens\"] !== undefined) {\n metadata[\"inputTokens\"] = llmResult.usage[\"inputTokens\"];\n }\n if (llmResult.usage[\"outputTokens\"] !== undefined) {\n metadata[\"outputTokens\"] = llmResult.usage[\"outputTokens\"];\n }\n }\n\n return metadata;\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { Destination } from \"@routecraft/routecraft\";\nimport { LlmDestinationAdapter } from \"./destination.ts\";\nimport type { LlmOptions, LlmResultWithOutput } from \"./types.ts\";\nimport type { RegisteredLlmModelId } from \"../registry.ts\";\n\n/**\n * Creates an LLM destination that calls a provider with a model. Use with .enrich() or .to().\n * Pass model id as \"providerId:modelName\" (e.g. ollama:lfm2.5-thinking). The provider must be\n * registered via llmPlugin({ providers: { ollama: { provider: \"ollama\" }, ... } }).\n * When options.outputSchema is provided, the result type narrows so body.output is typed downstream.\n *\n * @experimental\n * @param modelId - \"providerId:modelName\"; the provider is resolved from the plugin, the model name is sent to the provider.\n * @param options - Optional overrides (systemPrompt, userPrompt, temperature, maxTokens, outputSchema, etc.). User prompt defaults to exchange.body.\n */\nexport function llm<S extends StandardSchemaV1 | undefined = undefined>(\n modelId: RegisteredLlmModelId,\n options?: Partial<LlmOptions> & { outputSchema?: S },\n): Destination<unknown, LlmResultWithOutput<S>> {\n return new LlmDestinationAdapter<S>(modelId, options);\n}\n","import type { LlmPluginOptions, LlmProviderType } from \"./types.ts\";\n\nconst PROVIDERS: LlmProviderType[] = [\n \"openai\",\n \"anthropic\",\n \"openrouter\",\n \"ollama\",\n \"gemini\",\n];\n\nfunction isProvider(s: string): s is LlmProviderType {\n return (PROVIDERS as string[]).includes(s);\n}\n\n/**\n * Validates LLM plugin options at apply time.\n * Key is the provider; value is options for that provider (no provider field).\n */\nexport function validateLlmPluginOptions(options: LlmPluginOptions): void {\n if (!options || typeof options !== \"object\") {\n throw new TypeError(\"llmPlugin: options must be an object\");\n }\n if (!options.providers || typeof options.providers !== \"object\") {\n throw new TypeError(\n \"llmPlugin: options.providers must be an object (record of provider id → options)\",\n );\n }\n for (const [providerId, opts] of Object.entries(options.providers)) {\n if (opts === undefined) continue;\n if (!opts || typeof opts !== \"object\") {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"] must be an object`,\n );\n }\n if (!isProvider(providerId)) {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"] is not a supported provider. Supported: ${PROVIDERS.join(\", \")}`,\n );\n }\n switch (providerId) {\n case \"openai\":\n case \"anthropic\":\n case \"openrouter\":\n case \"gemini\":\n if (\n typeof (opts as { apiKey?: string }).apiKey !== \"string\" ||\n !(opts as { apiKey: string }).apiKey.trim()\n ) {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"].apiKey is required`,\n );\n }\n break;\n case \"ollama\":\n if (\n (opts as { baseURL?: string }).baseURL !== undefined &&\n typeof (opts as { baseURL?: string }).baseURL !== \"string\"\n ) {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"].baseURL must be a string when provided`,\n );\n }\n if (\n (opts as { modelId?: string }).modelId !== undefined &&\n (typeof (opts as { modelId?: string }).modelId !== \"string\" ||\n !(opts as { modelId: string }).modelId.trim())\n ) {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"].modelId must be a non-empty string when provided`,\n );\n }\n break;\n }\n }\n if (\n options.defaultOptions !== undefined &&\n (typeof options.defaultOptions !== \"object\" ||\n options.defaultOptions === null)\n ) {\n throw new TypeError(\n \"llmPlugin: defaultOptions must be an object when provided\",\n );\n }\n}\n","import type { CraftContext, CraftPlugin } from \"@routecraft/routecraft\";\nimport { ADAPTER_LLM_OPTIONS, ADAPTER_LLM_PROVIDERS } from \"./types.ts\";\nimport type {\n LlmModelConfig,\n LlmPluginOptions,\n LlmProviderOptionsMap,\n} from \"./types.ts\";\nimport { validateLlmPluginOptions } from \"./validate-options.ts\";\n\nconst PROVIDER_IDS = [\n \"openai\",\n \"anthropic\",\n \"openrouter\",\n \"ollama\",\n \"gemini\",\n] as const satisfies readonly LlmModelConfig[\"provider\"][];\n\n/** Normalize provider options to full LlmModelConfig (add provider field from key). */\nfunction toModelConfig<P extends LlmModelConfig[\"provider\"]>(\n providerId: P,\n opts: LlmProviderOptionsMap[P],\n): Extract<LlmModelConfig, { provider: P }> {\n return { provider: providerId, ...opts } as Extract<\n LlmModelConfig,\n { provider: P }\n >;\n}\n\n/**\n * LLM plugin: config-only helper (no lifecycle hooks). Registers providers and optional\n * default options in the context store so routes can use llm(\"providerId:modelName\", options),\n * e.g. llm(\"ollama:lfm2.5-thinking\"). Key is the provider; only set options you need.\n *\n * Advanced users can set the store directly: context.setStore(ADAPTER_LLM_PROVIDERS, map)\n * and context.setStore(ADAPTER_LLM_OPTIONS, partialOptions) without using this plugin.\n *\n * @experimental\n */\nexport function llmPlugin(\n options: LlmPluginOptions = { providers: {} },\n): CraftPlugin {\n validateLlmPluginOptions(options);\n\n return {\n apply(ctx: CraftContext) {\n const map = new Map<string, LlmModelConfig>();\n for (const providerId of PROVIDER_IDS) {\n const opts = options.providers[providerId];\n if (opts !== undefined)\n map.set(providerId, toModelConfig(providerId, opts));\n }\n ctx.setStore(\n ADAPTER_LLM_PROVIDERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n map,\n );\n if (\n options.defaultOptions &&\n Object.keys(options.defaultOptions).length > 0\n ) {\n ctx.setStore(\n ADAPTER_LLM_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n options.defaultOptions,\n );\n }\n },\n };\n}\n","import type {\n DirectRouteMetadata,\n DirectServerOptions,\n Exchange,\n} from \"@routecraft/routecraft\";\nimport type {\n OAuthPrincipal,\n Principal,\n ValidatorAuthOptions,\n} from \"@routecraft/routecraft\";\nimport type { McpToolRegistry } from \"./tool-registry.ts\";\n\n/**\n * Store key set by mcpPlugin() when applied; routes using .from(mcp(...)) require it.\n * @internal\n */\nexport const MCP_PLUGIN_REGISTERED = Symbol.for(\n \"routecraft.mcp.plugin.registered\",\n);\n\n/**\n * Store key for named remote MCP servers (mcpPlugin({ clients })). Used by McpClient to resolve serverId.\n * @internal\n */\nexport const ADAPTER_MCP_CLIENT_SERVERS = Symbol.for(\n \"routecraft.mcp.client.servers\",\n);\n\n/**\n * Store key for the unified MCP tool registry. Used by agent adapter for tool discovery.\n * @internal\n */\nexport const MCP_TOOL_REGISTRY = Symbol.for(\"routecraft.mcp.tool.registry\");\n\n/**\n * Store key for stdio client managers. Used by destination adapter to call tools on stdio clients.\n * @internal\n */\nexport const MCP_STDIO_MANAGERS = Symbol.for(\"routecraft.mcp.stdio.managers\");\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [MCP_PLUGIN_REGISTERED]: boolean;\n [ADAPTER_MCP_CLIENT_SERVERS]: Map<\n string,\n McpClientHttpConfig | McpClientStdioConfig | string\n >;\n [MCP_TOOL_REGISTRY]: McpToolRegistry;\n [MCP_STDIO_MANAGERS]: Map<\n string,\n {\n callTool(name: string, args: Record<string, unknown>): Promise<unknown>;\n }\n >;\n }\n\n interface RoutecraftHeaders {\n /** The MCP tool name that triggered this exchange. */\n \"routecraft.mcp.tool\"?: string;\n /** The MCP session identifier. */\n \"routecraft.mcp.session\"?: string;\n }\n}\n\n/**\n * HTTP client config for a remote MCP server (Streamable HTTP).\n * Used in mcpPlugin({ clients: { name: config } }).\n */\nexport interface McpClientHttpConfig {\n transport?: \"streamable-http\";\n url: string;\n /** Auth credentials sent on every request to this server. */\n auth?: McpClientAuthOptions;\n}\n\n/**\n * Stdio client config for a local MCP server subprocess.\n * Used in mcpPlugin({ clients: { name: config } }).\n * The plugin spawns the process, manages its lifecycle, and auto-restarts on crash.\n */\nexport interface McpClientStdioConfig {\n transport: \"stdio\";\n /** The executable to run (e.g. \"npx\", \"node\", \"python\"). */\n command: string;\n /** Command line arguments to pass to the executable. */\n args?: string[];\n /** Environment variables for the child process. Defaults to a safe subset of the parent env. */\n env?: Record<string, string>;\n /** Working directory for the child process. Defaults to the current working directory. */\n cwd?: string;\n}\n\n/** Union of client configs accepted by mcpPlugin({ clients }). */\nexport type McpClientServerConfig = McpClientHttpConfig | McpClientStdioConfig;\n\n/**\n * Header keys set on exchanges created by the MCP server.\n * Use these with `exchange.headers[McpHeadersKeys.AUTH_SUBJECT]` for type-safe access.\n *\n * @example\n * ```ts\n * import { McpHeadersKeys } from '@routecraft/ai'\n *\n * .process((ex) => {\n * const user = ex.headers[McpHeadersKeys.AUTH_SUBJECT]\n * const tool = ex.headers[McpHeadersKeys.TOOL]\n * })\n * ```\n */\n// The `routecraft.auth.*` key strings below mirror the RoutecraftHeaders\n// augmentation in `@routecraft/routecraft/src/auth/types.ts`. Any rename or\n// addition must be kept in sync in both places.\nexport enum McpHeadersKeys {\n /** The MCP tool name that triggered this exchange. */\n TOOL = \"routecraft.mcp.tool\",\n /** The MCP session identifier. */\n SESSION = \"routecraft.mcp.session\",\n /** Authenticated subject (from Principal). */\n AUTH_SUBJECT = \"routecraft.auth.subject\",\n /** Authentication scheme used. */\n AUTH_SCHEME = \"routecraft.auth.scheme\",\n /** Authentication kind (jwt | jwks | oauth | custom). */\n AUTH_KIND = \"routecraft.auth.kind\",\n /** Roles assigned to the authenticated principal. */\n AUTH_ROLES = \"routecraft.auth.roles\",\n /** Scopes granted to the authenticated principal. */\n AUTH_SCOPES = \"routecraft.auth.scopes\",\n /** Email of the authenticated principal. */\n AUTH_EMAIL = \"routecraft.auth.email\",\n /** Display name of the authenticated principal. */\n AUTH_NAME = \"routecraft.auth.name\",\n /** Token issuer (JWT `iss`). */\n AUTH_ISSUER = \"routecraft.auth.issuer\",\n /** Intended audience (JWT `aud`). */\n AUTH_AUDIENCE = \"routecraft.auth.audience\",\n /** OAuth client ID (distinct from subject). */\n AUTH_CLIENT_ID = \"routecraft.auth.client_id\",\n}\n\n/**\n * OAuth client info supplied to the `oauth()` factory via the `client` option.\n * Mirrors the MCP SDK's `OAuthClientInformationFull` with only the fields routecraft needs.\n *\n * Field names use snake_case to match the OAuth 2.0 Dynamic Client Registration\n * specification (RFC 7591) and the MCP SDK's `OAuthClientInformationFull`.\n *\n * @experimental\n */\nexport interface OAuthClientInfo {\n /** The client identifier. */\n client_id: string;\n /** Allowed redirect URIs for authorization code flow. */\n redirect_uris: string[];\n /** Human-readable client name. */\n client_name?: string;\n /** Client secret (for confidential clients). */\n client_secret?: string;\n}\n\n/**\n * Endpoint URLs for the upstream OAuth provider (used by the proxy).\n *\n * @experimental\n */\nexport interface OAuthProxyEndpoints {\n /** Authorization endpoint URL. */\n authorizationUrl: string;\n /** Token endpoint URL. */\n tokenUrl: string;\n /** Token revocation endpoint URL. */\n revocationUrl?: string;\n /** Dynamic client registration endpoint URL. */\n registrationUrl?: string;\n}\n\n/**\n * OAuth provider auth: full OAuth 2.1 server flow with proxy to upstream IdP.\n * Mounts discovery, authorization, token, and revocation endpoints alongside `/mcp`.\n * Uses the MCP SDK's `ProxyOAuthServerProvider` and `mcpAuthRouter` internally.\n *\n * @experimental\n */\nexport interface OAuthAuthOptions {\n /** Discriminant for the union. Always `\"oauth\"`. */\n provider: \"oauth\";\n /**\n * Issuer URL for OAuth metadata discovery (the MCP server's own issuer).\n * Must be HTTPS in production. Renamed from `issuerUrl` to disambiguate from\n * the IdP issuer inside the `verify` config.\n */\n resourceIssuerUrl: string | URL;\n /** Base URL for OAuth endpoints (defaults to resourceIssuerUrl). */\n baseUrl?: string | URL;\n /** Upstream OAuth provider endpoints to proxy. */\n endpoints: OAuthProxyEndpoints;\n /**\n * Verify an access token and return a populated {@link OAuthPrincipal}.\n * Called on every authenticated request to `/mcp`.\n *\n * The returned principal flows through to route exchanges as\n * `routecraft.auth.*` headers. `expiresAt` is part of the type contract\n * because the MCP SDK's bearer middleware requires it.\n */\n verifyAccessToken: (token: string) => Promise<OAuthPrincipal>;\n /**\n * Look up a registered OAuth client by ID.\n * Return `undefined` to reject the client.\n */\n getClient: (clientId: string) => Promise<OAuthClientInfo | undefined>;\n /** OAuth scopes the server advertises as supported. */\n scopesSupported?: string[];\n /** Scopes required on every request to `/mcp`. */\n requiredScopes?: string[];\n /** URL to service documentation (included in OAuth metadata). */\n serviceDocumentationUrl?: string | URL;\n /** Human-readable resource name (included in OAuth metadata). */\n resourceName?: string;\n}\n\n/**\n * Authentication options for the MCP HTTP server.\n * Only applies when `transport` is `\"http\"`. Ignored for stdio.\n *\n * Two strategies are supported:\n * - `Validator`: simple bearer token check via `jwt()` / `jwks()` / or custom function.\n * - `OAuth`: full OAuth 2.1 server flow via `oauth()`, proxying to an upstream IdP.\n *\n * @experimental\n */\nexport type McpHttpAuthOptions = ValidatorAuthOptions | OAuthAuthOptions;\n\n/**\n * Type guard: returns `true` when auth is configured for OAuth provider mode.\n */\nexport function isOAuthAuth(\n auth: McpHttpAuthOptions,\n): auth is OAuthAuthOptions {\n return \"provider\" in auth && auth.provider === \"oauth\";\n}\n\n/**\n * A function that provides a bearer token for outbound requests.\n * Called on every request; may be synchronous or asynchronous.\n * Useful for dynamic tokens (JWT refresh, rotating API keys, etc.).\n *\n * @experimental\n */\nexport type McpClientTokenProvider = () => string | Promise<string>;\n\n/**\n * Auth config for an outbound MCP HTTP client connection.\n * Passed as request headers on every connection to the remote server.\n *\n * @experimental\n */\nexport interface McpClientAuthOptions {\n /**\n * Bearer token(s) or provider for the `Authorization` header.\n * Builds `Authorization: Bearer <token>`.\n *\n * - `string` -- single static token.\n * - `string[]` -- array of tokens; one is selected per request (round-robin).\n * - `() => string | Promise<string>` -- called per request for dynamic tokens.\n */\n token?: string | string[] | McpClientTokenProvider;\n /**\n * Additional headers to include on every request to the remote server.\n * If `Authorization` is set here, it overrides `token`.\n */\n headers?: Record<string, string>;\n}\n\n/**\n * Options for the MCP plugin (mcpPlugin).\n * One plugin per adapter: this is the single options type for the MCP plugin.\n */\nexport interface McpPluginOptions {\n /** Server name in MCP protocol handshake. Default: \"routecraft\" */\n name?: string;\n\n /** Server version. Default: \"1.0.0\" */\n version?: string;\n\n /** Transport mode for MCP server. Default: \"stdio\" */\n transport?: \"stdio\" | \"http\";\n\n /** Port for the streamable-http MCP server. Default: 3001 (only used with transport: \"http\") */\n port?: number;\n\n /** Host to bind to. Default: \"localhost\" (only used with transport: \"http\") */\n host?: string;\n\n /**\n * Authentication for the HTTP transport. When set, every request to `/mcp` must\n * include a valid `Authorization: Bearer <token>` header. Ignored for stdio.\n *\n * @example\n * ```ts\n * import { jwt } from \"@routecraft/ai\";\n * auth: jwt({ secret: process.env.JWT_SECRET! })\n * ```\n */\n auth?: McpHttpAuthOptions;\n\n /**\n * Filter which tools to expose. Default: all mcp() routes.\n * Can be an array of endpoint names or a filter function.\n */\n tools?: string[] | ((meta: DirectRouteMetadata) => boolean);\n\n /**\n * Named remote MCP servers for .to(mcp(\"name:tool\")).\n * Keys are server names; values are HTTP or stdio config.\n * Stdio clients are managed as subprocesses with auto-restart.\n * HTTP clients are used for ephemeral tool calls.\n */\n clients?: Record<string, McpClientHttpConfig | McpClientStdioConfig>;\n\n /**\n * Max auto-restart attempts for stdio clients before giving up.\n * Applies to all stdio clients. Default: 5.\n */\n maxRestarts?: number;\n\n /**\n * Base delay in ms before the first restart attempt.\n * Subsequent attempts use exponential backoff. Default: 1000.\n */\n restartDelayMs?: number;\n\n /**\n * Multiplier for exponential backoff between restart attempts.\n * Delay = restartDelayMs * (restartBackoffMultiplier ^ restartCount). Default: 2.\n */\n restartBackoffMultiplier?: number;\n\n /**\n * Interval in ms to re-list tools from HTTP clients.\n * Set to 0 to disable periodic refresh. Default: 60000 (60s).\n */\n toolRefreshIntervalMs?: number;\n}\n\n/**\n * MCP tool annotations describing tool behavior to clients.\n * All properties are hints; clients should not rely on them for correctness or safety.\n *\n * Mirrors the MCP specification (2025-03-26) `ToolAnnotations` shape.\n *\n * @see https://modelcontextprotocol.io/specification/2025-03-26/server/tools#annotations\n */\nexport interface McpToolAnnotations {\n /** Human-readable title for the tool (used for display in UIs). */\n title?: string;\n /** If true, the tool does not modify any state (default assumed false by clients). */\n readOnlyHint?: boolean;\n /** If true, the tool may perform destructive operations (default assumed true by clients). */\n destructiveHint?: boolean;\n /** If true, calling the tool repeatedly with the same args has no additional effect (default assumed false by clients). */\n idempotentHint?: boolean;\n /** If true, the tool may interact with the \"open world\" (external systems, network, etc.) (default assumed true by clients). */\n openWorldHint?: boolean;\n}\n\n/**\n * Options for mcp() when used as a server in .from().\n * Description is required for AI/MCP discoverability.\n */\nexport interface McpServerOptions extends DirectServerOptions {\n /** Human-readable description (required for MCP tools). */\n description: string;\n\n /**\n * MCP tool annotations describing behavior hints (read-only, destructive, etc.).\n * Passed to MCP clients in the tool listing response.\n *\n * @example\n * ```ts\n * .from(mcp(\"list-users\", {\n * description: \"List all users\",\n * annotations: { readOnlyHint: true, destructiveHint: false },\n * }))\n * ```\n */\n annotations?: McpToolAnnotations;\n}\n\nexport type McpOptions = McpServerOptions;\n\n/**\n * Extracts MCP tool arguments from an exchange. Default implementation uses exchange.body.\n */\nexport type McpArgsExtractor = (\n exchange: Exchange<unknown>,\n) => Record<string, unknown>;\n\n/**\n * Options for mcp() when used as a Client in .to() to call a remote MCP server.\n * Provide either url (inline HTTP) or serverId (from plugin/store); tool is required.\n *\n * Supported transports:\n * - **HTTP:** use `url` for an inline endpoint or `serverId` for a named backend.\n * - **Stdio:** use `serverId` referencing a stdio client from mcpPlugin({ clients }).\n * The destination adapter resolves the manager from the context store and calls\n * tools directly on the subprocess -- no HTTP involved.\n */\nexport interface McpClientOptions {\n /** URL of the remote MCP server (HTTP/HTTPS only). Omit when using serverId. */\n url?: string;\n /** Tool name to invoke. If omitted, exchange body may specify it or a default applies. */\n tool?: string;\n /** Server id from context store; resolved to URL at runtime. Use when URL is registered via mcpPlugin({ clients }). */\n serverId?: string;\n /**\n * Extract tool arguments from the exchange. Receives the full exchange.\n * Default: body as object -> use as args; otherwise { input: body }.\n */\n args?: McpArgsExtractor;\n /**\n * Auth credentials for the outbound HTTP connection.\n * When using `serverId`, auth flows automatically from `mcpPlugin({ clients })`\n * so this field is rarely needed. Use it to override registered auth or to\n * supply credentials when using inline `url`.\n */\n auth?: McpClientAuthOptions;\n}\n\n/**\n * Represents a tool exposed via MCP\n */\nexport interface McpTool {\n name: string;\n description?: string;\n inputSchema: {\n type: \"object\";\n properties?: Record<string, unknown>;\n required?: string[];\n [key: string]: unknown;\n };\n /** MCP tool annotations (behavior hints) reported by the server. */\n annotations?: McpToolAnnotations;\n}\n\n/**\n * A tool entry in the unified MCP tool registry.\n * Combines local mcp() route tools and remote client tools (stdio and HTTP).\n */\nexport interface McpToolRegistryEntry {\n /** Tool name (unique within a source, may collide across sources). */\n name: string;\n /** Human-readable description of the tool. */\n description?: string;\n /** JSON Schema for tool input. */\n inputSchema: Record<string, unknown>;\n /** Source server ID (e.g. a stdio/HTTP client name). */\n source: string;\n /**\n * Transport type of the source. stdio/http are populated automatically by mcpPlugin.\n * \"local\" is reserved for callers who manually register tools with local provenance.\n */\n transport: \"stdio\" | \"http\" | \"local\";\n /** MCP tool annotations (behavior hints). */\n annotations?: McpToolAnnotations;\n}\n\n/**\n * MCP tool call result\n */\nexport interface McpToolResult {\n content: Array<{\n type: \"text\" | \"image\" | \"resource\";\n text?: string;\n data?: string;\n mimeType?: string;\n }>;\n isError?: boolean;\n}\n\n// Re-export Principal for convenience so consumers don't have to import from core.\nexport type { Principal };\n","/**\n * Brand symbol for MCP adapter type checking.\n * Used internally to identify MCP adapters.\n * @experimental\n */\nexport const BRAND_MCP_ADAPTER = Symbol.for(\"routecraft.mcp.adapter\");\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport {\n direct,\n rcError,\n type CraftContext,\n type Exchange,\n type ExchangeHeaders,\n type Source,\n} from \"@routecraft/routecraft\";\nimport { MCP_PLUGIN_REGISTERED, type McpServerOptions } from \"../../types.ts\";\nimport type { McpMessage } from \"./types.ts\";\nimport { BRAND_MCP_ADAPTER } from \"./shared.ts\";\n\n/**\n * McpSourceAdapter implements the Source interface for the MCP adapter.\n *\n * This adapter is used when mcp() is called with two arguments:\n * - `mcp(endpoint, options)` where options contains a description (required for MCP)\n *\n * It delegates to the direct() adapter internally after validating the MCP plugin is registered.\n * The MCP plugin will expose these routes as tools via the MCP protocol.\n */\nexport class McpSourceAdapter<\n S extends StandardSchemaV1 | undefined = undefined,\n> implements Source<McpMessage<S>> {\n readonly adapterId: string = \"routecraft.adapter.mcp\";\n\n private endpoint: string;\n private options: McpServerOptions & { schema?: S };\n\n constructor(endpoint: string, options: McpServerOptions & { schema?: S }) {\n (this as unknown as Record<symbol, boolean>)[BRAND_MCP_ADAPTER] = true;\n\n // Validate endpoint and options\n if (typeof endpoint !== \"string\") {\n throw rcError(\"RC5003\", undefined, {\n message: \"Dynamic endpoints cannot be used as source\",\n suggestion:\n \"Use a static string endpoint for source: .from(mcp('endpoint', options)).\",\n });\n }\n\n if (\"url\" in options || \"serverId\" in options) {\n throw rcError(\"RC5003\", undefined, {\n message:\n \"mcp() with url or serverId must be used as destination: .to(mcp({ url, tool }))\",\n suggestion:\n \"Use .to(mcp({ url: '...', tool: '...' })) to call a remote MCP server.\",\n });\n }\n\n if (\n \"args\" in options &&\n (options as { args?: unknown }).args !== undefined &&\n !(\"description\" in options)\n ) {\n throw rcError(\"RC5003\", undefined, {\n message:\n \"mcp(endpoint, { args }) is for client usage with a 'server:tool' target, not for defining a source\",\n suggestion:\n \"Use .to(mcp('server:tool', { args })) to call a remote tool, or .from(mcp('endpoint', { description: '...' })) to define a source.\",\n });\n }\n\n if (\n !(\"description\" in options) ||\n typeof options.description !== \"string\"\n ) {\n throw rcError(\"RC5003\", undefined, {\n message:\n \"mcp(endpoint, options) as source requires options.description\",\n suggestion:\n \"Use .from(mcp('endpoint', { description: '...' })) to define a source.\",\n });\n }\n\n this.endpoint = endpoint;\n this.options = options;\n }\n\n async subscribe(\n context: CraftContext,\n handler: (\n message: McpMessage<S>,\n headers?: ExchangeHeaders,\n ) => Promise<Exchange>,\n abortController: AbortController,\n onReady?: () => void,\n ): Promise<void> {\n // Verify MCP plugin is registered\n const registered = context.getStore(\n MCP_PLUGIN_REGISTERED as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as boolean | undefined;\n if (registered !== true) {\n throw new Error(\n \"MCP plugin required: routes using .from(mcp(...)) require the MCP plugin. Add mcpPlugin() to your config: plugins: [mcpPlugin()].\",\n );\n }\n\n // Delegate to direct adapter\n const directAdapter = direct(this.endpoint, this.options);\n return directAdapter.subscribe(context, handler, abortController, onReady);\n }\n}\n","/**\n * Extract content from an MCP tool response.\n *\n * - Single text item: returns the string directly for convenience.\n * - Multiple items or non-text items: returns the full content array so\n * callers can inspect type/text/data on each entry.\n * - No content: returns the raw response object.\n */\nexport function extractContent(\n response: {\n content?: Array<{ type: string; text?: string; data?: string }>;\n } | null,\n): unknown {\n const content = response?.content;\n if (!Array.isArray(content) || content.length === 0) return response;\n\n // Single text entry: return the string for backward compatibility\n if (content.length === 1) {\n const item = content[0];\n if (item.type === \"text\" && typeof item.text === \"string\") return item.text;\n if (typeof item.data === \"string\") return item.data;\n }\n\n // Multiple items or non-text: return the full array\n return content;\n}\n","import type { McpClientAuthOptions } from \"./types.ts\";\n\n/** Round-robin index for array tokens, keyed by the array reference. */\nconst rrIndexes = new WeakMap<string[], number>();\n\n/**\n * Resolve the raw token value from the various accepted forms.\n * @internal\n */\nasync function resolveToken(\n token: NonNullable<McpClientAuthOptions[\"token\"]>,\n): Promise<string> {\n if (typeof token === \"function\") {\n return token();\n }\n if (Array.isArray(token)) {\n if (token.length === 0) {\n throw new Error(\"McpClientAuthOptions.token array must not be empty\");\n }\n const idx = (rrIndexes.get(token) ?? 0) % token.length;\n rrIndexes.set(token, idx + 1);\n return token[idx];\n }\n return token;\n}\n\n/**\n * Build HTTP headers from MCP client auth options.\n * Returns undefined when no headers are needed.\n * @internal\n */\nexport async function buildAuthHeaders(\n auth?: McpClientAuthOptions,\n): Promise<Record<string, string> | undefined> {\n if (!auth) return undefined;\n\n const headers: Record<string, string> = {};\n const customHeaders = auth.headers ?? {};\n\n // Check if custom headers provide an Authorization override (case-insensitive)\n const authorizationOverride = Object.entries(customHeaders).find(\n ([name]) => name.toLowerCase() === \"authorization\",\n )?.[1];\n\n if (authorizationOverride) {\n headers[\"Authorization\"] = authorizationOverride;\n } else if (auth.token !== undefined) {\n const resolved = await resolveToken(auth.token);\n if (resolved.length === 0) {\n throw new Error(\n \"McpClientAuthOptions.token must be a non-empty string when provided\",\n );\n }\n headers[\"Authorization\"] = `Bearer ${resolved}`;\n }\n\n // Merge remaining custom headers, skipping any authorization variant\n for (const [name, value] of Object.entries(customHeaders)) {\n if (name.toLowerCase() !== \"authorization\") {\n headers[name] = value;\n }\n }\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n","import type { Exchange, Destination } from \"@routecraft/routecraft\";\nimport { getExchangeContext } from \"@routecraft/routecraft\";\nimport type {\n McpClientOptions,\n McpArgsExtractor,\n McpClientAuthOptions,\n McpClientHttpConfig,\n} from \"../../types.ts\";\nimport { ADAPTER_MCP_CLIENT_SERVERS, MCP_STDIO_MANAGERS } from \"../../types.ts\";\nimport { BRAND_MCP_ADAPTER } from \"./shared.ts\";\nimport { extractContent } from \"../../extract-content.ts\";\nimport { buildAuthHeaders } from \"../../build-auth-headers.ts\";\n\n/** Ensure inline url is HTTP(S) only. Stdio clients are resolved via MCP_STDIO_MANAGERS store. */\nfunction assertHttpUrl(url: string): void {\n const trimmed = url.trim().toLowerCase();\n if (!trimmed.startsWith(\"http://\") && !trimmed.startsWith(\"https://\")) {\n throw new Error(\n `MCP client: url must be HTTP or HTTPS. Stdio is not supported in routes; register stdio clients via mcpPlugin({ clients: { name: { command, args } } }). Got: \"${url.slice(0, 50)}${url.length > 50 ? \"...\" : \"\"}\"`,\n );\n }\n}\n\n/**\n * Look up the registered server config from the context store.\n * Returns undefined when no context or no matching serverId.\n * Backward-compat: store value may be a plain string (url only).\n */\nfunction resolveServerConfig(\n options: McpClientOptions,\n context: ReturnType<typeof getExchangeContext>,\n): McpClientHttpConfig | string | undefined {\n if (!options.serverId || !context) return undefined;\n const servers = context.getStore(\n ADAPTER_MCP_CLIENT_SERVERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, McpClientHttpConfig | string> | undefined;\n return servers?.get(options.serverId);\n}\n\n/**\n * Resolves the URL and auth for the MCP server from options or context (serverId).\n * Returns both in a single lookup to avoid duplicate store reads.\n */\nfunction resolveConnection(\n options: McpClientOptions,\n context: ReturnType<typeof getExchangeContext>,\n): { url: string; auth?: McpClientAuthOptions | undefined } {\n if (options.url) {\n assertHttpUrl(options.url);\n return { url: options.url, auth: options.auth };\n }\n if (options.serverId && !context) {\n throw new Error(\n `MCP client: serverId \"${options.serverId}\" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store \"${String(ADAPTER_MCP_CLIENT_SERVERS)}\" can be read.`,\n );\n }\n if (options.serverId && context) {\n const config = resolveServerConfig(options, context);\n if (!config) {\n throw new Error(\n `MCP client: serverId \"${options.serverId}\" not found in context store. Register it with context store key \"${String(ADAPTER_MCP_CLIENT_SERVERS)}\".`,\n );\n }\n const url = typeof config === \"string\" ? config : config.url;\n const auth =\n options.auth ??\n (typeof config === \"object\" && \"auth\" in config\n ? config.auth\n : undefined);\n return { url, auth };\n }\n throw new Error(\n \"MCP client: either url or serverId must be provided in McpClientOptions.\",\n );\n}\n\n/**\n * Default args extractor: use exchange body as tool arguments.\n * If body is a non-null object, use it as the args; otherwise use { input: body }.\n */\nexport const defaultArgs: McpArgsExtractor = (exchange) =>\n typeof exchange.body === \"object\" && exchange.body !== null\n ? (exchange.body as Record<string, unknown>)\n : { input: exchange.body };\n\n/**\n * McpDestinationAdapter implements the Destination interface for the MCP adapter.\n *\n * This adapter is used when mcp() is called with client options:\n * - `mcp({ url, tool })` - Direct HTTP URL\n * - `mcp({ serverId, tool })` - Server registered via mcpPlugin\n * - `mcp('server:tool')` - Shorthand for serverId:tool\n *\n * It makes HTTP calls to remote MCP servers using the MCP SDK.\n */\nexport class McpDestinationAdapter implements Destination<unknown, unknown> {\n readonly adapterId: string = \"routecraft.adapter.mcp\";\n\n constructor(private readonly options: McpClientOptions) {\n (this as unknown as Record<symbol, boolean>)[BRAND_MCP_ADAPTER] = true;\n\n // Validate client options\n if (!options.url && !options.serverId) {\n throw new Error(\n \"MCP client: either url or serverId must be provided in McpClientOptions.\",\n );\n }\n\n if (options.url && options.serverId) {\n throw new Error(\n \"MCP client: cannot provide both url and serverId. Use either url for direct HTTP or serverId for registered servers.\",\n );\n }\n }\n\n async send(exchange: Exchange<unknown>): Promise<unknown> {\n const context = getExchangeContext(exchange);\n const toolName =\n this.options.tool ??\n (typeof exchange.body === \"object\" &&\n exchange.body !== null &&\n \"tool\" in exchange.body &&\n typeof (exchange.body as { tool: string }).tool === \"string\"\n ? (exchange.body as { tool: string }).tool\n : undefined);\n if (!toolName) {\n throw new Error(\n \"MCP client: tool name required. Set options.tool or exchange.body.tool.\",\n );\n }\n const argsExtractor = this.options.args ?? defaultArgs;\n const args = argsExtractor(exchange);\n\n // Check for stdio manager first (registered via mcpPlugin)\n if (this.options.serverId && context) {\n const stdioManagers = context.getStore(\n MCP_STDIO_MANAGERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as\n | Map<\n string,\n {\n callTool(\n name: string,\n args: Record<string, unknown>,\n ): Promise<unknown>;\n }\n >\n | undefined;\n const manager = stdioManagers?.get(this.options.serverId);\n if (manager) {\n const result = await manager.callTool(toolName, args);\n if (result && typeof result === \"object\") {\n (result as Record<string, unknown>)[\"metadata\"] = {\n toolName,\n transport: \"stdio\",\n serverId: this.options.serverId,\n };\n }\n return result;\n }\n\n // Guard: if the registered config is stdio-type but the manager is missing,\n // throw a clear error instead of falling through to HTTP (which would fail\n // confusingly since stdio configs have no url property).\n const servers = context.getStore(\n ADAPTER_MCP_CLIENT_SERVERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, unknown> | undefined;\n const serverConfig = servers?.get(this.options.serverId);\n if (\n serverConfig &&\n typeof serverConfig === \"object\" &&\n \"transport\" in serverConfig &&\n (serverConfig as { transport: string }).transport === \"stdio\"\n ) {\n throw new Error(\n `MCP client: stdio server \"${this.options.serverId}\" is not running. Ensure mcpPlugin is applied and the stdio client started successfully.`,\n );\n }\n }\n\n // Fall through to HTTP\n const { url, auth } = resolveConnection(this.options, context);\n const result = await this.callRemoteTool(url, toolName, args, auth);\n\n // Attach metadata to result for getMetadata() to read (eliminates race condition)\n if (result && typeof result === \"object\") {\n (result as Record<string, unknown>)[\"metadata\"] = {\n toolName,\n url,\n transport: \"http\",\n ...(this.options.serverId ? { serverId: this.options.serverId } : {}),\n };\n }\n\n return result;\n }\n\n /**\n * Extract metadata from MCP adapter execution.\n * Reads metadata from the result object to avoid race conditions with concurrent exchanges.\n */\n getMetadata(result: unknown): Record<string, unknown> {\n if (result && typeof result === \"object\" && \"metadata\" in result) {\n return (result as { metadata: Record<string, unknown> }).metadata;\n }\n return {\n toolName: \"unknown\",\n transport: \"unknown\",\n };\n }\n\n private async callRemoteTool(\n serverUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n auth?: McpClientAuthOptions,\n ): Promise<unknown> {\n let clientModule: {\n Client: new (\n info: { name: string; version: string },\n options?: { capabilities?: Record<string, unknown> },\n ) => unknown;\n };\n let transportModule: {\n StreamableHTTPClientTransport: new (\n url: URL,\n options?: {\n sessionId?: string;\n requestInit?: { headers?: Record<string, string> };\n },\n ) => unknown;\n };\n try {\n clientModule = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n transportModule =\n await import(\"@modelcontextprotocol/sdk/client/streamableHttp.js\");\n } catch {\n throw new Error(\n 'MCP client requires \"@modelcontextprotocol/sdk\". Install it with: pnpm add @modelcontextprotocol/sdk',\n );\n }\n const Client = clientModule.Client;\n const StreamableHTTPClientTransport =\n transportModule.StreamableHTTPClientTransport;\n\n const url = new URL(serverUrl);\n const headers = await buildAuthHeaders(auth);\n const transportOptions = headers ? { requestInit: { headers } } : undefined;\n const transport = new StreamableHTTPClientTransport(url, transportOptions);\n const clientInfo = { name: \"routecraft-mcp-client\", version: \"1.0.0\" };\n const client = new (Client as new (\n info: { name: string; version: string },\n options?: { capabilities?: Record<string, unknown> },\n ) => InstanceType<typeof clientModule.Client>)(clientInfo, {\n capabilities: {},\n });\n try {\n const connect = (\n client as unknown as { connect(transport: unknown): Promise<void> }\n ).connect;\n await connect.call(client, transport);\n\n const callTool = (\n client as unknown as {\n callTool(params: {\n name: string;\n arguments?: Record<string, unknown>;\n }): Promise<{ content?: Array<{ type: string; text?: string }> }>;\n }\n ).callTool;\n const response = await callTool.call(client, {\n name: toolName,\n arguments: args,\n });\n\n return extractContent(response);\n } finally {\n const clientCleanup = client as unknown as {\n close?: () => void | Promise<void>;\n disconnect?: () => void | Promise<void>;\n };\n const closeOrDisconnect = clientCleanup.close ?? clientCleanup.disconnect;\n if (typeof closeOrDisconnect === \"function\") {\n try {\n await Promise.resolve(closeOrDisconnect.call(client));\n } catch {\n // Ignore cleanup errors so original error propagates\n }\n }\n const transportCleanup = transport as unknown as {\n close?: () => void | Promise<void>;\n destroy?: () => void;\n };\n const closeOrDestroy = transportCleanup.close ?? transportCleanup.destroy;\n if (typeof closeOrDestroy === \"function\") {\n try {\n await Promise.resolve(closeOrDestroy.call(transport));\n } catch {\n // Ignore cleanup errors so original error propagates\n }\n }\n }\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport {\n rcError,\n type Exchange,\n type Source,\n type Destination,\n} from \"@routecraft/routecraft\";\nimport type {\n McpArgsExtractor,\n McpClientOptions,\n McpServerOptions,\n} from \"../../types.ts\";\nimport type { RegisteredMcpShorthand } from \"../../../registry.ts\";\nimport { McpSourceAdapter } from \"./source.ts\";\nimport { McpDestinationAdapter } from \"./destination.ts\";\nimport type { McpMessage } from \"./types.ts\";\n\n/**\n * Creates an MCP adapter for communicating with MCP servers.\n *\n * - **Source (for `.from()`):** Call with two arguments: `mcp(endpoint, options)`.\n * Options must include a `description` field (required for MCP tool exposure).\n * Requires the MCP plugin: `plugins: [mcpPlugin()]`.\n * Body type is inferred from `options.schema` when provided.\n *\n * - **Destination (for `.to()` / `.tap()`):** Call with one argument containing client options:\n * - `mcp({ url, tool })` - Direct HTTP URL to remote MCP server\n * - `mcp({ serverId, tool })` - Server ID registered via mcpPlugin({ clients })\n * - `mcp('server:tool', { args? })` - Shorthand for serverId:tool with optional args extractor\n *\n * The MCP adapter delegates to the direct() adapter for source routes and makes HTTP calls\n * to remote MCP servers for destination routes.\n *\n * @param endpointOrOptions - Endpoint string (source) or client options object (destination) or 'server:tool' string (destination)\n * @param options - Server options (source) or args extractor (destination)\n * @returns Source when called with two arguments; Destination when called with one argument\n *\n * @experimental\n *\n * @example\n * ```typescript\n * // Source route (MCP tool)\n * .from(mcp('/search', { description: 'Search documents', schema: mySchema }))\n *\n * // Destination (call remote MCP server)\n * .to(mcp({ url: 'http://localhost:3001/mcp', tool: 'search' }))\n * .to(mcp({ serverId: 'my-server', tool: 'search' }))\n * .to(mcp('my-server:search'))\n * .to(mcp('my-server:search', { args: (ex) => ex.body.params }))\n * ```\n */\nexport function mcp<S extends StandardSchemaV1 | undefined = undefined>(\n endpoint: string,\n options: McpServerOptions & { schema?: S },\n): Source<McpMessage<S>>;\nexport function mcp(\n clientOptions: McpClientOptions,\n): Destination<unknown, unknown>;\nexport function mcp(\n shorthand: RegisteredMcpShorthand,\n options?: { args?: McpArgsExtractor },\n): Destination<unknown, unknown>;\nexport function mcp<S extends StandardSchemaV1 | undefined = undefined>(\n endpointOrOptions:\n | string\n | ((exchange: Exchange<McpMessage<S>>) => string)\n | McpClientOptions,\n options?: (McpServerOptions & { schema?: S }) | { args?: McpArgsExtractor },\n): Source<McpMessage<S>> | Destination<unknown, unknown> {\n // Client: object with url or serverId\n if (\n typeof endpointOrOptions === \"object\" &&\n endpointOrOptions !== null &&\n (\"url\" in endpointOrOptions || \"serverId\" in endpointOrOptions)\n ) {\n const clientOpts = endpointOrOptions as McpClientOptions;\n if (typeof clientOpts.auth?.token === \"string\") {\n if (clientOpts.auth.token.trim().length === 0) {\n throw new TypeError(\n \"mcp(): auth.token must be a non-empty string when provided\",\n );\n }\n }\n if (Array.isArray(clientOpts.auth?.token)) {\n if (clientOpts.auth.token.length === 0) {\n throw new TypeError(\"mcp(): auth.token array must not be empty\");\n }\n for (let i = 0; i < clientOpts.auth.token.length; i++) {\n const entry = clientOpts.auth.token[i];\n if (typeof entry !== \"string\" || entry.trim().length === 0) {\n throw new TypeError(\n `mcp(): auth.token[${i}] must be a non-empty string`,\n );\n }\n }\n }\n return new McpDestinationAdapter(clientOpts);\n }\n\n // Client: \"server:tool\" string with optional args\n const isClientColonOptions =\n options === undefined ||\n (typeof options === \"object\" &&\n options !== null &&\n !(\"description\" in options));\n if (\n typeof endpointOrOptions === \"string\" &&\n endpointOrOptions.includes(\":\") &&\n isClientColonOptions\n ) {\n const colonIndex = endpointOrOptions.indexOf(\":\");\n const serverId = endpointOrOptions.slice(0, colonIndex);\n const tool = endpointOrOptions.slice(colonIndex + 1);\n const clientOptions: McpClientOptions = { serverId, tool };\n if (\n options !== undefined &&\n typeof options === \"object\" &&\n \"args\" in options &&\n options.args !== undefined\n ) {\n clientOptions.args = options.args as McpArgsExtractor;\n }\n return new McpDestinationAdapter(clientOptions);\n }\n\n // Server: endpoint + options with description\n const endpoint = endpointOrOptions as\n | string\n | ((exchange: Exchange<McpMessage<S>>) => string);\n if (options !== undefined) {\n return new McpSourceAdapter<S>(\n endpoint as string,\n options as McpServerOptions & { schema?: S },\n );\n }\n\n // Invalid: endpoint only (no options) — direct not supported\n throw rcError(\"RC5003\", undefined, {\n message:\n \"mcp() with only an endpoint is not supported. Use direct('endpoint') for in-process. For MCP server use .from(mcp('endpoint', { description: '...' })); for client use .to(mcp({ url, tool })) or .to(mcp('server:tool', { args })).\",\n suggestion:\n \"Use .from(mcp('endpoint', { description: '...' })) or .to(mcp({ url, tool })) or direct('endpoint').\",\n });\n}\n\n// Re-export types for public API\nexport type {\n McpMessage,\n McpArgsExtractor,\n McpClientHttpConfig,\n} from \"./types\";\nexport { BRAND_MCP_ADAPTER } from \"./shared\";\nexport { defaultArgs } from \"./destination\";\n","import type {\n OAuthPrincipal,\n OAuthTokenVerifier,\n OAuthValidatorAuthOptions,\n} from \"@routecraft/routecraft\";\nimport type {\n OAuthAuthOptions,\n OAuthClientInfo,\n OAuthProxyEndpoints,\n} from \"./types.ts\";\n\n/**\n * Supplier for a registered OAuth client.\n *\n * Called **per request** by the MCP SDK's proxy provider during the OAuth\n * flow (authorize, token exchange, revoke) with the incoming `client_id`.\n * Return the matching {@link OAuthClientInfo} or `undefined` to reject the\n * client with a standard OAuth error.\n *\n * Avoid blocking I/O on the hot path when possible. Cache database reads or\n * load the registry at boot.\n *\n * @experimental\n */\nexport type OAuthClientSupplier = (\n clientId: string,\n) => Promise<OAuthClientInfo | undefined> | OAuthClientInfo | undefined;\n\n/**\n * The `verify` option accepted by `oauth()`.\n *\n * Pass:\n * - An `OAuthValidatorAuthOptions` (output of `jwt()` or `jwks()`) to compose\n * a validator-based verifier, or\n * - A raw `OAuthTokenVerifier` function for custom logic.\n *\n * Both shapes guarantee an {@link OAuthPrincipal} with `expiresAt`, which the\n * MCP SDK's bearer middleware requires. The type system rejects verifiers\n * that do not uphold that contract -- no more runtime surprises from a\n * well-typed verifier that forgot to populate `expiresAt`.\n *\n * @experimental\n */\nexport type OAuthVerifier = OAuthValidatorAuthOptions | OAuthTokenVerifier;\n\n/**\n * Options for the `oauth()` factory.\n *\n * @experimental\n */\nexport interface OAuthFactoryOptions {\n /**\n * Issuer URL for this MCP server's OAuth metadata discovery endpoint.\n * Must be HTTPS in production.\n *\n * Renamed from `issuerUrl` to avoid confusion with the IdP issuer inside\n * the `verify` config.\n */\n resourceIssuerUrl: string | URL;\n /** Base URL for OAuth endpoints (defaults to resourceIssuerUrl). */\n baseUrl?: string | URL;\n /** Upstream OAuth provider endpoints to proxy. */\n endpoints: OAuthProxyEndpoints;\n /**\n * Token verifier for access tokens arriving at `/mcp`.\n *\n * Accept:\n * - `jwks({ jwksUrl, issuer, audience })` -- JWKS-backed verification (the common case)\n * - `jwt({ secret, issuer, audience })` -- static-key verification (rare)\n * - A raw `(token) => Principal | Promise<Principal>` function -- custom logic\n *\n * The verifier is called on every authenticated request.\n */\n verify: OAuthVerifier;\n /**\n * Registered OAuth client(s). Accepts either:\n * - a static {@link OAuthClientInfo} for the single-client case (matched on\n * `client_id`; unknown IDs are rejected), or\n * - an {@link OAuthClientSupplier} `(clientId) => OAuthClientInfo | undefined`\n * for dynamic lookup (database, registry, etc.).\n *\n * The supplier is invoked **per request** by the MCP SDK's proxy provider\n * during every authorize/token/revoke call; treat it as a hot path.\n */\n client: OAuthClientInfo | OAuthClientSupplier;\n /** OAuth scopes the server advertises as supported. */\n scopesSupported?: string[];\n /** Scopes required on every request to `/mcp`. */\n requiredScopes?: string[];\n /** URL to service documentation (included in OAuth metadata). */\n serviceDocumentationUrl?: string | URL;\n /** Human-readable resource name (included in OAuth metadata). */\n resourceName?: string;\n}\n\n/**\n * Normalise the factory-level `client` option into the `(clientId) =>\n * Promise<OAuthClientInfo | undefined>` shape expected by the MCP SDK's\n * `ProxyOAuthServerProvider`.\n *\n * When a static {@link OAuthClientInfo} is supplied, the returned lookup\n * accepts only requests whose `clientId` matches the object's `client_id`;\n * unknown IDs are rejected so an accidental single-client setup cannot\n * silently authorize other clients.\n */\nfunction normaliseClientSupplier(\n input: OAuthClientInfo | OAuthClientSupplier,\n): (clientId: string) => Promise<OAuthClientInfo | undefined> {\n if (typeof input === \"function\") {\n return async (clientId) => input(clientId);\n }\n const staticClient = input;\n return async (clientId) =>\n clientId === staticClient.client_id ? staticClient : undefined;\n}\n\n/**\n * Normalise the `verify` option into a `(token) => Promise<OAuthPrincipal>`\n * callback.\n */\nfunction buildVerifier(\n verify: OAuthVerifier,\n): (token: string) => Promise<OAuthPrincipal> {\n if (!verify) {\n throw new TypeError(\n \"oauth: `verify` is required. Pass jwks(...), jwt(...), or a custom (token) => OAuthPrincipal function.\",\n );\n }\n if (typeof verify === \"function\") {\n return async (token) => verify(token);\n }\n return async (token) => verify.validator(token);\n}\n\n/**\n * Built-in OAuth authentication helper for MCP HTTP servers.\n * Configures a full OAuth 2.1 server flow that proxies to an upstream identity\n * provider using the MCP SDK's `ProxyOAuthServerProvider` and `mcpAuthRouter`.\n *\n * Returns an {@link OAuthAuthOptions} that can be passed directly to\n * `mcpPlugin({ auth: oauth({ ... }) })`.\n *\n * The server will mount OAuth endpoints (`/.well-known/oauth-authorization-server`,\n * `/authorize`, `/token`, `/revoke`) alongside the `/mcp` transport endpoint.\n *\n * @example JWKS-backed OAuth (e.g. Clerk)\n * ```ts\n * import { mcpPlugin, oauth, jwks } from \"@routecraft/ai\";\n *\n * mcpPlugin({\n * transport: \"http\",\n * auth: oauth({\n * resourceIssuerUrl: \"https://mcp.example.com\",\n * endpoints: {\n * authorizationUrl: \"https://idp.example.com/authorize\",\n * tokenUrl: \"https://idp.example.com/token\",\n * },\n * verify: jwks({\n * jwksUrl: \"https://idp.example.com/.well-known/jwks.json\",\n * issuer: \"https://idp.example.com\",\n * audience: \"https://mcp.example.com\",\n * }),\n * client: {\n * client_id: \"my-mcp-server\",\n * redirect_uris: [\"http://localhost:3000/callback\"],\n * },\n * }),\n * });\n * ```\n *\n * @example Dynamic client lookup (e.g. DCR, database-backed registry)\n * ```ts\n * oauth({\n * // ...\n * client: async (clientId) => await db.clients.findByClientId(clientId),\n * })\n * ```\n *\n * @example Custom verification (opaque tokens, introspection, etc.)\n * ```ts\n * oauth({\n * resourceIssuerUrl: \"https://mcp.example.com\",\n * endpoints: { authorizationUrl: \"...\", tokenUrl: \"...\" },\n * verify: async (token) => {\n * const principal = await myIntrospectionCall(token);\n * return {\n * kind: \"custom\",\n * scheme: \"bearer\",\n * subject: principal.userId,\n * clientId: principal.clientId,\n * expiresAt: principal.exp,\n * };\n * },\n * client: { ... },\n * });\n * ```\n *\n * @experimental\n */\nexport function oauth(options: OAuthFactoryOptions): OAuthAuthOptions {\n const issuer = new URL(options.resourceIssuerUrl.toString());\n if (\n issuer.protocol !== \"https:\" &&\n process.env[\"NODE_ENV\"] === \"production\"\n ) {\n throw new TypeError(\n \"oauth: resourceIssuerUrl must use HTTPS in production\",\n );\n }\n\n const verifyAccessToken = buildVerifier(options.verify);\n const getClient = normaliseClientSupplier(options.client);\n\n const result: OAuthAuthOptions = {\n provider: \"oauth\",\n resourceIssuerUrl: options.resourceIssuerUrl,\n endpoints: options.endpoints,\n verifyAccessToken,\n getClient,\n ...(options.baseUrl !== undefined && { baseUrl: options.baseUrl }),\n ...(options.scopesSupported !== undefined && {\n scopesSupported: options.scopesSupported,\n }),\n ...(options.requiredScopes !== undefined && {\n requiredScopes: options.requiredScopes,\n }),\n ...(options.serviceDocumentationUrl !== undefined && {\n serviceDocumentationUrl: options.serviceDocumentationUrl,\n }),\n ...(options.resourceName !== undefined && {\n resourceName: options.resourceName,\n }),\n };\n\n return result;\n}\n","import type { CraftContext, DirectRouteMetadata } from \"@routecraft/routecraft\";\nimport {\n ADAPTER_DIRECT_REGISTRY,\n ADAPTER_DIRECT_STORE,\n DefaultExchange,\n isRoutecraftError,\n} from \"@routecraft/routecraft\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { createServer } from \"node:http\";\nimport type { IncomingMessage } from \"node:http\";\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport type {\n OAuthPrincipal,\n Principal,\n ValidatorAuthOptions,\n} from \"@routecraft/routecraft\";\nimport { McpHeadersKeys, isOAuthAuth } from \"./types.ts\";\nimport type {\n McpPluginOptions,\n McpTool,\n McpToolAnnotations,\n OAuthAuthOptions,\n} from \"./types.ts\";\n\n/**\n * MCP SDK `AuthInfo` shape. Imported as a type so nothing is required at\n * runtime from the SDK just for this alias; `import type` is erased by the\n * compiler.\n */\ntype SdkAuthInfo = AuthInfo;\n\n/**\n * Request-scoped storage for the authenticated principal.\n * Set in the HTTP request handler after auth validation;\n * read in handleToolCall to populate exchange headers.\n */\nconst principalStore = new AsyncLocalStorage<Principal | undefined>();\n\nconst MCP_SDK_INSTALL =\n 'MCP server requires \"@modelcontextprotocol/sdk\". Install it with: pnpm add @modelcontextprotocol/sdk';\n\n/** Resolved options with defaults applied (internal use). */\ntype McpServerResolvedOptions = Required<\n Pick<McpPluginOptions, \"name\" | \"version\" | \"transport\" | \"port\" | \"host\">\n> &\n Pick<McpPluginOptions, \"tools\" | \"auth\">;\n\n/**\n * McpServer wraps the MCP SDK and bridges it to Routecraft's DirectChannel infrastructure.\n * It reads the MCP route registry lazily (on first tools/list request) to ensure routes have subscribed.\n *\n * Note: Uses dynamic imports to avoid TypeScript compatibility issues with the MCP SDK.\n * Supports both stdio and streamable-http transports.\n *\n * @experimental\n */\nexport class McpServer {\n private context: CraftContext;\n private options: McpServerResolvedOptions;\n private server: unknown = null;\n private transport: unknown = null;\n /**\n * Node HTTP server when transport is http; used to listen on port and close on stop.\n * When OAuth is enabled this holds the Express app's underlying server.\n */\n private httpServer: ReturnType<typeof createServer> | null = null;\n /** Active HTTP sessions keyed by session ID (each session has its own server+transport pair). */\n private httpSessions = new Map<\n string,\n { server: unknown; transport: unknown }\n >();\n private running = false;\n private toolsListLogged = false;\n\n constructor(context: CraftContext, options: McpPluginOptions = {}) {\n this.context = context;\n this.options = {\n name: \"routecraft\",\n version: \"1.0.0\",\n transport: \"stdio\",\n port: 3001,\n host: \"localhost\",\n ...options,\n };\n }\n\n /**\n * Start the MCP server and listen for connections\n */\n async start(): Promise<void> {\n if (this.running) {\n this.context.logger.warn({}, \"MCP server already running\");\n return;\n }\n\n try {\n const transport = this.options.transport;\n\n if (transport === \"http\") {\n await this.startHttp();\n } else {\n await this.startStdio();\n }\n\n this.running = true;\n this.context.logger.info(\n {\n name: this.options.name,\n version: this.options.version,\n transport,\n },\n \"MCP server started\",\n );\n this.logExposedToolsOnce();\n } catch (error) {\n const msg = isRoutecraftError(error)\n ? (error as unknown as { meta: { message: string } }).meta.message\n : error instanceof Error\n ? error.message\n : \"Failed to start MCP server\";\n this.context.logger.error({ err: error }, msg);\n throw error;\n }\n }\n\n /**\n * Start stdio transport\n */\n private async startStdio(): Promise<void> {\n let Server: new (\n info: { name: string; version: string },\n options: { capabilities: { tools: Record<string, unknown> } },\n ) => unknown;\n let StdioServerTransport: new () => unknown;\n try {\n const serverMod =\n await import(\"@modelcontextprotocol/sdk/server/index.js\");\n Server = serverMod.Server;\n const stdioMod =\n await import(\"@modelcontextprotocol/sdk/server/stdio.js\");\n StdioServerTransport = stdioMod.StdioServerTransport;\n } catch {\n throw new Error(MCP_SDK_INSTALL);\n }\n\n this.server = new Server(\n {\n name: this.options.name,\n version: this.options.version,\n },\n { capabilities: { tools: {} } },\n );\n\n await this.setupRequestHandlers();\n\n this.transport = new StdioServerTransport();\n const srvWithConnect = this.server as Record<\n string,\n (transport: unknown) => Promise<void>\n >;\n await srvWithConnect[\"connect\"](this.transport);\n }\n\n /**\n * Start HTTP transport (streamable-http).\n * Dispatches to the OAuth or raw-HTTP path depending on the auth config.\n */\n private async startHttp(): Promise<void> {\n if (this.options.auth && isOAuthAuth(this.options.auth)) {\n await this.startHttpWithOAuth(this.options.auth);\n } else {\n await this.startHttpWithValidator();\n }\n }\n\n /**\n * Import the MCP SDK Server constructor and StreamableHTTPServerTransport.\n * Shared by both HTTP startup paths.\n */\n private async importSdkHttp(): Promise<{\n ServerCtor: new (\n info: { name: string; version: string },\n options: { capabilities: { tools: Record<string, unknown> } },\n ) => unknown;\n TransportClass: new (options?: {\n sessionIdGenerator?: () => string;\n onsessioninitialized?: (sessionId: string) => void;\n enableJsonResponse?: boolean;\n }) => unknown;\n }> {\n let ServerCtor: new (\n info: { name: string; version: string },\n options: { capabilities: { tools: Record<string, unknown> } },\n ) => unknown;\n try {\n const serverModule =\n await import(\"@modelcontextprotocol/sdk/server/index.js\");\n ServerCtor = serverModule.Server;\n } catch {\n throw new Error(MCP_SDK_INSTALL);\n }\n\n const streamableModule =\n await import(\"@modelcontextprotocol/sdk/server/streamableHttp.js\").catch(\n () => null,\n );\n const TransportClass = (\n streamableModule as Record<string, unknown> | null\n )?.[\"StreamableHTTPServerTransport\"] as\n | (new (options?: {\n sessionIdGenerator?: () => string;\n onsessioninitialized?: (sessionId: string) => void;\n enableJsonResponse?: boolean;\n }) => unknown)\n | undefined;\n\n if (!TransportClass) {\n throw new Error(\n \"StreamableHTTPServerTransport not found in MCP SDK - ensure @modelcontextprotocol/sdk v1.26.0+ is installed\",\n );\n }\n\n return { ServerCtor, TransportClass };\n }\n\n /**\n * Creates a new MCP Server + Transport pair for a single HTTP session.\n * Called on every initialization request (no session ID header).\n */\n private async createSession(\n ServerCtor: new (\n info: { name: string; version: string },\n options: { capabilities: { tools: Record<string, unknown> } },\n ) => unknown,\n TransportClass: new (options?: {\n sessionIdGenerator?: () => string;\n onsessioninitialized?: (sessionId: string) => void;\n enableJsonResponse?: boolean;\n }) => unknown,\n ): Promise<{\n transport: unknown;\n handleRequest: (\n req: unknown,\n res: unknown,\n parsedBody?: unknown,\n ) => Promise<void>;\n }> {\n const server = new ServerCtor(\n { name: this.options.name, version: this.options.version },\n { capabilities: { tools: {} } },\n );\n\n await this.setupRequestHandlersOn(server);\n\n const transport = new TransportClass({\n sessionIdGenerator: () => crypto.randomUUID(),\n onsessioninitialized: (sessionId: string) => {\n this.httpSessions.set(sessionId, { server, transport });\n this.context.logger.debug({ sessionId }, \"MCP session created\");\n this.context.emit(\"plugin:mcp:session:created\", { sessionId });\n },\n enableJsonResponse: true,\n });\n\n const srvWithConnect = server as Record<\n string,\n (t: unknown) => Promise<void>\n >;\n await srvWithConnect[\"connect\"](transport);\n\n // Clean up on transport close so the session map does not leak.\n const tr = transport as Record<string, unknown>;\n const prevOnClose = tr[\"onclose\"] as (() => void) | undefined;\n tr[\"onclose\"] = () => {\n const sid = (transport as { sessionId?: string }).sessionId;\n if (sid) {\n this.httpSessions.delete(sid);\n this.context.logger.debug({ sessionId: sid }, \"MCP session closed\");\n this.context.emit(\"plugin:mcp:session:closed\", {\n sessionId: sid,\n });\n }\n prevOnClose?.();\n };\n\n const handleRequest = (\n transport as Record<\n string,\n (req: unknown, res: unknown, parsedBody?: unknown) => Promise<void>\n >\n )[\"handleRequest\"];\n if (typeof handleRequest !== \"function\") {\n throw new Error(\n \"StreamableHTTPServerTransport.handleRequest not found - SDK may have changed\",\n );\n }\n\n return {\n transport,\n handleRequest: handleRequest.bind(transport) as (\n req: unknown,\n res: unknown,\n parsedBody?: unknown,\n ) => Promise<void>,\n };\n }\n\n /**\n * Route an MCP request through session management with principal context.\n * Shared by both HTTP startup paths.\n */\n private async handleMcpRequest(\n req: IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n principal: Principal | undefined,\n createSessionFn: () => Promise<{\n handleRequest: (\n req: unknown,\n res: unknown,\n parsedBody?: unknown,\n ) => Promise<void>;\n }>,\n ): Promise<void> {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n const runWithPrincipal = <T>(fn: () => Promise<T>): Promise<T> =>\n principalStore.run(principal, fn);\n\n try {\n if (sessionId && this.httpSessions.has(sessionId)) {\n const session = this.httpSessions.get(sessionId)!;\n const hr = (\n session.transport as Record<\n string,\n (req: unknown, res: unknown, parsedBody?: unknown) => Promise<void>\n >\n )[\"handleRequest\"];\n await runWithPrincipal(() => hr.call(session.transport, req, res));\n } else if (!sessionId || req.method === \"POST\") {\n const { handleRequest } = await createSessionFn();\n await runWithPrincipal(() => handleRequest(req, res));\n } else {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Session not found\" }));\n }\n } catch (err) {\n const msg = isRoutecraftError(err)\n ? (err as unknown as { meta: { message: string } }).meta.message\n : err instanceof Error\n ? err.message\n : \"MCP HTTP request error\";\n this.context.logger.error({ err }, msg);\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal Server Error\" }));\n }\n }\n }\n\n /**\n * Start HTTP transport with validator-based auth (existing behavior).\n * Uses raw Node.js `http.createServer`.\n */\n private async startHttpWithValidator(): Promise<void> {\n const { ServerCtor, TransportClass } = await this.importSdkHttp();\n const port = this.options.port;\n const host = this.options.host;\n\n const createSessionFn = () =>\n this.createSession(ServerCtor, TransportClass);\n\n this.httpServer = createServer(async (req, res) => {\n const url = req.url?.split(\"?\")[0] ?? \"\";\n if (url !== \"/mcp\" && url !== \"/mcp/\") {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not Found\", path: url }));\n return;\n }\n\n let principal: Principal | undefined;\n if (this.options.auth) {\n const result = await this.validateAuth(req);\n if (!result) {\n res.writeHead(401, {\n \"Content-Type\": \"application/json\",\n \"WWW-Authenticate\": 'Bearer realm=\"mcp\"',\n });\n res.end(JSON.stringify({ error: \"Unauthorized\" }));\n return;\n }\n principal = result;\n }\n\n await this.handleMcpRequest(req, res, principal, createSessionFn);\n });\n\n await this.listenHttp(port, host);\n }\n\n /**\n * Start HTTP transport with OAuth provider auth.\n * Uses Express to mount `mcpAuthRouter` (OAuth endpoints) alongside `/mcp`.\n * Express is available as a transitive dependency of `@modelcontextprotocol/sdk`.\n *\n * Note: if the server runs behind a reverse proxy, `req.ip` and `req.protocol`\n * may be incorrect. Users should set `trust proxy` on the Express app via a\n * future configuration option or by using a custom HTTP server.\n */\n private async startHttpWithOAuth(\n oauthOptions: OAuthAuthOptions,\n ): Promise<void> {\n const { ServerCtor, TransportClass } = await this.importSdkHttp();\n\n // Dynamic imports for Express and SDK OAuth infrastructure.\n // Express types are not available at compile time (transitive dep of SDK),\n // so all Express values are typed as unknown and accessed dynamically.\n let expressFn: (...args: unknown[]) => {\n use: (...args: unknown[]) => void;\n all: (...args: unknown[]) => void;\n listen: (\n port: number,\n host: string,\n cb: () => void,\n ) => ReturnType<typeof createServer>;\n };\n let mcpAuthRouter: (options: Record<string, unknown>) => unknown;\n let requireBearerAuth: (options: Record<string, unknown>) => unknown;\n let ProxyOAuthServerProvider: new (\n options: Record<string, unknown>,\n ) => unknown;\n\n try {\n // @ts-expect-error -- Express is a transitive dep of @modelcontextprotocol/sdk; no type declarations in this project\n const expressMod = (await import(\"express\")) as Record<string, unknown>;\n expressFn = (expressMod[\"default\"] ?? expressMod) as typeof expressFn;\n } catch {\n throw new Error(\n 'OAuth auth requires \"express\" (optional peer dependency of @routecraft/ai). Install it with: pnpm add express',\n );\n }\n\n try {\n const routerMod =\n await import(\"@modelcontextprotocol/sdk/server/auth/router.js\");\n mcpAuthRouter = (routerMod as Record<string, unknown>)[\n \"mcpAuthRouter\"\n ] as typeof mcpAuthRouter;\n\n const bearerMod =\n await import(\"@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js\");\n requireBearerAuth = (bearerMod as Record<string, unknown>)[\n \"requireBearerAuth\"\n ] as typeof requireBearerAuth;\n\n const proxyMod =\n await import(\"@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js\");\n ProxyOAuthServerProvider = (proxyMod as Record<string, unknown>)[\n \"ProxyOAuthServerProvider\"\n ] as typeof ProxyOAuthServerProvider;\n } catch {\n throw new Error(\n \"OAuth auth requires @modelcontextprotocol/sdk v1.27.0+ with OAuth support. \" +\n \"Install it with: pnpm add @modelcontextprotocol/sdk\",\n );\n }\n\n // Wrap the user's verifier so the MCP SDK sees a clean AuthInfo while the\n // rich OAuthPrincipal rides through in `extra.principal` for\n // this.authInfoToPrincipal. Token verification errors are logged and\n // emitted as `auth:rejected` so operators can observe brute-force\n // attempts, expired tokens, and mismatched audiences alongside the\n // validator path's rejections.\n const wrappedVerifier = async (token: string): Promise<SdkAuthInfo> => {\n let principal: OAuthPrincipal;\n try {\n principal = await oauthOptions.verifyAccessToken(token);\n } catch (err) {\n const reason = err instanceof Error ? err.message : \"invalid_token\";\n const detail = {\n reason,\n scheme: \"bearer\",\n source: \"mcp\",\n path: \"oauth\",\n };\n this.context.logger.warn(\n { err, ...detail },\n \"Auth rejected: token validation failed\",\n );\n this.context.emit(\"auth:rejected\", detail);\n throw err;\n }\n // Belt-and-suspenders: the type system already guarantees `expiresAt`,\n // but third-party code using `as any` or dynamic plugin wiring could\n // still hand us an incomplete principal. Emit a structured rejection\n // so an operator can trace the mis-wired verifier instead of debugging\n // a silent 401 from the SDK bearer middleware.\n if ((principal as { expiresAt?: number }).expiresAt === undefined) {\n const detail = {\n reason: \"missing_expires_at\",\n scheme: \"bearer\",\n source: \"mcp\",\n path: \"oauth\",\n };\n this.context.logger.warn(\n detail,\n \"Auth rejected: OAuth principal is missing expiresAt\",\n );\n this.context.emit(\"auth:rejected\", detail);\n throw new Error(\n \"oauth: verifyAccessToken must return a principal with expiresAt (required by MCP SDK bearer middleware)\",\n );\n }\n if (!principal.clientId) {\n this.context.logger.debug(\n { subject: principal.subject },\n \"oauth: principal missing clientId; using subject as fallback for AuthInfo.clientId\",\n );\n }\n const authInfo: SdkAuthInfo = {\n token,\n clientId: principal.clientId ?? principal.subject,\n scopes: principal.scopes ?? [],\n expiresAt: principal.expiresAt,\n extra: { principal },\n };\n return authInfo;\n };\n\n // Build the ProxyOAuthServerProvider from the user's config.\n const provider = new ProxyOAuthServerProvider({\n endpoints: {\n authorizationUrl: oauthOptions.endpoints.authorizationUrl,\n tokenUrl: oauthOptions.endpoints.tokenUrl,\n revocationUrl: oauthOptions.endpoints.revocationUrl,\n registrationUrl: oauthOptions.endpoints.registrationUrl,\n },\n verifyAccessToken: wrappedVerifier,\n getClient: oauthOptions.getClient,\n });\n\n const port = this.options.port;\n const host = this.options.host;\n\n const app = expressFn();\n\n // Mount OAuth endpoints at root (discovery, authorize, token, revoke).\n const authRouterOptions: Record<string, unknown> = {\n provider,\n issuerUrl: new URL(oauthOptions.resourceIssuerUrl.toString()),\n };\n if (oauthOptions.baseUrl) {\n authRouterOptions[\"baseUrl\"] = new URL(oauthOptions.baseUrl.toString());\n }\n if (oauthOptions.scopesSupported) {\n authRouterOptions[\"scopesSupported\"] = oauthOptions.scopesSupported;\n }\n if (oauthOptions.serviceDocumentationUrl) {\n authRouterOptions[\"serviceDocumentationUrl\"] = new URL(\n oauthOptions.serviceDocumentationUrl.toString(),\n );\n }\n if (oauthOptions.resourceName) {\n authRouterOptions[\"resourceName\"] = oauthOptions.resourceName;\n }\n app.use(mcpAuthRouter(authRouterOptions));\n\n // Bearer auth middleware for /mcp.\n const bearerOptions: Record<string, unknown> = { verifier: provider };\n if (oauthOptions.requiredScopes) {\n bearerOptions[\"requiredScopes\"] = oauthOptions.requiredScopes;\n }\n app.use(\"/mcp\", requireBearerAuth(bearerOptions));\n\n const createSessionFn = () =>\n this.createSession(ServerCtor, TransportClass);\n\n // MCP transport handler at /mcp.\n app.all(\"/mcp\", async (req: unknown, res: unknown) => {\n const nodeReq = req as IncomingMessage;\n const nodeRes = res as import(\"node:http\").ServerResponse;\n\n // The SDK's requireBearerAuth sets req.auth with the verified AuthInfo.\n const authInfo = (req as Record<string, unknown>)[\"auth\"] as\n | SdkAuthInfo\n | undefined;\n const principal = this.authInfoToPrincipal(authInfo);\n\n if (principal) {\n const successDetail = {\n subject: principal.subject,\n scheme: principal.scheme,\n source: \"mcp\",\n };\n this.context.logger.info(successDetail, \"Auth succeeded\");\n this.context.emit(\"auth:success\", successDetail);\n }\n\n await this.handleMcpRequest(nodeReq, nodeRes, principal, createSessionFn);\n });\n\n // Wrap the Express app in a raw HTTP server so listenHttp can bind it.\n // Express apps are callable as (req, res) request handlers.\n this.httpServer = createServer(\n app as unknown as (\n req: import(\"node:http\").IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n ) => void,\n );\n await this.listenHttp(port, host);\n }\n\n /**\n * Bind the HTTP server to the configured port and host.\n * Used by the validator path.\n */\n private async listenHttp(port: number, host: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n this.httpServer!.listen(port, host, () => resolve());\n this.httpServer!.on(\"error\", (err) => {\n const msg = isRoutecraftError(err)\n ? (err as unknown as { meta: { message: string } }).meta.message\n : err instanceof Error\n ? err.message\n : \"MCP HTTP server listen failed\";\n this.context.logger.error({ err }, msg);\n reject(err);\n });\n });\n\n const boundPort = this.getHttpPort() ?? port;\n const listenDetail = { host, port: boundPort, path: \"/mcp\" };\n this.context.logger.info(listenDetail, \"MCP HTTP server listening\");\n this.context.emit(\"plugin:mcp:server:listening\", listenDetail);\n }\n\n /**\n * Convert the MCP SDK's AuthInfo (set by requireBearerAuth) to a Principal\n * for routecraft's exchange headers.\n *\n * The OAuth path's wrapped `verifyAccessToken` stashes the fully-populated\n * {@link Principal} in `authInfo.extra.principal`. If the stash is absent\n * (e.g. a third party plugged a bare `ProxyOAuthServerProvider` in some\n * custom setup), fall back to a minimal principal from the SDK-level `AuthInfo`.\n */\n private authInfoToPrincipal(\n authInfo: SdkAuthInfo | undefined,\n ): Principal | undefined {\n if (!authInfo) return undefined;\n const stashed = (authInfo.extra as { principal?: Principal } | undefined)\n ?.principal;\n if (stashed) return stashed;\n\n const fallback: Principal = {\n kind: \"oauth\",\n scheme: \"bearer\",\n subject: authInfo.clientId,\n clientId: authInfo.clientId,\n scopes: authInfo.scopes,\n };\n if (authInfo.expiresAt !== undefined) {\n fallback.expiresAt = authInfo.expiresAt;\n }\n return fallback;\n }\n\n /**\n * When transport is http, returns the bound port (useful when port 0 was used). Otherwise undefined.\n */\n getHttpPort(): number | undefined {\n const addr = this.httpServer?.address();\n if (addr && typeof addr === \"object\" && \"port\" in addr) {\n return (addr as { port: number }).port;\n }\n return undefined;\n }\n\n /**\n * Validate the Authorization header using the configured validator.\n * Only used on the validator auth path (not OAuth -- that uses Express middleware).\n * Returns the authenticated principal on success, or `null` to reject with 401.\n */\n private async validateAuth(req: IncomingMessage): Promise<Principal | null> {\n const authOptions = this.options.auth as ValidatorAuthOptions | undefined;\n if (!authOptions || !(\"validator\" in authOptions)) return null;\n\n const rawHeader = req.headers[\"authorization\"];\n if (!rawHeader || Array.isArray(rawHeader)) {\n const detail = {\n reason: \"missing_header\",\n scheme: \"bearer\",\n source: \"mcp\",\n };\n this.context.logger.warn(\n detail,\n \"Auth rejected: missing or malformed Authorization header\",\n );\n this.context.emit(\"auth:rejected\", detail);\n return null;\n }\n\n const schemeMatch = /^bearer\\s+(.+)$/i.exec(rawHeader);\n if (!schemeMatch) {\n const detail = {\n reason: \"unsupported_scheme\",\n scheme: \"bearer\",\n source: \"mcp\",\n };\n this.context.logger.warn(\n detail,\n \"Auth rejected: unsupported authorization scheme\",\n );\n this.context.emit(\"auth:rejected\", detail);\n return null;\n }\n const token = schemeMatch[1];\n\n // Delegate to the validator. Throw to reject; return Principal to accept.\n try {\n const result = await authOptions.validator(token);\n const successDetail = {\n subject: result.subject,\n scheme: result.scheme,\n source: \"mcp\",\n };\n this.context.logger.info(successDetail, \"Auth succeeded\");\n this.context.emit(\"auth:success\", successDetail);\n return result;\n } catch (err) {\n const reason = err instanceof Error ? err.message : \"invalid_token\";\n const detail = {\n reason,\n scheme: \"bearer\",\n source: \"mcp\",\n };\n this.context.logger.warn(\n { err, ...detail },\n \"Auth rejected: token validation failed\",\n );\n this.context.emit(\"auth:rejected\", detail);\n return null;\n }\n }\n\n /**\n * Set up request handlers on this.server (used by stdio transport).\n */\n private async setupRequestHandlers(): Promise<void> {\n await this.setupRequestHandlersOn(this.server);\n }\n\n /**\n * Set up request handlers on the given server instance.\n * Uses SDK request schemas so setRequestHandler receives a proper schema (method literal).\n */\n private async setupRequestHandlersOn(server: unknown): Promise<void> {\n let typesModule: Record<string, unknown>;\n try {\n typesModule =\n (await import(\"@modelcontextprotocol/sdk/types.js\")) as Record<\n string,\n unknown\n >;\n } catch {\n throw new Error(MCP_SDK_INSTALL);\n }\n const t = typesModule;\n const ListToolsRequestSchema = t[\"ListToolsRequestSchema\"];\n const CallToolRequestSchema = t[\"CallToolRequestSchema\"];\n\n if (!ListToolsRequestSchema || !CallToolRequestSchema) {\n throw new Error(\n \"MCP SDK types missing ListToolsRequestSchema or CallToolRequestSchema - ensure @modelcontextprotocol/sdk is installed\",\n );\n }\n\n const srv = server as Record<\n string,\n (schema: unknown, handler: (request: unknown) => Promise<unknown>) => void\n >;\n\n srv[\"setRequestHandler\"](ListToolsRequestSchema, async () => {\n const tools = this.getAvailableTools();\n this.logExposedToolsOnce();\n return { tools };\n });\n\n srv[\"setRequestHandler\"](\n CallToolRequestSchema,\n async (request: unknown) => {\n const req = request as Record<string, unknown>;\n const params = req[\"params\"] as Record<string, unknown>;\n return await this.handleToolCall(\n (params[\"name\"] as string) || \"\",\n (params[\"arguments\"] as Record<string, unknown>) || {},\n );\n },\n );\n }\n\n /**\n * Stop the MCP server\n */\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n try {\n if (this.httpServer) {\n // Close all active HTTP sessions.\n for (const [, session] of this.httpSessions) {\n const tr = session.transport as Record<string, () => Promise<void>>;\n if (typeof tr[\"close\"] === \"function\") {\n await tr[\"close\"]();\n }\n }\n this.httpSessions.clear();\n\n await new Promise<void>((resolve) => {\n this.httpServer!.close(() => resolve());\n });\n this.httpServer = null;\n }\n if (this.transport) {\n const tr = this.transport as Record<string, () => Promise<void>>;\n if (typeof tr[\"close\"] === \"function\") {\n await tr[\"close\"]();\n }\n }\n this.running = false;\n this.context.logger.info({}, \"MCP server stopped\");\n } catch (error) {\n const msg = isRoutecraftError(error)\n ? (error as unknown as { meta: { message: string } }).meta.message\n : error instanceof Error\n ? error.message\n : \"Error stopping MCP server\";\n this.context.logger.error({ err: error }, msg);\n }\n }\n\n /**\n * Log exposed MCP tool names once (at start or on first tools/list).\n */\n private logExposedToolsOnce(): void {\n if (this.toolsListLogged) return;\n const tools = this.getAvailableTools();\n if (tools.length === 0) return;\n const names = tools.map((t) => t.name);\n const exposedDetail = { tools: names, count: names.length };\n this.context.logger.info(exposedDetail, \"Exposing MCP tools\");\n this.context.emit(\"plugin:mcp:server:tools:exposed\", exposedDetail);\n this.toolsListLogged = true;\n }\n\n /**\n * Get list of tools that should be exposed via MCP.\n * Reads the registry lazily - called on every tools/list request and for tests.\n */\n getAvailableTools(): McpTool[] {\n const registry = this.context.getStore(ADAPTER_DIRECT_REGISTRY) as\n | Map<string, DirectRouteMetadata>\n | undefined;\n\n if (!registry) {\n return [];\n }\n\n // Get all mcp() routes (those with description)\n let tools = Array.from(registry.values()).filter(\n (t) => t.description !== undefined,\n );\n\n // Apply user filter if provided\n const toolsFilter = this.options.tools;\n if (toolsFilter) {\n if (Array.isArray(toolsFilter)) {\n const allowed = new Set(toolsFilter);\n tools = tools.filter((t) => allowed.has(t.endpoint));\n } else if (typeof toolsFilter === \"function\") {\n tools = tools.filter(toolsFilter);\n }\n }\n\n // Convert to MCP tool format\n return tools.map((meta) => this.metadataToMcpTool(meta));\n }\n\n /**\n * Convert Routecraft mcp() route metadata to MCP tool format\n */\n private metadataToMcpTool(metadata: DirectRouteMetadata): McpTool {\n const tool: McpTool = {\n name: metadata.endpoint,\n description: metadata.description || \"\",\n inputSchema: this.schemaToJsonSchema(\n metadata.schema,\n ) as McpTool[\"inputSchema\"],\n };\n // metadata.annotations is the core direct-adapter pass-through bag; the\n // write site (McpServerOptions.annotations) constrains it to McpToolAnnotations,\n // so this cast restores that type at the read boundary.\n if (metadata.annotations !== undefined) {\n tool.annotations = metadata.annotations as McpToolAnnotations;\n }\n return tool;\n }\n\n /**\n * Convert to JSON Schema using Standard JSON Schema (schema['~standard'].jsonSchema.input)\n * when available; otherwise return a generic object schema.\n * Works with any spec-compliant library (Zod 4.2+, ArkType, Valibot via toStandardJsonSchema).\n */\n private schemaToJsonSchema(schema: unknown): Record<string, unknown> {\n if (!schema || typeof schema !== \"object\") {\n return { type: \"object\" };\n }\n\n const standard = (schema as Record<string, unknown>)[\"~standard\"] as\n | {\n jsonSchema?: {\n input?: (opts: { target: string }) => Record<string, unknown>;\n };\n }\n | undefined;\n if (standard?.jsonSchema?.input) {\n try {\n const out = standard.jsonSchema.input({\n target: \"draft-2020-12\",\n });\n return typeof out === \"object\" && out !== null\n ? out\n : { type: \"object\" };\n } catch (error) {\n this.context.logger.debug(\n error,\n \"Standard JSON Schema conversion failed\",\n );\n return { type: \"object\" };\n }\n }\n\n if (\"~standard\" in schema) {\n return { type: \"object\", additionalProperties: true };\n }\n return { type: \"object\" };\n }\n\n /**\n * Handle a tool call from MCP client\n */\n private async handleToolCall(\n toolName: string,\n args: Record<string, unknown>,\n ): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n }> {\n try {\n // Get the direct channel store\n const channelStore = this.context.getStore(ADAPTER_DIRECT_STORE) as\n | Map<string, Record<string, unknown>>\n | undefined;\n\n if (!channelStore) {\n const err = new Error(\"No direct channels available\");\n this.context.emit(`plugin:mcp:tool:failed`, {\n tool: toolName,\n error: err.message,\n });\n return {\n isError: true,\n content: [\n { type: \"text\", text: `Error: No direct channels available` },\n ],\n };\n }\n\n // Get the channel for this tool endpoint\n const channel = channelStore.get(toolName);\n if (!channel) {\n const err = new Error(`Tool not found: ${toolName}`);\n this.context.emit(`plugin:mcp:tool:failed`, {\n tool: toolName,\n error: err.message,\n });\n return {\n isError: true,\n content: [\n { type: \"text\", text: `Error: Tool not found: ${toolName}` },\n ],\n };\n }\n\n // Ensure body is an object when client sends JSON (SDK may pass parsed object or raw string)\n const body =\n typeof args === \"string\"\n ? (() => {\n try {\n return (JSON.parse(args) as Record<string, unknown>) || {};\n } catch {\n return { input: args };\n }\n })()\n : args && typeof args === \"object\"\n ? args\n : {};\n\n this.context.logger.debug(\n { bodyType: typeof body, body },\n \"MCP tool call exchange body\",\n );\n\n // Build exchange headers, including auth principal if present.\n const principal = principalStore.getStore();\n const headers: Record<string, string | string[] | undefined> = {\n [McpHeadersKeys.TOOL]: toolName,\n [McpHeadersKeys.SESSION]: `mcp-${Date.now()}`,\n };\n if (principal) {\n headers[McpHeadersKeys.AUTH_SUBJECT] = principal.subject;\n headers[McpHeadersKeys.AUTH_SCHEME] = principal.scheme;\n headers[McpHeadersKeys.AUTH_KIND] = principal.kind;\n if (principal.name) headers[McpHeadersKeys.AUTH_NAME] = principal.name;\n if (principal.email)\n headers[McpHeadersKeys.AUTH_EMAIL] = principal.email;\n if (principal.roles)\n headers[McpHeadersKeys.AUTH_ROLES] = principal.roles;\n if (principal.scopes)\n headers[McpHeadersKeys.AUTH_SCOPES] = principal.scopes;\n if (principal.issuer)\n headers[McpHeadersKeys.AUTH_ISSUER] = principal.issuer;\n if (principal.audience)\n headers[McpHeadersKeys.AUTH_AUDIENCE] = principal.audience;\n if (principal.clientId)\n headers[McpHeadersKeys.AUTH_CLIENT_ID] = principal.clientId;\n }\n\n const exchange = new DefaultExchange(this.context, {\n body,\n headers,\n });\n\n this.context.emit(`plugin:mcp:tool:called`, {\n tool: toolName,\n args,\n });\n\n // Send the exchange through the direct channel\n const channelTyped = channel as Record<\n string,\n (name: string, ex: unknown) => Promise<unknown>\n >;\n const resultExchange = (await channelTyped[\"send\"](\n toolName,\n exchange,\n )) as Record<string, unknown>;\n\n // Convert result to MCP format\n const resultText =\n typeof resultExchange[\"body\"] === \"string\"\n ? (resultExchange[\"body\"] as string)\n : JSON.stringify(resultExchange[\"body\"]);\n\n this.context.emit(`plugin:mcp:tool:completed`, {\n tool: toolName,\n });\n\n return {\n content: [{ type: \"text\", text: resultText }],\n };\n } catch (error) {\n const logMsg = isRoutecraftError(error)\n ? (error as unknown as { meta: { message: string } }).meta.message\n : error instanceof Error\n ? error.message\n : String(error);\n this.context.logger.error({ tool: toolName, err: error }, logMsg);\n this.context.emit(`plugin:mcp:tool:failed`, {\n tool: toolName,\n error: logMsg,\n });\n\n // Build a clean user-facing message: include the cause (e.g. schema\n // field errors) but never expose stack traces or internal details.\n let userMsg = logMsg;\n if (isRoutecraftError(error)) {\n const cause = (error as { cause?: Error }).cause;\n if (cause?.message) {\n userMsg = `${logMsg}: ${cause.message}`;\n }\n }\n\n return {\n content: [{ type: \"text\", text: `Error: ${userMsg}` }],\n isError: true,\n };\n }\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { formatSchemaIssues } from \"@routecraft/routecraft\";\nimport type { McpPluginOptions } from \"./types.ts\";\n\n/** Standard Schema validate result: success has value, failure has issues. */\ntype ValidateResult<T = unknown> =\n | { value: T; issues?: never }\n | { value?: never; issues: readonly unknown[] };\n\n/**\n * Validates MCP plugin options at apply time.\n * For full schema validation (required props, shape), use validateWithSchema() with a\n * StandardSchemaV1 from Zod, Valibot, or ArkType before calling mcpPlugin().\n */\nexport function validateMcpPluginOptions(options: McpPluginOptions): void {\n if (options.transport === \"http\") {\n if (options.port !== undefined) {\n if (typeof options.port !== \"number\") {\n throw new TypeError(\n \"mcpPlugin: when transport is 'http', port must be a number\",\n );\n }\n if (options.port < 0 || options.port > 65535) {\n throw new RangeError(\n \"mcpPlugin: port must be between 0 and 65535 when transport is 'http'\",\n );\n }\n }\n if (options.host !== undefined && typeof options.host !== \"string\") {\n throw new TypeError(\"mcpPlugin: when provided, host must be a string\");\n }\n }\n\n // Validate auth options\n if (options.auth !== undefined) {\n if (\"provider\" in options.auth) {\n // OAuth provider auth -- validated by the oauth() factory.\n if (options.auth.provider !== \"oauth\") {\n throw new TypeError(\n 'mcpPlugin: auth.provider must be \"oauth\". Use the oauth() helper.',\n );\n }\n } else if (\"validator\" in options.auth) {\n if (typeof options.auth.validator !== \"function\") {\n throw new TypeError(\n \"mcpPlugin: auth.validator must be a function that returns a Principal (throw to reject)\",\n );\n }\n } else {\n throw new TypeError(\n \"mcpPlugin: auth must have either a 'validator' function or 'provider' set to 'oauth'. \" +\n \"Use jwt(), jwks(), oauth(), or a custom { validator } object.\",\n );\n }\n }\n\n // Validate stdio client configs\n if (options.clients) {\n for (const [name, config] of Object.entries(options.clients)) {\n if (\n typeof config === \"object\" &&\n config !== null &&\n \"transport\" in config &&\n config.transport === \"stdio\"\n ) {\n if (!config.command || typeof config.command !== \"string\") {\n throw new TypeError(\n `mcpPlugin: stdio client \"${name}\" must have a non-empty command string`,\n );\n }\n }\n }\n }\n\n // Validate restart options\n if (options.maxRestarts !== undefined) {\n if (\n typeof options.maxRestarts !== \"number\" ||\n !Number.isInteger(options.maxRestarts) ||\n options.maxRestarts < 0\n ) {\n throw new TypeError(\n \"mcpPlugin: maxRestarts must be a non-negative integer\",\n );\n }\n }\n if (options.restartDelayMs !== undefined) {\n if (\n typeof options.restartDelayMs !== \"number\" ||\n options.restartDelayMs <= 0\n ) {\n throw new TypeError(\n \"mcpPlugin: restartDelayMs must be a positive number\",\n );\n }\n }\n if (options.restartBackoffMultiplier !== undefined) {\n if (\n typeof options.restartBackoffMultiplier !== \"number\" ||\n options.restartBackoffMultiplier < 1\n ) {\n throw new TypeError(\"mcpPlugin: restartBackoffMultiplier must be >= 1\");\n }\n }\n\n // Validate HTTP tool refresh interval\n if (options.toolRefreshIntervalMs !== undefined) {\n if (\n typeof options.toolRefreshIntervalMs !== \"number\" ||\n !Number.isInteger(options.toolRefreshIntervalMs) ||\n options.toolRefreshIntervalMs < 0\n ) {\n throw new TypeError(\n \"mcpPlugin: toolRefreshIntervalMs must be a non-negative integer\",\n );\n }\n }\n}\n\n/**\n * Validate plugin options with a StandardSchemaV1 (e.g. from Zod, Valibot, ArkType).\n * Use this when you need required props or full shape validation before mcpPlugin().\n *\n * @example\n * import { z } from \"zod\";\n * const schema = z.object({ transport: z.enum([\"stdio\", \"http\"]), port: z.number().optional() });\n * const validated = await validateWithSchema(options, schema);\n * mcpPlugin(validated);\n */\nexport async function validateWithSchema(\n options: McpPluginOptions,\n schema: StandardSchemaV1,\n): Promise<McpPluginOptions> {\n const standard = (\n schema as {\n \"~standard\"?: {\n validate: (\n v: unknown,\n ) => ValidateResult<unknown> | Promise<ValidateResult<unknown>>;\n };\n }\n )[\"~standard\"];\n if (!standard?.validate) {\n throw new Error(\n \"mcpPlugin: schema must be a StandardSchemaV1 with ~standard.validate\",\n );\n }\n let result = standard.validate(options);\n if (result instanceof Promise) {\n result = await result;\n }\n if (result.issues) {\n throw new Error(\n `mcpPlugin options validation failed: ${formatSchemaIssues(result.issues)}`,\n );\n }\n // Guard against schemas that pass (no issues) but omit value\n if (result.value === undefined) {\n throw new Error(\"mcpPlugin options validation failed: no value returned\");\n }\n return result.value as McpPluginOptions;\n}\n","import type { McpTool } from \"./types.ts\";\nimport { extractContent } from \"./extract-content.ts\";\n\nconst MCP_SDK_INSTALL =\n 'MCP stdio client requires \"@modelcontextprotocol/sdk\". Install it with: pnpm add @modelcontextprotocol/sdk';\n\nexport interface StdioClientManagerOptions {\n serverId: string;\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n maxRestarts: number;\n restartDelayMs: number;\n restartBackoffMultiplier: number;\n}\n\n/** Logger interface matching pino child logger shape used in Routecraft. */\ninterface Logger {\n info(obj: Record<string, unknown>, msg: string): void;\n warn(obj: Record<string, unknown>, msg: string): void;\n error(obj: Record<string, unknown>, msg: string): void;\n debug(obj: Record<string, unknown>, msg: string): void;\n}\n\n/** Typed subset of the MCP SDK Client used by StdioClientManager. */\ninterface McpSdkClient {\n connect(transport: unknown): Promise<void>;\n close(): Promise<void>;\n listTools(): Promise<{ tools: McpTool[] }>;\n callTool(params: {\n name: string;\n arguments?: Record<string, unknown>;\n }): Promise<{\n content?: Array<{ type: string; text?: string; data?: string }>;\n }>;\n}\n\n/**\n * Manages a single stdio MCP client subprocess.\n *\n * Delegates to the MCP SDK's Client + StdioClientTransport for process spawning,\n * protocol handling, and tool listing. Adds auto-restart with exponential backoff\n * and event bridging into Routecraft's event system.\n */\nexport class StdioClientManager {\n private client: McpSdkClient | null = null;\n private transport: unknown = null;\n private running = false;\n private stopping = false;\n private restartCount = 0;\n private restartTimer: ReturnType<typeof setTimeout> | null = null;\n private stabilityTimer: ReturnType<typeof setTimeout> | null = null;\n private tools: McpTool[] = [];\n\n /**\n * @param options - Subprocess command, restart policy, and server identity\n * @param logger - Logger matching the pino child logger shape\n * @param onEvent - Callback invoked for every lifecycle event\n * @param onToolsUpdated - Callback invoked whenever the tool list changes\n */\n constructor(\n private readonly options: StdioClientManagerOptions,\n private readonly logger: Logger,\n private readonly onEvent: (\n event: string,\n details: Record<string, unknown>,\n ) => void,\n private readonly onToolsUpdated: (\n serverId: string,\n tools: McpTool[],\n ) => void,\n ) {}\n\n /** Spawn the child process, perform the MCP handshake, and list initial tools. */\n async start(): Promise<void> {\n if (this.running) return;\n this.stopping = false;\n\n // Cancel any pending restart to avoid race with externally-initiated start\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n\n type SdkClientModule =\n typeof import(\"@modelcontextprotocol/sdk/client/index.js\");\n type SdkStdioModule =\n typeof import(\"@modelcontextprotocol/sdk/client/stdio.js\");\n\n let clientMod: SdkClientModule;\n let stdioMod: SdkStdioModule;\n\n try {\n clientMod = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n stdioMod = await import(\"@modelcontextprotocol/sdk/client/stdio.js\");\n } catch {\n throw new Error(MCP_SDK_INSTALL);\n }\n\n const { serverId, command, args, env, cwd } = this.options;\n\n // Create transport (spawns child process)\n this.transport = new stdioMod.StdioClientTransport({\n command,\n args: args ?? [],\n ...(env ? { env } : {}),\n ...(cwd ? { cwd } : {}),\n stderr: \"pipe\",\n });\n\n // Wire up transport error/close handlers\n const transport = this.transport as {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n stderr: {\n on?: (event: string, cb: (data: unknown) => void) => void;\n } | null;\n };\n\n transport.onerror = (error: Error) => {\n this.logger.error(\n { err: error, serverId },\n \"Stdio client transport error\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:error`, {\n serverId,\n error,\n });\n };\n\n transport.onclose = () => {\n if (!this.stopping) {\n this.running = false;\n this.handleDisconnect();\n }\n };\n\n // Log stderr from child process\n if (transport.stderr?.on) {\n transport.stderr.on(\"data\", (data: unknown) => {\n this.logger.debug(\n { serverId, stderr: String(data).trimEnd() },\n \"Stdio client stderr output\",\n );\n });\n }\n\n // Create client with listChanged support for auto tool refresh\n this.client = new clientMod.Client(\n { name: \"routecraft-mcp-client\", version: \"1.0.0\" },\n {\n capabilities: {},\n listChanged: {\n tools: {\n onChanged: (_error: unknown, tools: unknown) => {\n if (\n tools &&\n Array.isArray((tools as { tools: unknown[] }).tools)\n ) {\n this.tools = (tools as { tools: McpTool[] }).tools;\n this.onToolsUpdated(serverId, this.tools);\n this.onEvent(`plugin:mcp:client:${serverId}:tools:listed`, {\n serverId,\n toolCount: this.tools.length,\n });\n } else {\n // Server notified of change but SDK couldn't fetch; re-list manually\n void this.refreshTools();\n }\n },\n },\n },\n },\n ) as unknown as McpSdkClient;\n\n // Connect (performs MCP initialize handshake)\n await this.client.connect(this.transport);\n\n this.running = true;\n\n // List initial tools\n await this.refreshTools();\n\n this.logger.info(\n { serverId, toolCount: this.tools.length },\n \"Stdio client started\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:started`, {\n serverId,\n toolCount: this.tools.length,\n });\n }\n\n /** Gracefully close the client and transport, cancelling any pending restart. */\n async stop(): Promise<void> {\n this.stopping = true;\n\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n if (this.stabilityTimer) {\n clearTimeout(this.stabilityTimer);\n this.stabilityTimer = null;\n }\n\n const { serverId } = this.options;\n\n if (this.client) {\n try {\n await this.client.close();\n } catch {\n // Ignore cleanup errors\n }\n this.client = null;\n }\n\n if (this.transport) {\n const transportWithClose = this.transport as {\n close?: () => void | Promise<void>;\n };\n if (typeof transportWithClose.close === \"function\") {\n try {\n await Promise.resolve(transportWithClose.close());\n } catch {\n // Ignore cleanup errors\n }\n }\n this.transport = null;\n }\n\n this.running = false;\n this.logger.info({ serverId }, \"Stdio client stopped\");\n this.onEvent(`plugin:mcp:client:${serverId}:stopped`, {\n serverId,\n reason: \"graceful\",\n });\n }\n\n /**\n * Call a tool on the remote MCP server.\n * Delegates to SDK Client.callTool().\n *\n * @param name - Tool name to invoke\n * @param args - Arguments passed to the tool\n * @returns The tool result (text content extracted when available)\n */\n async callTool(\n name: string,\n args: Record<string, unknown>,\n ): Promise<unknown> {\n if (!this.running || !this.client) {\n throw new Error(\n `Stdio client \"${this.options.serverId}\" is not running. Cannot call tool \"${name}\".`,\n );\n }\n\n const response = await this.client.callTool({\n name,\n arguments: args,\n });\n\n return extractContent(response);\n }\n\n /** @returns The current list of tools advertised by this server. */\n getTools(): McpTool[] {\n return [...this.tools];\n }\n\n /** @returns Whether the subprocess is connected and running. */\n isRunning(): boolean {\n return this.running;\n }\n\n private async refreshTools(): Promise<void> {\n if (!this.client) return;\n\n const { serverId } = this.options;\n\n try {\n const result = await this.client.listTools();\n this.tools = result.tools ?? [];\n this.onToolsUpdated(serverId, this.tools);\n this.onEvent(`plugin:mcp:client:${serverId}:tools:listed`, {\n serverId,\n toolCount: this.tools.length,\n });\n } catch (err) {\n this.logger.warn(\n { err, serverId },\n \"Failed to list tools for stdio client\",\n );\n }\n }\n\n private handleDisconnect(): void {\n const { serverId, maxRestarts, restartDelayMs, restartBackoffMultiplier } =\n this.options;\n\n // Clear stale tools so consumers don't see tools from a dead process\n if (this.tools.length > 0) {\n this.tools = [];\n this.onToolsUpdated(serverId, []);\n }\n\n this.logger.warn({ serverId }, \"Stdio client disconnected unexpectedly\");\n this.onEvent(`plugin:mcp:client:${serverId}:stopped`, {\n serverId,\n reason: \"unexpected\",\n });\n\n if (this.restartCount >= maxRestarts) {\n this.logger.error(\n { serverId, restartCount: this.restartCount, maxRestarts },\n \"Stdio client exceeded max restarts, giving up\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:error`, {\n serverId,\n error: new Error(\n `Max restarts (${maxRestarts}) exceeded for stdio client \"${serverId}\"`,\n ),\n });\n return;\n }\n\n const delay =\n restartDelayMs * Math.pow(restartBackoffMultiplier, this.restartCount);\n this.logger.info(\n { serverId, restartCount: this.restartCount, delayMs: delay },\n \"Scheduling stdio client restart\",\n );\n\n this.restartTimer = setTimeout(() => {\n this.restartTimer = null;\n void this.restart();\n }, delay);\n }\n\n private async restart(): Promise<void> {\n const { serverId } = this.options;\n this.restartCount++;\n\n // Clean up stale references\n this.client = null;\n this.transport = null;\n\n try {\n await this.start();\n this.logger.info(\n { serverId, restartCount: this.restartCount },\n \"Stdio client restarted successfully\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:restarted`, {\n serverId,\n restartCount: this.restartCount,\n });\n // Reset restart count only after process stays alive for a stability period.\n // This prevents a flapping process from resetting the counter on every\n // momentary connection and bypassing maxRestarts.\n const stableMs = this.options.restartDelayMs * 2;\n this.stabilityTimer = setTimeout(() => {\n this.stabilityTimer = null;\n if (this.running) this.restartCount = 0;\n }, stableMs);\n } catch (err) {\n this.logger.error(\n { err, serverId, restartCount: this.restartCount },\n \"Stdio client restart failed\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:error`, {\n serverId,\n error: err,\n });\n // Schedule another restart attempt\n this.handleDisconnect();\n }\n }\n}\n","import type { McpTool, McpToolRegistryEntry } from \"./types.ts\";\n\n/**\n * Central registry of MCP tools discovered from remote MCP servers.\n * Stored in context store under MCP_TOOL_REGISTRY for agent adapter discovery.\n *\n * Populated automatically by mcpPlugin for these sources:\n * - stdio clients: long-lived subprocess MCP servers\n * - HTTP clients: remote HTTP MCP servers (tools refreshed periodically)\n *\n * Local `mcp()` routes defined in the same context are NOT auto-populated here;\n * they are read directly from ADAPTER_DIRECT_REGISTRY by the MCP server when\n * responding to `tools/list`. The \"local\" transport label remains a valid value\n * for callers that want to manually register tools with that provenance.\n *\n * @experimental\n */\nexport class McpToolRegistry {\n /** Nested Map: source -> toolName -> McpToolRegistryEntry */\n private tools = new Map<string, Map<string, McpToolRegistryEntry>>();\n\n /**\n * Set all tools for a given source (replaces previous tools from that source).\n * Called on initial tool listing and on re-listing after restart/refresh.\n *\n * @param source - Identifier for the tool source (e.g. server ID or \"local\")\n * @param transport - How the tools are reached (\"stdio\", \"http\", or \"local\")\n * @param tools - Tool definitions to register for this source\n */\n setToolsForSource(\n source: string,\n transport: \"stdio\" | \"http\" | \"local\",\n tools: McpTool[],\n ): void {\n const sourceMap = new Map<string, McpToolRegistryEntry>();\n\n for (const tool of tools) {\n const entry: McpToolRegistryEntry = {\n name: tool.name,\n inputSchema: tool.inputSchema as Record<string, unknown>,\n source,\n transport,\n };\n if (tool.description !== undefined) {\n entry.description = tool.description;\n }\n if (tool.annotations !== undefined) {\n entry.annotations = tool.annotations;\n }\n sourceMap.set(tool.name, entry);\n }\n\n this.tools.set(source, sourceMap);\n }\n\n /**\n * Remove all tools for a source (when a client is permanently stopped).\n *\n * @param source - Source identifier whose tools should be removed\n */\n removeSource(source: string): void {\n this.tools.delete(source);\n }\n\n /**\n * Get all tools across all sources.\n *\n * @returns Array of every registered tool entry\n */\n getTools(): McpToolRegistryEntry[] {\n const result: McpToolRegistryEntry[] = [];\n for (const sourceMap of this.tools.values()) {\n for (const entry of sourceMap.values()) {\n result.push(entry);\n }\n }\n return result;\n }\n\n /**\n * Get tools from a specific source/server.\n *\n * @param serverId - Source identifier to filter by\n * @returns Array of tool entries belonging to that source\n */\n getToolsByServer(serverId: string): McpToolRegistryEntry[] {\n const sourceMap = this.tools.get(serverId);\n if (!sourceMap) return [];\n return Array.from(sourceMap.values());\n }\n\n /**\n * Get a specific tool by name. Returns first match if name exists in multiple sources.\n *\n * @param name - Tool name to search for\n * @returns The first matching entry, or undefined\n */\n getTool(name: string): McpToolRegistryEntry | undefined {\n for (const sourceMap of this.tools.values()) {\n const entry = sourceMap.get(name);\n if (entry) return entry;\n }\n return undefined;\n }\n\n /**\n * Get a specific tool by source and name.\n *\n * @param source - Source identifier\n * @param name - Tool name\n * @returns The matching entry, or undefined\n */\n getToolBySource(\n source: string,\n name: string,\n ): McpToolRegistryEntry | undefined {\n return this.tools.get(source)?.get(name);\n }\n}\n","import {\n type CraftContext,\n type CraftPlugin,\n type EventName,\n} from \"@routecraft/routecraft\";\nimport { McpServer } from \"./server.ts\";\nimport {\n ADAPTER_MCP_CLIENT_SERVERS,\n MCP_PLUGIN_REGISTERED,\n MCP_STDIO_MANAGERS,\n MCP_TOOL_REGISTRY,\n} from \"./types.ts\";\nimport type {\n McpClientHttpConfig,\n McpClientStdioConfig,\n McpPluginOptions,\n McpTool,\n} from \"./types.ts\";\nimport { validateMcpPluginOptions } from \"./validate-options.ts\";\nimport { StdioClientManager } from \"./stdio-client-manager.ts\";\nimport { McpToolRegistry } from \"./tool-registry.ts\";\nimport { buildAuthHeaders } from \"./build-auth-headers.ts\";\n\ntype ClientConfig = McpClientHttpConfig | McpClientStdioConfig;\n\nfunction isStdioConfig(config: ClientConfig): config is McpClientStdioConfig {\n return \"transport\" in config && config.transport === \"stdio\";\n}\n\n/**\n * MCP plugin: one plugin per adapter. Starts the MCP server during plugin apply (before routes start) so startup failures fail context build. Exposes mcp() routes to external MCP clients.\n * Optional clients: register named remote MCP servers so routes can use .to(mcp(\"name:tool\")) without passing url.\n * Stdio clients are spawned as subprocesses with auto-restart; HTTP clients are used for ephemeral tool calls.\n * All discovered external tools (stdio, HTTP) are stored in a unified McpToolRegistry for agent adapter discovery.\n * Required when any route uses .from(mcp(...)); the route will fail at start if this plugin is not applied.\n *\n * @experimental\n */\nexport function mcpPlugin(options: McpPluginOptions = {}): CraftPlugin {\n validateMcpPluginOptions(options);\n\n let server: McpServer | null = null;\n const stdioManagers = new Map<string, StdioClientManager>();\n const httpClients = new Map<\n string,\n { close(): Promise<void>; listTools(): Promise<{ tools: McpTool[] }> }\n >();\n const httpRefreshTimers: ReturnType<typeof setInterval>[] = [];\n let toolRegistry: McpToolRegistry | null = null;\n\n return {\n async apply(ctx: CraftContext) {\n ctx.setStore(\n MCP_PLUGIN_REGISTERED as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n true,\n );\n\n // Create and store tool registry\n toolRegistry = new McpToolRegistry();\n ctx.setStore(\n MCP_TOOL_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n toolRegistry,\n );\n\n // Store stdio managers map so destination adapter can call tools on stdio clients\n ctx.setStore(\n MCP_STDIO_MANAGERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n stdioManagers as unknown as Map<\n string,\n {\n callTool(\n name: string,\n args: Record<string, unknown>,\n ): Promise<unknown>;\n }\n >,\n );\n\n if (options.clients && Object.keys(options.clients).length > 0) {\n const clientEntries = Object.entries(options.clients);\n const map = new Map<\n string,\n McpClientHttpConfig | McpClientStdioConfig | string\n >();\n for (const [k, v] of clientEntries) {\n map.set(k, v);\n }\n ctx.setStore(\n ADAPTER_MCP_CLIENT_SERVERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n map,\n );\n\n // Start stdio clients and list HTTP client tools\n for (const [serverId, config] of clientEntries) {\n if (isStdioConfig(config)) {\n await startStdioClient(ctx, serverId, config, toolRegistry);\n } else {\n // HTTP client: list tools immediately and optionally refresh periodically\n const httpConfig = config as McpClientHttpConfig;\n await listHttpClientTools(\n ctx,\n serverId,\n httpConfig.url,\n toolRegistry,\n httpConfig.auth,\n );\n setupHttpToolRefresh(\n ctx,\n serverId,\n httpConfig.url,\n toolRegistry,\n httpConfig.auth,\n );\n }\n\n const transport = isStdioConfig(config) ? \"stdio\" : \"http\";\n ctx.emit(\n `plugin:mcp:client:${serverId}:registered` as EventName,\n { serverId, transport } as Record<string, unknown>,\n );\n }\n }\n\n server = new McpServer(ctx, options);\n await server.start();\n },\n async teardown(ctx: CraftContext) {\n // Clear HTTP refresh timers\n for (const timer of httpRefreshTimers) {\n clearInterval(timer);\n }\n httpRefreshTimers.length = 0;\n\n // Close persistent HTTP clients\n for (const [serverId, client] of httpClients) {\n try {\n await client.close();\n } catch (error) {\n ctx.logger.error(\n { err: error, serverId, operation: \"close\" },\n \"Failed to close HTTP client\",\n );\n }\n }\n httpClients.clear();\n\n // Stop all stdio client managers\n for (const [serverId, manager] of stdioManagers) {\n try {\n await manager.stop();\n } catch (error) {\n ctx.logger.error(\n { err: error, serverId, operation: \"stop\" },\n \"Failed to stop stdio client\",\n );\n }\n }\n stdioManagers.clear();\n\n if (server) {\n try {\n await server.stop();\n } catch (error) {\n ctx.logger.error(\n { err: error, operation: \"stop\" },\n \"Failed to stop MCP server plugin\",\n );\n }\n server = null;\n }\n\n toolRegistry = null;\n },\n };\n\n async function startStdioClient(\n ctx: CraftContext,\n serverId: string,\n config: McpClientStdioConfig,\n registry: McpToolRegistry,\n ): Promise<void> {\n const managerOpts: import(\"./stdio-client-manager.ts\").StdioClientManagerOptions =\n {\n serverId,\n command: config.command,\n args: config.args ?? [],\n maxRestarts: options.maxRestarts ?? 5,\n restartDelayMs: options.restartDelayMs ?? 1000,\n restartBackoffMultiplier: options.restartBackoffMultiplier ?? 2,\n };\n if (config.env !== undefined) managerOpts.env = config.env;\n if (config.cwd !== undefined) managerOpts.cwd = config.cwd;\n\n const manager = new StdioClientManager(\n managerOpts,\n ctx.logger,\n (event, details) => {\n ctx.emit(event as EventName, details as Record<string, unknown>);\n },\n (_serverId, tools) => {\n registry.setToolsForSource(_serverId, \"stdio\", tools);\n },\n );\n\n stdioManagers.set(serverId, manager);\n\n try {\n await manager.start();\n } catch (error) {\n ctx.logger.error(\n { err: error, serverId, operation: \"start\" },\n \"Failed to start stdio client\",\n );\n ctx.emit(\n `plugin:mcp:client:${serverId}:error` as EventName,\n {\n serverId,\n error,\n } as Record<string, unknown>,\n );\n }\n }\n\n async function getOrCreateHttpClient(\n serverId: string,\n url: string,\n auth?: McpClientHttpConfig[\"auth\"],\n ): Promise<{\n close(): Promise<void>;\n listTools(): Promise<{ tools: McpTool[] }>;\n }> {\n const existing = httpClients.get(serverId);\n if (existing) return existing;\n\n const { Client } =\n await import(\"@modelcontextprotocol/sdk/client/index.js\");\n const { StreamableHTTPClientTransport } =\n await import(\"@modelcontextprotocol/sdk/client/streamableHttp.js\");\n\n const headers = await buildAuthHeaders(auth);\n const transportOptions = headers ? { requestInit: { headers } } : undefined;\n const transport = new (StreamableHTTPClientTransport as new (\n url: URL,\n options?: { requestInit?: { headers?: Record<string, string> } },\n ) => unknown)(new URL(url), transportOptions);\n const rawClient = new Client(\n { name: \"routecraft-mcp-client\", version: \"1.0.0\" },\n { capabilities: {} },\n );\n await (\n rawClient as unknown as { connect(t: unknown): Promise<void> }\n ).connect(transport);\n\n const typed = rawClient as unknown as {\n close(): Promise<void>;\n listTools(): Promise<{ tools: McpTool[] }>;\n };\n httpClients.set(serverId, typed);\n return typed;\n }\n\n async function listHttpClientTools(\n ctx: CraftContext,\n serverId: string,\n url: string,\n registry: McpToolRegistry,\n auth?: McpClientHttpConfig[\"auth\"],\n ): Promise<void> {\n try {\n const client = await getOrCreateHttpClient(serverId, url, auth);\n\n const result = await client.listTools();\n const tools = result.tools ?? [];\n registry.setToolsForSource(serverId, \"http\", tools);\n\n ctx.emit(\n `plugin:mcp:client:${serverId}:tools:listed` as EventName,\n {\n serverId,\n toolCount: tools.length,\n } as Record<string, unknown>,\n );\n } catch (error) {\n // Connection may have gone stale; discard so next attempt reconnects\n httpClients.delete(serverId);\n ctx.logger.warn(\n { err: error, serverId, url, operation: \"listTools\" },\n \"Failed to list tools from HTTP client\",\n );\n }\n }\n\n function setupHttpToolRefresh(\n ctx: CraftContext,\n serverId: string,\n url: string,\n registry: McpToolRegistry,\n auth?: McpClientHttpConfig[\"auth\"],\n ): void {\n const interval = options.toolRefreshIntervalMs ?? 60_000;\n if (interval <= 0) return;\n\n const timer = setInterval(() => {\n void listHttpClientTools(ctx, serverId, url, registry, auth);\n }, interval);\n httpRefreshTimers.push(timer);\n }\n}\n","import type { Exchange } from \"@routecraft/routecraft\";\nimport type { AgentOptions, AgentResult } from \"./types.ts\";\n\n/**\n * Internal runner for the agent loop. Phase 1: stub that passes through and returns\n * exchange body. Full implementation (LLM + tool dispatch) in Phase 2.\n */\nexport class AgentRunner {\n constructor(private readonly _options: AgentOptions) {}\n\n async run(exchange: Exchange<unknown>): Promise<AgentResult> {\n void this._options; // Phase 2 will use modelId, allowedRoutes, etc.\n // Phase 1: pass-through only\n if (exchange.logger) {\n exchange.logger.debug(\n { adapter: \"agent\" },\n \"Agent pass-through — implementation pending\",\n );\n }\n return {\n output: exchange.body,\n steps: 0,\n };\n }\n}\n","import type { Destination, Exchange } from \"@routecraft/routecraft\";\nimport { AgentRunner } from \"./runner.ts\";\nimport type { AgentOptions, AgentResult } from \"./types.ts\";\n\n/** Validate modelId format \"providerId:modelName\". */\nfunction validateModelId(modelId: string): void {\n const colon = modelId.indexOf(\":\");\n if (colon < 1 || colon === modelId.length - 1) {\n throw new Error(\n `Agent adapter: modelId must be \"providerId:modelName\" (e.g. ollama:llama3). Got: \"${modelId}\"`,\n );\n }\n}\n\n/**\n * Agent destination adapter.\n * Use via agent(); do not instantiate AgentRunner directly.\n *\n * @experimental\n */\nexport class AgentDestinationAdapter implements Destination<\n unknown,\n AgentResult\n> {\n readonly adapterId = \"routecraft.adapter.agent\";\n\n private readonly runner: AgentRunner;\n\n constructor(options: AgentOptions) {\n validateModelId(options.modelId);\n this.runner = new AgentRunner(options);\n }\n\n async send(exchange: Exchange<unknown>): Promise<AgentResult> {\n return this.runner.run(exchange);\n }\n}\n","import type { Destination } from \"@routecraft/routecraft\";\nimport { AgentDestinationAdapter } from \"./destination.ts\";\nimport type { AgentOptions, AgentResult } from \"./types.ts\";\n\n/**\n * Create an agent destination.\n *\n * @experimental\n * @param options Agent options (modelId, systemPrompt, allowedRoutes, etc.)\n * @returns Destination that produces AgentResult\n */\nexport function agent(\n options: AgentOptions,\n): Destination<unknown, AgentResult> {\n return new AgentDestinationAdapter(options);\n}\n","import type { EmbeddingModelConfig } from \"../types.ts\";\n\nexport interface CallEmbeddingParams {\n config: EmbeddingModelConfig;\n modelName: string;\n text: string;\n}\n\ntype PipelineFn = (\n text: string,\n options?: { pooling?: string; normalize?: boolean },\n) => Promise<unknown>;\n\ninterface CachedPipeline {\n run: PipelineFn;\n dispose?: (() => Promise<void>) | undefined;\n}\n\nconst pipelineCache = new Map<string, CachedPipeline>();\n\n/**\n * Dispose all cached HuggingFace pipelines and clear the cache. Call on context\n * shutdown so pipeline.dispose() releases native/ONNX resources.\n *\n * Callers must avoid process.exit() after this -- let the event loop drain\n * naturally so ONNX Runtime's C++ statics aren't torn down prematurely\n * (onnxruntime#25038: \"mutex lock failed: Invalid argument\").\n *\n * @experimental\n */\nexport async function disposeEmbeddingPipelineCache(): Promise<void> {\n const entries = [...pipelineCache.entries()];\n pipelineCache.clear();\n if (entries.length === 0) return;\n\n await Promise.all(\n entries.map(async ([, cached]) => {\n try {\n if (typeof cached.dispose === \"function\") {\n await cached.dispose();\n }\n } catch {\n // Ignore dispose errors during shutdown\n }\n }),\n );\n}\n\n/** Resolve to full Hugging Face repo id. Short names like \"all-MiniLM-L6-v2\" use Xenova/ (ONNX-converted). */\nfunction resolveHuggingFaceModel(modelName: string): string {\n if (modelName.includes(\"/\")) return modelName;\n return `Xenova/${modelName}`;\n}\n\nconst HUGGINGFACE_INSTALL =\n 'The Hugging Face embedding provider requires \"@huggingface/transformers\". Install it with: pnpm add @huggingface/transformers';\n\nfunction isModuleNotFoundFor(error: unknown, pkg: string): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message ?? \"\";\n return (\n (msg.includes(\"ERR_MODULE_NOT_FOUND\") ||\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Cannot find package\")) &&\n msg.includes(pkg)\n );\n}\n\nasync function getHuggingFacePipeline(modelName: string): Promise<PipelineFn> {\n const resolved = resolveHuggingFaceModel(modelName);\n const cached = pipelineCache.get(resolved);\n if (cached) return cached.run;\n\n let pipelineFn: (\n task: string,\n model: string,\n opts?: { dtype?: string },\n ) => Promise<unknown>;\n try {\n const mod = await import(\"@huggingface/transformers\");\n pipelineFn = mod.pipeline as typeof pipelineFn;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@huggingface/transformers\")) {\n throw new Error(HUGGINGFACE_INSTALL);\n }\n throw error;\n }\n const pipe = (await pipelineFn(\"feature-extraction\", resolved, {\n dtype: \"fp32\",\n })) as {\n (\n text: string,\n options?: { pooling?: string; normalize?: boolean },\n ): Promise<unknown>;\n dispose?: () => void;\n };\n const run: PipelineFn = (text, options) =>\n pipe(text, {\n pooling: (options?.pooling ?? \"mean\") as \"mean\",\n normalize: options?.normalize ?? true,\n });\n const entry: CachedPipeline = {\n run,\n dispose:\n typeof pipe.dispose === \"function\"\n ? () => Promise.resolve(pipe.dispose!())\n : undefined,\n };\n pipelineCache.set(resolved, entry);\n return run;\n}\n\nfunction previewForError(value: unknown): string {\n if (value === null) return \"null\";\n if (typeof value !== \"object\") return String(value);\n if (Array.isArray(value)) return `array(${value.length})`;\n try {\n const s = JSON.stringify(value);\n return s.length > 100 ? s.slice(0, 100) + \"...\" : s;\n } catch {\n return \"object\";\n }\n}\n\nfunction toNumberArray(data: Float32Array | number[] | unknown): number[] {\n if (Array.isArray(data)) return data as number[];\n if (data instanceof Float32Array) return Array.from(data);\n if (data && typeof data === \"object\" && \"data\" in data) {\n const d = (data as { data: unknown }).data;\n if (Array.isArray(d)) return d as number[];\n if (d instanceof Float32Array) return Array.from(d);\n throw new Error(\n `Embedding output .data must be an Array or Float32Array; got ${typeof d}: ${previewForError(d)}`,\n );\n }\n throw new Error(\n `Embedding output must be an Array, Float32Array, or object with .data; got ${typeof data}: ${previewForError(data)}`,\n );\n}\n\nexport async function callEmbedding(\n params: CallEmbeddingParams,\n): Promise<number[]> {\n const { config, modelName, text } = params;\n if (config.provider === \"mock\") {\n const dim = 8;\n const vec: number[] = [];\n for (let i = 0; i < dim; i++) {\n vec.push(((text.length + i) % 100) / 100);\n }\n return vec;\n }\n if (config.provider === \"huggingface\") {\n const pipe = await getHuggingFacePipeline(modelName);\n const output = await pipe(text, {\n pooling: \"mean\" as const,\n normalize: true,\n });\n const data =\n output && typeof output === \"object\" && \"data\" in output\n ? (output as { data: Float32Array | number[] }).data\n : output;\n return toNumberArray(data);\n }\n if (config.provider === \"ollama\" || config.provider === \"openai\") {\n throw new Error(\n `Embedding provider \"${config.provider}\" is not yet implemented. Use huggingface for now.`,\n );\n }\n throw new Error(\n `Unknown embedding provider: ${(config as EmbeddingModelConfig).provider}`,\n );\n}\n","import type { Exchange } from \"@routecraft/routecraft\";\n\n/** Store key for plugin-registered embedding providers (provider id → EmbeddingModelConfig). */\nexport const ADAPTER_EMBEDDING_PROVIDERS = Symbol.for(\n \"routecraft.adapter.embedding.providers\",\n);\n\n/** Store key for context-level default embedding options. */\nexport const ADAPTER_EMBEDDING_OPTIONS = Symbol.for(\n \"routecraft.adapter.embedding.options\",\n);\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [ADAPTER_EMBEDDING_PROVIDERS]: Map<string, EmbeddingModelConfig>;\n [ADAPTER_EMBEDDING_OPTIONS]: Partial<EmbeddingOptions>;\n }\n}\n\nexport interface EmbeddingModelConfigHuggingFace {\n provider: \"huggingface\";\n}\n\nexport interface EmbeddingModelConfigOllama {\n provider: \"ollama\";\n baseURL?: string;\n}\n\nexport interface EmbeddingModelConfigOpenAI {\n provider: \"openai\";\n apiKey: string;\n baseURL?: string;\n}\n\n/** Used by tests only: returns a deterministic vector, no model download. */\nexport interface EmbeddingModelConfigMock {\n provider: \"mock\";\n}\n\nexport type EmbeddingModelConfig =\n | EmbeddingModelConfigHuggingFace\n | EmbeddingModelConfigOllama\n | EmbeddingModelConfigOpenAI\n | EmbeddingModelConfigMock;\n\nexport type EmbeddingProviderType =\n | \"huggingface\"\n | \"ollama\"\n | \"openai\"\n | \"mock\";\n\nexport interface EmbeddingOptions<T = unknown> {\n /** Build the string to embed from the exchange (e.g. jobTitle + location). */\n using: (exchange: Exchange<T>) => string | string[];\n}\n\nexport interface EmbeddingResult {\n embedding: number[];\n}\n\n/** Provider options for embeddingPlugin({ providers }). Key is the provider id. */\nexport interface EmbeddingPluginProviders {\n huggingface?: Record<string, never>;\n ollama?: { baseURL?: string };\n openai?: { apiKey: string; baseURL?: string };\n /** Test-only: deterministic vector, no network. */\n mock?: Record<string, never>;\n}\n\nexport interface EmbeddingPluginOptions {\n providers: EmbeddingPluginProviders;\n /** Optional context-level default options. */\n defaultOptions?: Partial<EmbeddingOptions>;\n}\n\n/**\n * Recommended embedding model ids for autocomplete.\n * Format: \"providerId:modelName\". Custom models are allowed via string.\n * Updated for 2026.\n */\nexport type EmbeddingModelId =\n // HuggingFace\n | \"huggingface:all-MiniLM-L6-v2\"\n | \"huggingface:sentence-transformers/all-MiniLM-L6-v2\"\n | \"huggingface:sentence-transformers/all-mpnet-base-v2\"\n | \"huggingface:BAAI/bge-small-en-v1.5\"\n | \"huggingface:BAAI/bge-base-en-v1.5\"\n | \"huggingface:BAAI/bge-m3\"\n | \"huggingface:intfloat/e5-small-v2\"\n | \"huggingface:intfloat/e5-base-v2\"\n | \"huggingface:intfloat/multilingual-e5-large\"\n // OpenAI\n | \"openai:text-embedding-3-small\"\n | \"openai:text-embedding-3-large\"\n | \"openai:text-embedding-ada-002\"\n // Ollama\n | \"ollama:nomic-embed-text\"\n | \"ollama:nomic-embed-text-v1.5\"\n | \"ollama:mxbai-embed-large\"\n | \"ollama:all-minilm\"\n // Other (custom models)\n | string;\n","import {\n getExchangeContext,\n type CraftContext,\n type Destination,\n type Exchange,\n type MergedOptions,\n} from \"@routecraft/routecraft\";\nimport { callEmbedding } from \"./providers/index.ts\";\nimport type {\n EmbeddingModelConfig,\n EmbeddingOptions,\n EmbeddingResult,\n} from \"./types.ts\";\nimport {\n ADAPTER_EMBEDDING_OPTIONS,\n ADAPTER_EMBEDDING_PROVIDERS,\n} from \"./types.ts\";\n\nfunction parseProviderModel(id: string): {\n providerId: string;\n modelName: string;\n} {\n const colon = id.indexOf(\":\");\n if (colon < 1 || colon === id.length - 1) {\n throw new Error(\n `Embedding adapter: model id must be \"providerId:modelName\" (e.g. huggingface:all-MiniLM-L6-v2). Got: \"${id}\"`,\n );\n }\n return {\n providerId: id.slice(0, colon),\n modelName: id.slice(colon + 1),\n };\n}\n\nfunction resolveProviderAndModel(\n modelId: string,\n context: CraftContext | undefined,\n): { config: EmbeddingModelConfig; modelName: string } {\n if (!context) {\n throw new Error(\n `Embedding adapter: model id \"${modelId}\" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so embedding providers can be read.`,\n );\n }\n const store = context.getStore(\n ADAPTER_EMBEDDING_PROVIDERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, EmbeddingModelConfig> | undefined;\n if (!store) {\n throw new Error(\n \"Embedding provider not found: no providers registered. Add embeddingPlugin({ providers: { huggingface: {} } }) to your config.\",\n );\n }\n const { providerId, modelName } = parseProviderModel(modelId);\n const config = store.get(providerId);\n if (!config) {\n throw new Error(\n `Embedding provider \"${providerId}\" not found. Register it with embeddingPlugin({ providers: { \"${providerId}\": {} } }).`,\n );\n }\n return { config, modelName };\n}\n\nfunction buildText<T>(\n using: (exchange: Exchange<T>) => string | string[],\n): (exchange: Exchange<T>) => string {\n return (exchange: Exchange<T>) => {\n const value = using(exchange);\n return Array.isArray(value) ? value.filter(Boolean).join(\" | \") : value;\n };\n}\n\n/**\n * Embedding destination adapter. Expects model id as \"providerId:modelName\"\n * (e.g. huggingface:all-MiniLM-L6-v2), resolves the provider from the plugin store,\n * and returns { embedding: number[] }. Use with .enrich(embedding(\"provider:model\", { using: ... })).\n *\n * @experimental\n */\nexport class EmbeddingDestinationAdapter<T = unknown>\n implements Destination<T, EmbeddingResult>, MergedOptions<EmbeddingOptions>\n{\n readonly adapterId = \"routecraft.adapter.embedding\";\n\n constructor(\n private readonly modelId: string,\n options: Partial<EmbeddingOptions<T>> = {},\n ) {\n this.options = options as Partial<EmbeddingOptions>;\n }\n\n public options: Partial<EmbeddingOptions>;\n\n mergedOptions(context: CraftContext): EmbeddingOptions {\n const store = context.getStore(\n ADAPTER_EMBEDDING_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Partial<EmbeddingOptions> | undefined;\n return { ...store, ...this.options } as EmbeddingOptions;\n }\n\n async send(exchange: Exchange<T>): Promise<EmbeddingResult> {\n const context = getExchangeContext(exchange);\n const { config, modelName } = resolveProviderAndModel(\n this.modelId,\n context,\n );\n const merged = this.mergedOptions(context!);\n\n if (!merged.using) {\n throw new Error(\n \"Embedding adapter: options.using(exchange) is required to build the string to embed.\",\n );\n }\n\n const getText = buildText(\n merged.using as (e: Exchange<unknown>) => string | string[],\n );\n const text = getText(exchange as Exchange<unknown>);\n\n const embedding = await callEmbedding({ config, modelName, text });\n return { embedding };\n }\n}\n","import type { Destination } from \"@routecraft/routecraft\";\nimport { EmbeddingDestinationAdapter } from \"./destination.ts\";\nimport type {\n EmbeddingModelId,\n EmbeddingOptions,\n EmbeddingResult,\n} from \"./types.ts\";\n\n/**\n * Creates an embedding destination that computes a vector for the given text.\n * Use with .enrich(). Pass model id as \"providerId:modelName\" (e.g. huggingface:all-MiniLM-L6-v2).\n * The provider must be registered via embeddingPlugin({ providers: { huggingface: {} } }).\n *\n * @experimental\n * @param modelId - \"providerId:modelName\"; the provider is resolved from the plugin.\n * @param options - using(exchange) returns the string (or string[]) to embed.\n */\nexport function embedding<T = unknown>(\n modelId: EmbeddingModelId,\n options?: Partial<EmbeddingOptions<T>>,\n): Destination<T, EmbeddingResult> {\n return new EmbeddingDestinationAdapter<T>(modelId, options);\n}\n","import type { CraftContext, CraftPlugin } from \"@routecraft/routecraft\";\nimport { disposeEmbeddingPipelineCache } from \"./providers/index.ts\";\nimport {\n ADAPTER_EMBEDDING_OPTIONS,\n ADAPTER_EMBEDDING_PROVIDERS,\n} from \"./types.ts\";\nimport type { EmbeddingModelConfig, EmbeddingPluginOptions } from \"./types.ts\";\n\n/** Normalize provider options to full EmbeddingModelConfig (providerId wins over opts.provider). */\nfunction toModelConfig(\n providerId: string,\n opts: Record<string, unknown>,\n): EmbeddingModelConfig {\n return {\n ...opts,\n provider: providerId as EmbeddingModelConfig[\"provider\"],\n } as EmbeddingModelConfig;\n}\n\n/**\n * Embedding plugin: registers providers and teardown to clear the pipeline\n * cache when the context stops (releases native/ONNX resources).\n * Use embedding(\"providerId:modelName\", { using: ... }),\n * e.g. embedding(\"huggingface:all-MiniLM-L6-v2\", { using: (e) => e.body.title }).\n *\n * @experimental\n */\nexport function embeddingPlugin(\n options: EmbeddingPluginOptions = { providers: {} },\n): CraftPlugin {\n return {\n apply(ctx: CraftContext) {\n const map = new Map<string, EmbeddingModelConfig>();\n for (const [providerId, opts] of Object.entries(options.providers)) {\n if (opts !== undefined) {\n map.set(\n providerId,\n toModelConfig(providerId, opts as Record<string, unknown>),\n );\n }\n }\n ctx.setStore(\n ADAPTER_EMBEDDING_PROVIDERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n map,\n );\n if (\n options.defaultOptions &&\n Object.keys(options.defaultOptions).length > 0\n ) {\n ctx.setStore(\n ADAPTER_EMBEDDING_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n options.defaultOptions,\n );\n }\n },\n async teardown() {\n await disposeEmbeddingPipelineCache();\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/llm/types.ts","../src/llm/validate-options.ts","../src/llm/plugin.ts","../src/mcp/types.ts","../src/mcp/cors.ts","../src/mcp/default-icon.ts","../src/mcp/userinfo.ts","../src/mcp/auth-errors.ts","../src/mcp/server.ts","../src/mcp/validate-options.ts","../src/mcp/extract-content.ts","../src/mcp/stdio-client-manager.ts","../src/mcp/tool-registry.ts","../src/mcp/build-auth-headers.ts","../src/mcp/plugin.ts","../src/embedding/providers/index.ts","../src/embedding/types.ts","../src/embedding/plugin.ts","../src/llm/shared.ts","../src/llm/providers/llm-utils.ts","../src/llm/providers/resolve.ts","../src/agent/events.ts","../src/llm/providers/stream-llm.ts","../src/llm/providers/index.ts","../src/llm/structured-output.ts","../src/agent/tool-bridge.ts","../src/agent/session.ts","../src/agent/store.ts","../src/skill/types.ts","../src/agent/destination.ts","../src/fn/store.ts","../src/mcp/dispatch.ts","../src/agent/tools/types.ts","../src/agent/tools/builders.ts","../src/agent/tools/selection.ts","../src/agent/agent.ts","../src/fn/fn.ts","../src/agent/plugin.ts","../src/config.ts","../src/brand.ts","../src/llm/destination.ts","../src/llm/llm.ts","../src/mcp/adapters/mcp/shared.ts","../src/mcp/adapters/mcp/source.ts","../src/mcp/adapters/mcp/destination.ts","../src/mcp/adapters/mcp/index.ts","../src/mcp/oauth.ts","../src/skill/markdown.ts","../src/agent/loader.ts","../src/agent/suspend.ts","../src/skill/loader.ts","../src/embedding/destination.ts","../src/embedding/embedding.ts"],"names":["ADAPTER_LLM_PROVIDERS","ADAPTER_LLM_OPTIONS","PROVIDERS","isProvider","s","validateLlmPluginOptions","options","providerId","opts","PROVIDER_IDS","toModelConfig","llmPlugin","ctx","map","MCP_PLUGIN_REGISTERED","ADAPTER_MCP_CLIENT_SERVERS","MCP_TOOL_REGISTRY","MCP_STDIO_MANAGERS","MCP_LOCAL_TOOL_REGISTRY","McpHeadersKeys","isOAuthAuth","auth","ALLOW_METHODS","EXPOSE_HEADERS","LOOPBACK_HOSTS","defaultLoopbackOriginResolver","requestOrigin","parsed","resolveCorsOptions","input","origin","allowed","safeResolveOrigin","cors","buildCorsHeaders","preflight","headers","applyCorsHeaders","res","Vary","rest","name","value","PROTECTED_RESOURCE_METADATA_PATH","buildMcpOwnedPaths","resourceUrl","metadataPaths","rsPath","logoSvg","fill","toDataUri","svg","ROUTECRAFT_DEFAULT_ICONS","PROTECTED_FIELDS","DEFAULT_CACHE_MAX_ENTRIES","DEFAULT_DISCOVERY_TTL_SEC","UserinfoCache","maxEntries","token","expiresAt","compute","key","hashToken","cached","pending","promise","enrichment","err","oldest","createHash","parseMaxAge","headerValue","match","createUserinfoUrlResolver","option","issuer","url","base","discoveryUrl","cachedUrl","cachedUntil","inFlight","fetchAndCache","response","cause","rcError","doc","resolved","ttl","fetchUserinfo","mergeEnrichment","principal","merged","liftOidcClaims","payload","out","r","buildEnrichedVerifier","baseVerifier","userinfo","cache","resolveUserinfoUrl","responseSub","isExpiredTokenError","JOSE_INFRASTRUCTURE_CODES","NETWORK_ERROR_CODES","isInfrastructureError","current","depth","code","principalStore","AsyncLocalStorage","McpServer","context","fallback","info","description","websiteUrl","icons","instructions","explicit","transport","error","msg","isRoutecraftError","Server","loadOptionalPeer","StdioServerTransport","ServerCtor","TransportClass","server","sessionId","tr","prevOnClose","sid","handleRequest","req","createSessionFn","runWithPrincipal","fn","session","hr","host","port","metadata","resource","createServer","rawOrigin","originValue","resolvedResourceUrl","ownedPaths","result","oauthOptions","expressFn","expressMod","mcpAuthRouter","requireBearerAuth","ProxyOAuthServerProvider","InvalidTokenError","verifyAccessToken","wrappedVerifier","expired","detail","provider","app","oauthCors","next","nodeReq","nodeRes","serveMetadata","_req","path","authRouterOptions","resourceName","bearerOptions","authInfo","successDetail","resolve","reject","boundPort","listenDetail","stashed","addr","authOptions","verifier","rawHeader","schemeMatch","t","ListToolsRequestSchema","CallToolRequestSchema","srv","tools","request","params","names","exposedDetail","registry","entries","toolsFilter","e","entry","tool","schema","standard","toolName","args","body","HeadersKeys","markAuthentic","exchange","DefaultExchange","resultExchange","resultText","logMsg","userMsg","validateMcpPluginOptions","config","validateWithSchema","formatSchemaIssues","extractContent","content","item","StdioClientManager","logger","onEvent","onToolsUpdated","clientMod","stdioMod","serverId","command","env","cwd","data","_error","transportWithClose","maxRestarts","restartDelayMs","restartBackoffMultiplier","delay","stableMs","deriveTagsFromAnnotations","annotations","tags","McpToolRegistry","source","sourceMap","derivedTags","rrIndexes","resolveToken","idx","buildAuthHeaders","customHeaders","authorizationOverride","isStdioConfig","mcpPlugin","stdioManagers","httpClients","httpRefreshTimers","toolRegistry","clientEntries","k","v","startStdioClient","httpConfig","listHttpClientTools","setupHttpToolRefresh","timer","client","manager","managerOpts","event","details","_serverId","getOrCreateHttpClient","existing","Client","StreamableHTTPClientTransport","transportOptions","rawClient","typed","interval","pipelineCache","disposeEmbeddingPipelineCache","resolveHuggingFaceModel","modelName","HUGGINGFACE_INSTALL","isModuleNotFoundFor","pkg","getHuggingFacePipeline","pipelineFn","pipe","run","text","previewForError","toNumberArray","d","callEmbedding","vec","i","output","ADAPTER_EMBEDDING_PROVIDERS","ADAPTER_EMBEDDING_OPTIONS","embeddingPlugin","parseProviderModel","id","colon","resolveModel","model","store","resolvePrompt","resolveUserPromptDefault","PROVIDER_DEFAULTS","throwProviderInstallError","assertLanguageModelShape","providerName","modelId","m","toLlmUsage","u","getStructuredOutput","readReasoning","collectToolCalls","steps","step","calls","results","call","c","toolCallId","summary","buildExtras","buildSdkParams","system","user","extras","resolveLanguageModel","resolveOpenAI","resolveAnthropic","resolveGemini","resolveOpenRouter","resolveOllama","_","createOpenAI","settings","createAnthropic","createGoogleGenerativeAI","createOpenRouter","openrouter","resolvedId","rawModel","createOllama","ollama","normalizeStreamDelta","part","p","readString","obj","streamLlm","onDelta","runStreamGenerate","streamText","delta","frameworkLogger","usage","safeAwait","reasoning","structured","finishReason","toolCalls","callLlm","runGenerate","generateText","responseMessages","toAiSchema","direction","errorContext","primary","jsonSchemaObj","validate","jsonSchema","toAiInputSchema","toAiOutputSpec","aiSchema","Output","buildVercelTools","abortSignal","dispatchIdentity","guard","handler","baseCtx","makeFnHandlerContext","callOpts","callCtx","randomUUID","start","freezePrincipal","wasAuthentic","isAuthentic","snapshot","deepFreeze","seen","dispatchIdentityFrom","routeId","corr","DEFAULT_TEMPERATURE","DEFAULT_MAX_TOKENS","DEFAULT_MAX_TURNS","AgentSession","maxTurns","prepared","turnsUsed","currentUser","lastValidatorMsg","accumulatedToolCalls","remaining","callOnce","toAgentResult","verdict","buildRetryPrompt","modelConfig","vercelTools","remainingTurns","toolExtras","buildStopWhen","stepCountIs","initialUser","lastResult","validatorMsg","userMsgs","buildUserPrompt","ADAPTER_AGENT_REGISTRY","ADAPTER_AGENT_DEFAULT_OPTIONS","ADAPTER_SKILL_REGISTRY","AGENT_REGISTRY_STORE_DESCRIPTION","AgentDestinationAdapter","binding","getExchangeContext","baseOptions","mergeWithDefaults","resolveAgentTools","baseSystem","withSkills","appendSkillsToSystem","appendPrincipalToSystem","route","getExchangeRoute","found","known","defaults","skills","parts","skill","principalOption","section","formatCallerSection","lines","oneLine","roles","ADAPTER_FN_REGISTRY","dispatchMcpCall","http","callRemoteTool","serverUrl","clientModule","transportModule","clientCleanup","closeOrDisconnect","transportCleanup","closeOrDestroy","DEFERRED_FN_BRAND","isDeferredFn","cloneFrozenPrincipal","rp","EMPTY_OBJECT_JSON_SCHEMA","emptyObjectSchema","directTool","overrides","overrideTags","normalizeOverrideTags","fnId","readDirectRoute","hctx","dispatchDirect","trimmed","ADAPTER_DIRECT_REGISTRY","endpoint","sanitizeEndpoint","getDirectChannel","currentTime","randomUuid","TOOL_SELECTION_BRAND","isToolSelection","items","isMcpRefName","fnRegistryHas","resolveMcpRefs","resolveByName","wanted","normalizeTags","matches","resolveByTags","formatTags","fnEntry","resolveFnEntry","directMatch","toResolvedTool","listKnownNames","parseMcpRef","ref","inner","clientName","sep","clientTools","listKnownMcpClients","mcpEntryToResolvedTool","knownTools","n","wrapJsonSchemaAsStandard","rawInput","set","parseFromScope","from","wantedSet","scope","seenNames","coveredRouteIds","fnRegistry","peekDirectTags","directRegistry","meta","conventionName","mcpRegistry","fnNames","routeNames","validateAgentOptions","agent","arg","perCall","tagAdapter","factoryArgs","validateFnOptions","validateRegisteredAgent","agentPlugin","agents","functions","skillsMap","defaultOptions","validatePluginDefaults","existingAgents","agentMap","existingFns","fnMap","existingSkills","skillMap","mergePluginDefaults","raw","registerConfigApplier","BRAND","isBranded","isMcpAdapter","parseStructuredTextFallback","LlmDestinationAdapter","llmResult","llm","BRAND_MCP_ADAPTER","MCP_TOOL_NAME_RE","assertValidMcpToolName","McpSourceAdapter","abortController","onReady","discovery","assertHttpUrl","resolveServerConfig","cfg","resolveConnection","defaultArgs","McpDestinationAdapter","resolveServerTransport","mcp","clientOpts","colonIndex","clientOptions","normaliseClientSupplier","clientId","staticClient","buildVerifier","verify","oauth","getClient","verifyIssuer","cachedParseYaml","loadYamlParse","splitFrontmatter","filename","basename","extname","end","yamlText","readMarkdownFile","abs","readFileSync","readMarkdownDir","dir","stats","statSync","readdirSync","join","sentinelPath","sentinelStats","a","b","requireString","field","optionalStringArray","optionalBoolean","optionalPositiveInt","SUPPORTED_AGENT_KEYS","toAgent","frontmatter","modelRaw","toolNames","skillNames","applyOverride","override","docs","SuspendError","toSkill","sources","previousSource","resolveProviderAndModel","buildText","using","EmbeddingDestinationAdapter","embedding"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { Exchange } from \"@routecraft/routecraft\";\n\n/**\n * Store key for plugin-registered providers (provider id -> LlmModelConfig).\n * @internal\n */\nexport const ADAPTER_LLM_PROVIDERS = Symbol.for(\n \"routecraft.adapter.llm.providers\",\n);\n\n/**\n * Store key for context-level default LLM options.\n * @internal\n */\nexport const ADAPTER_LLM_OPTIONS = Symbol.for(\"routecraft.adapter.llm.options\");\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [ADAPTER_LLM_PROVIDERS]: Map<string, LlmModelConfig>;\n [ADAPTER_LLM_OPTIONS]: Partial<LlmOptionsMerged>;\n }\n}\n\nexport type LlmProviderType =\n | \"openai\"\n | \"anthropic\"\n | \"openrouter\"\n | \"ollama\"\n | \"gemini\";\n\nexport interface LlmModelConfigOpenAI {\n provider: \"openai\";\n apiKey: string;\n baseURL?: string;\n}\n\nexport interface LlmModelConfigAnthropic {\n provider: \"anthropic\";\n apiKey: string;\n}\n\nexport interface LlmModelConfigOpenRouter {\n provider: \"openrouter\";\n apiKey: string;\n /** OpenRouter model id (e.g. anthropic/claude-3.5-sonnet). Defaults to the registered key. */\n modelId?: string;\n}\n\nexport interface LlmModelConfigOllama {\n provider: \"ollama\";\n /**\n * Ollama server URL. Optional: defaults to http://localhost:11434/api.\n * Only set when using a remote Ollama or custom port.\n */\n baseURL?: string;\n /**\n * Override model name sent to Ollama. Optional: defaults to the model\n * from the llm(\"provider:model\") call (the part after the colon).\n */\n modelId?: string;\n}\n\nexport interface LlmModelConfigGemini {\n provider: \"gemini\";\n apiKey: string;\n}\n\nexport type LlmModelConfig =\n | LlmModelConfigOpenAI\n | LlmModelConfigAnthropic\n | LlmModelConfigOpenRouter\n | LlmModelConfigOllama\n | LlmModelConfigGemini;\n\n/**\n * Provider options for llmPlugin({ providers }). Key is the provider; no need to repeat provider in the value.\n */\nexport interface LlmOllamaProviderOptions {\n baseURL?: string;\n modelId?: string;\n}\nexport interface LlmOpenAIProviderOptions {\n apiKey: string;\n baseURL?: string;\n}\nexport interface LlmAnthropicProviderOptions {\n apiKey: string;\n}\nexport interface LlmOpenRouterProviderOptions {\n apiKey: string;\n modelId?: string;\n}\nexport interface LlmGeminiProviderOptions {\n apiKey: string;\n}\n\nexport interface LlmPluginProviders {\n ollama?: LlmOllamaProviderOptions;\n openai?: LlmOpenAIProviderOptions;\n anthropic?: LlmAnthropicProviderOptions;\n openrouter?: LlmOpenRouterProviderOptions;\n gemini?: LlmGeminiProviderOptions;\n}\n\n/** Map provider id → provider-specific options (for type-safe toModelConfig). */\nexport type LlmProviderOptionsMap = Required<LlmPluginProviders>;\n\n/**\n * Resolve system or user prompt from exchange (string or function).\n */\nexport type LlmPromptSource =\n | string\n | ((exchange: Exchange<unknown>) => string);\n\nexport interface LlmOptions {\n system?: LlmPromptSource;\n user?: LlmPromptSource;\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n frequencyPenalty?: number;\n presencePenalty?: number;\n /**\n * Optional output schema (Standard Schema). When set, the adapter requests\n * provider-level structured output and validates the result. Supported by\n * OpenAI (gpt-4o/mini) and Ollama; others may return JSON that is validated\n * after the call. On success, the parsed value is set on LlmResult.output.\n *\n * Mirrors the route-level `.output(schema)` naming so the same word is\n * used for \"declared output shape\" everywhere in the framework.\n */\n output?: StandardSchemaV1;\n}\n\n/** Internal merged type for adapter and store. */\nexport type LlmOptionsMerged = Required<\n Pick<LlmOptions, \"temperature\" | \"maxTokens\">\n> &\n Omit<LlmOptions, \"temperature\" | \"maxTokens\">;\n\n/**\n * Token usage. Matches Vercel AI SDK LanguageModelUsage shape (inputTokens/outputTokens)\n * so result.usage can be used interchangeably with generateText() return value.\n */\nexport interface LlmUsage {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n}\n\n/**\n * LLM result shape aligned with Vercel AI SDK generateText() return value.\n * Same property names (text, output, usage) so code and docs transfer directly.\n */\nexport interface LlmResult {\n /** Generated text (raw string from the model). */\n text: string;\n /** Parsed structured output when `output` schema was set and validation succeeded. */\n output?: unknown;\n /**\n * Raw reasoning text from the provider (Anthropic extended thinking,\n * OpenAI o1, etc.) when supplied. Most callers can ignore this; it is\n * useful for debugging, audit trails, and chain-of-thought displays.\n */\n reasoning?: string;\n /** Token usage for the last step. Same shape as AI SDK usage. */\n usage?: LlmUsage;\n /**\n * Reason the model loop terminated (`\"stop\"`, `\"length\"`, `\"tool-calls\"`,\n * etc.). Populated by both the sync (`generateText`) and streaming\n * (`streamText`) paths. The streaming path awaits the SDK's\n * `result.finishReason` Promise before resolving so callers always\n * see a normalised string value.\n */\n finishReason?: string;\n /**\n * Flat list of tool calls made during the loop, in invocation\n * order. Each entry pairs the model's call args with the handler's\n * return (or thrown error). Populated by both sync and streaming\n * paths; the agent layer surfaces these on `AgentResult.toolCalls`\n * for post-dispatch assertions.\n */\n toolCalls?: LlmToolCallSummary[];\n /**\n * Number of model steps the SDK consumed in this call. Mirrors\n * `result.steps.length` and is populated by both the sync and\n * streaming paths. The agent session uses this to track the shared\n * turn budget across `validate` retries: every retry's step count\n * is added to the running total and compared against `maxTurns`.\n */\n stepsCount?: number;\n /**\n * Conversation messages emitted during this call (assistant + tool\n * messages, in order; mirrors the SDK's `result.response.messages`).\n * The agent session uses this to assemble the messages array for a\n * `validate`-triggered retry: original user prompt + these response\n * messages + the corrective user message become the next call's\n * `prompt`.\n */\n responseMessages?: unknown[];\n /** Full generateText() result for advanced use (debugging, response metadata). */\n raw?: unknown;\n}\n\n/**\n * One tool invocation captured during an LLM dispatch. Mirrors the\n * shape of `AgentToolCallSummary` so the agent layer can re-export\n * it without re-mapping. Keep `unknown` types loose here; the agent\n * layer is the place to re-narrow if needed.\n */\nexport interface LlmToolCallSummary {\n toolCallId: string;\n toolName: string;\n input: unknown;\n output?: unknown;\n error?: unknown;\n}\n\n/**\n * When an `output` schema S is provided to llm(), the result type narrows\n * `output` to `InferOutput<S>`. Used for type inference from\n * `llm(modelId, { output })` so body.output is typed downstream.\n */\nexport type LlmResultWithOutput<S extends StandardSchemaV1 | undefined> =\n S extends StandardSchemaV1\n ? Omit<LlmResult, \"output\"> & {\n output?: StandardSchemaV1.InferOutput<S>;\n }\n : LlmResult;\n\n/**\n * Recommended LLM model ids for autocomplete (chat/completion use cases).\n * Format: \"providerId:modelName\". Custom models are allowed via string.\n * Updated for 2026.\n */\nexport type LlmModelId =\n // OpenAI (2026: GPT-5.2, Codex, o1)\n | \"openai:gpt-5.2\"\n | \"openai:gpt-5.2-codex\"\n | \"openai:gpt-5\"\n | \"openai:gpt-5.1-chat-latest\"\n | \"openai:gpt-5-mini\"\n | \"openai:gpt-5-codex-mini\"\n | \"openai:gpt-4o\"\n | \"openai:gpt-4o-mini\"\n | \"openai:o1\"\n | \"openai:o1-mini\"\n // Anthropic (2026: Claude 4.6 / 4.5)\n | \"anthropic:claude-opus-4-6\"\n | \"anthropic:claude-sonnet-4-6\"\n | \"anthropic:claude-haiku-4-5\"\n // Ollama (common local models)\n | \"ollama:qwen3\"\n | \"ollama:llama3.2\"\n | \"ollama:llama3.3\"\n | \"ollama:mistral\"\n | \"ollama:gemma2\"\n | \"ollama:deepseek-r1\"\n | \"ollama:lfm2.5-thinking\"\n // OpenRouter (top open-weight / frontier: GLM, Kimi, Qwen, DeepSeek)\n | \"openrouter:z-ai/glm-5\"\n | \"openrouter:z-ai/glm-4.7\"\n | \"openrouter:moonshotai/kimi-k2-thinking\"\n | \"openrouter:qwen/qwen3.5-plus-02-15\"\n | \"openrouter:qwen/qwen3-next\"\n | \"openrouter:deepseek/deepseek-v3.2\"\n | \"openrouter:deepseek/deepseek-r1\"\n | \"openrouter:meta-llama/llama-3.3-70b-instruct\"\n // Gemini (2026: 2.5 + 3.x preview)\n | \"gemini:gemini-2.5-pro\"\n | \"gemini:gemini-2.5-flash\"\n | \"gemini:gemini-2.5-flash-lite\"\n | \"gemini:gemini-3.1-pro-preview\"\n | \"gemini:gemini-3-pro-preview\"\n | \"gemini:gemini-3-flash-preview\"\n // Other (custom models)\n | string;\n\nexport interface LlmPluginOptions {\n /**\n * Supported providers keyed by id. Only set options you need (defaults for url etc. apply).\n * Routes use llm(\"providerId:modelName\"), e.g. llm(\"ollama:lfm2.5-thinking\").\n */\n providers: LlmPluginProviders;\n /** Optional context-level default options (system, temperature, etc.). */\n defaultOptions?: Partial<LlmOptionsMerged>;\n}\n","import type { LlmPluginOptions, LlmProviderType } from \"./types.ts\";\n\nconst PROVIDERS: LlmProviderType[] = [\n \"openai\",\n \"anthropic\",\n \"openrouter\",\n \"ollama\",\n \"gemini\",\n];\n\nfunction isProvider(s: string): s is LlmProviderType {\n return (PROVIDERS as string[]).includes(s);\n}\n\n/**\n * Validates LLM plugin options at apply time.\n * Key is the provider; value is options for that provider (no provider field).\n * @internal\n */\nexport function validateLlmPluginOptions(options: LlmPluginOptions): void {\n if (!options || typeof options !== \"object\") {\n throw new TypeError(\"llmPlugin: options must be an object\");\n }\n if (!options.providers || typeof options.providers !== \"object\") {\n throw new TypeError(\n \"llmPlugin: options.providers must be an object (record of provider id → options)\",\n );\n }\n for (const [providerId, opts] of Object.entries(options.providers)) {\n if (opts === undefined) continue;\n if (!opts || typeof opts !== \"object\") {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"] must be an object`,\n );\n }\n if (!isProvider(providerId)) {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"] is not a supported provider. Supported: ${PROVIDERS.join(\", \")}`,\n );\n }\n switch (providerId) {\n case \"openai\":\n case \"anthropic\":\n case \"openrouter\":\n case \"gemini\":\n if (\n typeof (opts as { apiKey?: string }).apiKey !== \"string\" ||\n !(opts as { apiKey: string }).apiKey.trim()\n ) {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"].apiKey is required`,\n );\n }\n break;\n case \"ollama\":\n if (\n (opts as { baseURL?: string }).baseURL !== undefined &&\n typeof (opts as { baseURL?: string }).baseURL !== \"string\"\n ) {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"].baseURL must be a string when provided`,\n );\n }\n if (\n (opts as { modelId?: string }).modelId !== undefined &&\n (typeof (opts as { modelId?: string }).modelId !== \"string\" ||\n !(opts as { modelId: string }).modelId.trim())\n ) {\n throw new TypeError(\n `llmPlugin: providers[\"${providerId}\"].modelId must be a non-empty string when provided`,\n );\n }\n break;\n }\n }\n if (\n options.defaultOptions !== undefined &&\n (typeof options.defaultOptions !== \"object\" ||\n options.defaultOptions === null)\n ) {\n throw new TypeError(\n \"llmPlugin: defaultOptions must be an object when provided\",\n );\n }\n}\n","import type { CraftContext, CraftPlugin } from \"@routecraft/routecraft\";\nimport { ADAPTER_LLM_OPTIONS, ADAPTER_LLM_PROVIDERS } from \"./types.ts\";\nimport type {\n LlmModelConfig,\n LlmPluginOptions,\n LlmProviderOptionsMap,\n} from \"./types.ts\";\nimport { validateLlmPluginOptions } from \"./validate-options.ts\";\n\nconst PROVIDER_IDS = [\n \"openai\",\n \"anthropic\",\n \"openrouter\",\n \"ollama\",\n \"gemini\",\n] as const satisfies readonly LlmModelConfig[\"provider\"][];\n\n/** Normalize provider options to full LlmModelConfig (add provider field from key). */\nfunction toModelConfig<P extends LlmModelConfig[\"provider\"]>(\n providerId: P,\n opts: LlmProviderOptionsMap[P],\n): Extract<LlmModelConfig, { provider: P }> {\n return { provider: providerId, ...opts } as Extract<\n LlmModelConfig,\n { provider: P }\n >;\n}\n\n/**\n * LLM plugin: config-only helper (no lifecycle hooks). Registers providers and optional\n * default options in the context store so routes can use llm(\"providerId:modelName\", options),\n * e.g. llm(\"ollama:lfm2.5-thinking\"). Key is the provider; only set options you need.\n *\n * Advanced users can set the store directly: context.setStore(ADAPTER_LLM_PROVIDERS, map)\n * and context.setStore(ADAPTER_LLM_OPTIONS, partialOptions) without using this plugin.\n */\nexport function llmPlugin(\n options: LlmPluginOptions = { providers: {} },\n): CraftPlugin {\n validateLlmPluginOptions(options);\n\n return {\n apply(ctx: CraftContext) {\n const map = new Map<string, LlmModelConfig>();\n for (const providerId of PROVIDER_IDS) {\n const opts = options.providers[providerId];\n if (opts !== undefined)\n map.set(providerId, toModelConfig(providerId, opts));\n }\n ctx.setStore(\n ADAPTER_LLM_PROVIDERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n map,\n );\n if (\n options.defaultOptions &&\n Object.keys(options.defaultOptions).length > 0\n ) {\n ctx.setStore(\n ADAPTER_LLM_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n options.defaultOptions,\n );\n }\n },\n };\n}\n","import type { Exchange, Tag } from \"@routecraft/routecraft\";\nimport type {\n OAuthPrincipal,\n Principal,\n ValidatorAuthOptions,\n} from \"@routecraft/routecraft\";\nimport type { McpCorsOptions } from \"./cors.ts\";\nimport type { McpToolRegistry } from \"./tool-registry.ts\";\nimport type { UserinfoOption } from \"./userinfo.ts\";\n\n/**\n * Store key set by mcpPlugin() when applied; routes using .from(mcp(...)) require it.\n * @internal\n */\nexport const MCP_PLUGIN_REGISTERED = Symbol.for(\n \"routecraft.mcp.plugin.registered\",\n);\n\n/**\n * Store key for named remote MCP servers (mcpPlugin({ clients })). Used by McpClient to resolve serverId.\n * @internal\n */\nexport const ADAPTER_MCP_CLIENT_SERVERS = Symbol.for(\n \"routecraft.mcp.client.servers\",\n);\n\n/**\n * Store key for the unified MCP tool registry. Used by agent adapter for tool discovery.\n * @internal\n */\nexport const MCP_TOOL_REGISTRY = Symbol.for(\"routecraft.mcp.tool.registry\");\n\n/**\n * Store key for stdio client managers. Used by destination adapter to call tools on stdio clients.\n * @internal\n */\nexport const MCP_STDIO_MANAGERS = Symbol.for(\"routecraft.mcp.stdio.managers\");\n\n/**\n * Store key for the MCP local tool registry. Populated at `mcp()` subscription time\n * with one entry per `.from(mcp(endpoint, options))` route in this context.\n *\n * Kept separate from {@link MCP_TOOL_REGISTRY}, which holds tools discovered from\n * external (stdio/HTTP) client servers and is consumed by the agent adapter.\n */\nexport const MCP_LOCAL_TOOL_REGISTRY = Symbol.for(\n \"routecraft.mcp.local-tool-registry\",\n);\n\n/**\n * @deprecated Use `RouteSchemas` from `@routecraft/routecraft`. Kept as an\n * alias so existing imports do not break during migration.\n */\nexport type McpInput = import(\"@routecraft/routecraft\").RouteSchemas;\n\n/**\n * @deprecated Use `RouteSchemas` from `@routecraft/routecraft`. Kept as an\n * alias so existing imports do not break during migration.\n */\nexport type McpOutput = import(\"@routecraft/routecraft\").RouteSchemas;\n\n/**\n * Entry in the {@link MCP_LOCAL_TOOL_REGISTRY}. One per `.from(mcp(endpoint, options))`\n * route. Holds the discovery metadata needed for `tools/list` and the invocation\n * handler used by `tools/call`.\n */\nexport interface McpLocalToolEntry {\n /** Tool name (matches the route id). Used as `tool.name` in MCP `tools/list`. */\n endpoint: string;\n /** Human-readable display title forwarded to `tools/list` when provided. */\n title?: string;\n /** Human-readable description of the tool (required for MCP discoverability). */\n description: string;\n /** Input schemas (request body, request headers). */\n input?: import(\"@routecraft/routecraft\").RouteSchemas;\n /** Output schemas (response body, response headers); forwarded to `tools/list`. */\n output?: import(\"@routecraft/routecraft\").RouteSchemas;\n /** MCP tool annotations (read-only hints, destructive hints, etc.). */\n annotations?: McpToolAnnotations;\n /** Icons forwarded to `tools/list` per the MCP spec. */\n icons?: McpIcon[];\n /**\n * Invocation handler. Receives an exchange pre-built by the MCP server\n * (with tool/session/auth headers and the request body) and returns the\n * resulting exchange after the route has processed it.\n */\n handler: (exchange: Exchange) => Promise<Exchange>;\n}\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [MCP_PLUGIN_REGISTERED]: boolean;\n [ADAPTER_MCP_CLIENT_SERVERS]: Map<\n string,\n McpClientHttpConfig | McpClientStdioConfig | string\n >;\n [MCP_TOOL_REGISTRY]: McpToolRegistry;\n [MCP_LOCAL_TOOL_REGISTRY]: Map<string, McpLocalToolEntry>;\n [MCP_STDIO_MANAGERS]: Map<\n string,\n {\n callTool(name: string, args: Record<string, unknown>): Promise<unknown>;\n }\n >;\n }\n\n interface RoutecraftHeaders {\n /** The MCP tool name that triggered this exchange. */\n \"routecraft.mcp.tool\"?: string;\n /** The MCP session identifier. */\n \"routecraft.mcp.session\"?: string;\n }\n}\n\n/**\n * HTTP client config for a remote MCP server (Streamable HTTP).\n * Used in mcpPlugin({ clients: { name: config } }).\n */\nexport interface McpClientHttpConfig {\n transport?: \"streamable-http\";\n url: string;\n /** Auth credentials sent on every request to this server. */\n auth?: McpClientAuthOptions;\n}\n\n/**\n * Stdio client config for a local MCP server subprocess.\n * Used in mcpPlugin({ clients: { name: config } }).\n * The plugin spawns the process, manages its lifecycle, and auto-restarts on crash.\n */\nexport interface McpClientStdioConfig {\n transport: \"stdio\";\n /** The executable to run (e.g. \"npx\", \"node\", \"python\"). */\n command: string;\n /** Command line arguments to pass to the executable. */\n args?: string[];\n /** Environment variables for the child process. Defaults to a safe subset of the parent env. */\n env?: Record<string, string>;\n /** Working directory for the child process. Defaults to the current working directory. */\n cwd?: string;\n}\n\n/**\n * Union of client configs accepted by mcpPlugin({ clients }).\n */\nexport type McpClientServerConfig = McpClientHttpConfig | McpClientStdioConfig;\n\n/**\n * Header keys set on exchanges created by the MCP server.\n *\n * Authenticated identity is exposed via `ex.principal` (a getter over\n * `ex.headers[\"routecraft.auth.principal\"]`); read principal fields off the\n * structured object instead of looking them up under flat header keys.\n *\n * @example\n * ```ts\n * import { McpHeadersKeys } from '@routecraft/ai'\n *\n * .process((ex) => {\n * const subject = ex.principal?.subject\n * const tool = ex.headers[McpHeadersKeys.TOOL]\n * })\n * ```\n */\nexport enum McpHeadersKeys {\n /** The MCP tool name that triggered this exchange. */\n TOOL = \"routecraft.mcp.tool\",\n /** The MCP session identifier. */\n SESSION = \"routecraft.mcp.session\",\n}\n\n/**\n * OAuth client info supplied to the `oauth()` factory via the `client` option.\n * Mirrors the MCP SDK's `OAuthClientInformationFull` with only the fields routecraft needs.\n *\n * Field names use snake_case to match the OAuth 2.0 Dynamic Client Registration\n * specification (RFC 7591) and the MCP SDK's `OAuthClientInformationFull`.\n */\nexport interface OAuthClientInfo {\n /** The client identifier. */\n client_id: string;\n /** Allowed redirect URIs for authorization code flow. */\n redirect_uris: string[];\n /** Human-readable client name. */\n client_name?: string;\n /** Client secret (for confidential clients). */\n client_secret?: string;\n}\n\n/**\n * Endpoint URLs for the upstream OAuth provider (used by the proxy).\n */\nexport interface OAuthProxyEndpoints {\n /** Authorization endpoint URL. */\n authorizationUrl: string;\n /** Token endpoint URL. */\n tokenUrl: string;\n /** Token revocation endpoint URL. */\n revocationUrl?: string;\n /** Dynamic client registration endpoint URL. */\n registrationUrl?: string;\n}\n\n/**\n * Protected-resource (RFC 9728) metadata for the MCP server.\n *\n * Used by both validator-mode and OAuth-proxy auth to populate\n * `/.well-known/oauth-protected-resource` and the `resource_metadata`\n * parameter on 401 responses. Orthogonal to the auth mode: identifies WHAT\n * is being protected, not HOW it authenticates.\n *\n * When omitted entirely, the framework still advertises a baseline metadata\n * document built from the bound URL and (in validator mode) the IdP issuer\n * surfaced by `jwks()` / `jwt()`.\n */\nexport interface McpResourceOptions {\n /**\n * Identifies this MCP server as an OAuth 2.0 Protected Resource (RFC 9728).\n * Becomes the `resource` field in the metadata document. Must be HTTPS in\n * production. Defaults to `http://{host}:{port}/mcp` when unset.\n */\n url?: string | URL;\n /**\n * OAuth scopes this resource advertises as supported.\n * Becomes the `scopes_supported` field in the metadata document. An empty\n * array is treated as unset and the field is omitted entirely (RFC 9728\n * §2 permits this; most MCP clients treat absence and empty as equivalent).\n */\n scopesSupported?: string[];\n /**\n * URL to human-readable documentation describing this protected resource.\n * Becomes the `resource_documentation` field in the metadata document.\n */\n documentationUrl?: string | URL;\n}\n\n/**\n * OAuth provider auth: full OAuth 2.1 server flow with proxy to upstream IdP.\n * Mounts discovery, authorization, token, and revocation endpoints alongside `/mcp`.\n * Uses the MCP SDK's `ProxyOAuthServerProvider` and `mcpAuthRouter` internally.\n *\n * Protected-resource metadata (`resource`, `scopes_supported`, etc.) lives on\n * `mcpPlugin({ resource })`, not here -- it is orthogonal to the auth mode.\n */\nexport interface OAuthAuthOptions {\n /** Discriminant for the union. Always `\"oauth\"`. */\n provider: \"oauth\";\n /** Base URL for OAuth endpoints (defaults to the resolved resource URL). */\n baseUrl?: string | URL;\n /** Upstream OAuth provider endpoints to proxy. */\n endpoints: OAuthProxyEndpoints;\n /**\n * Verify an access token and return a populated {@link OAuthPrincipal}.\n * Called on every authenticated request to `/mcp`.\n *\n * The returned principal flows through to route exchanges as\n * `headers[\"routecraft.auth.principal\"]` (surfaced via the `ex.principal`\n * getter). `expiresAt` is part of the type contract because the MCP\n * SDK's bearer middleware requires it.\n */\n verifyAccessToken: (token: string) => Promise<OAuthPrincipal>;\n /**\n * Look up a registered OAuth client by ID.\n * Return `undefined` to reject the client.\n */\n getClient: (clientId: string) => Promise<OAuthClientInfo | undefined>;\n /** Scopes required on every request to `/mcp`. Enforcement policy, not metadata. */\n requiredScopes?: string[];\n /**\n * IdP issuer surfaced from the `verify` helper (`jwks()` / `jwt()`). Read by\n * the server to resolve the OIDC Discovery document when plugin-level\n * `mcpPlugin({ userinfo: true })` is configured. Not user-set; populated by\n * the `oauth()` factory.\n */\n issuer?: string | string[];\n}\n\n/**\n * Authentication options for the MCP HTTP server.\n * Only applies when `transport` is `\"http\"`. Ignored for stdio.\n *\n * Two strategies are supported:\n * - `Validator`: simple bearer token check via `jwt()` / `jwks()` / or custom function.\n * - `OAuth`: full OAuth 2.1 server flow via `oauth()`, proxying to an upstream IdP.\n */\nexport type McpHttpAuthOptions = ValidatorAuthOptions | OAuthAuthOptions;\n\n/**\n * Type guard: returns `true` when auth is configured for OAuth provider mode.\n */\nexport function isOAuthAuth(\n auth: McpHttpAuthOptions,\n): auth is OAuthAuthOptions {\n return \"provider\" in auth && auth.provider === \"oauth\";\n}\n\n/**\n * A function that provides a bearer token for outbound requests.\n * Called on every request; may be synchronous or asynchronous.\n * Useful for dynamic tokens (JWT refresh, rotating API keys, etc.).\n */\nexport type McpClientTokenProvider = () => string | Promise<string>;\n\n/**\n * Auth config for an outbound MCP HTTP client connection.\n * Passed as request headers on every connection to the remote server.\n */\nexport interface McpClientAuthOptions {\n /**\n * Bearer token(s) or provider for the `Authorization` header.\n * Builds `Authorization: Bearer <token>`.\n *\n * - `string` -- single static token.\n * - `string[]` -- array of tokens; one is selected per request (round-robin).\n * - `() => string | Promise<string>` -- called per request for dynamic tokens.\n */\n token?: string | string[] | McpClientTokenProvider;\n /**\n * Additional headers to include on every request to the remote server.\n * If `Authorization` is set here, it overrides `token`.\n */\n headers?: Record<string, string>;\n}\n\n/**\n * Options for the MCP plugin (mcpPlugin).\n * One plugin per adapter: this is the single options type for the MCP plugin.\n */\nexport interface McpPluginOptions {\n /** Server name in MCP protocol handshake. Default: \"routecraft\". Machine identifier. */\n name?: string;\n\n /**\n * Human-readable display title for this MCP server. Defaults to `name` when unset.\n * Used for MCP `serverInfo.title` (where the SDK protocol exposes it) and as\n * the `resource_name` field in RFC 9728 protected-resource metadata.\n */\n title?: string;\n\n /** Server version. Default: \"1.0.0\" */\n version?: string;\n\n /**\n * Human-readable server description, forwarded as MCP `serverInfo.description`.\n * Defaults to `\"Powered by Routecraft.dev\"` when unset; pass an empty string\n * (`\"\"`) to omit it entirely.\n */\n description?: string;\n\n /**\n * Server website, forwarded as MCP `serverInfo.websiteUrl`. Defaults to\n * `\"https://routecraft.dev\"` when unset; pass an empty string (`\"\"`) to omit it.\n */\n websiteUrl?: string;\n\n /**\n * Server-wide usage guidance, forwarded as the MCP `initialize` result's\n * `instructions`. Clients may inject it into the model's context as a hint\n * (advisory per the spec, not guaranteed). Use it for cross-tool guidance the\n * model cannot infer from individual tool schemas.\n */\n instructions?: string;\n\n /**\n * Icons identifying this server, forwarded as MCP `serverInfo.icons` and\n * inherited by tools that do not set their own icons. Defaults to the\n * Routecraft logo (light and dark variants) when unset; pass an empty array\n * (`[]`) to serve no icon.\n */\n icons?: McpIcon[];\n\n /** Transport mode for MCP server. Default: \"stdio\" */\n transport?: \"stdio\" | \"http\";\n\n /** Port for the streamable-http MCP server. Default: 3001 (only used with transport: \"http\") */\n port?: number;\n\n /** Host to bind to. Default: \"localhost\" (only used with transport: \"http\") */\n host?: string;\n\n /**\n * Protected-resource (RFC 9728) metadata for the HTTP transport. When set,\n * the server advertises `/.well-known/oauth-protected-resource` and adds\n * `resource_metadata=\"...\"` to 401 `WWW-Authenticate` headers. Used by both\n * validator and OAuth-proxy auth modes; ignored for stdio.\n *\n * When omitted, baseline metadata is still served (deriving `resource` from\n * the bound URL and `authorization_servers` from the validator's IdP\n * issuer when present).\n */\n resource?: McpResourceOptions;\n\n /**\n * Authentication for the HTTP transport. When set, every request to `/mcp` must\n * include a valid `Authorization: Bearer <token>` header. Ignored for stdio.\n *\n * @example\n * ```ts\n * import { jwt } from \"@routecraft/ai\";\n * auth: jwt({ secret: process.env.JWT_SECRET! })\n * ```\n */\n auth?: McpHttpAuthOptions;\n\n /**\n * Principal enrichment that runs after `auth` verifies a token, for the\n * HTTP transport. Orthogonal to the auth mode: works with `jwks()` /\n * `jwt()` (validator mode), a custom `{ validator }`, and `oauth()`.\n * Three input shapes:\n *\n * - `true`: auto-discover the userinfo endpoint via OIDC Discovery at\n * `${issuer}/.well-known/openid-configuration`. Requires the verifier to\n * expose a single-string `issuer` (`jwks()` / `jwt()` do).\n * - `string | URL`: explicit userinfo endpoint URL. The framework fetches\n * it with the bearer token and lifts standard OIDC claims (`email`,\n * `name`, `roles`) onto the principal.\n * - `(principal, token) => Promise<Partial<Principal>>`: custom enrichment\n * from any backend (WorkOS / Clerk Backend API, internal DB, etc.).\n *\n * For URL and discovery modes the userinfo response `sub` MUST equal the\n * verified token's `sub` (OIDC Core §5.3.2); mismatches reject the\n * request. Verify wins on `subject`, `issuer`, `audience`, `expiresAt`,\n * `claims`; other fields are overwritten by the enrichment, and the raw\n * userinfo response is surfaced on `principal.userinfoClaims`. Results are\n * cached per token (SHA-256 keyed) and evicted at `expiresAt`; concurrent\n * requests for the same token share one in-flight fetch. All enrichment\n * errors are fail-closed (the request is rejected). Defaults to no\n * enrichment.\n */\n userinfo?: UserinfoOption;\n\n /**\n * CORS configuration for the HTTP transport. Controls which browser origins\n * can read responses from `/mcp`, `/.well-known/oauth-protected-resource`,\n * and the 401 `WWW-Authenticate` hint. Ignored for stdio.\n *\n * Default (when omitted): **loopback-only**. Browser MCP clients on\n * `localhost`, `127.0.0.1`, or `[::1]` (any port, http or https) work out of\n * the box; non-loopback browser origins must be allowlisted explicitly. This\n * is production-safe by construction; see `.standards/security.md` ->\n * \"Security defaults policy\".\n *\n * - `cors: false` -- disable CORS entirely (e.g. fronted by a CDN/proxy that owns CORS).\n * - `cors: { origin: \"https://app.example.com\" }` -- exact origin allowlist.\n * - `cors: { origin: [\"https://a.example\", \"https://b.example\"] }` -- multi-origin allowlist.\n * - `cors: { origin: \"*\" }` -- permissive opt-in.\n * - `cors: { origin: (req) => ... }` -- custom resolver.\n *\n * Server-to-server callers (curl, `mcp-remote`, the MCP CLI) are unaffected\n * regardless of this setting because they do not send an `Origin` header.\n *\n * Method, allowed-header, exposed-header, credentials, and preflight-cache\n * values are framework constants and not user-configurable. `WWW-Authenticate`\n * is always exposed so browser clients can read the RFC 9728 hint on a 401.\n */\n cors?: false | McpCorsOptions;\n\n /**\n * Filter which tools to expose. Default: all mcp() routes.\n * Can be an array of endpoint names or a filter function.\n */\n tools?: string[] | ((entry: McpLocalToolEntry) => boolean);\n\n /**\n * Named remote MCP servers for .to(mcp(\"name:tool\")).\n * Keys are server names; values are HTTP or stdio config.\n * Stdio clients are managed as subprocesses with auto-restart.\n * HTTP clients are used for ephemeral tool calls.\n */\n clients?: Record<string, McpClientHttpConfig | McpClientStdioConfig>;\n\n /**\n * Max auto-restart attempts for stdio clients before giving up.\n * Applies to all stdio clients. Default: 5.\n */\n maxRestarts?: number;\n\n /**\n * Base delay in ms before the first restart attempt.\n * Subsequent attempts use exponential backoff. Default: 1000.\n */\n restartDelayMs?: number;\n\n /**\n * Multiplier for exponential backoff between restart attempts.\n * Delay = restartDelayMs * (restartBackoffMultiplier ^ restartCount). Default: 2.\n */\n restartBackoffMultiplier?: number;\n\n /**\n * Interval in ms to re-list tools from HTTP clients.\n * Set to 0 to disable periodic refresh. Default: 60000 (60s).\n */\n toolRefreshIntervalMs?: number;\n}\n\n/**\n * MCP tool annotations describing tool behavior to clients.\n * All properties are hints; clients should not rely on them for correctness or safety.\n *\n * Mirrors the MCP specification (2025-03-26) `ToolAnnotations` shape.\n *\n * @see https://modelcontextprotocol.io/specification/2025-03-26/server/tools#annotations\n */\nexport interface McpToolAnnotations {\n /** Human-readable title for the tool (used for display in UIs). */\n title?: string;\n /** If true, the tool does not modify any state (default assumed false by clients). */\n readOnlyHint?: boolean;\n /** If true, the tool may perform destructive operations (default assumed true by clients). */\n destructiveHint?: boolean;\n /** If true, calling the tool repeatedly with the same args has no additional effect (default assumed false by clients). */\n idempotentHint?: boolean;\n /** If true, the tool may interact with the \"open world\" (external systems, network, etc.) (default assumed true by clients). */\n openWorldHint?: boolean;\n}\n\n/**\n * Icon reference for an MCP server or tool. Mirrors the MCP specification's\n * `Icon` shape, which is reused by `serverInfo.icons`, `Tool.icons`, and the\n * resource/prompt primitives.\n */\nexport interface McpIcon {\n /** URL or data URI of the icon. */\n src: string;\n /** MIME type of the icon, e.g. `\"image/svg+xml\"` or `\"image/png\"`. */\n mimeType?: string;\n /** One or more icon sizes, e.g. `[\"48x48\"]` or `[\"48x48\", \"96x96\"]`. */\n sizes?: string[];\n /** The client UI theme this icon is designed for. */\n theme?: \"light\" | \"dark\";\n}\n\n/**\n * Options for `mcp()` when used as a server in `.from()`.\n *\n * MCP-protocol-specific extras only. Shared discovery fields (title,\n * description, input, output schemas) live on the route via `.title()` /\n * `.description()` / `.input()` / `.output()` and are enforced by the\n * framework; `description` is required for MCP tools and the source will\n * reject a subscribe call whose route has no description set.\n */\nexport interface McpServerOptions {\n /**\n * MCP tool annotations describing behavior hints (read-only, destructive, etc.).\n * Forwarded on `tools/list`.\n *\n * @example\n * ```ts\n * .id(\"list-users\")\n * .description(\"List all users\")\n * .from(mcp({ annotations: { readOnlyHint: true, destructiveHint: false } }))\n * ```\n */\n annotations?: McpToolAnnotations;\n\n /** Icons forwarded on `tools/list` per the MCP spec. */\n icons?: McpIcon[];\n}\n\nexport type McpOptions = McpServerOptions;\n\n/**\n * Extracts MCP tool arguments from an exchange. Default implementation uses exchange.body.\n */\nexport type McpArgsExtractor = (\n exchange: Exchange<unknown>,\n) => Record<string, unknown>;\n\n/**\n * Options for mcp() when used as a Client in .to() to call a remote MCP server.\n * Provide either url (inline HTTP) or serverId (from plugin/store); tool is required.\n *\n * Supported transports:\n * - **HTTP:** use `url` for an inline endpoint or `serverId` for a named backend.\n * - **Stdio:** use `serverId` referencing a stdio client from mcpPlugin({ clients }).\n * The destination adapter resolves the manager from the context store and calls\n * tools directly on the subprocess -- no HTTP involved.\n */\nexport interface McpClientOptions {\n /** URL of the remote MCP server (HTTP/HTTPS only). Omit when using serverId. */\n url?: string;\n /** Tool name to invoke. If omitted, exchange body may specify it or a default applies. */\n tool?: string;\n /** Server id from context store; resolved to URL at runtime. Use when URL is registered via mcpPlugin({ clients }). */\n serverId?: string;\n /**\n * Extract tool arguments from the exchange. Receives the full exchange.\n * Default: body as object -> use as args; otherwise { input: body }.\n */\n args?: McpArgsExtractor;\n /**\n * Auth credentials for the outbound HTTP connection.\n * When using `serverId`, auth flows automatically from `mcpPlugin({ clients })`\n * so this field is rarely needed. Use it to override registered auth or to\n * supply credentials when using inline `url`.\n */\n auth?: McpClientAuthOptions;\n}\n\n/**\n * Represents a tool exposed via MCP\n */\nexport interface McpTool {\n name: string;\n /** Human-readable display title. */\n title?: string;\n description?: string;\n inputSchema: {\n type: \"object\";\n properties?: Record<string, unknown>;\n required?: string[];\n [key: string]: unknown;\n };\n /** JSON Schema for the tool output when the route declares one. */\n outputSchema?: {\n type: \"object\";\n properties?: Record<string, unknown>;\n required?: string[];\n [key: string]: unknown;\n };\n /** MCP tool annotations (behavior hints) reported by the server. */\n annotations?: McpToolAnnotations;\n /** Icons forwarded to clients per the MCP spec. */\n icons?: McpIcon[];\n}\n\n/**\n * A tool entry in the unified MCP tool registry.\n * Combines local mcp() route tools and remote client tools (stdio and HTTP).\n */\nexport interface McpToolRegistryEntry {\n /** Tool name (unique within a source, may collide across sources). */\n name: string;\n /** Human-readable description of the tool. */\n description?: string;\n /** JSON Schema for tool input. */\n inputSchema: Record<string, unknown>;\n /** Source server ID (e.g. a stdio/HTTP client name). */\n source: string;\n /**\n * Transport type of the source. stdio/http are populated automatically by mcpPlugin.\n * \"local\" is reserved for callers who manually register tools with local provenance.\n */\n transport: \"stdio\" | \"http\" | \"local\";\n /** MCP tool annotations (behavior hints). */\n annotations?: McpToolAnnotations;\n /**\n * Capability tags derived from the MCP `annotations` field at\n * registration time. Mirrors the `Tag` namespace fns and direct\n * routes use, so the agent `tools([{ tagged: \"read-only\" }])`\n * selector matches MCP tools alongside fn/route entries.\n *\n * Mapping: `readOnlyHint -> \"read-only\"`,\n * `destructiveHint -> \"destructive\"`, `idempotentHint -> \"idempotent\"`,\n * `openWorldHint -> \"open-world\"`.\n */\n tags?: readonly Tag[];\n}\n\n/**\n * MCP tool call result\n */\nexport interface McpToolResult {\n content: Array<{\n type: \"text\" | \"image\" | \"resource\";\n text?: string;\n data?: string;\n mimeType?: string;\n }>;\n isError?: boolean;\n}\n\n// Re-export Principal for convenience so consumers don't have to import from core.\nexport type { Principal };\n","/**\n * CORS for the MCP HTTP transport.\n *\n * Browser-based MCP clients (MCP Inspector UI, Claude.ai custom connectors,\n * web-hosted Claude Desktop) cannot read responses from the MCP HTTP transport\n * without CORS headers. This module owns the policy and the header math.\n *\n * The default is **loopback-only**: a request whose `Origin` is on `localhost`,\n * `127.0.0.1`, or `::1` (any port, http or https) gets reflected; everything\n * else gets no `Access-Control-Allow-Origin` header back and is blocked by the\n * browser. This is intentionally production-safe by construction: local\n * browser tooling works with zero config, while production deployments must\n * opt their real origins in explicitly. See `.standards/security.md` ->\n * \"Security defaults policy\" for the broader principle.\n *\n * Server-to-server callers (curl, `mcp-remote`, the MCP CLI) are unaffected by\n * CORS because they do not send an `Origin` header.\n *\n * The public option surface is intentionally minimal: only `origin` is\n * configurable. Method, header, expose-header, credentials, and preflight-cache\n * values are framework-controlled constants -- chosen to satisfy the RFC 9728\n * discovery contract and the MCP JSON-RPC handshake -- and can be expanded\n * later if a real use case demands it.\n */\n\nimport type { ServerResponse } from \"node:http\";\n\n/**\n * Resolver form of `origin`. Receives the request's `Origin` header (or\n * `undefined` when absent) and returns either the value to echo in\n * `Access-Control-Allow-Origin`, or `false` to disallow.\n *\n * Implementations SHOULD NOT throw. A thrown error is caught at the request\n * boundary and treated as `false` (fail-closed), but emitting an exception\n * also clears CORS for that request silently. Return `false` explicitly to\n * disallow.\n *\n * Keeping this transport-agnostic (no `IncomingMessage`) lets the helper run\n * on Bun, Node, and in tests without coupling to `node:http`.\n */\nexport type McpCorsOriginResolver = (\n requestOrigin: string | undefined,\n) => string | false;\n\n/**\n * CORS configuration for the MCP HTTP transport. Passed via\n * `mcpPlugin({ cors: { origin: ... } })`.\n *\n * Omitting `cors` entirely applies the loopback-only default. Pass\n * `cors: false` on `McpPluginOptions` to disable CORS handling completely\n * (useful when a reverse proxy or CDN owns CORS).\n */\nexport interface McpCorsOptions {\n /**\n * Allowed origin(s).\n *\n * - `\"*\"` -- permissive, no `Vary: Origin` emitted.\n * - `string` -- exact match against the request `Origin`; non-match returns no allow header.\n * - `string[]` -- allowlist; if the request `Origin` matches one entry, it is reflected.\n * - {@link McpCorsOriginResolver} -- custom resolver, returns the value to echo or `false` to disallow.\n */\n origin: \"*\" | string | string[] | McpCorsOriginResolver;\n}\n\n/**\n * Internal resolved CORS shape. The consumer never has to branch on string vs\n * array vs function form of `origin`. Not exported beyond this file.\n *\n * @internal\n */\ninterface ResolvedMcpCors {\n resolveOrigin: McpCorsOriginResolver;\n /** `true` when `origin` was the literal `\"*\"`. Skips `Vary: Origin`. */\n isWildcard: boolean;\n}\n\n/**\n * Framework-controlled CORS constants. Not user-configurable; chosen to\n * satisfy the RFC 9728 discovery contract and the MCP JSON-RPC handshake.\n *\n * - `Access-Control-Allow-Methods`: the verbs the transport accepts.\n * - `Access-Control-Allow-Headers`: `*` is the right default; `Authorization`,\n * `Content-Type`, and `MCP-Protocol-Version` are the headers MCP clients\n * send today, but the spec permits more and we do not want to gate.\n * - `Access-Control-Expose-Headers` (non-preflight only): the response headers\n * browser clients must be able to read.\n * - `WWW-Authenticate` -- RFC 9728 `resource_metadata` hint on a 401.\n * - `Mcp-Session-Id` -- emitted by the SDK on `initialize` in stateful mode\n * (see `server.ts` createSession). The MCP spec requires clients to echo\n * this value on every subsequent request; browsers cannot read it\n * cross-origin without it being exposed.\n * - `Last-Event-ID` -- SSE resume cursor; required for browser-based SSE\n * reconnection.\n *\n * @internal\n */\nconst ALLOW_METHODS = \"GET, POST, OPTIONS\";\nconst ALLOW_HEADERS = \"*\";\nconst EXPOSE_HEADERS = \"WWW-Authenticate, Mcp-Session-Id, Last-Event-ID\";\n\n/**\n * Hostnames recognised as loopback by the default policy.\n *\n * IPv6: both Node and Bun's `URL.hostname` return the bracketed form\n * `\"[::1]\"` for `http://[::1]:8080`, not `\"::1\"`. The unbracketed `\"::1\"`\n * entry is kept as defence-in-depth in case a future URL parser surfaces it\n * (the WHATWG URL spec is unsettled on this; older parsers and some\n * synthesised inputs may produce the unbracketed form).\n */\nconst LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\", \"[::1]\"]);\n\n/**\n * Default origin resolver: reflect the request `Origin` iff it is loopback\n * AND in canonical form per RFC 6454 §7.1 (`scheme://host[:port]`, no path,\n * no userinfo, no query, no fragment). Returns `false` otherwise.\n *\n * Real browsers never emit anything other than a canonical Origin, so this\n * tightening costs nothing in practice while ensuring we never echo a\n * malformed value into `Access-Control-Allow-Origin`.\n *\n * @internal\n */\nexport function defaultLoopbackOriginResolver(\n requestOrigin: string | undefined,\n): string | false {\n if (!requestOrigin) return false;\n if (requestOrigin === \"null\") return false;\n let parsed: URL;\n try {\n parsed = new URL(requestOrigin);\n } catch {\n return false;\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return false;\n if (parsed.username || parsed.password) return false;\n if (parsed.pathname !== \"/\" && parsed.pathname !== \"\") return false;\n if (parsed.search || parsed.hash) return false;\n return LOOPBACK_HOSTS.has(parsed.hostname) ? requestOrigin : false;\n}\n\n/**\n * Resolve a `cors` config slot into either a fully-populated internal shape or\n * `null` (CORS disabled entirely). `undefined` produces the loopback default.\n *\n * @internal\n */\nexport function resolveCorsOptions(\n input: false | McpCorsOptions | undefined,\n): ResolvedMcpCors | null {\n if (input === false) return null;\n if (input === undefined) {\n return {\n resolveOrigin: defaultLoopbackOriginResolver,\n isWildcard: false,\n };\n }\n\n const { origin } = input;\n if (origin === \"*\") {\n return { resolveOrigin: () => \"*\", isWildcard: true };\n }\n if (typeof origin === \"string\") {\n const allowed = origin;\n return {\n resolveOrigin: (requestOrigin) =>\n requestOrigin === allowed ? allowed : false,\n isWildcard: false,\n };\n }\n if (Array.isArray(origin)) {\n const allowed = new Set(origin);\n return {\n resolveOrigin: (requestOrigin) =>\n requestOrigin !== undefined && allowed.has(requestOrigin)\n ? requestOrigin\n : false,\n isWildcard: false,\n };\n }\n if (typeof origin === \"function\") {\n return { resolveOrigin: origin, isWildcard: false };\n }\n throw new TypeError(\n \"mcpPlugin: cors.origin must be '*', a string, a string array, or a function\",\n );\n}\n\n/**\n * Run the resolver in a try/catch so a misbehaving custom origin function\n * fails closed rather than crashing the in-flight MCP request.\n */\nfunction safeResolveOrigin(\n cors: ResolvedMcpCors,\n requestOrigin: string | undefined,\n): string | false {\n try {\n return cors.resolveOrigin(requestOrigin);\n } catch {\n return false;\n }\n}\n\n/**\n * Build the response headers to add for a given request `Origin`.\n *\n * Returns an empty object when CORS is disabled (`cors === null`).\n *\n * When the policy is origin-dependent (non-wildcard), `Vary: Origin` is\n * **always** included -- including for rejected origins -- so a shared cache\n * keyed by the response cannot serve a no-CORS response back to a loopback\n * origin. Disallowed origins receive `{ Vary: \"Origin\" }` only, with no\n * `Access-Control-Allow-Origin`.\n *\n * The caller is responsible for applying these headers. Use\n * {@link applyCorsHeaders} on a Node `ServerResponse` to merge `Vary` with\n * any existing value (compression middleware, etc.); spread the record into\n * a `writeHead` call when no prior `setHeader(\"Vary\", ...)` is in play.\n *\n * @param cors Resolved CORS options, or `null` to short-circuit.\n * @param requestOrigin Value of the request's `Origin` header.\n * @param preflight `true` to include `Access-Control-Allow-Methods/Headers`.\n * @internal\n */\nexport function buildCorsHeaders(\n cors: ResolvedMcpCors | null,\n requestOrigin: string | undefined,\n preflight: boolean,\n): Record<string, string> {\n if (!cors) return {};\n\n const headers: Record<string, string> = {};\n if (!cors.isWildcard) {\n headers[\"Vary\"] = \"Origin\";\n }\n\n const allowed = safeResolveOrigin(cors, requestOrigin);\n if (allowed === false) return headers;\n\n headers[\"Access-Control-Allow-Origin\"] = allowed;\n // Allow-Methods/Allow-Headers belong on preflight (204) only;\n // Expose-Headers belongs on the actual response only (browsers ignore it\n // on a preflight per the Fetch spec). Mirror that asymmetry here.\n if (preflight) {\n headers[\"Access-Control-Allow-Methods\"] = ALLOW_METHODS;\n headers[\"Access-Control-Allow-Headers\"] = ALLOW_HEADERS;\n // Chrome Private Network Access: when a non-loopback Origin reaches a\n // loopback/private target (e.g. a hosted browser MCP client tunneled\n // to a local MCP server during integration testing), Chrome blocks the\n // preflight unless the server opts in via this header. The header is\n // ignored by other browsers and by Chrome when the cross-network\n // condition does not apply, so emitting it unconditionally on preflight\n // -- gated on the origin already being allowlisted by the policy --\n // is safe and avoids threading the request headers through the helper.\n // Spec: https://wicg.github.io/private-network-access/\n headers[\"Access-Control-Allow-Private-Network\"] = \"true\";\n } else {\n headers[\"Access-Control-Expose-Headers\"] = EXPOSE_HEADERS;\n }\n return headers;\n}\n\n/**\n * Apply CORS headers to a Node `ServerResponse`. Uses `setHeader` for the\n * `Access-Control-*` family and `appendHeader` for `Vary` so any existing\n * `Vary` value (e.g. `Vary: Accept-Encoding` from compression middleware)\n * is preserved.\n *\n * A no-op when `cors === null`.\n *\n * @internal\n */\nexport function applyCorsHeaders(\n res: ServerResponse,\n cors: ResolvedMcpCors | null,\n requestOrigin: string | undefined,\n preflight: boolean,\n): void {\n if (!cors) return;\n const { Vary, ...rest } = buildCorsHeaders(cors, requestOrigin, preflight);\n for (const [name, value] of Object.entries(rest)) {\n res.setHeader(name, value);\n }\n if (Vary !== undefined) {\n res.appendHeader(\"Vary\", Vary);\n }\n}\n\n/** Root path of the RFC 9728 protected-resource metadata document. */\nexport const PROTECTED_RESOURCE_METADATA_PATH =\n \"/.well-known/oauth-protected-resource\";\n\n/**\n * Build the set of paths the MCP HTTP transport owns for CORS purposes, given\n * the resolved resource URL.\n *\n * The transport always listens on `/mcp` (and `/mcp/`). RFC 9728 §3 metadata\n * lives at the root path **and** at a path-suffixed variant derived from\n * `resource.url`'s pathname: e.g. for `resource.url = https://example.com/api/mcp`\n * the canonical client probe is `/.well-known/oauth-protected-resource/api/mcp`.\n * Both metadata URLs serve the identical document.\n *\n * The path-suffixed URL is derived dynamically because the MCP SDK's\n * `mcpAuthRouter` mounts its own path-aware doc at the same SDK-derived URL\n * (`/.well-known/oauth-protected-resource${rsPath}`); we must register our\n * handler at the same URL to shadow it and preserve the\n * \"identical JSON regardless of auth mode\" promise in\n * `.standards/security.md` §6.\n *\n * Returns the set of owned paths (always includes `/mcp`, `/mcp/`, and the\n * root metadata path; conditionally includes the path-suffixed metadata path).\n * The `metadataPaths` field is the subset on which the metadata document\n * is served.\n *\n * @internal\n */\nexport interface McpOwnedPaths {\n /** All paths the framework owns (CORS allowlist + OPTIONS short-circuit). */\n ownedPaths: ReadonlySet<string>;\n /** Subset of ownedPaths on which the RFC 9728 metadata doc is served. */\n metadataPaths: ReadonlySet<string>;\n}\n\nexport function buildMcpOwnedPaths(resourceUrl: URL): McpOwnedPaths {\n const metadataPaths = new Set<string>([PROTECTED_RESOURCE_METADATA_PATH]);\n const rsPath = resourceUrl.pathname;\n if (rsPath && rsPath !== \"/\" && rsPath !== \"\") {\n metadataPaths.add(`${PROTECTED_RESOURCE_METADATA_PATH}${rsPath}`);\n }\n const ownedPaths = new Set<string>([...metadataPaths, \"/mcp\", \"/mcp/\"]);\n return { ownedPaths, metadataPaths };\n}\n","import type { McpIcon } from \"./types.ts\";\n\n/**\n * The Routecraft logo as an inline SVG, parameterised by fill colour so we can\n * emit a light-theme (dark logo) and dark-theme (light logo) variant from one\n * source. Geometry is taken from `routecraft.svg` at the repo root.\n */\nconst logoSvg = (fill: string): string =>\n `<svg width=\"162\" height=\"153\" viewBox=\"0 0 162 153\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M141.881 62.9617C141.881 44.2319 126.65 29.0002 107.92 29.0002H30.1636L52.4304 52.2797L71.8879 52.3014L62.5672 42.4107H107.92C119.252 42.4107 128.471 51.6298 128.471 62.9617C128.471 74.293 119.252 83.5128 107.92 83.5128H101.193H88.5983H54.5814C50.8822 83.5128 47.8762 86.5187 47.8762 90.2173C47.8762 93.9278 50.8822 96.9225 54.5814 96.9225H95.4038L120.815 123.997H139.227L113.374 96.4753C129.522 93.8717 141.881 79.8359 141.881 62.9617Z\" fill=\"${fill}\"/><path d=\"M54.8718 110.59C43.5966 110.59 34.4105 101.403 34.4105 90.1282C34.4105 78.8411 43.5966 69.6662 54.8718 69.6662H107.115C110.814 69.6662 113.82 66.6714 113.82 62.9617C113.82 59.2624 110.814 56.2564 107.115 56.2564H54.8718C36.1988 56.2564 21 71.4545 21 90.1282C21 108.802 36.1988 124 54.8718 124H113.597L101.014 110.59H54.8718Z\" fill=\"${fill}\"/></svg>`;\n\nconst toDataUri = (svg: string): string =>\n `data:image/svg+xml;base64,${Buffer.from(svg, \"utf8\").toString(\"base64\")}`;\n\n/**\n * Default Routecraft branding for `serverInfo.icons` when a consumer does not\n * set their own. Two variants so the mark stays legible on either client theme:\n * a white logo for dark UIs and a black logo for light UIs.\n */\n// Frozen because this single array is handed out by reference to every server's\n// serverInfo and every inheriting tool; freezing prevents an accidental in-place\n// mutation from leaking process-wide into the shared default.\nexport const ROUTECRAFT_DEFAULT_ICONS: McpIcon[] = Object.freeze([\n Object.freeze({\n src: toDataUri(logoSvg(\"#ffffff\")),\n mimeType: \"image/svg+xml\",\n theme: \"dark\",\n }),\n Object.freeze({\n src: toDataUri(logoSvg(\"#000000\")),\n mimeType: \"image/svg+xml\",\n theme: \"light\",\n }),\n]) as McpIcon[];\n","import { createHash } from \"node:crypto\";\nimport { rcError, type Principal } from \"@routecraft/routecraft\";\n\n/**\n * Custom enrichment function. Receives the verified principal and the raw\n * bearer token and returns a partial principal whose non-protected fields are\n * merged onto the result.\n *\n * Trusted by contract: the framework does not enforce the `sub` invariant for\n * the function variant (unlike URL / discovery modes), since the caller is\n * already free to consult any backend they choose. Protected fields\n * (`subject`, `issuer`, `audience`, `expiresAt`, `claims`) from the verified\n * token always win regardless of what the function returns. If you want the\n * raw upstream response surfaced, return `{ userinfoClaims: ... }`.\n *\n * The `principal` parameter is typed as {@link Principal} because enrichment\n * works in both validator and OAuth-proxy modes. When the verifier is\n * `jwks()` / `jwt()` / `oauth()`, the principal carries `expiresAt` at\n * runtime (it is an `OAuthPrincipal`); a custom `{ validator }` may not.\n */\nexport type UserinfoFn = (\n principal: Principal,\n token: string,\n) => Promise<Partial<Principal>>;\n\n/**\n * Input shape for the `userinfo` slot on `mcpPlugin({})`.\n *\n * - `true`: auto-discover the userinfo endpoint via OIDC Discovery. The\n * discovery document is fetched relative to the verify helper's `issuer`,\n * so a single-string issuer (with or without a path) is required.\n * - `string | URL`: explicit userinfo endpoint URL.\n * - `UserinfoFn`: custom enrichment function for non-OIDC sources (Clerk\n * Backend API, internal DB, etc.).\n */\nexport type UserinfoOption = true | string | URL | UserinfoFn;\n\n/**\n * Fields that come from the verified token and cannot be overridden by\n * enrichment. `claims` is protected so URL / discovery enrichment does not\n * clobber the JWT payload that consumers expect on `principal.claims`; the\n * raw userinfo response lives on `userinfoClaims` instead.\n */\nconst PROTECTED_FIELDS = [\n \"subject\",\n \"issuer\",\n \"audience\",\n \"expiresAt\",\n \"claims\",\n] as const;\n\n/** Default cap on cached enriched principals. Tuned for typical MCP fleets; tokens self-evict at `expiresAt`. */\nconst DEFAULT_CACHE_MAX_ENTRIES = 10_000;\n\n/** Default discovery-document TTL when the IdP does not advertise `Cache-Control: max-age`. */\nconst DEFAULT_DISCOVERY_TTL_SEC = 3600;\n\ninterface CacheEntry {\n enrichment: Partial<Principal>;\n expiresAt: number;\n}\n\n/**\n * Token-bound enrichment cache with in-flight request coalescing.\n *\n * Caches the enrichment payload (a `Partial<OAuthPrincipal>`), NOT the\n * fully merged principal. The base verifier runs on every request so any\n * dynamic checks the verifier performs (introspection, revocation, clock\n * comparisons) still fire per request; only the userinfo / function-mode\n * enrichment is memoised.\n *\n * Entries are keyed by a SHA-256 hash of the bearer token so a heap dump\n * or accidental log snapshot does not expose plaintext bearers. Entries\n * self-evict at the principal's `expiresAt`; a configurable\n * insertion-order cap (`maxEntries`) provides a hard memory ceiling so a\n * misbehaving client that never reuses a token cannot grow the map\n * without bound.\n *\n * Concurrent calls for the same uncached token share a single in-flight\n * enrichment promise; the IdP receives one userinfo fetch per\n * (token, expiresAt) window, not one per inbound request.\n *\n * @internal\n */\nexport class UserinfoCache {\n private readonly entries = new Map<string, CacheEntry>();\n private readonly inFlight = new Map<string, Promise<Partial<Principal>>>();\n private readonly maxEntries: number;\n\n constructor(maxEntries: number = DEFAULT_CACHE_MAX_ENTRIES) {\n this.maxEntries = maxEntries;\n }\n\n /**\n * Return the cached enrichment for the token, or run `compute()` to\n * produce one and cache the result. Concurrent callers for the same\n * token share the in-flight promise. The cached entry self-evicts at\n * `expiresAt` (Unix epoch seconds, typically the principal's expiry).\n *\n * When `expiresAt` is `undefined` or non-finite (a custom validator that\n * produced a principal without `exp`), the result is computed fresh on\n * every call: there is no natural TTL to bound a cache entry, so caching\n * is skipped rather than guessed.\n */\n async getOrCompute(\n token: string,\n expiresAt: number | undefined,\n compute: () => Promise<Partial<Principal>>,\n ): Promise<Partial<Principal>> {\n if (expiresAt === undefined || !Number.isFinite(expiresAt)) {\n return compute();\n }\n const key = hashToken(token);\n const cached = this.entries.get(key);\n if (cached) {\n if (Date.now() / 1000 < cached.expiresAt) return cached.enrichment;\n this.entries.delete(key);\n }\n\n const pending = this.inFlight.get(key);\n if (pending) return pending;\n\n const promise = compute().then(\n (enrichment) => {\n this.store(key, enrichment, expiresAt);\n this.inFlight.delete(key);\n return enrichment;\n },\n (err: unknown) => {\n this.inFlight.delete(key);\n throw err;\n },\n );\n this.inFlight.set(key, promise);\n return promise;\n }\n\n /** Clear every cached entry. Intended for tests. */\n clear(): void {\n this.entries.clear();\n this.inFlight.clear();\n }\n\n private store(\n key: string,\n enrichment: Partial<Principal>,\n expiresAt: number,\n ): void {\n if (this.entries.has(key)) this.entries.delete(key);\n this.entries.set(key, { enrichment, expiresAt });\n while (this.entries.size > this.maxEntries) {\n const oldest = this.entries.keys().next().value;\n if (oldest === undefined) break;\n this.entries.delete(oldest);\n }\n }\n}\n\nfunction hashToken(token: string): string {\n return createHash(\"sha256\").update(token).digest(\"hex\");\n}\n\ninterface OidcDiscoveryDoc {\n userinfo_endpoint?: string;\n}\n\n/**\n * Parse `Cache-Control: max-age=<seconds>` (RFC 9111). Returns the parsed TTL\n * in seconds, or `undefined` if the header is absent or unparseable.\n */\nfunction parseMaxAge(headerValue: string | null): number | undefined {\n if (!headerValue) return undefined;\n const match = headerValue.match(/(?:^|,\\s*)max-age=(\\d+)/i);\n if (!match) return undefined;\n const value = Number.parseInt(match[1]!, 10);\n return Number.isFinite(value) && value >= 0 ? value : undefined;\n}\n\n/**\n * Resolve the userinfo endpoint URL from the `userinfo` option.\n *\n * For literal `string | URL`, returns it directly. For `true`, fetches the\n * OIDC Discovery document relative to the issuer (preserving the issuer's\n * path component, so Keycloak realms and tenant-prefixed IdPs resolve\n * correctly) and reads `userinfo_endpoint`. The discovery URL is cached for\n * the lifetime advertised by `Cache-Control: max-age`, defaulting to one\n * hour. Concurrent first-callers share a single in-flight fetch.\n *\n * Sync errors at construction time:\n * - `TypeError` if `userinfo: true` and no issuer is exposed by `verify`.\n * - `TypeError` if `userinfo: true` and the resolved issuer is an array.\n *\n * Async errors (per call, wrapped in `RC5021`):\n * - Discovery fetch failure (non-2xx, network error, malformed JSON).\n * - Discovery document missing `userinfo_endpoint`.\n *\n * @internal\n */\nfunction createUserinfoUrlResolver(\n option: true | string | URL,\n issuer: string | string[] | undefined,\n): () => Promise<URL> {\n if (option !== true) {\n const url = new URL(option.toString());\n return async () => url;\n }\n\n if (issuer === undefined) {\n throw new TypeError(\n \"oauth: `userinfo: true` requires the verify helper to expose an `issuer`. \" +\n \"Use `jwks({ issuer, ... })` / `jwt({ issuer, ... })`, pass an explicit \" +\n '`userinfo: \"https://idp.example.com/oauth/userinfo\"`, or use a function.',\n );\n }\n if (Array.isArray(issuer)) {\n throw new TypeError(\n \"oauth: `userinfo: true` requires a single-string `issuer`; got an array. \" +\n \"OIDC Discovery resolves one issuer to one userinfo endpoint. Pass an \" +\n \"explicit userinfo URL or function instead.\",\n );\n }\n\n const base = issuer.endsWith(\"/\") ? issuer : `${issuer}/`;\n const discoveryUrl = new URL(\".well-known/openid-configuration\", base);\n\n let cachedUrl: URL | null = null;\n let cachedUntil = 0;\n let inFlight: Promise<URL> | null = null;\n\n const fetchAndCache = async (): Promise<URL> => {\n let response: Response;\n try {\n response = await fetch(discoveryUrl);\n } catch (cause) {\n throw rcError(\"RC5021\", cause, {\n message: `OIDC Discovery fetch failed at ${discoveryUrl.toString()}`,\n suggestion:\n \"Verify network access to the IdP and that the issuer URL is reachable. Pass an explicit `userinfo` URL or function if the IdP does not advertise discovery.\",\n });\n }\n if (!response.ok) {\n throw rcError(\n \"RC5021\",\n new Error(\n `OIDC Discovery fetch returned ${response.status} ${response.statusText}`,\n ),\n {\n message: `OIDC Discovery fetch failed at ${discoveryUrl.toString()} (status ${response.status})`,\n suggestion:\n \"Verify the issuer hosts an OIDC Discovery document. Pass an explicit `userinfo` URL or function if it does not.\",\n },\n );\n }\n let doc: OidcDiscoveryDoc;\n try {\n doc = (await response.json()) as OidcDiscoveryDoc;\n } catch (cause) {\n throw rcError(\"RC5021\", cause, {\n message: `OIDC Discovery document at ${discoveryUrl.toString()} is not valid JSON`,\n suggestion:\n \"Inspect the discovery endpoint manually. Pass an explicit `userinfo` URL or function if the IdP is non-compliant.\",\n });\n }\n if (typeof doc.userinfo_endpoint !== \"string\" || !doc.userinfo_endpoint) {\n throw rcError(\n \"RC5021\",\n new Error(\"missing userinfo_endpoint in discovery document\"),\n {\n message: `OIDC Discovery document at ${discoveryUrl.toString()} does not advertise a userinfo_endpoint`,\n suggestion:\n \"Pass an explicit `userinfo` URL or function for this IdP; it does not advertise auto-discoverable userinfo.\",\n },\n );\n }\n const resolved = new URL(doc.userinfo_endpoint);\n const ttl =\n parseMaxAge(response.headers.get(\"cache-control\")) ??\n DEFAULT_DISCOVERY_TTL_SEC;\n cachedUrl = resolved;\n cachedUntil = Date.now() / 1000 + ttl;\n return resolved;\n };\n\n return async () => {\n if (cachedUrl && Date.now() / 1000 < cachedUntil) return cachedUrl;\n if (inFlight) return inFlight;\n inFlight = fetchAndCache().finally(() => {\n inFlight = null;\n });\n return inFlight;\n };\n}\n\n/**\n * Fetch the userinfo response from the given endpoint using the bearer token.\n * Throws `RC5021` when the response is non-2xx or not valid JSON. All errors\n * are surfaced to the verifier which rejects the request (fail-closed).\n */\nasync function fetchUserinfo(\n url: URL,\n token: string,\n): Promise<Record<string, unknown>> {\n let response: Response;\n try {\n response = await fetch(url, {\n headers: { Authorization: `Bearer ${token}` },\n });\n } catch (cause) {\n throw rcError(\"RC5021\", cause, {\n message: `userinfo fetch failed at ${url.toString()}`,\n suggestion:\n \"Verify network access to the IdP's userinfo endpoint and that the bearer token's scopes permit it.\",\n });\n }\n if (!response.ok) {\n throw rcError(\n \"RC5021\",\n new Error(`userinfo returned ${response.status} ${response.statusText}`),\n {\n message: `userinfo fetch failed at ${url.toString()} (status ${response.status})`,\n suggestion:\n \"Check the bearer token has the scopes required by the IdP's userinfo endpoint (typically `openid`, `email`, `profile`).\",\n },\n );\n }\n try {\n return (await response.json()) as Record<string, unknown>;\n } catch (cause) {\n throw rcError(\"RC5021\", cause, {\n message: `userinfo response at ${url.toString()} is not valid JSON`,\n suggestion:\n \"Inspect the userinfo endpoint manually; it must return a JSON object per OIDC Core §5.3.2.\",\n });\n }\n}\n\n/**\n * Merge an enrichment payload onto the verified principal. Protected fields\n * (`subject`, `issuer`, `audience`, `expiresAt`, `claims`) from the verified\n * token always win; every other field on the enrichment overwrites the\n * principal's. The raw userinfo response lives on `userinfoClaims` in URL /\n * discovery mode; function-mode enrichment can populate it explicitly.\n */\nfunction mergeEnrichment<P extends Principal>(\n principal: P,\n enrichment: Partial<Principal> | Record<string, unknown>,\n): P {\n // Copy into a plain record so the indexed write type-checks under a generic\n // `P`; every original field is preserved, only non-protected fields are\n // overwritten, so the cast back to `P` is sound.\n const merged: Record<string, unknown> = {\n ...(principal as Record<string, unknown>),\n };\n for (const [key, value] of Object.entries(enrichment)) {\n if ((PROTECTED_FIELDS as readonly string[]).includes(key)) continue;\n if (value === undefined) continue;\n merged[key] = value;\n }\n return merged as P;\n}\n\n/**\n * Lift standard OIDC claims off a userinfo response payload onto a\n * `Partial<OAuthPrincipal>` shape. Per OIDC Core §5.3.2 the response is a\n * flat JSON object keyed by claim name. The framework lifts the identity\n * claims that have a first-class field on `Principal` (`email`, `name`,\n * `roles`) and stashes the full response under `userinfoClaims` for callers\n * that want the raw payload. The verified JWT payload on `principal.claims`\n * is preserved.\n */\nfunction liftOidcClaims(payload: Record<string, unknown>): Partial<Principal> {\n const out: Partial<Principal> = { userinfoClaims: payload };\n if (typeof payload[\"email\"] === \"string\") out.email = payload[\"email\"];\n if (typeof payload[\"name\"] === \"string\") out.name = payload[\"name\"];\n if (Array.isArray(payload[\"roles\"])) {\n out.roles = (payload[\"roles\"] as unknown[]).filter(\n (r): r is string => typeof r === \"string\",\n );\n }\n return out;\n}\n\n/**\n * Wrap a base verifier with userinfo enrichment.\n *\n * The base verifier runs on every request so any dynamic checks it\n * performs (introspection, revocation, clock comparisons) still fire per\n * request. Only the enrichment payload is memoised, keyed by\n * SHA-256(token) and TTL'd to `principal.expiresAt`.\n *\n * Generic over the principal type so the same wrapper serves validator\n * mode (`jwks()` / `jwt()` / custom `{ validator }`) and OAuth-proxy mode\n * (`oauth()`); the caller supplies the base verifier and the IdP `issuer`\n * (needed only for `userinfo: true` OIDC Discovery).\n *\n * Concurrent first-callers for the same token share a single in-flight\n * enrichment promise, so the IdP receives one userinfo fetch per\n * (token, expiresAt) window. The merge is recomputed on every request\n * against the freshly-verified principal, so the returned object is never\n * a shared reference into the cache.\n *\n * Sub-invariant enforcement (URL / discovery modes only): the userinfo\n * response `sub` MUST match the first verified principal's `subject` (per\n * OIDC Core §5.3.2). Mismatches raise `RC5022`; the function variant is\n * trusted by contract. Network / fetch / parse failures raise `RC5021`.\n * Fail-closed throughout.\n *\n * For `userinfo: true`, this throws synchronously at call time when no\n * single-string `issuer` is available, so the server can fail fast at\n * startup rather than on the first request.\n *\n * @internal\n */\nexport function buildEnrichedVerifier<P extends Principal>(\n baseVerifier: (token: string) => Promise<P>,\n userinfo: UserinfoOption,\n issuer: string | string[] | undefined,\n): (token: string) => Promise<P> {\n const cache = new UserinfoCache();\n\n if (typeof userinfo === \"function\") {\n return async (token: string) => {\n const principal = await baseVerifier(token);\n const enrichment = await cache.getOrCompute(\n token,\n principal.expiresAt,\n () => userinfo(principal, token),\n );\n return mergeEnrichment(principal, enrichment);\n };\n }\n\n const resolveUserinfoUrl = createUserinfoUrlResolver(userinfo, issuer);\n\n return async (token: string) => {\n const principal = await baseVerifier(token);\n const enrichment = await cache.getOrCompute(\n token,\n principal.expiresAt,\n async () => {\n const url = await resolveUserinfoUrl();\n const payload = await fetchUserinfo(url, token);\n const responseSub = payload[\"sub\"];\n if (typeof responseSub !== \"string\" || responseSub.length === 0) {\n throw rcError(\n \"RC5022\",\n new Error(\"userinfo response is missing `sub`\"),\n {\n message:\n \"userinfo response is missing `sub` (required per OIDC Core §5.3.2)\",\n suggestion:\n \"Inspect the userinfo endpoint manually; the response MUST include a `sub` claim. If the IdP returns a non-standard identifier, use a function-mode `userinfo` and map it yourself.\",\n },\n );\n }\n if (responseSub !== principal.subject) {\n throw rcError(\n \"RC5022\",\n new Error(\n `userinfo \\`sub\\` (${responseSub}) does not match token \\`sub\\` (${principal.subject})`,\n ),\n {\n message:\n \"userinfo response `sub` does not match the verified token's `sub` (OIDC Core §5.3.2 violation)\",\n suggestion:\n \"This indicates a compromised userinfo endpoint or a misconfigured userinfo URL. Verify the issuer / userinfo mapping; do not relax this check.\",\n },\n );\n }\n return liftOidcClaims(payload);\n },\n );\n return mergeEnrichment(principal, enrichment);\n };\n}\n","/**\n * Whether a token verification error represents an expired token.\n *\n * An expired token is a routine part of the client lifecycle: clients present a\n * stale cached token, receive a 401, then refresh and retry. Callers log it at\n * `debug` so the `warn` channel stays reserved for failures that genuinely\n * warrant attention (bad signature, wrong audience or issuer, malformed token).\n *\n * Detection keys off `jose`'s stable `ERR_JWT_EXPIRED` code, thrown by `jwks()`\n * and surfaced unchanged through userinfo enrichment, and now also tagged on\n * `jwt()`'s expiry error so both built-in verifiers classify uniformly. `jose`\n * raises this code only for expiry, so audience and issuer mismatches\n * (`ERR_JWT_CLAIM_VALIDATION_FAILED`) correctly fall through. Validators that\n * reject expiry without this code also fall through to `warn`, the safe default\n * for an unclassified rejection.\n *\n * @internal\n */\nexport function isExpiredTokenError(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n (err as { code?: unknown }).code === \"ERR_JWT_EXPIRED\"\n );\n}\n\n/**\n * `jose` error codes that denote a server-side failure to fetch or parse the\n * JWKS, not a problem with the presented token. `ERR_JWKS_NO_MATCHING_KEY` is\n * deliberately absent: `jose` only surfaces it after re-fetching the key set, so\n * a propagated no-matching-key means the token references an unknown signing key\n * (a token problem, 401), not an infrastructure failure.\n */\nconst JOSE_INFRASTRUCTURE_CODES = new Set([\n \"ERR_JWKS_TIMEOUT\", // JWKS endpoint did not respond within the timeout\n \"ERR_JWKS_INVALID\", // JWKS document was structurally invalid\n \"ERR_JOSE_GENERIC\", // jose's catch-all: non-200 / unparseable JWKS response\n]);\n\n/**\n * Node / undici surface a `fetch` network failure as a `TypeError` whose\n * `cause` carries the real errno. These are the codes seen when the IdP's JWKS\n * endpoint is unreachable (DNS failure, connection refused, socket timeout).\n */\nconst NETWORK_ERROR_CODES = new Set([\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"ETIMEDOUT\",\n \"UND_ERR_CONNECT_TIMEOUT\",\n \"UND_ERR_HEADERS_TIMEOUT\",\n \"UND_ERR_SOCKET\",\n]);\n\n/**\n * Whether a token verification error is a server-side infrastructure failure\n * (JWKS endpoint unreachable, timed out, or returning a bad response) rather\n * than the verifier rejecting the presented token.\n *\n * The distinction matters for the HTTP status: an infrastructure failure must\n * map to 500 (so the client retries later), never to `401 invalid_token`, which\n * would make every client discard its valid cached token and stampede an\n * already-struggling IdP with refreshes. A token rejection is the opposite: it\n * must be 401 so the client refreshes. Callers therefore treat anything that is\n * NOT an infrastructure failure (and not a framework error) as a token\n * rejection, which keeps custom and built-in `jwt()` validators that throw a\n * plain `Error` mapping to 401.\n *\n * The whole `cause` chain is inspected, not just the immediate error: Node /\n * undici nest the real errno under a `fetch failed` TypeError, and a verifier\n * may wrap the underlying failure one or more levels deep. The walk is bounded\n * to guard against a self-referential `cause` cycle.\n *\n * @internal\n */\nexport function isInfrastructureError(err: unknown): boolean {\n let current: unknown = err;\n for (let depth = 0; depth < 5; depth++) {\n if (typeof current !== \"object\" || current === null) return false;\n const code = (current as { code?: unknown }).code;\n if (\n typeof code === \"string\" &&\n (JOSE_INFRASTRUCTURE_CODES.has(code) || NETWORK_ERROR_CODES.has(code))\n ) {\n return true;\n }\n current = (current as { cause?: unknown }).cause;\n }\n return false;\n}\n","import type { CraftContext } from \"@routecraft/routecraft\";\nimport {\n DefaultExchange,\n HeadersKeys,\n isRoutecraftError,\n loadOptionalPeer,\n markAuthentic,\n} from \"@routecraft/routecraft\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { createServer } from \"node:http\";\nimport type { IncomingMessage } from \"node:http\";\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport type {\n OAuthPrincipal,\n OAuthValidatorAuthOptions,\n Principal,\n ValidatorAuthOptions,\n} from \"@routecraft/routecraft\";\nimport {\n MCP_LOCAL_TOOL_REGISTRY,\n McpHeadersKeys,\n isOAuthAuth,\n} from \"./types.ts\";\nimport type {\n McpIcon,\n McpLocalToolEntry,\n McpPluginOptions,\n McpTool,\n OAuthAuthOptions,\n} from \"./types.ts\";\nimport {\n applyCorsHeaders,\n buildMcpOwnedPaths,\n PROTECTED_RESOURCE_METADATA_PATH,\n resolveCorsOptions,\n} from \"./cors.ts\";\nimport { ROUTECRAFT_DEFAULT_ICONS } from \"./default-icon.ts\";\nimport { buildEnrichedVerifier } from \"./userinfo.ts\";\nimport { isExpiredTokenError, isInfrastructureError } from \"./auth-errors.ts\";\n\n/**\n * MCP SDK `AuthInfo` shape. Imported as a type so nothing is required at\n * runtime from the SDK just for this alias; `import type` is erased by the\n * compiler.\n */\ntype SdkAuthInfo = AuthInfo;\n\n/**\n * Request-scoped storage for the authenticated principal.\n * Set in the HTTP request handler after auth validation;\n * read in handleToolCall to populate exchange headers.\n */\nconst principalStore = new AsyncLocalStorage<Principal | undefined>();\n\n/** Resolved options with defaults applied (internal use). */\ntype McpServerResolvedOptions = Required<\n Pick<McpPluginOptions, \"name\" | \"version\" | \"transport\" | \"port\" | \"host\">\n> &\n Pick<\n McpPluginOptions,\n | \"tools\"\n | \"auth\"\n | \"title\"\n | \"resource\"\n | \"cors\"\n | \"userinfo\"\n | \"description\"\n | \"websiteUrl\"\n | \"instructions\"\n | \"icons\"\n >;\n\n/** The MCP SDK `Server` constructor info arg (the fields we populate). */\ntype SdkServerInfo = {\n name: string;\n version: string;\n title?: string;\n description?: string;\n websiteUrl?: string;\n icons?: McpIcon[];\n};\n\n/** The MCP SDK `Server` constructor options arg (the fields we populate). */\ntype SdkServerOptions = {\n capabilities: { tools: Record<string, unknown> };\n instructions?: string;\n};\n\n/** The MCP SDK `Server` constructor as we consume it via dynamic import. */\ntype SdkServerCtor = new (\n info: SdkServerInfo,\n options: SdkServerOptions,\n) => unknown;\n\n/**\n * RFC 9728 OAuth 2.0 Protected Resource Metadata payload returned by\n * `GET /.well-known/oauth-protected-resource`. Optional fields are omitted\n * from the JSON when unset.\n *\n * @internal\n */\ninterface ProtectedResourceMetadata {\n resource: string;\n resource_name?: string;\n authorization_servers?: string[];\n bearer_methods_supported: [\"header\"];\n scopes_supported?: string[];\n resource_documentation?: string;\n}\n\n/**\n * McpServer wraps the MCP SDK and bridges it to Routecraft's DirectChannel infrastructure.\n * It reads the MCP route registry lazily (on first tools/list request) to ensure routes have subscribed.\n *\n * Note: Uses dynamic imports to avoid TypeScript compatibility issues with the MCP SDK.\n * Supports both stdio and streamable-http transports.\n */\nexport class McpServer {\n private context: CraftContext;\n private options: McpServerResolvedOptions;\n private server: unknown = null;\n private transport: unknown = null;\n /**\n * Node HTTP server when transport is http; used to listen on port and close on stop.\n * When OAuth is enabled this holds the Express app's underlying server.\n */\n private httpServer: ReturnType<typeof createServer> | null = null;\n /** Active HTTP sessions keyed by session ID (each session has its own server+transport pair). */\n private httpSessions = new Map<\n string,\n { server: unknown; transport: unknown }\n >();\n private running = false;\n private toolsListLogged = false;\n /**\n * Validator-mode token verifier, optionally wrapped with `userinfo`\n * enrichment. Built eagerly in `startHttpWithValidator` so a misconfigured\n * `userinfo: true` (no issuer) fails at startup rather than on first\n * request. `null` until the validator HTTP path starts.\n */\n private validatorVerifier: ((token: string) => Promise<Principal>) | null =\n null;\n\n constructor(context: CraftContext, options: McpPluginOptions = {}) {\n this.context = context;\n this.options = {\n name: \"routecraft\",\n version: \"1.0.0\",\n transport: \"stdio\",\n port: 3001,\n host: \"localhost\",\n ...options,\n };\n this.validateResourceConfig();\n }\n\n /**\n * Resolve the server-level icons: the Routecraft default when unset, the\n * consumer's icons otherwise (an explicit empty array means \"no icon\").\n */\n private resolveServerIcons(): McpIcon[] {\n return this.options.icons === undefined\n ? ROUTECRAFT_DEFAULT_ICONS\n : this.options.icons;\n }\n\n /**\n * Apply a default when the value is unset, then treat an empty string as an\n * explicit opt-out (returns `undefined` so the caller omits the field). This\n * is the uniform \"default unless empty\" contract used by every optional\n * string field of the server identity.\n */\n private defaultUnlessEmpty(\n value: string | undefined,\n fallback: string,\n ): string | undefined {\n const resolved = value ?? fallback;\n return resolved === \"\" ? undefined : resolved;\n }\n\n /**\n * Build the MCP `serverInfo` (`Implementation`) object shared by both\n * transports. Applies the Routecraft \"powered by\" defaults for description,\n * websiteUrl, and icons; an empty string/array opts out of a given field.\n */\n private buildServerInfo(): SdkServerInfo {\n const info: SdkServerInfo = {\n name: this.options.name,\n version: this.options.version,\n };\n if (this.options.title !== undefined) {\n info.title = this.options.title;\n }\n\n const description = this.defaultUnlessEmpty(\n this.options.description,\n \"Powered by Routecraft.dev\",\n );\n if (description !== undefined) {\n info.description = description;\n }\n\n const websiteUrl = this.defaultUnlessEmpty(\n this.options.websiteUrl,\n \"https://routecraft.dev\",\n );\n if (websiteUrl !== undefined) {\n info.websiteUrl = websiteUrl;\n }\n\n const icons = this.resolveServerIcons();\n if (icons.length > 0) {\n info.icons = icons;\n }\n return info;\n }\n\n /**\n * Build the MCP `Server` options arg (capabilities plus optional\n * instructions). `instructions` has no default; an empty string opts out,\n * matching the empty-value contract of the serverInfo string fields.\n */\n private buildServerOptions(): SdkServerOptions {\n const options: SdkServerOptions = { capabilities: { tools: {} } };\n const instructions = this.defaultUnlessEmpty(this.options.instructions, \"\");\n if (instructions !== undefined) {\n options.instructions = instructions;\n }\n return options;\n }\n\n /**\n * Validate plugin-level resource config at construction time. Runs the\n * HTTPS-in-production guard on an explicit `resource.url`. The default\n * fallback `http://{host}:{port}/mcp` is permitted as a dev-only\n * convenience; the guard only fires when the user explicitly opted in to\n * an `http://` URL in production.\n */\n private validateResourceConfig(): void {\n const explicit = this.options.resource?.url;\n if (explicit === undefined) return;\n const parsed = new URL(explicit.toString());\n if (\n parsed.protocol !== \"https:\" &&\n process.env[\"NODE_ENV\"] === \"production\"\n ) {\n throw new TypeError(\n \"mcpPlugin: resource.url must use HTTPS in production\",\n );\n }\n }\n\n /**\n * Start the MCP server and listen for connections\n */\n async start(): Promise<void> {\n if (this.running) {\n this.context.logger.warn({}, \"MCP server already running\");\n return;\n }\n\n try {\n const transport = this.options.transport;\n\n if (transport === \"http\") {\n await this.startHttp();\n } else {\n await this.startStdio();\n }\n\n this.running = true;\n this.context.logger.info(\n {\n name: this.options.name,\n version: this.options.version,\n transport,\n },\n \"MCP server started\",\n );\n this.logExposedToolsOnce();\n } catch (error) {\n const msg = isRoutecraftError(error)\n ? (error as unknown as { meta: { message: string } }).meta.message\n : error instanceof Error\n ? error.message\n : \"Failed to start MCP server\";\n this.context.logger.error({ err: error }, msg);\n throw error;\n }\n }\n\n /**\n * Start stdio transport\n */\n private async startStdio(): Promise<void> {\n const serverMod = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/server/index.js\"),\n { adapterName: \"mcp (stdio)\", packageName: \"@modelcontextprotocol/sdk\" },\n );\n const Server = serverMod.Server as SdkServerCtor;\n const stdioMod = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/server/stdio.js\"),\n { adapterName: \"mcp (stdio)\", packageName: \"@modelcontextprotocol/sdk\" },\n );\n const StdioServerTransport =\n stdioMod.StdioServerTransport as new () => unknown;\n\n this.server = new Server(this.buildServerInfo(), this.buildServerOptions());\n\n await this.setupRequestHandlers();\n\n this.transport = new StdioServerTransport();\n const srvWithConnect = this.server as Record<\n string,\n (transport: unknown) => Promise<void>\n >;\n await srvWithConnect[\"connect\"](this.transport);\n }\n\n /**\n * Start HTTP transport (streamable-http).\n * Dispatches to the OAuth or raw-HTTP path depending on the auth config.\n */\n private async startHttp(): Promise<void> {\n if (this.options.auth && isOAuthAuth(this.options.auth)) {\n await this.startHttpWithOAuth(this.options.auth);\n } else {\n await this.startHttpWithValidator();\n }\n }\n\n /**\n * Import the MCP SDK Server constructor and StreamableHTTPServerTransport.\n * Shared by both HTTP startup paths.\n */\n private async importSdkHttp(): Promise<{\n ServerCtor: SdkServerCtor;\n TransportClass: new (options?: {\n sessionIdGenerator?: () => string;\n onsessioninitialized?: (sessionId: string) => void;\n enableJsonResponse?: boolean;\n }) => unknown;\n }> {\n const serverModule = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/server/index.js\"),\n { adapterName: \"mcp (http)\", packageName: \"@modelcontextprotocol/sdk\" },\n );\n const ServerCtor = serverModule.Server as SdkServerCtor;\n\n // streamableHttp is a sub-export that may not exist on older SDK\n // versions; the `.catch(() => null)` lets the OAuth-aware fallback\n // kick in instead of failing the whole startup. Don't route through\n // loadOptionalPeer here because the missing-sub-export case is\n // distinct from the missing-package case.\n const streamableModule =\n await import(\"@modelcontextprotocol/sdk/server/streamableHttp.js\").catch(\n () => null,\n );\n const TransportClass = (\n streamableModule as Record<string, unknown> | null\n )?.[\"StreamableHTTPServerTransport\"] as\n | (new (options?: {\n sessionIdGenerator?: () => string;\n onsessioninitialized?: (sessionId: string) => void;\n enableJsonResponse?: boolean;\n }) => unknown)\n | undefined;\n\n if (!TransportClass) {\n throw new Error(\n \"StreamableHTTPServerTransport not found in MCP SDK - ensure @modelcontextprotocol/sdk v1.26.0+ is installed\",\n );\n }\n\n return { ServerCtor, TransportClass };\n }\n\n /**\n * Creates a new MCP Server + Transport pair for a single HTTP session.\n * Called on every initialization request (no session ID header).\n */\n private async createSession(\n ServerCtor: SdkServerCtor,\n TransportClass: new (options?: {\n sessionIdGenerator?: () => string;\n onsessioninitialized?: (sessionId: string) => void;\n enableJsonResponse?: boolean;\n }) => unknown,\n ): Promise<{\n transport: unknown;\n handleRequest: (\n req: unknown,\n res: unknown,\n parsedBody?: unknown,\n ) => Promise<void>;\n }> {\n const server = new ServerCtor(\n this.buildServerInfo(),\n this.buildServerOptions(),\n );\n\n await this.setupRequestHandlersOn(server);\n\n const transport = new TransportClass({\n sessionIdGenerator: () => crypto.randomUUID(),\n onsessioninitialized: (sessionId: string) => {\n this.httpSessions.set(sessionId, { server, transport });\n this.context.logger.debug({ sessionId }, \"MCP session created\");\n this.context.emit(\"plugin:mcp:session:created\", { sessionId });\n },\n enableJsonResponse: true,\n });\n\n const srvWithConnect = server as Record<\n string,\n (t: unknown) => Promise<void>\n >;\n await srvWithConnect[\"connect\"](transport);\n\n // Clean up on transport close so the session map does not leak.\n const tr = transport as Record<string, unknown>;\n const prevOnClose = tr[\"onclose\"] as (() => void) | undefined;\n tr[\"onclose\"] = () => {\n const sid = (transport as { sessionId?: string }).sessionId;\n if (sid) {\n this.httpSessions.delete(sid);\n this.context.logger.debug({ sessionId: sid }, \"MCP session closed\");\n this.context.emit(\"plugin:mcp:session:closed\", {\n sessionId: sid,\n });\n }\n prevOnClose?.();\n };\n\n const handleRequest = (\n transport as Record<\n string,\n (req: unknown, res: unknown, parsedBody?: unknown) => Promise<void>\n >\n )[\"handleRequest\"];\n if (typeof handleRequest !== \"function\") {\n throw new Error(\n \"StreamableHTTPServerTransport.handleRequest not found - SDK may have changed\",\n );\n }\n\n return {\n transport,\n handleRequest: handleRequest.bind(transport) as (\n req: unknown,\n res: unknown,\n parsedBody?: unknown,\n ) => Promise<void>,\n };\n }\n\n /**\n * Route an MCP request through session management with principal context.\n * Shared by both HTTP startup paths.\n */\n private async handleMcpRequest(\n req: IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n principal: Principal | undefined,\n createSessionFn: () => Promise<{\n handleRequest: (\n req: unknown,\n res: unknown,\n parsedBody?: unknown,\n ) => Promise<void>;\n }>,\n ): Promise<void> {\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n const runWithPrincipal = <T>(fn: () => Promise<T>): Promise<T> =>\n principalStore.run(principal, fn);\n\n try {\n if (sessionId && this.httpSessions.has(sessionId)) {\n const session = this.httpSessions.get(sessionId)!;\n const hr = (\n session.transport as Record<\n string,\n (req: unknown, res: unknown, parsedBody?: unknown) => Promise<void>\n >\n )[\"handleRequest\"];\n await runWithPrincipal(() => hr.call(session.transport, req, res));\n } else if (!sessionId || req.method === \"POST\") {\n const { handleRequest } = await createSessionFn();\n await runWithPrincipal(() => handleRequest(req, res));\n } else {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Session not found\" }));\n }\n } catch (err) {\n const msg = isRoutecraftError(err)\n ? (err as unknown as { meta: { message: string } }).meta.message\n : err instanceof Error\n ? err.message\n : \"MCP HTTP request error\";\n this.context.logger.error({ err }, msg);\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal Server Error\" }));\n }\n }\n }\n\n /**\n * Resolve the RFC 9728 `resource` URL. Resolution order:\n * 1. `mcpPlugin({ resource: { url } })`\n * 2. bound fallback `http://{host}:{port}/mcp`\n *\n * The HTTPS-in-production guard on an explicit `resource.url` runs eagerly\n * in the constructor (see `validateResourceConfig`); this resolver is a\n * pure projection. Should be called after `.listen()` so the bound port is\n * known. The OAuth path resolves at startup (pre-listen) because the MCP\n * SDK closes over the URL when middleware is registered; that path\n * forbids `port: 0` with an unset `resource.url` separately to avoid\n * baking `:0` into advertised URLs.\n */\n private resolveResourceUrl(): string {\n const explicit = this.options.resource?.url;\n if (explicit !== undefined) return explicit.toString();\n const host = this.options.host;\n const port = this.getHttpPort() ?? this.options.port;\n return `http://${host}:${port}/mcp`;\n }\n\n /**\n * Resolve the RFC 9728 `resource_name` value: `title` -> `name`.\n */\n private resolveResourceName(): string {\n return this.options.title ?? this.options.name;\n }\n\n /**\n * Build the RFC 9728 protected-resource metadata document.\n *\n * `authorization_servers` is populated from the validator's `issuer` (when\n * `auth` is `OAuthValidatorAuthOptions` from `jwks()` / `jwt()`). When the\n * verifier exposes no issuer, the field is omitted (RFC 9728 allows that).\n *\n * @internal\n */\n private buildProtectedResourceMetadata(): ProtectedResourceMetadata {\n const metadata: ProtectedResourceMetadata = {\n resource: this.resolveResourceUrl(),\n bearer_methods_supported: [\"header\"],\n };\n metadata.resource_name = this.resolveResourceName();\n\n const auth = this.options.auth;\n if (auth && !(\"provider\" in auth) && \"issuer\" in auth) {\n const issuer = (auth as OAuthValidatorAuthOptions).issuer;\n if (issuer !== undefined) {\n metadata.authorization_servers = Array.isArray(issuer)\n ? issuer\n : [issuer];\n }\n }\n\n const resource = this.options.resource;\n if (resource?.scopesSupported && resource.scopesSupported.length > 0) {\n metadata.scopes_supported = resource.scopesSupported;\n }\n if (resource?.documentationUrl !== undefined) {\n metadata.resource_documentation = resource.documentationUrl.toString();\n }\n\n return metadata;\n }\n\n /**\n * Build the absolute URL of the protected-resource metadata document.\n * Combines `PROTECTED_RESOURCE_METADATA_PATH` (always rooted at origin)\n * with the resolved `resource.url`'s origin.\n *\n * @internal\n */\n private resolveResourceMetadataUrl(): string {\n return new URL(\n PROTECTED_RESOURCE_METADATA_PATH,\n this.resolveResourceUrl(),\n ).toString();\n }\n\n /**\n * Build the `WWW-Authenticate` header value for a 401, with an absolute\n * `resource_metadata` URL per RFC 9728 §5.1.\n */\n private buildWwwAuthenticateHeader(): string {\n const metadataUrl = this.resolveResourceMetadataUrl();\n return `Bearer realm=\"mcp\", resource_metadata=\"${metadataUrl}\"`;\n }\n\n /**\n * Serve the RFC 9728 protected-resource metadata document.\n *\n * Shared between validator and OAuth-proxy modes so both produce the\n * exact same JSON shape. Default `Cache-Control: public, max-age=3600`\n * follows RFC 9728 §3.3's caching guidance; auto-discovering MCP clients\n * fetch this document on every connection, so a short cache prevents the\n * IdP from being polled needlessly.\n *\n * @internal\n */\n private serveProtectedResourceMetadata(\n res: import(\"node:http\").ServerResponse,\n ): void {\n const metadata = this.buildProtectedResourceMetadata();\n // CORS headers, when applicable, are committed by the surrounding\n // request handler via `applyCorsHeaders` before this helper runs. They\n // survive `writeHead` because the headers object below does not name\n // any `Access-Control-*` or `Vary` key.\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": \"public, max-age=3600\",\n });\n res.end(JSON.stringify(metadata));\n }\n\n /**\n * Start HTTP transport with validator-based auth (existing behavior).\n * Uses raw Node.js `http.createServer`.\n */\n private async startHttpWithValidator(): Promise<void> {\n const { ServerCtor, TransportClass } = await this.importSdkHttp();\n const port = this.options.port;\n const host = this.options.host;\n const cors = resolveCorsOptions(this.options.cors);\n\n // Build the (optionally enriched) validator verifier eagerly so a\n // misconfigured `userinfo: true` (no issuer) throws at startup, not on\n // the first request.\n this.validatorVerifier = this.buildValidatorVerifier();\n\n const createSessionFn = () =>\n this.createSession(ServerCtor, TransportClass);\n\n this.httpServer = createServer(async (req, res) => {\n const url = req.url?.split(\"?\")[0] ?? \"\";\n const rawOrigin = req.headers[\"origin\"];\n const originValue = Array.isArray(rawOrigin) ? rawOrigin[0] : rawOrigin;\n // Resolved owned/metadata paths derived from the bound resource URL.\n // Computed per-request because `resolveResourceUrl()` depends on the\n // bound port for the default fallback (port: 0 is only known after\n // .listen()). The computation is cheap (URL parse + small set build).\n const resolvedResourceUrl = new URL(this.resolveResourceUrl());\n const { ownedPaths, metadataPaths } =\n buildMcpOwnedPaths(resolvedResourceUrl);\n\n // OPTIONS preflight on an owned path: answer 204 with CORS headers.\n // When `cors === null` (user opted out via `cors: false`) we DO NOT\n // synthesize a preflight response -- the user said a fronting\n // proxy/CDN owns CORS, so we must let the request fall through\n // rather than swallowing OPTIONS here.\n if (req.method === \"OPTIONS\" && cors !== null && ownedPaths.has(url)) {\n applyCorsHeaders(res, cors, originValue, true);\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Commit CORS headers via setHeader/appendHeader for every non-OPTIONS\n // response, including the catch-all 404 below. Browser clients that\n // probe unknown paths (e.g. RFC 9728 discovery fallbacks) need to read\n // the status, not a misleading CORS error. Gated on `!= OPTIONS` so\n // unowned-path OPTIONS (which fell through the short-circuit above)\n // do not pick up non-preflight `Expose-Headers` they cannot use.\n // `applyCorsHeaders` is a no-op when `cors === null`.\n if (req.method !== \"OPTIONS\") {\n applyCorsHeaders(res, cors, originValue, false);\n }\n\n if (metadataPaths.has(url)) {\n this.serveProtectedResourceMetadata(res);\n return;\n }\n\n if (url !== \"/mcp\" && url !== \"/mcp/\") {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not Found\", path: url }));\n return;\n }\n\n let principal: Principal | undefined;\n if (this.options.auth) {\n const result = await this.validateAuth(req);\n if (!result) {\n res.writeHead(401, {\n \"Content-Type\": \"application/json\",\n \"WWW-Authenticate\": this.buildWwwAuthenticateHeader(),\n });\n res.end(JSON.stringify({ error: \"Unauthorized\" }));\n return;\n }\n principal = result;\n }\n\n await this.handleMcpRequest(req, res, principal, createSessionFn);\n });\n\n await this.listenHttp(port, host);\n }\n\n /**\n * Start HTTP transport with OAuth provider auth.\n * Uses Express to mount `mcpAuthRouter` (OAuth endpoints) alongside `/mcp`.\n * Express is available as a transitive dependency of `@modelcontextprotocol/sdk`.\n *\n * Note: if the server runs behind a reverse proxy, `req.ip` and `req.protocol`\n * may be incorrect. Users should set `trust proxy` on the Express app via a\n * future configuration option or by using a custom HTTP server.\n */\n private async startHttpWithOAuth(\n oauthOptions: OAuthAuthOptions,\n ): Promise<void> {\n const { ServerCtor, TransportClass } = await this.importSdkHttp();\n\n // Dynamic imports for Express and SDK OAuth infrastructure.\n // Express types are not available at compile time (transitive dep of SDK),\n // so all Express values are typed as unknown and accessed dynamically.\n let expressFn: (...args: unknown[]) => {\n get: (...args: unknown[]) => void;\n use: (...args: unknown[]) => void;\n all: (...args: unknown[]) => void;\n listen: (\n port: number,\n host: string,\n cb: () => void,\n ) => ReturnType<typeof createServer>;\n };\n\n try {\n // @ts-expect-error -- Express is a transitive dep of @modelcontextprotocol/sdk; no type declarations in this project\n const expressMod = (await import(\"express\")) as Record<string, unknown>;\n expressFn = (expressMod[\"default\"] ?? expressMod) as typeof expressFn;\n } catch {\n throw new Error(\n 'OAuth auth requires \"express\" (optional peer dependency of @routecraft/ai). Install it with: bun add express',\n );\n }\n\n // OAuth sub-modules require @modelcontextprotocol/sdk v1.27.0+. If the\n // package is missing entirely loadOptionalPeer fires RC5017 with the\n // install hint. If the package is present but the sub-path is not (older\n // SDK), the underlying ERR_MODULE_NOT_FOUND for the sub-path propagates,\n // which is more diagnostic than a generic \"install\" message.\n const routerMod = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/server/auth/router.js\"),\n { adapterName: \"mcp (oauth)\", packageName: \"@modelcontextprotocol/sdk\" },\n );\n const mcpAuthRouter = (routerMod as Record<string, unknown>)[\n \"mcpAuthRouter\"\n ] as (options: Record<string, unknown>) => unknown;\n\n const bearerMod = await loadOptionalPeer(\n () =>\n import(\"@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js\"),\n { adapterName: \"mcp (oauth)\", packageName: \"@modelcontextprotocol/sdk\" },\n );\n const requireBearerAuth = (bearerMod as Record<string, unknown>)[\n \"requireBearerAuth\"\n ] as (options: Record<string, unknown>) => unknown;\n\n const proxyMod = await loadOptionalPeer(\n () =>\n import(\"@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js\"),\n { adapterName: \"mcp (oauth)\", packageName: \"@modelcontextprotocol/sdk\" },\n );\n const ProxyOAuthServerProvider = (proxyMod as Record<string, unknown>)[\n \"ProxyOAuthServerProvider\"\n ] as new (options: Record<string, unknown>) => unknown;\n\n // The SDK's bearer middleware maps a thrown verify error to an HTTP status\n // by its type: only an `InvalidTokenError` becomes a 401 (with a\n // `WWW-Authenticate: Bearer error=\"invalid_token\"` header that drives the\n // client to refresh); anything else falls through to a generic 500. The\n // wrapped verifier below converts token-validation failures into this error\n // so an expired or invalid bearer yields 401, not 500.\n const errorsMod = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/server/auth/errors.js\"),\n { adapterName: \"mcp (oauth)\", packageName: \"@modelcontextprotocol/sdk\" },\n );\n const InvalidTokenError = (errorsMod as Record<string, unknown>)[\n \"InvalidTokenError\"\n ] as new (message: string) => Error;\n\n // Apply plugin-level `userinfo` enrichment to the OAuth verifier. The\n // issuer for `userinfo: true` discovery is surfaced on the oauth() result\n // from the verify helper. Built eagerly so a misconfigured `userinfo: true`\n // (no issuer) throws at startup.\n const verifyAccessToken =\n this.options.userinfo === undefined\n ? oauthOptions.verifyAccessToken\n : buildEnrichedVerifier(\n oauthOptions.verifyAccessToken,\n this.options.userinfo,\n oauthOptions.issuer,\n );\n\n // Wrap the user's verifier so the MCP SDK sees a clean AuthInfo while the\n // rich OAuthPrincipal rides through in `extra.principal` for\n // this.authInfoToPrincipal. Token verification failures emit `auth:rejected`\n // so operators can observe brute-force attempts, mismatched audiences, and\n // expired tokens alongside the validator path's rejections. Expiry is\n // routine (the client refreshes and retries) so it logs at `debug`; every\n // other failure logs at `warn`. A token-validation failure is re-thrown as\n // InvalidTokenError so the SDK answers 401 (the client refreshes), not 500.\n const wrappedVerifier = async (token: string): Promise<SdkAuthInfo> => {\n let principal: OAuthPrincipal;\n try {\n principal = await verifyAccessToken(token);\n } catch (err) {\n const expired = isExpiredTokenError(err);\n const reason = err instanceof Error ? err.message : \"invalid_token\";\n const detail = {\n reason,\n scheme: \"bearer\",\n source: \"mcp\",\n path: \"oauth\",\n };\n if (expired) {\n this.context.logger.debug(\n { err, ...detail },\n \"Auth rejected: token expired\",\n );\n } else {\n this.context.logger.warn(\n { err, ...detail },\n \"Auth rejected: token validation failed\",\n );\n }\n this.context.emit(\"auth:rejected\", detail);\n // A server-side failure (RC5021 userinfo/discovery fetch, RC5022 sub\n // mismatch, or a JWKS endpoint that is unreachable, slow, or returns a\n // bad response) propagates unchanged so the SDK maps it to 500: the\n // client must retry later, not discard a token that may be valid. Every\n // other throw is the verifier rejecting the token, so surface it as\n // InvalidTokenError for 401 invalid_token (which drives the refresh).\n if (isRoutecraftError(err) || isInfrastructureError(err)) throw err;\n throw new InvalidTokenError(\n expired ? \"Token has expired\" : \"Invalid token\",\n );\n }\n // Belt-and-suspenders: the type system already guarantees `expiresAt`,\n // but third-party code using `as any` or dynamic plugin wiring could\n // still hand us an incomplete principal. Emit a structured rejection\n // so an operator can trace the mis-wired verifier instead of debugging\n // a silent 401 from the SDK bearer middleware.\n if ((principal as { expiresAt?: number }).expiresAt === undefined) {\n const detail = {\n reason: \"missing_expires_at\",\n scheme: \"bearer\",\n source: \"mcp\",\n path: \"oauth\",\n };\n this.context.logger.warn(\n detail,\n \"Auth rejected: OAuth principal is missing expiresAt\",\n );\n this.context.emit(\"auth:rejected\", detail);\n throw new Error(\n \"oauth: verifyAccessToken must return a principal with expiresAt (required by MCP SDK bearer middleware)\",\n );\n }\n if (!principal.clientId) {\n this.context.logger.debug(\n { subject: principal.subject },\n \"oauth: principal missing clientId; using subject as fallback for AuthInfo.clientId\",\n );\n }\n const authInfo: SdkAuthInfo = {\n token,\n clientId: principal.clientId ?? principal.subject,\n scopes: principal.scopes ?? [],\n expiresAt: principal.expiresAt,\n extra: { principal },\n };\n return authInfo;\n };\n\n // Build the ProxyOAuthServerProvider from the user's config.\n const provider = new ProxyOAuthServerProvider({\n endpoints: {\n authorizationUrl: oauthOptions.endpoints.authorizationUrl,\n tokenUrl: oauthOptions.endpoints.tokenUrl,\n revocationUrl: oauthOptions.endpoints.revocationUrl,\n registrationUrl: oauthOptions.endpoints.registrationUrl,\n },\n verifyAccessToken: wrappedVerifier,\n getClient: oauthOptions.getClient,\n });\n\n const port = this.options.port;\n const host = this.options.host;\n\n // OAuth-proxy mode resolves the resource URL at startup because the MCP\n // SDK's `mcpAuthRouter` and `requireBearerAuth` middleware close over\n // the URL when they are mounted. With `port: 0` (an ephemeral port,\n // commonly used in tests) and no explicit `resource.url`, the bound\n // port is unknown at this point and would be baked into the discovery\n // document and `WWW-Authenticate` header as `:0`. Reject that\n // combination loudly so the user picks a fixed port or a public URL.\n if (port === 0 && this.options.resource?.url === undefined) {\n throw new TypeError(\n \"mcpPlugin: OAuth-proxy mode requires either a fixed `port` or an explicit `resource.url`. \" +\n \"With `port: 0` (ephemeral) and no `resource.url`, the protected-resource metadata URL \" +\n 'would advertise `:0`. Pass `resource: { url: \"https://...\" }` or a non-zero `port`.',\n );\n }\n\n // Single source of truth for the resource URL (validates HTTPS in\n // production when explicitly set; falls back to the configured port\n // otherwise).\n const resourceUrl = new URL(this.resolveResourceUrl());\n const { ownedPaths, metadataPaths } = buildMcpOwnedPaths(resourceUrl);\n\n const app = expressFn();\n\n const oauthCors = resolveCorsOptions(this.options.cors);\n\n // CORS middleware for our owned routes (`/mcp` and the protected-resource\n // metadata endpoint). Mounted FIRST so OPTIONS preflight short-circuits\n // before bearer auth runs (a preflight has no Authorization header by\n // design). The SDK-owned OAuth endpoints (`/register`, `/token`,\n // `/revoke`, the SDK's metadata) carry their own permissive CORS via\n // `mcpAuthRouter` -> the `cors` npm package -- we leave those alone.\n //\n // When `oauthCors === null` (user opted out via `cors: false`) the\n // middleware is not registered at all: preflight requests fall through\n // to the bearer middleware / route handler, exactly as they would if\n // CORS support had never been built. The user told us a fronting\n // proxy/CDN owns CORS.\n if (oauthCors !== null) {\n app.use((req: unknown, res: unknown, next: unknown) => {\n const nodeReq = req as IncomingMessage;\n const nodeRes = res as import(\"node:http\").ServerResponse;\n const url = nodeReq.url?.split(\"?\")[0] ?? \"\";\n const rawOrigin = nodeReq.headers[\"origin\"];\n const originValue = Array.isArray(rawOrigin) ? rawOrigin[0] : rawOrigin;\n // OPTIONS preflight: we only short-circuit on the paths we own.\n // SDK-owned OAuth endpoints (`/register`, `/token`, ...) have their\n // own `cors()` middleware that handles preflight per their policy,\n // and we must not swallow those.\n if (nodeReq.method === \"OPTIONS\" && ownedPaths.has(url)) {\n applyCorsHeaders(nodeRes, oauthCors, originValue, true);\n nodeRes.writeHead(204);\n nodeRes.end();\n return;\n }\n // Apply CORS headers via setHeader on every other non-OPTIONS request,\n // including unowned paths. For SDK endpoints the SDK's own `cors()`\n // runs later and overrides via setHeader; for the Express default\n // 404 fallthrough on unknown paths our values persist so browser\n // clients can read the status rather than seeing a misleading CORS\n // error. Unowned-path OPTIONS (e.g. preflight against a route we\n // don't handle) is left untouched so the SDK's per-route preflight\n // policy is the only one in play there.\n if (nodeReq.method !== \"OPTIONS\") {\n applyCorsHeaders(nodeRes, oauthCors, originValue, false);\n }\n (next as () => void)();\n });\n }\n\n // Mount our own protected-resource metadata handler BEFORE\n // `mcpAuthRouter`. The SDK's router also mounts a doc, but at a\n // path-aware URL (`/.well-known/oauth-protected-resource{rsPath}`)\n // and without the `bearer_methods_supported` field RFC 9728 §2\n // recommends. Mounting ours first means clients fetching the URL we\n // advertise in the 401 always get the same JSON shape as validator\n // mode -- the design's \"auto-mount, same shape, regardless of auth\n // mode\" promise. Express runs middleware in registration order, so the\n // handler registered first wins for the matching URL; do NOT move this\n // below `app.use(mcpAuthRouter(...))` or the SDK's path-aware doc will\n // shadow ours when the resource URL collapses to root.\n // CORS headers are committed by the middleware above via `setHeader`,\n // so the handler does not need to re-emit them in `writeHead`.\n //\n // Mount on every metadata path resolved from the resource URL (RFC 9728\n // §3): root plus the path-suffixed variant matching the SDK's `rsPath`\n // math (derived from `resource.url.pathname`). Both URLs return the\n // identical document; this guarantees we shadow the SDK's path-aware\n // doc at whichever URL it chose to mount, regardless of how the user\n // configured `resource.url`.\n const serveMetadata = (_req: unknown, res: unknown) => {\n this.serveProtectedResourceMetadata(\n res as import(\"node:http\").ServerResponse,\n );\n };\n for (const path of metadataPaths) {\n app.get(path, serveMetadata);\n }\n\n // Mount OAuth endpoints at root (discovery, authorize, token, revoke).\n const authRouterOptions: Record<string, unknown> = {\n provider,\n issuerUrl: resourceUrl,\n };\n if (oauthOptions.baseUrl) {\n authRouterOptions[\"baseUrl\"] = new URL(oauthOptions.baseUrl.toString());\n }\n const resource = this.options.resource;\n if (resource?.scopesSupported && resource.scopesSupported.length > 0) {\n authRouterOptions[\"scopesSupported\"] = resource.scopesSupported;\n }\n if (resource?.documentationUrl !== undefined) {\n authRouterOptions[\"serviceDocumentationUrl\"] = new URL(\n resource.documentationUrl.toString(),\n );\n }\n const resourceName = this.resolveResourceName();\n if (resourceName) {\n authRouterOptions[\"resourceName\"] = resourceName;\n }\n app.use(mcpAuthRouter(authRouterOptions));\n\n // Bearer auth middleware for /mcp. The SDK appends\n // `resource_metadata=\"...\"` to its 401 WWW-Authenticate header when\n // `resourceMetadataUrl` is provided. Use an absolute URL (RFC 9728\n // §5.1 SHOULD) that points at the doc we just mounted above.\n const bearerOptions: Record<string, unknown> = {\n verifier: provider,\n resourceMetadataUrl: this.resolveResourceMetadataUrl(),\n };\n if (oauthOptions.requiredScopes) {\n bearerOptions[\"requiredScopes\"] = oauthOptions.requiredScopes;\n }\n app.use(\"/mcp\", requireBearerAuth(bearerOptions));\n\n const createSessionFn = () =>\n this.createSession(ServerCtor, TransportClass);\n\n // MCP transport handler at /mcp.\n app.all(\"/mcp\", async (req: unknown, res: unknown) => {\n const nodeReq = req as IncomingMessage;\n const nodeRes = res as import(\"node:http\").ServerResponse;\n\n // The SDK's requireBearerAuth sets req.auth with the verified AuthInfo.\n const authInfo = (req as Record<string, unknown>)[\"auth\"] as\n | SdkAuthInfo\n | undefined;\n const principal = this.authInfoToPrincipal(authInfo);\n\n if (principal) {\n const successDetail = {\n subject: principal.subject,\n scheme: principal.scheme,\n source: \"mcp\",\n };\n this.context.logger.info(successDetail, \"Auth succeeded\");\n this.context.emit(\"auth:success\", successDetail);\n }\n\n await this.handleMcpRequest(nodeReq, nodeRes, principal, createSessionFn);\n });\n\n // Wrap the Express app in a raw HTTP server so listenHttp can bind it.\n // Express apps are callable as (req, res) request handlers.\n this.httpServer = createServer(\n app as unknown as (\n req: import(\"node:http\").IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n ) => void,\n );\n await this.listenHttp(port, host);\n }\n\n /**\n * Bind the HTTP server to the configured port and host.\n * Used by the validator path.\n */\n private async listenHttp(port: number, host: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n this.httpServer!.listen(port, host, () => resolve());\n this.httpServer!.on(\"error\", (err) => {\n const msg = isRoutecraftError(err)\n ? (err as unknown as { meta: { message: string } }).meta.message\n : err instanceof Error\n ? err.message\n : \"MCP HTTP server listen failed\";\n this.context.logger.error({ err }, msg);\n reject(err);\n });\n });\n\n const boundPort = this.getHttpPort() ?? port;\n const listenDetail = { host, port: boundPort, path: \"/mcp\" };\n this.context.logger.info(listenDetail, \"MCP HTTP server listening\");\n this.context.emit(\"plugin:mcp:server:listening\", listenDetail);\n }\n\n /**\n * Convert the MCP SDK's AuthInfo (set by requireBearerAuth) to a Principal\n * for routecraft's exchange headers.\n *\n * The OAuth path's wrapped `verifyAccessToken` stashes the fully-populated\n * {@link Principal} in `authInfo.extra.principal`. If the stash is absent\n * (e.g. a third party plugged a bare `ProxyOAuthServerProvider` in some\n * custom setup), fall back to a minimal principal from the SDK-level `AuthInfo`.\n */\n private authInfoToPrincipal(\n authInfo: SdkAuthInfo | undefined,\n ): Principal | undefined {\n if (!authInfo) return undefined;\n const stashed = (authInfo.extra as { principal?: Principal } | undefined)\n ?.principal;\n if (stashed) return stashed;\n\n const fallback: Principal = {\n kind: \"oauth\",\n scheme: \"bearer\",\n subject: authInfo.clientId,\n clientId: authInfo.clientId,\n scopes: authInfo.scopes,\n };\n if (authInfo.expiresAt !== undefined) {\n fallback.expiresAt = authInfo.expiresAt;\n }\n return fallback;\n }\n\n /**\n * When transport is http, returns the bound port (useful when port 0 was used). Otherwise undefined.\n */\n getHttpPort(): number | undefined {\n const addr = this.httpServer?.address();\n if (addr && typeof addr === \"object\" && \"port\" in addr) {\n return (addr as { port: number }).port;\n }\n return undefined;\n }\n\n /**\n * Build the validator-mode token verifier, optionally wrapped with\n * `userinfo` enrichment. The base verifier is the configured `validator`;\n * when `mcpPlugin({ userinfo })` is set, it is wrapped with\n * `buildEnrichedVerifier` (token cache, in-flight coalescing, sub\n * invariant, fail-closed). The issuer for `userinfo: true` discovery comes\n * from the verifier's `issuer` (surfaced by `jwks()` / `jwt()`).\n */\n private buildValidatorVerifier():\n | ((token: string) => Promise<Principal>)\n | null {\n const authOptions = this.options.auth as\n | (ValidatorAuthOptions & { issuer?: string | string[] })\n | undefined;\n if (!authOptions || !(\"validator\" in authOptions)) return null;\n\n const base = (token: string): Promise<Principal> =>\n Promise.resolve(authOptions.validator(token));\n if (this.options.userinfo === undefined) return base;\n return buildEnrichedVerifier(\n base,\n this.options.userinfo,\n authOptions.issuer,\n );\n }\n\n /**\n * Validate the Authorization header using the configured validator.\n * Only used on the validator auth path (not OAuth -- that uses Express middleware).\n * Returns the authenticated principal on success, or `null` to reject with 401.\n */\n private async validateAuth(req: IncomingMessage): Promise<Principal | null> {\n const authOptions = this.options.auth as ValidatorAuthOptions | undefined;\n if (!authOptions || !(\"validator\" in authOptions)) return null;\n const verifier = this.validatorVerifier ?? this.buildValidatorVerifier();\n if (!verifier) return null;\n\n const rawHeader = req.headers[\"authorization\"];\n if (!rawHeader || Array.isArray(rawHeader)) {\n const detail = {\n reason: \"missing_header\",\n scheme: \"bearer\",\n source: \"mcp\",\n };\n // A tokenless request is the spec-defined MCP OAuth discovery probe (the\n // client fetches without credentials to read the 401 + WWW-Authenticate,\n // then runs the flow and retries), so it is logged at `debug`. The\n // `auth:rejected` event still fires so observers can count probes.\n this.context.logger.debug(\n detail,\n \"Auth rejected: missing or malformed Authorization header\",\n );\n this.context.emit(\"auth:rejected\", detail);\n return null;\n }\n\n const schemeMatch = /^bearer\\s+(.+)$/i.exec(rawHeader);\n if (!schemeMatch) {\n const detail = {\n reason: \"unsupported_scheme\",\n scheme: \"bearer\",\n source: \"mcp\",\n };\n // Same class as a tokenless probe: the client has not authenticated yet,\n // so this is routine discovery noise rather than a failed authentication.\n // Logged at `debug`; the `auth:rejected` event still fires.\n this.context.logger.debug(\n detail,\n \"Auth rejected: unsupported authorization scheme\",\n );\n this.context.emit(\"auth:rejected\", detail);\n return null;\n }\n const token = schemeMatch[1];\n\n // Delegate to the verifier (validator + optional userinfo enrichment).\n // Throw to reject; return Principal to accept.\n try {\n const result = await verifier(token);\n const successDetail = {\n subject: result.subject,\n scheme: result.scheme,\n source: \"mcp\",\n };\n this.context.logger.info(successDetail, \"Auth succeeded\");\n this.context.emit(\"auth:success\", successDetail);\n return result;\n } catch (err) {\n const reason = err instanceof Error ? err.message : \"invalid_token\";\n const detail = {\n reason,\n scheme: \"bearer\",\n source: \"mcp\",\n };\n // An expired token is routine (the client refreshes and retries), so it\n // logs at `debug`; any other validation failure stays at `warn` as an\n // operator signal. The `auth:rejected` event fires for both.\n if (isExpiredTokenError(err)) {\n this.context.logger.debug(\n { err, ...detail },\n \"Auth rejected: token expired\",\n );\n } else {\n this.context.logger.warn(\n { err, ...detail },\n \"Auth rejected: token validation failed\",\n );\n }\n this.context.emit(\"auth:rejected\", detail);\n return null;\n }\n }\n\n /**\n * Set up request handlers on this.server (used by stdio transport).\n */\n private async setupRequestHandlers(): Promise<void> {\n await this.setupRequestHandlersOn(this.server);\n }\n\n /**\n * Set up request handlers on the given server instance.\n * Uses SDK request schemas so setRequestHandler receives a proper schema (method literal).\n */\n private async setupRequestHandlersOn(server: unknown): Promise<void> {\n const typesModule = (await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/types.js\"),\n { adapterName: \"mcp\", packageName: \"@modelcontextprotocol/sdk\" },\n )) as Record<string, unknown>;\n const t = typesModule;\n const ListToolsRequestSchema = t[\"ListToolsRequestSchema\"];\n const CallToolRequestSchema = t[\"CallToolRequestSchema\"];\n\n if (!ListToolsRequestSchema || !CallToolRequestSchema) {\n throw new Error(\n \"MCP SDK types missing ListToolsRequestSchema or CallToolRequestSchema - ensure @modelcontextprotocol/sdk is installed\",\n );\n }\n\n const srv = server as Record<\n string,\n (schema: unknown, handler: (request: unknown) => Promise<unknown>) => void\n >;\n\n srv[\"setRequestHandler\"](ListToolsRequestSchema, async () => {\n const tools = this.getAvailableTools();\n this.logExposedToolsOnce();\n return { tools };\n });\n\n srv[\"setRequestHandler\"](\n CallToolRequestSchema,\n async (request: unknown) => {\n const req = request as Record<string, unknown>;\n const params = req[\"params\"] as Record<string, unknown>;\n return await this.handleToolCall(\n (params[\"name\"] as string) || \"\",\n (params[\"arguments\"] as Record<string, unknown>) || {},\n );\n },\n );\n }\n\n /**\n * Stop the MCP server\n */\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n try {\n if (this.httpServer) {\n // Close all active HTTP sessions.\n for (const [, session] of this.httpSessions) {\n const tr = session.transport as Record<string, () => Promise<void>>;\n if (typeof tr[\"close\"] === \"function\") {\n await tr[\"close\"]();\n }\n }\n this.httpSessions.clear();\n\n // Force-close any lingering connections (e.g. SSE streams that keep\n // the socket open indefinitely). closeAllConnections() is available\n // in Node 18.2+ and Bun; without it, server.close() would hang\n // forever waiting for long-lived SSE connections to drain.\n const srv = this.httpServer as unknown as Record<string, unknown>;\n if (typeof srv[\"closeAllConnections\"] === \"function\") {\n (srv[\"closeAllConnections\"] as () => void)();\n }\n\n await new Promise<void>((resolve) => {\n this.httpServer!.close(() => resolve());\n });\n this.httpServer = null;\n }\n if (this.transport) {\n const tr = this.transport as Record<string, () => Promise<void>>;\n if (typeof tr[\"close\"] === \"function\") {\n await tr[\"close\"]();\n }\n }\n this.running = false;\n this.context.logger.info({}, \"MCP server stopped\");\n } catch (error) {\n const msg = isRoutecraftError(error)\n ? (error as unknown as { meta: { message: string } }).meta.message\n : error instanceof Error\n ? error.message\n : \"Error stopping MCP server\";\n this.context.logger.error({ err: error }, msg);\n }\n }\n\n /**\n * Log exposed MCP tool names once (at start or on first tools/list).\n */\n private logExposedToolsOnce(): void {\n if (this.toolsListLogged) return;\n const tools = this.getAvailableTools();\n if (tools.length === 0) return;\n const names = tools.map((t) => t.name);\n const exposedDetail = { tools: names, count: names.length };\n this.context.logger.info(exposedDetail, \"Exposing MCP tools\");\n this.context.emit(\"plugin:mcp:server:tools:exposed\", exposedDetail);\n this.toolsListLogged = true;\n }\n\n /**\n * Get list of tools that should be exposed via MCP.\n * Reads the MCP local tool registry lazily so routes have time to subscribe\n * before the first `tools/list` request.\n */\n getAvailableTools(): McpTool[] {\n const registry = this.context.getStore(MCP_LOCAL_TOOL_REGISTRY) as\n | Map<string, McpLocalToolEntry>\n | undefined;\n\n if (!registry) {\n return [];\n }\n\n let entries = Array.from(registry.values());\n\n const toolsFilter = this.options.tools;\n if (toolsFilter) {\n if (Array.isArray(toolsFilter)) {\n const allowed = new Set(toolsFilter);\n entries = entries.filter((e) => allowed.has(e.endpoint));\n } else if (typeof toolsFilter === \"function\") {\n entries = entries.filter(toolsFilter);\n }\n }\n\n return entries.map((entry) => this.entryToMcpTool(entry));\n }\n\n /**\n * Convert an MCP local tool registry entry to the MCP `tools/list` wire\n * format. `entry.input.body` flattens to `tool.inputSchema`; `entry.output.body`\n * flattens to `tool.outputSchema`. Header schemas are not part of the MCP\n * spec wire and are not forwarded.\n */\n private entryToMcpTool(entry: McpLocalToolEntry): McpTool {\n const tool: McpTool = {\n name: entry.endpoint,\n description: entry.description,\n inputSchema: this.schemaToJsonSchema(\n entry.input?.body,\n ) as McpTool[\"inputSchema\"],\n };\n if (entry.title !== undefined) {\n tool.title = entry.title;\n }\n if (entry.output?.body !== undefined) {\n tool.outputSchema = this.schemaToJsonSchema(\n entry.output.body,\n ) as NonNullable<McpTool[\"outputSchema\"]>;\n }\n if (entry.annotations !== undefined) {\n tool.annotations = entry.annotations;\n }\n const icons = entry.icons ?? this.resolveServerIcons();\n if (icons.length > 0) {\n tool.icons = icons;\n }\n return tool;\n }\n\n /**\n * Convert to JSON Schema using Standard JSON Schema (schema['~standard'].jsonSchema.input)\n * when available; otherwise return a generic object schema.\n * Works with any spec-compliant library (Zod 4.2+, ArkType, Valibot via toStandardJsonSchema).\n */\n private schemaToJsonSchema(schema: unknown): Record<string, unknown> {\n if (!schema || typeof schema !== \"object\") {\n return { type: \"object\" };\n }\n\n const standard = (schema as Record<string, unknown>)[\"~standard\"] as\n | {\n jsonSchema?: {\n input?: (opts: { target: string }) => Record<string, unknown>;\n };\n }\n | undefined;\n if (standard?.jsonSchema?.input) {\n try {\n const out = standard.jsonSchema.input({\n target: \"draft-2020-12\",\n });\n return typeof out === \"object\" && out !== null\n ? out\n : { type: \"object\" };\n } catch (error) {\n this.context.logger.debug(\n error,\n \"Standard JSON Schema conversion failed\",\n );\n return { type: \"object\" };\n }\n }\n\n if (\"~standard\" in schema) {\n return { type: \"object\", additionalProperties: true };\n }\n return { type: \"object\" };\n }\n\n /**\n * Handle a tool call from MCP client\n */\n private async handleToolCall(\n toolName: string,\n args: Record<string, unknown>,\n ): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n }> {\n try {\n const registry = this.context.getStore(MCP_LOCAL_TOOL_REGISTRY) as\n | Map<string, McpLocalToolEntry>\n | undefined;\n\n const entry = registry?.get(toolName);\n if (!entry) {\n const err = new Error(`Tool not found: ${toolName}`);\n this.context.emit(`plugin:mcp:tool:failed`, {\n tool: toolName,\n error: err.message,\n });\n return {\n isError: true,\n content: [\n { type: \"text\", text: `Error: Tool not found: ${toolName}` },\n ],\n };\n }\n\n // Ensure body is an object when client sends JSON (SDK may pass parsed object or raw string)\n const body =\n typeof args === \"string\"\n ? (() => {\n try {\n return (JSON.parse(args) as Record<string, unknown>) || {};\n } catch {\n return { input: args };\n }\n })()\n : args && typeof args === \"object\"\n ? args\n : {};\n\n this.context.logger.debug(\n { bodyType: typeof body, body },\n \"MCP tool call exchange body\",\n );\n\n // Build exchange headers. The authenticated principal (when present)\n // rides as a single structured header rather than ten flat keys; the\n // `ex.principal` getter on the exchange surfaces it ergonomically.\n // This is the single attach point for every MCP auth mode (validator\n // jwt/jwks/custom and OAuth proxy) and runs after any userinfo\n // enrichment, so branding here marks the verified identity as\n // authentic for downstream `authorize()` without freezing it too\n // early to enrich.\n const principal = principalStore.getStore();\n const headers: Record<string, unknown> = {\n [McpHeadersKeys.TOOL]: toolName,\n [McpHeadersKeys.SESSION]: `mcp-${Date.now()}`,\n };\n if (principal) {\n headers[HeadersKeys.AUTH_PRINCIPAL] = markAuthentic(principal);\n }\n\n const exchange = new DefaultExchange(this.context, {\n body,\n headers,\n });\n\n this.context.emit(`plugin:mcp:tool:called`, {\n tool: toolName,\n args,\n });\n\n const resultExchange = await entry.handler(exchange);\n\n const resultText =\n typeof resultExchange.body === \"string\"\n ? resultExchange.body\n : JSON.stringify(resultExchange.body);\n\n this.context.emit(`plugin:mcp:tool:completed`, {\n tool: toolName,\n });\n\n return {\n content: [{ type: \"text\", text: resultText }],\n };\n } catch (error) {\n const logMsg = isRoutecraftError(error)\n ? (error as unknown as { meta: { message: string } }).meta.message\n : error instanceof Error\n ? error.message\n : String(error);\n this.context.logger.error({ tool: toolName, err: error }, logMsg);\n this.context.emit(`plugin:mcp:tool:failed`, {\n tool: toolName,\n error: logMsg,\n });\n\n // Build a clean user-facing message: include the cause (e.g. schema\n // field errors) but never expose stack traces or internal details.\n let userMsg = logMsg;\n if (isRoutecraftError(error)) {\n const cause = (error as { cause?: Error }).cause;\n if (cause?.message) {\n userMsg = `${logMsg}: ${cause.message}`;\n }\n }\n\n return {\n content: [{ type: \"text\", text: `Error: ${userMsg}` }],\n isError: true,\n };\n }\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { formatSchemaIssues } from \"@routecraft/routecraft\";\nimport type { McpPluginOptions } from \"./types.ts\";\n\n/** Standard Schema validate result: success has value, failure has issues. */\ntype ValidateResult<T = unknown> =\n | { value: T; issues?: never }\n | { value?: never; issues: readonly unknown[] };\n\n/**\n * Validates MCP plugin options at apply time.\n * For full schema validation (required props, shape), use validateWithSchema() with a\n * StandardSchemaV1 from Zod, Valibot, or ArkType before calling mcpPlugin().\n * @internal\n */\nexport function validateMcpPluginOptions(options: McpPluginOptions): void {\n if (options.transport === \"http\") {\n if (options.port !== undefined) {\n if (typeof options.port !== \"number\") {\n throw new TypeError(\n \"mcpPlugin: when transport is 'http', port must be a number\",\n );\n }\n if (options.port < 0 || options.port > 65535) {\n throw new RangeError(\n \"mcpPlugin: port must be between 0 and 65535 when transport is 'http'\",\n );\n }\n }\n if (options.host !== undefined && typeof options.host !== \"string\") {\n throw new TypeError(\"mcpPlugin: when provided, host must be a string\");\n }\n }\n\n // Note: `cors` is silently ignored when transport is not 'http', matching\n // the `auth` posture. The stdio startup path simply does not read it.\n // The shape of `cors.origin` is validated here so misconfiguration fails at\n // plugin-apply time alongside `auth`, `port`, and `host`; `resolveCorsOptions`\n // keeps the same throw as defence-in-depth for callers who bypass this gate.\n if (\n options.transport === \"http\" &&\n options.cors !== undefined &&\n options.cors !== false\n ) {\n const { origin } = options.cors;\n const ok =\n origin === \"*\" ||\n typeof origin === \"string\" ||\n Array.isArray(origin) ||\n typeof origin === \"function\";\n if (!ok) {\n throw new TypeError(\n \"mcpPlugin: cors.origin must be '*', a string, a string array, or a function\",\n );\n }\n }\n\n // Validate auth options\n if (options.auth !== undefined) {\n if (\"provider\" in options.auth) {\n // OAuth provider auth -- validated by the oauth() factory.\n if (options.auth.provider !== \"oauth\") {\n throw new TypeError(\n 'mcpPlugin: auth.provider must be \"oauth\". Use the oauth() helper.',\n );\n }\n } else if (\"validator\" in options.auth) {\n if (typeof options.auth.validator !== \"function\") {\n throw new TypeError(\n \"mcpPlugin: auth.validator must be a function that returns a Principal (throw to reject)\",\n );\n }\n } else {\n throw new TypeError(\n \"mcpPlugin: auth must have either a 'validator' function or 'provider' set to 'oauth'. \" +\n \"Use jwt(), jwks(), oauth(), or a custom { validator } object.\",\n );\n }\n }\n\n // Validate stdio client configs\n if (options.clients) {\n for (const [name, config] of Object.entries(options.clients)) {\n if (\n typeof config === \"object\" &&\n config !== null &&\n \"transport\" in config &&\n config.transport === \"stdio\"\n ) {\n if (!config.command || typeof config.command !== \"string\") {\n throw new TypeError(\n `mcpPlugin: stdio client \"${name}\" must have a non-empty command string`,\n );\n }\n }\n }\n }\n\n // Validate restart options\n if (options.maxRestarts !== undefined) {\n if (\n typeof options.maxRestarts !== \"number\" ||\n !Number.isInteger(options.maxRestarts) ||\n options.maxRestarts < 0\n ) {\n throw new TypeError(\n \"mcpPlugin: maxRestarts must be a non-negative integer\",\n );\n }\n }\n if (options.restartDelayMs !== undefined) {\n if (\n typeof options.restartDelayMs !== \"number\" ||\n options.restartDelayMs <= 0\n ) {\n throw new TypeError(\n \"mcpPlugin: restartDelayMs must be a positive number\",\n );\n }\n }\n if (options.restartBackoffMultiplier !== undefined) {\n if (\n typeof options.restartBackoffMultiplier !== \"number\" ||\n options.restartBackoffMultiplier < 1\n ) {\n throw new TypeError(\"mcpPlugin: restartBackoffMultiplier must be >= 1\");\n }\n }\n\n // Validate HTTP tool refresh interval\n if (options.toolRefreshIntervalMs !== undefined) {\n if (\n typeof options.toolRefreshIntervalMs !== \"number\" ||\n !Number.isInteger(options.toolRefreshIntervalMs) ||\n options.toolRefreshIntervalMs < 0\n ) {\n throw new TypeError(\n \"mcpPlugin: toolRefreshIntervalMs must be a non-negative integer\",\n );\n }\n }\n}\n\n/**\n * Validate plugin options with a StandardSchemaV1 (e.g. from Zod, Valibot, ArkType).\n * Use this when you need required props or full shape validation before mcpPlugin().\n *\n * @example\n * import { z } from \"zod\";\n * const schema = z.object({ transport: z.enum([\"stdio\", \"http\"]), port: z.number().optional() });\n * const validated = await validateWithSchema(options, schema);\n * mcpPlugin(validated);\n */\nexport async function validateWithSchema(\n options: McpPluginOptions,\n schema: StandardSchemaV1,\n): Promise<McpPluginOptions> {\n const standard = (\n schema as {\n \"~standard\"?: {\n validate: (\n v: unknown,\n ) => ValidateResult<unknown> | Promise<ValidateResult<unknown>>;\n };\n }\n )[\"~standard\"];\n if (!standard?.validate) {\n throw new Error(\n \"mcpPlugin: schema must be a StandardSchemaV1 with ~standard.validate\",\n );\n }\n let result = standard.validate(options);\n if (result instanceof Promise) {\n result = await result;\n }\n if (result.issues) {\n throw new Error(\n `mcpPlugin options validation failed: ${formatSchemaIssues(result.issues)}`,\n );\n }\n // Guard against schemas that pass (no issues) but omit value\n if (result.value === undefined) {\n throw new Error(\"mcpPlugin options validation failed: no value returned\");\n }\n return result.value as McpPluginOptions;\n}\n","/**\n * Extract content from an MCP tool response.\n *\n * - Single text item: returns the string directly for convenience.\n * - Multiple items or non-text items: returns the full content array so\n * callers can inspect type/text/data on each entry.\n * - No content: returns the raw response object.\n */\nexport function extractContent(\n response: {\n content?: Array<{ type: string; text?: string; data?: string }>;\n } | null,\n): unknown {\n const content = response?.content;\n if (!Array.isArray(content) || content.length === 0) return response;\n\n // Single text entry: return the string for backward compatibility\n if (content.length === 1) {\n const item = content[0];\n if (item.type === \"text\" && typeof item.text === \"string\") return item.text;\n if (typeof item.data === \"string\") return item.data;\n }\n\n // Multiple items or non-text: return the full array\n return content;\n}\n","import { loadOptionalPeer } from \"@routecraft/routecraft\";\nimport type { McpTool } from \"./types.ts\";\nimport { extractContent } from \"./extract-content.ts\";\n\nexport interface StdioClientManagerOptions {\n serverId: string;\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n maxRestarts: number;\n restartDelayMs: number;\n restartBackoffMultiplier: number;\n}\n\n/** Logger interface matching pino child logger shape used in Routecraft. */\ninterface Logger {\n info(obj: Record<string, unknown>, msg: string): void;\n warn(obj: Record<string, unknown>, msg: string): void;\n error(obj: Record<string, unknown>, msg: string): void;\n debug(obj: Record<string, unknown>, msg: string): void;\n}\n\n/** Typed subset of the MCP SDK Client used by StdioClientManager. */\ninterface McpSdkClient {\n connect(transport: unknown): Promise<void>;\n close(): Promise<void>;\n listTools(): Promise<{ tools: McpTool[] }>;\n callTool(params: {\n name: string;\n arguments?: Record<string, unknown>;\n }): Promise<{\n content?: Array<{ type: string; text?: string; data?: string }>;\n }>;\n}\n\n/**\n * Manages a single stdio MCP client subprocess.\n *\n * Delegates to the MCP SDK's Client + StdioClientTransport for process spawning,\n * protocol handling, and tool listing. Adds auto-restart with exponential backoff\n * and event bridging into Routecraft's event system.\n */\nexport class StdioClientManager {\n private client: McpSdkClient | null = null;\n private transport: unknown = null;\n private running = false;\n private stopping = false;\n private restartCount = 0;\n private restartTimer: ReturnType<typeof setTimeout> | null = null;\n private stabilityTimer: ReturnType<typeof setTimeout> | null = null;\n private tools: McpTool[] = [];\n\n /**\n * @param options - Subprocess command, restart policy, and server identity\n * @param logger - Logger matching the pino child logger shape\n * @param onEvent - Callback invoked for every lifecycle event\n * @param onToolsUpdated - Callback invoked whenever the tool list changes\n */\n constructor(\n private readonly options: StdioClientManagerOptions,\n private readonly logger: Logger,\n private readonly onEvent: (\n event: string,\n details: Record<string, unknown>,\n ) => void,\n private readonly onToolsUpdated: (\n serverId: string,\n tools: McpTool[],\n ) => void,\n ) {}\n\n /** Spawn the child process, perform the MCP handshake, and list initial tools. */\n async start(): Promise<void> {\n if (this.running) return;\n this.stopping = false;\n\n // Cancel any pending restart to avoid race with externally-initiated start\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n\n const clientMod = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/client/index.js\"),\n {\n adapterName: \"mcp (stdio client)\",\n packageName: \"@modelcontextprotocol/sdk\",\n },\n );\n const stdioMod = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/client/stdio.js\"),\n {\n adapterName: \"mcp (stdio client)\",\n packageName: \"@modelcontextprotocol/sdk\",\n },\n );\n\n const { serverId, command, args, env, cwd } = this.options;\n\n // Create transport (spawns child process)\n this.transport = new stdioMod.StdioClientTransport({\n command,\n args: args ?? [],\n ...(env ? { env } : {}),\n ...(cwd ? { cwd } : {}),\n stderr: \"pipe\",\n });\n\n // Wire up transport error/close handlers\n const transport = this.transport as {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n stderr: {\n on?: (event: string, cb: (data: unknown) => void) => void;\n } | null;\n };\n\n transport.onerror = (error: Error) => {\n this.logger.error(\n { err: error, serverId },\n \"Stdio client transport error\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:error`, {\n serverId,\n error,\n });\n };\n\n transport.onclose = () => {\n if (!this.stopping) {\n this.running = false;\n this.handleDisconnect();\n }\n };\n\n // Log stderr from child process\n if (transport.stderr?.on) {\n transport.stderr.on(\"data\", (data: unknown) => {\n this.logger.debug(\n { serverId, stderr: String(data).trimEnd() },\n \"Stdio client stderr output\",\n );\n });\n }\n\n // Create client with listChanged support for auto tool refresh\n this.client = new clientMod.Client(\n { name: \"routecraft-mcp-client\", version: \"1.0.0\" },\n {\n capabilities: {},\n listChanged: {\n tools: {\n onChanged: (_error: unknown, tools: unknown) => {\n if (\n tools &&\n Array.isArray((tools as { tools: unknown[] }).tools)\n ) {\n this.tools = (tools as { tools: McpTool[] }).tools;\n this.onToolsUpdated(serverId, this.tools);\n this.onEvent(`plugin:mcp:client:${serverId}:tools:listed`, {\n serverId,\n toolCount: this.tools.length,\n });\n } else {\n // Server notified of change but SDK couldn't fetch; re-list manually\n void this.refreshTools();\n }\n },\n },\n },\n },\n ) as unknown as McpSdkClient;\n\n // Connect (performs MCP initialize handshake)\n await this.client.connect(this.transport);\n\n this.running = true;\n\n // List initial tools\n await this.refreshTools();\n\n this.logger.info(\n { serverId, toolCount: this.tools.length },\n \"Stdio client started\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:started`, {\n serverId,\n toolCount: this.tools.length,\n });\n }\n\n /** Gracefully close the client and transport, cancelling any pending restart. */\n async stop(): Promise<void> {\n this.stopping = true;\n\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n if (this.stabilityTimer) {\n clearTimeout(this.stabilityTimer);\n this.stabilityTimer = null;\n }\n\n const { serverId } = this.options;\n\n if (this.client) {\n try {\n await this.client.close();\n } catch {\n // Ignore cleanup errors\n }\n this.client = null;\n }\n\n if (this.transport) {\n const transportWithClose = this.transport as {\n close?: () => void | Promise<void>;\n };\n if (typeof transportWithClose.close === \"function\") {\n try {\n await Promise.resolve(transportWithClose.close());\n } catch {\n // Ignore cleanup errors\n }\n }\n this.transport = null;\n }\n\n this.running = false;\n this.logger.info({ serverId }, \"Stdio client stopped\");\n this.onEvent(`plugin:mcp:client:${serverId}:stopped`, {\n serverId,\n reason: \"graceful\",\n });\n }\n\n /**\n * Call a tool on the remote MCP server.\n * Delegates to SDK Client.callTool().\n *\n * @param name - Tool name to invoke\n * @param args - Arguments passed to the tool\n * @returns The tool result (text content extracted when available)\n */\n async callTool(\n name: string,\n args: Record<string, unknown>,\n ): Promise<unknown> {\n if (!this.running || !this.client) {\n throw new Error(\n `Stdio client \"${this.options.serverId}\" is not running. Cannot call tool \"${name}\".`,\n );\n }\n\n const response = await this.client.callTool({\n name,\n arguments: args,\n });\n\n return extractContent(response);\n }\n\n /** @returns The current list of tools advertised by this server. */\n getTools(): McpTool[] {\n return [...this.tools];\n }\n\n /** @returns Whether the subprocess is connected and running. */\n isRunning(): boolean {\n return this.running;\n }\n\n private async refreshTools(): Promise<void> {\n if (!this.client) return;\n\n const { serverId } = this.options;\n\n try {\n const result = await this.client.listTools();\n this.tools = result.tools ?? [];\n this.onToolsUpdated(serverId, this.tools);\n this.onEvent(`plugin:mcp:client:${serverId}:tools:listed`, {\n serverId,\n toolCount: this.tools.length,\n });\n } catch (err) {\n this.logger.warn(\n { err, serverId },\n \"Failed to list tools for stdio client\",\n );\n }\n }\n\n private handleDisconnect(): void {\n const { serverId, maxRestarts, restartDelayMs, restartBackoffMultiplier } =\n this.options;\n\n // Clear stale tools so consumers don't see tools from a dead process\n if (this.tools.length > 0) {\n this.tools = [];\n this.onToolsUpdated(serverId, []);\n }\n\n this.logger.warn({ serverId }, \"Stdio client disconnected unexpectedly\");\n this.onEvent(`plugin:mcp:client:${serverId}:stopped`, {\n serverId,\n reason: \"unexpected\",\n });\n\n if (this.restartCount >= maxRestarts) {\n this.logger.error(\n { serverId, restartCount: this.restartCount, maxRestarts },\n \"Stdio client exceeded max restarts, giving up\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:error`, {\n serverId,\n error: new Error(\n `Max restarts (${maxRestarts}) exceeded for stdio client \"${serverId}\"`,\n ),\n });\n return;\n }\n\n const delay =\n restartDelayMs * Math.pow(restartBackoffMultiplier, this.restartCount);\n this.logger.info(\n { serverId, restartCount: this.restartCount, delayMs: delay },\n \"Scheduling stdio client restart\",\n );\n\n this.restartTimer = setTimeout(() => {\n this.restartTimer = null;\n void this.restart();\n }, delay);\n }\n\n private async restart(): Promise<void> {\n const { serverId } = this.options;\n this.restartCount++;\n\n // Clean up stale references\n this.client = null;\n this.transport = null;\n\n try {\n await this.start();\n this.logger.info(\n { serverId, restartCount: this.restartCount },\n \"Stdio client restarted successfully\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:restarted`, {\n serverId,\n restartCount: this.restartCount,\n });\n // Reset restart count only after process stays alive for a stability period.\n // This prevents a flapping process from resetting the counter on every\n // momentary connection and bypassing maxRestarts.\n const stableMs = this.options.restartDelayMs * 2;\n this.stabilityTimer = setTimeout(() => {\n this.stabilityTimer = null;\n if (this.running) this.restartCount = 0;\n }, stableMs);\n } catch (err) {\n this.logger.error(\n { err, serverId, restartCount: this.restartCount },\n \"Stdio client restart failed\",\n );\n this.onEvent(`plugin:mcp:client:${serverId}:error`, {\n serverId,\n error: err,\n });\n // Schedule another restart attempt\n this.handleDisconnect();\n }\n }\n}\n","import type { Tag } from \"@routecraft/routecraft\";\nimport type {\n McpTool,\n McpToolAnnotations,\n McpToolRegistryEntry,\n} from \"./types.ts\";\n\n/**\n * Derive capability tags from MCP `annotations` hints so MCP tools\n * surface alongside fns and direct routes under the same `Tag`\n * selectors (`tools([{ tagged: \"read-only\" }])`).\n *\n * Mapping: `readOnlyHint -> \"read-only\"`,\n * `destructiveHint -> \"destructive\"`, `idempotentHint -> \"idempotent\"`,\n * `openWorldHint -> \"open-world\"`. Returns an empty array (omitted\n * from the entry) when no hints apply.\n *\n * @internal\n */\nfunction deriveTagsFromAnnotations(\n annotations: McpToolAnnotations | undefined,\n): Tag[] {\n if (!annotations) return [];\n const tags: Tag[] = [];\n if (annotations.readOnlyHint) tags.push(\"read-only\");\n if (annotations.destructiveHint) tags.push(\"destructive\");\n if (annotations.idempotentHint) tags.push(\"idempotent\");\n if (annotations.openWorldHint) tags.push(\"open-world\");\n return tags;\n}\n\n/**\n * Central registry of MCP tools discovered from remote MCP servers.\n * Stored in context store under MCP_TOOL_REGISTRY for agent adapter discovery.\n *\n * Populated automatically by mcpPlugin for these sources:\n * - stdio clients: long-lived subprocess MCP servers\n * - HTTP clients: remote HTTP MCP servers (tools refreshed periodically)\n *\n * Local `mcp()` routes defined in the same context are NOT auto-populated here;\n * they live in the parallel `MCP_LOCAL_TOOL_REGISTRY` store and are read from\n * there by the MCP server when responding to `tools/list`. The \"local\" transport\n * label remains a valid value for callers that want to manually register tools\n * with that provenance.\n */\nexport class McpToolRegistry {\n /** Nested Map: source -> toolName -> McpToolRegistryEntry */\n private tools = new Map<string, Map<string, McpToolRegistryEntry>>();\n\n /**\n * Set all tools for a given source (replaces previous tools from that source).\n * Called on initial tool listing and on re-listing after restart/refresh.\n *\n * @param source - Identifier for the tool source (e.g. server ID or \"local\")\n * @param transport - How the tools are reached (\"stdio\", \"http\", or \"local\")\n * @param tools - Tool definitions to register for this source\n */\n setToolsForSource(\n source: string,\n transport: \"stdio\" | \"http\" | \"local\",\n tools: McpTool[],\n ): void {\n const sourceMap = new Map<string, McpToolRegistryEntry>();\n\n for (const tool of tools) {\n const entry: McpToolRegistryEntry = {\n name: tool.name,\n inputSchema: tool.inputSchema as Record<string, unknown>,\n source,\n transport,\n };\n if (tool.description !== undefined) {\n entry.description = tool.description;\n }\n if (tool.annotations !== undefined) {\n entry.annotations = tool.annotations;\n }\n const derivedTags = deriveTagsFromAnnotations(tool.annotations);\n if (derivedTags.length > 0) {\n entry.tags = derivedTags;\n }\n sourceMap.set(tool.name, entry);\n }\n\n this.tools.set(source, sourceMap);\n }\n\n /**\n * Remove all tools for a source (when a client is permanently stopped).\n *\n * @param source - Source identifier whose tools should be removed\n */\n removeSource(source: string): void {\n this.tools.delete(source);\n }\n\n /**\n * Get all tools across all sources.\n *\n * @returns Array of every registered tool entry\n */\n getTools(): McpToolRegistryEntry[] {\n const result: McpToolRegistryEntry[] = [];\n for (const sourceMap of this.tools.values()) {\n for (const entry of sourceMap.values()) {\n result.push(entry);\n }\n }\n return result;\n }\n\n /**\n * Get tools from a specific source/server.\n *\n * @param serverId - Source identifier to filter by\n * @returns Array of tool entries belonging to that source\n */\n getToolsByServer(serverId: string): McpToolRegistryEntry[] {\n const sourceMap = this.tools.get(serverId);\n if (!sourceMap) return [];\n return Array.from(sourceMap.values());\n }\n\n /**\n * Get a specific tool by name. Returns first match if name exists in multiple sources.\n *\n * @param name - Tool name to search for\n * @returns The first matching entry, or undefined\n */\n getTool(name: string): McpToolRegistryEntry | undefined {\n for (const sourceMap of this.tools.values()) {\n const entry = sourceMap.get(name);\n if (entry) return entry;\n }\n return undefined;\n }\n\n /**\n * Get a specific tool by source and name.\n *\n * @param source - Source identifier\n * @param name - Tool name\n * @returns The matching entry, or undefined\n */\n getToolBySource(\n source: string,\n name: string,\n ): McpToolRegistryEntry | undefined {\n return this.tools.get(source)?.get(name);\n }\n}\n","import type { McpClientAuthOptions } from \"./types.ts\";\n\n/** Round-robin index for array tokens, keyed by the array reference. */\nconst rrIndexes = new WeakMap<string[], number>();\n\n/**\n * Resolve the raw token value from the various accepted forms.\n * @internal\n */\nasync function resolveToken(\n token: NonNullable<McpClientAuthOptions[\"token\"]>,\n): Promise<string> {\n if (typeof token === \"function\") {\n return token();\n }\n if (Array.isArray(token)) {\n if (token.length === 0) {\n throw new Error(\"McpClientAuthOptions.token array must not be empty\");\n }\n const idx = (rrIndexes.get(token) ?? 0) % token.length;\n rrIndexes.set(token, idx + 1);\n return token[idx];\n }\n return token;\n}\n\n/**\n * Build HTTP headers from MCP client auth options.\n * Returns undefined when no headers are needed.\n * @internal\n */\nexport async function buildAuthHeaders(\n auth?: McpClientAuthOptions,\n): Promise<Record<string, string> | undefined> {\n if (!auth) return undefined;\n\n const headers: Record<string, string> = {};\n const customHeaders = auth.headers ?? {};\n\n // Check if custom headers provide an Authorization override (case-insensitive)\n const authorizationOverride = Object.entries(customHeaders).find(\n ([name]) => name.toLowerCase() === \"authorization\",\n )?.[1];\n\n if (authorizationOverride) {\n headers[\"Authorization\"] = authorizationOverride;\n } else if (auth.token !== undefined) {\n const resolved = await resolveToken(auth.token);\n if (resolved.length === 0) {\n throw new Error(\n \"McpClientAuthOptions.token must be a non-empty string when provided\",\n );\n }\n headers[\"Authorization\"] = `Bearer ${resolved}`;\n }\n\n // Merge remaining custom headers, skipping any authorization variant\n for (const [name, value] of Object.entries(customHeaders)) {\n if (name.toLowerCase() !== \"authorization\") {\n headers[name] = value;\n }\n }\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n","import {\n type CraftContext,\n type CraftPlugin,\n type EventName,\n loadOptionalPeer,\n} from \"@routecraft/routecraft\";\nimport { McpServer } from \"./server.ts\";\nimport {\n ADAPTER_MCP_CLIENT_SERVERS,\n MCP_PLUGIN_REGISTERED,\n MCP_STDIO_MANAGERS,\n MCP_TOOL_REGISTRY,\n} from \"./types.ts\";\nimport type {\n McpClientHttpConfig,\n McpClientStdioConfig,\n McpPluginOptions,\n McpTool,\n} from \"./types.ts\";\nimport { validateMcpPluginOptions } from \"./validate-options.ts\";\nimport { StdioClientManager } from \"./stdio-client-manager.ts\";\nimport { McpToolRegistry } from \"./tool-registry.ts\";\nimport { buildAuthHeaders } from \"./build-auth-headers.ts\";\n\ntype ClientConfig = McpClientHttpConfig | McpClientStdioConfig;\n\nfunction isStdioConfig(config: ClientConfig): config is McpClientStdioConfig {\n return \"transport\" in config && config.transport === \"stdio\";\n}\n\n/**\n * MCP plugin: one plugin per adapter. Starts the MCP server during plugin apply (before routes start) so startup failures fail context build. Exposes mcp() routes to external MCP clients.\n * Optional clients: register named remote MCP servers so routes can use .to(mcp(\"name:tool\")) without passing url.\n * Stdio clients are spawned as subprocesses with auto-restart; HTTP clients are used for ephemeral tool calls.\n * All discovered external tools (stdio, HTTP) are stored in a unified McpToolRegistry for agent adapter discovery.\n * Required when any route uses .from(mcp(...)); the route will fail at start if this plugin is not applied.\n */\nexport function mcpPlugin(options: McpPluginOptions = {}): CraftPlugin {\n validateMcpPluginOptions(options);\n\n let server: McpServer | null = null;\n const stdioManagers = new Map<string, StdioClientManager>();\n const httpClients = new Map<\n string,\n { close(): Promise<void>; listTools(): Promise<{ tools: McpTool[] }> }\n >();\n const httpRefreshTimers: ReturnType<typeof setInterval>[] = [];\n let toolRegistry: McpToolRegistry | null = null;\n\n return {\n async apply(ctx: CraftContext) {\n ctx.setStore(\n MCP_PLUGIN_REGISTERED as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n true,\n );\n\n // Create and store tool registry\n toolRegistry = new McpToolRegistry();\n ctx.setStore(\n MCP_TOOL_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n toolRegistry,\n );\n\n // Store stdio managers map so destination adapter can call tools on stdio clients\n ctx.setStore(\n MCP_STDIO_MANAGERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n stdioManagers as unknown as Map<\n string,\n {\n callTool(\n name: string,\n args: Record<string, unknown>,\n ): Promise<unknown>;\n }\n >,\n );\n\n if (options.clients && Object.keys(options.clients).length > 0) {\n const clientEntries = Object.entries(options.clients);\n const map = new Map<\n string,\n McpClientHttpConfig | McpClientStdioConfig | string\n >();\n for (const [k, v] of clientEntries) {\n map.set(k, v);\n }\n ctx.setStore(\n ADAPTER_MCP_CLIENT_SERVERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n map,\n );\n\n // Start stdio clients and list HTTP client tools\n for (const [serverId, config] of clientEntries) {\n if (isStdioConfig(config)) {\n await startStdioClient(ctx, serverId, config, toolRegistry);\n } else {\n // HTTP client: list tools immediately and optionally refresh periodically\n const httpConfig = config as McpClientHttpConfig;\n await listHttpClientTools(\n ctx,\n serverId,\n httpConfig.url,\n toolRegistry,\n httpConfig.auth,\n );\n setupHttpToolRefresh(\n ctx,\n serverId,\n httpConfig.url,\n toolRegistry,\n httpConfig.auth,\n );\n }\n\n const transport = isStdioConfig(config) ? \"stdio\" : \"http\";\n ctx.emit(\n `plugin:mcp:client:${serverId}:registered` as EventName,\n { serverId, transport } as Record<string, unknown>,\n );\n }\n }\n\n server = new McpServer(ctx, options);\n await server.start();\n },\n async teardown(ctx: CraftContext) {\n // Clear HTTP refresh timers\n for (const timer of httpRefreshTimers) {\n clearInterval(timer);\n }\n httpRefreshTimers.length = 0;\n\n // Close persistent HTTP clients\n for (const [serverId, client] of httpClients) {\n try {\n await client.close();\n } catch (error) {\n ctx.logger.error(\n { err: error, serverId, operation: \"close\" },\n \"Failed to close HTTP client\",\n );\n }\n }\n httpClients.clear();\n\n // Stop all stdio client managers\n for (const [serverId, manager] of stdioManagers) {\n try {\n await manager.stop();\n } catch (error) {\n ctx.logger.error(\n { err: error, serverId, operation: \"stop\" },\n \"Failed to stop stdio client\",\n );\n }\n }\n stdioManagers.clear();\n\n if (server) {\n try {\n await server.stop();\n } catch (error) {\n ctx.logger.error(\n { err: error, operation: \"stop\" },\n \"Failed to stop MCP server plugin\",\n );\n }\n server = null;\n }\n\n toolRegistry = null;\n },\n };\n\n async function startStdioClient(\n ctx: CraftContext,\n serverId: string,\n config: McpClientStdioConfig,\n registry: McpToolRegistry,\n ): Promise<void> {\n const managerOpts: import(\"./stdio-client-manager.ts\").StdioClientManagerOptions =\n {\n serverId,\n command: config.command,\n args: config.args ?? [],\n maxRestarts: options.maxRestarts ?? 5,\n restartDelayMs: options.restartDelayMs ?? 1000,\n restartBackoffMultiplier: options.restartBackoffMultiplier ?? 2,\n };\n if (config.env !== undefined) managerOpts.env = config.env;\n if (config.cwd !== undefined) managerOpts.cwd = config.cwd;\n\n const manager = new StdioClientManager(\n managerOpts,\n ctx.logger,\n (event, details) => {\n ctx.emit(event as EventName, details as Record<string, unknown>);\n },\n (_serverId, tools) => {\n registry.setToolsForSource(_serverId, \"stdio\", tools);\n },\n );\n\n stdioManagers.set(serverId, manager);\n\n try {\n await manager.start();\n } catch (error) {\n ctx.logger.error(\n { err: error, serverId, operation: \"start\" },\n \"Failed to start stdio client\",\n );\n ctx.emit(\n `plugin:mcp:client:${serverId}:error` as EventName,\n {\n serverId,\n error,\n } as Record<string, unknown>,\n );\n }\n }\n\n async function getOrCreateHttpClient(\n serverId: string,\n url: string,\n auth?: McpClientHttpConfig[\"auth\"],\n ): Promise<{\n close(): Promise<void>;\n listTools(): Promise<{ tools: McpTool[] }>;\n }> {\n const existing = httpClients.get(serverId);\n if (existing) return existing;\n\n const { Client } = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/client/index.js\"),\n {\n adapterName: \"mcp (http client)\",\n packageName: \"@modelcontextprotocol/sdk\",\n },\n );\n const { StreamableHTTPClientTransport } = await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/client/streamableHttp.js\"),\n {\n adapterName: \"mcp (http client)\",\n packageName: \"@modelcontextprotocol/sdk\",\n },\n );\n\n const headers = await buildAuthHeaders(auth);\n const transportOptions = headers ? { requestInit: { headers } } : undefined;\n const transport = new (StreamableHTTPClientTransport as new (\n url: URL,\n options?: { requestInit?: { headers?: Record<string, string> } },\n ) => unknown)(new URL(url), transportOptions);\n const rawClient = new Client(\n { name: \"routecraft-mcp-client\", version: \"1.0.0\" },\n { capabilities: {} },\n );\n await (\n rawClient as unknown as { connect(t: unknown): Promise<void> }\n ).connect(transport);\n\n const typed = rawClient as unknown as {\n close(): Promise<void>;\n listTools(): Promise<{ tools: McpTool[] }>;\n };\n httpClients.set(serverId, typed);\n return typed;\n }\n\n async function listHttpClientTools(\n ctx: CraftContext,\n serverId: string,\n url: string,\n registry: McpToolRegistry,\n auth?: McpClientHttpConfig[\"auth\"],\n ): Promise<void> {\n try {\n const client = await getOrCreateHttpClient(serverId, url, auth);\n\n const result = await client.listTools();\n const tools = result.tools ?? [];\n registry.setToolsForSource(serverId, \"http\", tools);\n\n ctx.emit(\n `plugin:mcp:client:${serverId}:tools:listed` as EventName,\n {\n serverId,\n toolCount: tools.length,\n } as Record<string, unknown>,\n );\n } catch (error) {\n // Connection may have gone stale; discard so next attempt reconnects\n httpClients.delete(serverId);\n ctx.logger.warn(\n { err: error, serverId, url, operation: \"listTools\" },\n \"Failed to list tools from HTTP client\",\n );\n }\n }\n\n function setupHttpToolRefresh(\n ctx: CraftContext,\n serverId: string,\n url: string,\n registry: McpToolRegistry,\n auth?: McpClientHttpConfig[\"auth\"],\n ): void {\n const interval = options.toolRefreshIntervalMs ?? 60_000;\n if (interval <= 0) return;\n\n const timer = setInterval(() => {\n void listHttpClientTools(ctx, serverId, url, registry, auth);\n }, interval);\n httpRefreshTimers.push(timer);\n }\n}\n","import type { EmbeddingModelConfig } from \"../types.ts\";\n\nexport interface CallEmbeddingParams {\n config: EmbeddingModelConfig;\n modelName: string;\n text: string;\n}\n\ntype PipelineFn = (\n text: string,\n options?: { pooling?: string; normalize?: boolean },\n) => Promise<unknown>;\n\ninterface CachedPipeline {\n run: PipelineFn;\n dispose?: (() => Promise<void>) | undefined;\n}\n\nconst pipelineCache = new Map<string, CachedPipeline>();\n\n/**\n * Dispose all cached HuggingFace pipelines and clear the cache. Call on context\n * shutdown so pipeline.dispose() releases native/ONNX resources.\n *\n * Callers must avoid process.exit() after this -- let the event loop drain\n * naturally so ONNX Runtime's C++ statics aren't torn down prematurely\n * (onnxruntime#25038: \"mutex lock failed: Invalid argument\").\n */\nexport async function disposeEmbeddingPipelineCache(): Promise<void> {\n const entries = [...pipelineCache.entries()];\n pipelineCache.clear();\n if (entries.length === 0) return;\n\n await Promise.all(\n entries.map(async ([, cached]) => {\n try {\n if (typeof cached.dispose === \"function\") {\n await cached.dispose();\n }\n } catch {\n // Ignore dispose errors during shutdown\n }\n }),\n );\n}\n\n/** Resolve to full Hugging Face repo id. Short names like \"all-MiniLM-L6-v2\" use Xenova/ (ONNX-converted). */\nfunction resolveHuggingFaceModel(modelName: string): string {\n if (modelName.includes(\"/\")) return modelName;\n return `Xenova/${modelName}`;\n}\n\nconst HUGGINGFACE_INSTALL =\n 'The Hugging Face embedding provider requires \"@huggingface/transformers\". Install it with: bun add @huggingface/transformers';\n\nfunction isModuleNotFoundFor(error: unknown, pkg: string): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message ?? \"\";\n return (\n (msg.includes(\"ERR_MODULE_NOT_FOUND\") ||\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Cannot find package\")) &&\n msg.includes(pkg)\n );\n}\n\nasync function getHuggingFacePipeline(modelName: string): Promise<PipelineFn> {\n const resolved = resolveHuggingFaceModel(modelName);\n const cached = pipelineCache.get(resolved);\n if (cached) return cached.run;\n\n let pipelineFn: (\n task: string,\n model: string,\n opts?: { dtype?: string },\n ) => Promise<unknown>;\n try {\n const mod = await import(\"@huggingface/transformers\");\n pipelineFn = mod.pipeline as typeof pipelineFn;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@huggingface/transformers\")) {\n throw new Error(HUGGINGFACE_INSTALL);\n }\n throw error;\n }\n const pipe = (await pipelineFn(\"feature-extraction\", resolved, {\n dtype: \"fp32\",\n })) as {\n (\n text: string,\n options?: { pooling?: string; normalize?: boolean },\n ): Promise<unknown>;\n dispose?: () => void;\n };\n const run: PipelineFn = (text, options) =>\n pipe(text, {\n pooling: (options?.pooling ?? \"mean\") as \"mean\",\n normalize: options?.normalize ?? true,\n });\n const entry: CachedPipeline = {\n run,\n dispose:\n typeof pipe.dispose === \"function\"\n ? () => Promise.resolve(pipe.dispose!())\n : undefined,\n };\n pipelineCache.set(resolved, entry);\n return run;\n}\n\nfunction previewForError(value: unknown): string {\n if (value === null) return \"null\";\n if (typeof value !== \"object\") return String(value);\n if (Array.isArray(value)) return `array(${value.length})`;\n try {\n const s = JSON.stringify(value);\n return s.length > 100 ? s.slice(0, 100) + \"...\" : s;\n } catch {\n return \"object\";\n }\n}\n\nfunction toNumberArray(data: Float32Array | number[] | unknown): number[] {\n if (Array.isArray(data)) return data as number[];\n if (data instanceof Float32Array) return Array.from(data);\n if (data && typeof data === \"object\" && \"data\" in data) {\n const d = (data as { data: unknown }).data;\n if (Array.isArray(d)) return d as number[];\n if (d instanceof Float32Array) return Array.from(d);\n throw new Error(\n `Embedding output .data must be an Array or Float32Array; got ${typeof d}: ${previewForError(d)}`,\n );\n }\n throw new Error(\n `Embedding output must be an Array, Float32Array, or object with .data; got ${typeof data}: ${previewForError(data)}`,\n );\n}\n\nexport async function callEmbedding(\n params: CallEmbeddingParams,\n): Promise<number[]> {\n const { config, modelName, text } = params;\n if (config.provider === \"mock\") {\n const dim = 8;\n const vec: number[] = [];\n for (let i = 0; i < dim; i++) {\n vec.push(((text.length + i) % 100) / 100);\n }\n return vec;\n }\n if (config.provider === \"huggingface\") {\n const pipe = await getHuggingFacePipeline(modelName);\n const output = await pipe(text, {\n pooling: \"mean\" as const,\n normalize: true,\n });\n const data =\n output && typeof output === \"object\" && \"data\" in output\n ? (output as { data: Float32Array | number[] }).data\n : output;\n return toNumberArray(data);\n }\n if (config.provider === \"ollama\" || config.provider === \"openai\") {\n throw new Error(\n `Embedding provider \"${config.provider}\" is not yet implemented. Use huggingface for now.`,\n );\n }\n throw new Error(\n `Unknown embedding provider: ${(config as EmbeddingModelConfig).provider}`,\n );\n}\n","import type { Exchange } from \"@routecraft/routecraft\";\n\n/** Store key for plugin-registered embedding providers (provider id → EmbeddingModelConfig). */\nexport const ADAPTER_EMBEDDING_PROVIDERS = Symbol.for(\n \"routecraft.adapter.embedding.providers\",\n);\n\n/** Store key for context-level default embedding options. */\nexport const ADAPTER_EMBEDDING_OPTIONS = Symbol.for(\n \"routecraft.adapter.embedding.options\",\n);\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [ADAPTER_EMBEDDING_PROVIDERS]: Map<string, EmbeddingModelConfig>;\n [ADAPTER_EMBEDDING_OPTIONS]: Partial<EmbeddingOptions>;\n }\n}\n\nexport interface EmbeddingModelConfigHuggingFace {\n provider: \"huggingface\";\n}\n\nexport interface EmbeddingModelConfigOllama {\n provider: \"ollama\";\n baseURL?: string;\n}\n\nexport interface EmbeddingModelConfigOpenAI {\n provider: \"openai\";\n apiKey: string;\n baseURL?: string;\n}\n\n/** Used by tests only: returns a deterministic vector, no model download. */\nexport interface EmbeddingModelConfigMock {\n provider: \"mock\";\n}\n\nexport type EmbeddingModelConfig =\n | EmbeddingModelConfigHuggingFace\n | EmbeddingModelConfigOllama\n | EmbeddingModelConfigOpenAI\n | EmbeddingModelConfigMock;\n\nexport type EmbeddingProviderType =\n | \"huggingface\"\n | \"ollama\"\n | \"openai\"\n | \"mock\";\n\nexport interface EmbeddingOptions<T = unknown> {\n /** Build the string to embed from the exchange (e.g. jobTitle + location). */\n using: (exchange: Exchange<T>) => string | string[];\n}\n\nexport interface EmbeddingResult {\n embedding: number[];\n}\n\n/**\n * Provider options for embeddingPlugin({ providers }). Key is the provider id.\n */\nexport interface EmbeddingPluginProviders {\n huggingface?: Record<string, never>;\n ollama?: { baseURL?: string };\n openai?: { apiKey: string; baseURL?: string };\n /** Test-only: deterministic vector, no network. */\n mock?: Record<string, never>;\n}\n\nexport interface EmbeddingPluginOptions {\n providers: EmbeddingPluginProviders;\n /** Optional context-level default options. */\n defaultOptions?: Partial<EmbeddingOptions>;\n}\n\n/**\n * Recommended embedding model ids for autocomplete.\n * Format: \"providerId:modelName\". Custom models are allowed via string.\n * Updated for 2026.\n */\nexport type EmbeddingModelId =\n // HuggingFace\n | \"huggingface:all-MiniLM-L6-v2\"\n | \"huggingface:sentence-transformers/all-MiniLM-L6-v2\"\n | \"huggingface:sentence-transformers/all-mpnet-base-v2\"\n | \"huggingface:BAAI/bge-small-en-v1.5\"\n | \"huggingface:BAAI/bge-base-en-v1.5\"\n | \"huggingface:BAAI/bge-m3\"\n | \"huggingface:intfloat/e5-small-v2\"\n | \"huggingface:intfloat/e5-base-v2\"\n | \"huggingface:intfloat/multilingual-e5-large\"\n // OpenAI\n | \"openai:text-embedding-3-small\"\n | \"openai:text-embedding-3-large\"\n | \"openai:text-embedding-ada-002\"\n // Ollama\n | \"ollama:nomic-embed-text\"\n | \"ollama:nomic-embed-text-v1.5\"\n | \"ollama:mxbai-embed-large\"\n | \"ollama:all-minilm\"\n // Other (custom models)\n | string;\n","import type { CraftContext, CraftPlugin } from \"@routecraft/routecraft\";\nimport { disposeEmbeddingPipelineCache } from \"./providers/index.ts\";\nimport {\n ADAPTER_EMBEDDING_OPTIONS,\n ADAPTER_EMBEDDING_PROVIDERS,\n} from \"./types.ts\";\nimport type { EmbeddingModelConfig, EmbeddingPluginOptions } from \"./types.ts\";\n\n/** Normalize provider options to full EmbeddingModelConfig (providerId wins over opts.provider). */\nfunction toModelConfig(\n providerId: string,\n opts: Record<string, unknown>,\n): EmbeddingModelConfig {\n return {\n ...opts,\n provider: providerId as EmbeddingModelConfig[\"provider\"],\n } as EmbeddingModelConfig;\n}\n\n/**\n * Embedding plugin: registers providers and teardown to clear the pipeline\n * cache when the context stops (releases native/ONNX resources).\n * Use embedding(\"providerId:modelName\", { using: ... }),\n * e.g. embedding(\"huggingface:all-MiniLM-L6-v2\", { using: (e) => e.body.title }).\n */\nexport function embeddingPlugin(\n options: EmbeddingPluginOptions = { providers: {} },\n): CraftPlugin {\n return {\n apply(ctx: CraftContext) {\n const map = new Map<string, EmbeddingModelConfig>();\n for (const [providerId, opts] of Object.entries(options.providers)) {\n if (opts !== undefined) {\n map.set(\n providerId,\n toModelConfig(providerId, opts as Record<string, unknown>),\n );\n }\n }\n ctx.setStore(\n ADAPTER_EMBEDDING_PROVIDERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n map,\n );\n if (\n options.defaultOptions &&\n Object.keys(options.defaultOptions).length > 0\n ) {\n ctx.setStore(\n ADAPTER_EMBEDDING_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n options.defaultOptions,\n );\n }\n },\n async teardown() {\n await disposeEmbeddingPipelineCache();\n },\n };\n}\n","import {\n rcError,\n type CraftContext,\n type Exchange,\n} from \"@routecraft/routecraft\";\nimport type { LlmModelConfig, LlmPromptSource } from \"./types.ts\";\nimport { ADAPTER_LLM_PROVIDERS } from \"./types.ts\";\n\n/** Parses a \"providerId:modelName\" id string into its parts. Throws when malformed. */\nexport function parseProviderModel(id: string): {\n providerId: string;\n modelName: string;\n} {\n const colon = id.indexOf(\":\");\n if (colon < 1 || colon === id.length - 1) {\n throw new Error(\n `LLM model id must be \"providerId:modelName\" (e.g. ollama:lfm2.5-thinking). Got: \"${id}\"`,\n );\n }\n return {\n providerId: id.slice(0, colon),\n modelName: id.slice(colon + 1),\n };\n}\n\n/**\n * Resolves a provider config and model name from a model reference. The\n * reference can be either a \"provider:model\" string (resolved via the\n * llmPlugin store) or an inline `LlmModelConfig` (used directly, with the\n * model name taken from the config's `modelId` when set).\n */\nexport function resolveModel(\n model: string | LlmModelConfig,\n context: CraftContext | undefined,\n): { config: LlmModelConfig; modelName: string } {\n if (typeof model !== \"string\") {\n const modelName = (model as { modelId?: string }).modelId ?? \"\";\n if (modelName.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message:\n `LLM model: inline LlmModelConfig for provider \"${model.provider}\" did not resolve to a model name. ` +\n `Either pass the model as a \"providerId:modelName\" string (e.g. \"${model.provider}:<model>\") ` +\n `or set \"modelId\" on the config. Providers \"openai\", \"anthropic\", and \"gemini\" do not carry ` +\n `a modelId field, so those must use the string form.`,\n });\n }\n return { config: model, modelName };\n }\n\n if (!context) {\n throw new Error(\n `LLM model id \"${model}\" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store \"${ADAPTER_LLM_PROVIDERS.description}\" can be read.`,\n );\n }\n\n const store = context.getStore(\n ADAPTER_LLM_PROVIDERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, LlmModelConfig> | undefined;\n if (!store) {\n throw new Error(\n `LLM provider not found: no providers registered. Add llmPlugin({ providers: { ollama: { provider: \"ollama\" }, ... } }) to your config.`,\n );\n }\n\n const { providerId, modelName } = parseProviderModel(model);\n const config = store.get(providerId);\n if (!config) {\n throw new Error(\n `LLM provider \"${providerId}\" not found. Register it with llmPlugin({ providers: { \"${providerId}\": { provider, apiKey?, baseURL? } } }).`,\n );\n }\n return { config, modelName };\n}\n\n/** Resolves a prompt source (string or function) against an exchange. Empty source returns \"\". */\nexport function resolvePrompt(\n source: LlmPromptSource | undefined,\n exchange: Exchange<unknown>,\n): string {\n if (source === undefined || source === \"\") return \"\";\n if (typeof source === \"function\") return source(exchange);\n return source;\n}\n\n/** Default user-prompt derivation: string body as-is, JSON for objects, String() otherwise. */\nexport function resolveUserPromptDefault(exchange: Exchange<unknown>): string {\n const body = exchange.body;\n if (typeof body === \"string\") return body;\n if (body === null || body === undefined) return \"\";\n if (typeof body === \"object\") return JSON.stringify(body);\n return String(body);\n}\n","import type {\n LlmModelConfig,\n LlmOptionsMerged,\n LlmToolCallSummary,\n LlmUsage,\n} from \"../types.ts\";\n\nexport interface CallLlmParams {\n config: LlmModelConfig;\n modelId: string;\n options: Pick<\n LlmOptionsMerged,\n | \"temperature\"\n | \"maxTokens\"\n | \"topP\"\n | \"frequencyPenalty\"\n | \"presencePenalty\"\n >;\n system: string;\n /**\n * User-side conversation. When a string, it is sent as a single\n * user prompt. When an array, it is forwarded directly to the SDK\n * as the `prompt` argument (Vercel AI SDK accepts\n * `string | Array<ModelMessage>` for `prompt`). The agent session\n * uses the array form to feed back the prior assistant + tool\n * messages plus a validator-corrective user message on a `validate`\n * retry, so the model sees the full history rather than a fresh\n * conversation.\n */\n user: string | unknown[];\n /** Optional structured output spec (from toAiOutputSpec). */\n output?: unknown;\n /**\n * Optional Vercel AI SDK tool map. When supplied the SDK runs the\n * tool-calling loop.\n */\n tools?: Record<string, unknown>;\n /**\n * Optional stop condition for the tool-calling loop.\n */\n stopWhen?: unknown;\n /**\n * Optional abort signal forwarded into `generateText` / `streamText`.\n */\n abortSignal?: AbortSignal;\n}\n\n/** Provider-level defaults so users can register models with minimal config (e.g. { provider: \"ollama\" }). */\nexport const PROVIDER_DEFAULTS = {\n ollama: {\n baseURL: \"http://localhost:11434/api\",\n },\n} as const;\n\nexport function throwProviderInstallError(\n pkg: string,\n provider: string,\n): never {\n throw new Error(\n `The ${provider} LLM provider requires the \"${pkg}\" package. Install it with: bun add ${pkg}`,\n );\n}\n\nexport function isModuleNotFoundFor(error: unknown, pkg: string): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message ?? \"\";\n return (\n (msg.includes(\"ERR_MODULE_NOT_FOUND\") ||\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Cannot find package\")) &&\n msg.includes(pkg)\n );\n}\n\nexport function assertLanguageModelShape(\n model: unknown,\n providerName: string,\n modelId: string,\n): void {\n if (model === null || typeof model !== \"object\") {\n throw new Error(\n `[${providerName}] Invalid model: expected an object, got ${typeof model}. Model id: ${modelId}`,\n );\n }\n const m = model as Record<string, unknown>;\n if (typeof m[\"doGenerate\"] !== \"function\") {\n throw new Error(\n `[${providerName}] Invalid model: missing or invalid doGenerate method. Model id: ${modelId}. ` +\n \"Ensure the provider returns an AI SDK-compatible language model.\",\n );\n }\n if (typeof m[\"doStream\"] !== \"function\") {\n throw new Error(\n `[${providerName}] Invalid model: missing or invalid doStream method. Model id: ${modelId}. ` +\n \"Ensure the provider returns an AI SDK-compatible language model.\",\n );\n }\n}\n\n/** Pass through AI SDK usage so LlmUsage matches LanguageModelUsage (inputTokens/outputTokens). */\nexport function toLlmUsage(u: {\n inputTokens?: number | undefined;\n outputTokens?: number | undefined;\n totalTokens?: number | undefined;\n}): LlmUsage {\n return {\n ...(u.inputTokens !== undefined && { inputTokens: u.inputTokens }),\n ...(u.outputTokens !== undefined && { outputTokens: u.outputTokens }),\n ...(u.totalTokens !== undefined && { totalTokens: u.totalTokens }),\n };\n}\n\n/**\n * Safely read structured output from generateText result. The AI SDK's result.output\n * is a getter that throws AI_NoOutputGeneratedError when the model didn't produce\n * valid structured output (e.g. empty, blocked, or unparseable). Catching here\n * allows returning without output so the adapter can try parsing result.text.\n */\nexport function getStructuredOutput(result: { output?: unknown }): unknown {\n try {\n if (\"output\" in result && result.output !== undefined) return result.output;\n } catch {\n // SDK getter threw (e.g. AI_NoOutputGeneratedError); leave output undefined.\n }\n return undefined;\n}\n\n/**\n * Defensive accessor for reasoning text. Vercel AI SDK exposes\n * `reasoningText` (concatenated string) when the provider returned\n * reasoning blocks (Anthropic extended thinking, OpenAI o1, etc.).\n */\nexport function readReasoning(result: unknown): string | undefined {\n const r = result as { reasoningText?: unknown };\n if (typeof r.reasoningText === \"string\" && r.reasoningText.length > 0) {\n return r.reasoningText;\n }\n return undefined;\n}\n\n/**\n * Walk an SDK result's `steps` array (sync or post-await) and\n * produce a flat list of `LlmToolCallSummary` entries pairing each\n * tool call with its result or error.\n */\nexport function collectToolCalls(result: unknown): LlmToolCallSummary[] {\n if (result === null || typeof result !== \"object\") return [];\n const steps = (result as { steps?: unknown }).steps;\n if (!Array.isArray(steps)) return [];\n const out: LlmToolCallSummary[] = [];\n for (const step of steps) {\n if (step === null || typeof step !== \"object\") continue;\n const calls = (step as { toolCalls?: unknown }).toolCalls;\n const results = (step as { toolResults?: unknown }).toolResults;\n if (!Array.isArray(calls)) continue;\n for (const call of calls) {\n if (call === null || typeof call !== \"object\") continue;\n const c = call as Record<string, unknown>;\n const toolCallId =\n typeof c[\"toolCallId\"] === \"string\" ? c[\"toolCallId\"] : \"\";\n const toolName = typeof c[\"toolName\"] === \"string\" ? c[\"toolName\"] : \"\";\n const input = c[\"input\"] ?? c[\"args\"];\n const summary: LlmToolCallSummary = { toolCallId, toolName, input };\n if (Array.isArray(results)) {\n const match = (results as Record<string, unknown>[]).find(\n (r) => r[\"toolCallId\"] === toolCallId,\n );\n if (match) {\n if (\"output\" in match || \"result\" in match) {\n summary.output = match[\"output\"] ?? match[\"result\"];\n }\n if (\"error\" in match && match[\"error\"] !== undefined) {\n summary.error = match[\"error\"];\n }\n }\n }\n out.push(summary);\n }\n }\n return out;\n}\n\n/** Per-provider extras forwarded into `generateText` / `streamText`. */\nexport interface ProviderExtras {\n output?: unknown;\n tools?: Record<string, unknown>;\n stopWhen?: unknown;\n abortSignal?: AbortSignal;\n}\n\nexport function buildExtras(\n params: Pick<CallLlmParams, \"output\" | \"tools\" | \"stopWhen\" | \"abortSignal\">,\n): ProviderExtras {\n const out: ProviderExtras = {};\n if (params.output !== undefined) out.output = params.output;\n if (params.tools !== undefined && Object.keys(params.tools).length > 0) {\n out.tools = params.tools;\n if (params.stopWhen !== undefined) out.stopWhen = params.stopWhen;\n }\n if (params.abortSignal !== undefined) out.abortSignal = params.abortSignal;\n return out;\n}\n\nexport function buildSdkParams(\n model: unknown,\n options: Pick<\n LlmOptionsMerged,\n | \"temperature\"\n | \"maxTokens\"\n | \"topP\"\n | \"frequencyPenalty\"\n | \"presencePenalty\"\n >,\n system: string,\n user: string | unknown[],\n extras: ProviderExtras,\n): Record<string, unknown> {\n const params: Record<string, unknown> = {\n model,\n prompt: user,\n temperature: options.temperature,\n };\n if (options.maxTokens !== undefined)\n params[\"maxOutputTokens\"] = options.maxTokens;\n if (system) params[\"system\"] = system;\n if (options.topP !== undefined) params[\"topP\"] = options.topP;\n if (options.frequencyPenalty !== undefined) {\n params[\"frequencyPenalty\"] = options.frequencyPenalty;\n }\n if (options.presencePenalty !== undefined) {\n params[\"presencePenalty\"] = options.presencePenalty;\n }\n return { ...params, ...extras };\n}\n","import {\n assertLanguageModelShape,\n isModuleNotFoundFor,\n PROVIDER_DEFAULTS,\n throwProviderInstallError,\n} from \"./llm-utils.ts\";\nimport type { LlmModelConfig } from \"../types.ts\";\n\n/**\n * Resolve the AI SDK `LanguageModel` for a given provider config.\n * Single source of truth used by both the synchronous and streaming\n * dispatch paths so provider setup is not duplicated per dispatch mode.\n */\nexport async function resolveLanguageModel(\n config: LlmModelConfig,\n modelId: string,\n): Promise<unknown> {\n switch (config.provider) {\n case \"openai\":\n return resolveOpenAI(config, modelId);\n case \"anthropic\":\n return resolveAnthropic(config, modelId);\n case \"gemini\":\n return resolveGemini(config, modelId);\n case \"openrouter\":\n return resolveOpenRouter(config, modelId);\n case \"ollama\":\n return resolveOllama(config, modelId);\n default: {\n const _: never = config;\n throw new Error(\n `LLM provider not implemented: ${(_ as LlmModelConfig).provider}`,\n );\n }\n }\n}\n\nasync function resolveOpenAI(\n config: import(\"../types.ts\").LlmModelConfigOpenAI,\n modelId: string,\n): Promise<unknown> {\n let createOpenAI: (s: {\n apiKey: string;\n baseURL?: string;\n }) => (m: string) => unknown;\n try {\n const mod = await import(\"@ai-sdk/openai\");\n createOpenAI = mod.createOpenAI as typeof createOpenAI;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@ai-sdk/openai\")) {\n throwProviderInstallError(\"@ai-sdk/openai\", \"OpenAI\");\n }\n throw error;\n }\n const settings: { apiKey: string; baseURL?: string } = {\n apiKey: config.apiKey,\n };\n if (config.baseURL !== undefined) settings.baseURL = config.baseURL;\n const openai = createOpenAI(settings);\n return openai(modelId);\n}\n\nasync function resolveAnthropic(\n config: import(\"../types.ts\").LlmModelConfigAnthropic,\n modelId: string,\n): Promise<unknown> {\n let createAnthropic: (s: { apiKey: string }) => (m: string) => unknown;\n try {\n const mod = await import(\"@ai-sdk/anthropic\");\n createAnthropic = mod.createAnthropic as typeof createAnthropic;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@ai-sdk/anthropic\")) {\n throwProviderInstallError(\"@ai-sdk/anthropic\", \"Anthropic\");\n }\n throw error;\n }\n const anthropic = createAnthropic({ apiKey: config.apiKey });\n return anthropic(modelId);\n}\n\nasync function resolveGemini(\n config: import(\"../types.ts\").LlmModelConfigGemini,\n modelId: string,\n): Promise<unknown> {\n let createGoogleGenerativeAI: (s: {\n apiKey: string;\n }) => (m: string) => unknown;\n try {\n const mod = await import(\"@ai-sdk/google\");\n createGoogleGenerativeAI =\n mod.createGoogleGenerativeAI as typeof createGoogleGenerativeAI;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@ai-sdk/google\")) {\n throwProviderInstallError(\"@ai-sdk/google\", \"Gemini\");\n }\n throw error;\n }\n const google = createGoogleGenerativeAI({ apiKey: config.apiKey });\n return google(modelId);\n}\n\nasync function resolveOpenRouter(\n config: import(\"../types.ts\").LlmModelConfigOpenRouter,\n modelId: string,\n): Promise<unknown> {\n let createOpenRouter: (s: { apiKey: string }) => {\n chat: (id: string) => unknown;\n };\n try {\n const mod = await import(\"@openrouter/ai-sdk-provider\");\n createOpenRouter = mod.createOpenRouter as typeof createOpenRouter;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"@openrouter/ai-sdk-provider\")) {\n throwProviderInstallError(\"@openrouter/ai-sdk-provider\", \"OpenRouter\");\n }\n throw error;\n }\n const openrouter = createOpenRouter({ apiKey: config.apiKey });\n const resolvedId = config.modelId ?? modelId;\n const rawModel = openrouter.chat(resolvedId);\n assertLanguageModelShape(rawModel, \"OpenRouter\", resolvedId);\n return rawModel;\n}\n\nasync function resolveOllama(\n config: import(\"../types.ts\").LlmModelConfigOllama,\n modelId: string,\n): Promise<unknown> {\n let createOllama: (s: { baseURL?: string }) => (name: string) => unknown;\n try {\n const mod = await import(\"ollama-ai-provider-v2\");\n createOllama = mod.createOllama as typeof createOllama;\n } catch (error) {\n if (isModuleNotFoundFor(error, \"ollama-ai-provider-v2\")) {\n throwProviderInstallError(\"ollama-ai-provider-v2\", \"Ollama\");\n }\n throw error;\n }\n const ollama = createOllama({\n baseURL: config.baseURL ?? PROVIDER_DEFAULTS.ollama.baseURL,\n });\n const name = config.modelId ?? modelId;\n const rawModel = ollama(name);\n assertLanguageModelShape(rawModel, \"Ollama\", name);\n return rawModel;\n}\n","/**\n * Token-level delta emitted while a streaming agent dispatch writes\n * its response. Forwarded to the user-supplied `AgentOptions.onDelta`\n * listener as the model emits tokens.\n *\n * `AgentDelta` is INTENTIONALLY narrow: it covers only token-level\n * incremental updates that need a directed, back-pressure-aware\n * delivery channel (the canonical case is forwarding to a single\n * SSE / WebSocket / TUI consumer). Coarse decision events (tool-call,\n * tool-result, step-finished, finished) live on the context bus\n * (`route:<id>:agent:*`) where they're broadcast to every subscriber\n * without per-call wiring.\n */\nexport type AgentDelta =\n /** Incremental text from the model. Concatenate to render tokens live. */\n | { type: \"text-delta\"; text: string }\n /**\n * Incremental reasoning text from the provider (Anthropic extended\n * thinking, OpenAI o1). Useful for \"thinking...\" UI; safe to ignore.\n */\n | { type: \"reasoning-delta\"; text: string };\n\n/**\n * Listener for streaming agent dispatches. Set on\n * `AgentOptions.onDelta` to receive token-level deltas. Async\n * listeners are awaited so back-pressure on a slow consumer (e.g. an\n * SSE channel) propagates into the stream.\n *\n * Throws inside the listener are caught and logged; they do not abort\n * the agent dispatch.\n */\nexport type AgentDeltaListener = (delta: AgentDelta) => void | Promise<void>;\n\n/**\n * Convert a Vercel AI SDK `streamText` full-stream part into an\n * `AgentDelta`. Returns `null` for parts that have no public-surface\n * equivalent on the delta channel (text-start/end markers,\n * tool-input-* deltas, abort, raw provider parts, AND tool-call /\n * tool-result / finish-step / finish / error parts that now flow\n * through the context bus instead).\n *\n * @internal\n */\nexport function normalizeStreamDelta(part: unknown): AgentDelta | null {\n if (part === null || typeof part !== \"object\") return null;\n const p = part as Record<string, unknown>;\n const type = p[\"type\"];\n switch (type) {\n case \"text-delta\": {\n const text = readString(p, \"text\") ?? readString(p, \"textDelta\");\n if (text === undefined || text.length === 0) return null;\n return { type: \"text-delta\", text };\n }\n case \"reasoning-delta\": {\n const text = readString(p, \"text\") ?? readString(p, \"delta\");\n if (text === undefined || text.length === 0) return null;\n return { type: \"reasoning-delta\", text };\n }\n default:\n return null;\n }\n}\n\nfunction readString(\n obj: Record<string, unknown>,\n key: string,\n): string | undefined {\n const v = obj[key];\n return typeof v === \"string\" ? v : undefined;\n}\n","import { logger as frameworkLogger } from \"@routecraft/routecraft\";\nimport type { AgentDeltaListener } from \"../../agent/events.ts\";\nimport { normalizeStreamDelta } from \"../../agent/events.ts\";\nimport type { LlmResult } from \"../types.ts\";\nimport {\n buildExtras,\n buildSdkParams,\n collectToolCalls,\n toLlmUsage,\n type CallLlmParams,\n type ProviderExtras,\n} from \"./llm-utils.ts\";\nimport { resolveLanguageModel } from \"./resolve.ts\";\n\n/**\n * Streaming counterpart to `callLlm`. Resolves the language model\n * for the configured provider, calls Vercel's `streamText`, forwards\n * each normalised token-level delta to `onDelta`, and finally returns\n * the consolidated `LlmResult` once the stream drains.\n *\n * Listener errors are caught and logged; they do not abort the\n * dispatch. Stream errors propagate out of `await result.text`.\n *\n * Exported from its own module so `stream-llm.bun.test.ts` can import\n * it directly without conflicting with `agent-bus-events.bun.test.ts`'s\n * `mock.module(\"../llm/providers/index.ts\", ...)`. Bun 1.3.11 shares\n * the module registry across all files in a `bun test` run, so the two\n * test files must mock non-overlapping paths.\n */\nexport async function streamLlm(\n params: CallLlmParams & { onDelta: AgentDeltaListener },\n): Promise<LlmResult> {\n const { config, modelId, options, system, user, onDelta } = params;\n const model = await resolveLanguageModel(config, modelId);\n return runStreamGenerate(\n model,\n options,\n system,\n user,\n buildExtras(params),\n onDelta,\n );\n}\n\n/**\n * Shared `streamText` invocation. Iterates the SDK's `fullStream`,\n * forwards each token-level delta to `onDelta`, then awaits the\n * consolidated values once the stream drains.\n *\n * Listener errors are caught and logged; they do not abort the dispatch.\n */\nexport async function runStreamGenerate(\n model: unknown,\n options: CallLlmParams[\"options\"],\n system: string,\n user: string | unknown[],\n extras: ProviderExtras,\n onDelta: AgentDeltaListener,\n): Promise<LlmResult> {\n const { streamText } = await import(\"ai\");\n const params = buildSdkParams(model, options, system, user, extras);\n const result = streamText(params as Parameters<typeof streamText>[0]);\n\n for await (const part of result.fullStream) {\n const delta = normalizeStreamDelta(part);\n if (delta === null) continue;\n try {\n await onDelta(delta);\n } catch (err) {\n frameworkLogger.warn(\n { err },\n \"agent.onDelta listener threw; ignoring and continuing stream\",\n );\n }\n }\n\n const text = await result.text;\n const out: LlmResult = { text: text ?? \"\", raw: result };\n const usage = await safeAwait<{\n inputTokens?: number | undefined;\n outputTokens?: number | undefined;\n totalTokens?: number | undefined;\n }>(result.usage);\n if (usage) out.usage = toLlmUsage(usage);\n const reasoning = await safeAwait<string | undefined>(\n (result as { reasoningText?: PromiseLike<string | undefined> })\n .reasoningText,\n );\n if (typeof reasoning === \"string\" && reasoning.length > 0) {\n out.reasoning = reasoning;\n }\n const structured = await safeAwait<unknown>(\n (result as { output?: PromiseLike<unknown> }).output,\n );\n if (structured !== undefined) out.output = structured;\n const finishReason = await safeAwait<string | undefined>(\n (result as { finishReason?: PromiseLike<string | undefined> }).finishReason,\n );\n if (typeof finishReason === \"string\") out.finishReason = finishReason;\n const steps = await safeAwait<unknown>(\n (result as { steps?: PromiseLike<unknown> }).steps,\n );\n const toolCalls = collectToolCalls({ steps });\n if (toolCalls.length > 0) out.toolCalls = toolCalls;\n if (Array.isArray(steps)) out.stepsCount = steps.length;\n const response = await safeAwait<{ messages?: unknown }>(\n (result as { response?: PromiseLike<{ messages?: unknown }> }).response,\n );\n if (response && Array.isArray(response.messages)) {\n out.responseMessages = response.messages;\n }\n return out;\n}\n\nasync function safeAwait<T>(\n value: T | PromiseLike<T> | undefined,\n): Promise<T | undefined> {\n if (value === undefined) return undefined;\n try {\n return await value;\n } catch (err) {\n frameworkLogger.debug(\n { err },\n \"llm.streamLlm: optional accessor rejected; treating as absent\",\n );\n return undefined;\n }\n}\n","import type { LlmResult } from \"../types.ts\";\nimport {\n buildExtras,\n buildSdkParams,\n collectToolCalls,\n getStructuredOutput,\n readReasoning,\n toLlmUsage,\n type CallLlmParams,\n type ProviderExtras,\n} from \"./llm-utils.ts\";\nimport { resolveLanguageModel } from \"./resolve.ts\";\nimport { streamLlm as _streamLlm } from \"./stream-llm.ts\";\nimport type { AgentDeltaListener } from \"../../agent/events.ts\";\n\nexport type { CallLlmParams } from \"./llm-utils.ts\";\n\n/**\n * Wrapper exported from the barrel so that `agent-bus-events.bun.test.ts`\n * can mock this barrel without bun 1.3.11 propagating the mock through the\n * syntactic re-export chain into `stream-llm.ts` itself.\n * `stream-llm.bun.test.ts` imports directly from `stream-llm.ts` and must\n * get the real implementation; a syntactic re-export here would cause bun to\n * conflate the two modules in the process-global mock registry.\n */\nexport async function streamLlm(\n params: CallLlmParams & { onDelta: AgentDeltaListener },\n): Promise<LlmResult> {\n return _streamLlm(params);\n}\n\n/**\n * Dispatch via Vercel AI SDK `generateText` and return a normalised\n * `LlmResult`. Resolves the language model for the configured\n * provider, then delegates to the shared `runGenerate` helper.\n */\nexport async function callLlm(params: CallLlmParams): Promise<LlmResult> {\n const { config, modelId, options, system, user } = params;\n const model = await resolveLanguageModel(config, modelId);\n return runGenerate(model, options, system, user, buildExtras(params));\n}\n\nasync function runGenerate(\n model: unknown,\n options: CallLlmParams[\"options\"],\n system: string,\n user: string | unknown[],\n extras: ProviderExtras,\n): Promise<LlmResult> {\n const { generateText } = await import(\"ai\");\n const params = buildSdkParams(model, options, system, user, extras);\n const result = await generateText(\n params as Parameters<typeof generateText>[0],\n );\n const out: LlmResult = { text: result.text ?? \"\", raw: result };\n if (result.usage) out.usage = toLlmUsage(result.usage);\n const parsed = getStructuredOutput(result as { output?: unknown });\n if (parsed !== undefined) out.output = parsed;\n const reasoning = readReasoning(result);\n if (reasoning) out.reasoning = reasoning;\n const finishReason = (result as { finishReason?: unknown }).finishReason;\n if (typeof finishReason === \"string\") out.finishReason = finishReason;\n const toolCalls = collectToolCalls(result);\n if (toolCalls.length > 0) out.toolCalls = toolCalls;\n const steps = (result as { steps?: unknown }).steps;\n if (Array.isArray(steps)) out.stepsCount = steps.length;\n const responseMessages = (result as { response?: { messages?: unknown } })\n .response?.messages;\n if (Array.isArray(responseMessages)) out.responseMessages = responseMessages;\n return out;\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { formatSchemaIssues } from \"@routecraft/routecraft\";\nimport { Output, jsonSchema } from \"ai\";\n\n/**\n * Build an AI SDK schema (`jsonSchema(...)`) from a Standard Schema. The\n * `direction` argument selects which JSON-schema variant the underlying\n * Standard Schema exposes:\n *\n * - `\"output\"` (provider structured output): prefer `~standard.jsonSchema.output`,\n * fall back to `.input`. The SDK validates the model's structured response\n * and we return the parsed value on `LlmResult.output` / `AgentResult.output`.\n * - `\"input\"` (tool input schema): prefer `~standard.jsonSchema.input`, fall\n * back to `.output`. The SDK shows the JSON schema to the model in the tool\n * list and validates the model's tool-call args before calling `execute`.\n *\n * @internal\n */\nfunction toAiSchema(\n schema: StandardSchemaV1,\n direction: \"input\" | \"output\",\n errorContext: string,\n): unknown {\n const standard = (schema as unknown as Record<string, unknown>)[\n \"~standard\"\n ] as\n | {\n validate: (\n value: unknown,\n ) =>\n | { value?: unknown; issues?: unknown }\n | Promise<{ value?: unknown; issues?: unknown }>;\n jsonSchema?: {\n output?: (opts: { target: string }) => Record<string, unknown>;\n input?: (opts: { target: string }) => Record<string, unknown>;\n };\n }\n | undefined;\n\n if (!standard?.validate) {\n throw new Error(\n `${errorContext} must be a StandardSchemaV1 with ~standard.validate`,\n );\n }\n\n const primary =\n direction === \"input\"\n ? standard.jsonSchema?.input\n : standard.jsonSchema?.output;\n const fallback =\n direction === \"input\"\n ? standard.jsonSchema?.output\n : standard.jsonSchema?.input;\n const jsonSchemaObj =\n primary?.({ target: \"draft-2020-12\" }) ??\n fallback?.({ target: \"draft-2020-12\" });\n\n if (!jsonSchemaObj || typeof jsonSchemaObj !== \"object\") {\n throw new Error(\n `${errorContext} must expose ~standard.jsonSchema.input or .output for AI SDK use`,\n );\n }\n\n function validate(\n value: unknown,\n ): { success: true; value: unknown } | { success: false; error: Error } {\n let result:\n | { value?: unknown; issues?: unknown }\n | Promise<{\n value?: unknown;\n issues?: unknown;\n }>;\n try {\n result = standard!.validate(value);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err : new Error(String(err)),\n };\n }\n if (result instanceof Promise) {\n return {\n success: false,\n error: new Error(\n `${errorContext}: async schema validation is not supported`,\n ),\n };\n }\n const hasIssues =\n result.issues != null &&\n (Array.isArray(result.issues)\n ? result.issues.length > 0\n : typeof result.issues === \"object\" && result.issues !== null\n ? Object.keys(result.issues).length > 0\n : Boolean(result.issues));\n if (hasIssues) {\n return {\n success: false,\n error: new Error(formatSchemaIssues(result.issues)),\n };\n }\n return { success: true, value: result.value };\n }\n\n return jsonSchema(jsonSchemaObj as Parameters<typeof jsonSchema>[0], {\n validate,\n });\n}\n\n/**\n * Build an AI SDK input schema for tool definitions\n * (`tool({ inputSchema, execute })`). The SDK presents this schema to\n * the model in the tool list and validates the model's tool-call\n * arguments before invoking `execute`.\n *\n * @internal\n */\nexport function toAiInputSchema(schema: StandardSchemaV1): unknown {\n return toAiSchema(schema, \"input\", \"Tool input schema\");\n}\n\n/**\n * Build an AI SDK output spec from a Standard Schema for provider-level\n * structured output (OpenAI response_format, Ollama format, etc.) and\n * validation. Delegates to {@link toAiSchema} so the JSON-schema\n * extraction, validation wrapper, and error messages stay aligned with\n * the input-schema path used by tool definitions (no risk of drift\n * between the two paths).\n *\n * The AI SDK accepts Zod directly in Output.object({ schema: z.object(...) }).\n * This package uses Standard Schema (per .standards/type-safety-and-schemas.md),\n * so it cannot depend on Zod. The `toAiSchema` helper bridges any\n * Standard Schema (Zod, Valibot, ArkType, etc.) by using the SDK's\n * lower-level `jsonSchema(jsonSchemaObj, { validate })`.\n */\nexport function toAiOutputSpec(schema: StandardSchemaV1): unknown {\n const aiSchema = toAiSchema(\n schema,\n \"output\",\n \"LLM output schema\",\n ) as Parameters<typeof Output.object>[0][\"schema\"];\n return Output.object({ schema: aiSchema });\n}\n","import { randomUUID } from \"node:crypto\";\nimport {\n logger as frameworkLogger,\n isAuthentic,\n markAuthentic,\n type CraftContext,\n type EventName,\n type Principal,\n} from \"@routecraft/routecraft\";\nimport { toAiInputSchema } from \"../llm/structured-output.ts\";\nimport type { FnHandlerContext } from \"../fn/types.ts\";\nimport type { AgentDispatchIdentity } from \"./session.ts\";\nimport type { ResolvedTool } from \"./tools/selection.ts\";\n\n/**\n * Convert a list of `ResolvedTool` entries (the output of\n * `tools([...]).resolve(ctx)`) into a Vercel AI SDK tool map suitable\n * for `generateText({ tools })`.\n *\n * Each resulting tool runs:\n * 1. Emit `route:<routeId>:agent:tool:invoked` on the context bus so\n * cross-cutting observability (telemetry, dashboards, audit) sees\n * the call before the handler runs.\n * 2. The optional guard (registered via `tools([{ name, guard }])` or\n * `tools([{ tagged, guard }])`). Throwing inside the guard surfaces\n * back to the model as a tool error so the model can self-correct;\n * the wrapper emits `agent:tool:error` before rethrowing.\n * 3. The underlying handler with `(input, fnHandlerContext)`. On\n * success the wrapper emits `agent:tool:result`; on throw it\n * emits `agent:tool:error` and rethrows.\n *\n * Schema validation is delegated to the SDK: when the model's tool-call\n * args fail to match `inputSchema`, the SDK reports a tool error to\n * the model without calling `execute`. Successful validation passes\n * the parsed value through to `execute`.\n *\n * @internal\n */\nexport async function buildVercelTools(\n resolved: ResolvedTool[],\n ctx: CraftContext | undefined,\n abortSignal: AbortSignal,\n dispatchIdentity?: AgentDispatchIdentity,\n principal?: Principal,\n): Promise<Record<string, unknown>> {\n if (resolved.length === 0)\n return Object.create(null) as Record<string, unknown>;\n const { tool } = await import(\"ai\");\n\n // Use a null-prototype object so dynamic tool names supplied at\n // resolution time can never mutate Object.prototype (e.g. a tool\n // accidentally named \"__proto__\" would otherwise be a vector for\n // prototype pollution).\n const out: Record<string, unknown> = Object.create(null);\n for (const r of resolved) {\n const guard = r.guard;\n const handler = r.handler;\n const baseCtx: FnHandlerContext = makeFnHandlerContext(\n r.name,\n abortSignal,\n principal,\n );\n out[r.name] = tool({\n description: r.description,\n inputSchema: toAiInputSchema(r.input) as Parameters<\n typeof tool\n >[0][\"inputSchema\"],\n execute: async (\n input: unknown,\n callOpts?: {\n abortSignal?: AbortSignal;\n toolCallId?: string;\n messages?: unknown[];\n },\n ) => {\n // Merge per-call options (the SDK passes its own abortSignal\n // and toolCallId per invocation) into the handler context so\n // a tool can react to per-step cancellation, not just the\n // session-wide signal captured at buildVercelTools time.\n const callCtx: FnHandlerContext = {\n ...baseCtx,\n abortSignal: callOpts?.abortSignal ?? baseCtx.abortSignal,\n };\n // The Vercel SDK passes a unique toolCallId per invocation;\n // synthesise one when absent so invoked → result events still\n // correlate (a shared empty-string id would alias every call).\n const toolCallId = callOpts?.toolCallId ?? randomUUID();\n const start = Date.now();\n\n if (ctx && dispatchIdentity) {\n ctx.emit(\n `route:${dispatchIdentity.routeId}:agent:tool:invoked` as EventName,\n {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n toolName: r.name,\n input,\n },\n );\n }\n\n try {\n if (guard) await guard(input, callCtx);\n const output = await handler(input, callCtx);\n if (ctx && dispatchIdentity) {\n ctx.emit(\n `route:${dispatchIdentity.routeId}:agent:tool:result` as EventName,\n {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n toolName: r.name,\n output,\n duration: Date.now() - start,\n },\n );\n }\n return output;\n } catch (err) {\n if (ctx && dispatchIdentity) {\n ctx.emit(\n `route:${dispatchIdentity.routeId}:agent:tool:error` as EventName,\n {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n toolName: r.name,\n error: err,\n duration: Date.now() - start,\n },\n );\n }\n throw err;\n }\n },\n });\n }\n return out;\n}\n\n/**\n * Construct the synthetic `FnHandlerContext` handed to a tool's guard\n * and handler during agent dispatch. Mirrors the shape `testFn`\n * provides: `logger`, `abortSignal`, optional `principal` (carried\n * over from the dispatching exchange so guards can authorise without\n * re-reading the source request), optional `correlationId` (not yet\n * populated by the runtime), and optional `checkpointId`\n * (durable-agents epic).\n *\n * Intentionally does not expose the framework `CraftContext` to tool\n * handlers; built-in tool builders that need to forward to a route\n * (e.g. `directTool`) capture the context at resolve time and thread\n * it through their own closure.\n */\nfunction makeFnHandlerContext(\n toolName: string,\n abortSignal: AbortSignal,\n principal: Principal | undefined,\n): FnHandlerContext {\n return {\n logger: frameworkLogger.child({ tool: toolName }),\n abortSignal,\n ...(principal ? { principal: freezePrincipal(principal) } : {}),\n };\n}\n\n/**\n * Build a deep-frozen snapshot of the dispatching exchange's\n * principal so a tool handler that bypasses the `ReadonlyPrincipal`\n * type cannot mutate it at runtime.\n *\n * Clones first because `exchange.principal` is mutable by design\n * (the routecraft pipeline lets a `.process()` step attach a custom\n * principal), so freezing the live object in place would break\n * downstream steps.\n *\n * `claims` is deep-cloned via `structuredClone` so that nested\n * claim objects (e.g. `claims.perms.write`) are not shared with the\n * original principal: shallow-cloning the top-level keys would let\n * a tool handler mutate a nested value and have it leak back into\n * the dispatching exchange's principal. After cloning, the entire\n * snapshot is recursively frozen so any runtime mutation attempt\n * (top-level field, array entry, nested claim object) throws.\n *\n * Runs once per dispatch in `buildVercelTools` and the same frozen\n * reference is reused for every tool invocation in that dispatch.\n *\n * @internal\n */\nfunction freezePrincipal(principal: Principal): Principal {\n // Capture the trusted-origin signal before cloning: the spread below\n // produces a fresh object that is not a member of the authenticity\n // WeakSet, so authenticity must be re-derived from the live principal.\n const wasAuthentic = isAuthentic(principal);\n const snapshot: Principal = { ...principal };\n if (snapshot.audience) snapshot.audience = [...snapshot.audience];\n if (snapshot.scopes) snapshot.scopes = [...snapshot.scopes];\n if (snapshot.roles) snapshot.roles = [...snapshot.roles];\n if (snapshot.claims) snapshot.claims = structuredClone(snapshot.claims);\n deepFreeze(snapshot);\n // Preserve authenticity across the snapshot: a snapshot of an authentic\n // principal is exactly as authentic as its source, and a snapshot of a\n // self-asserted (plain-object) principal must stay non-authentic so a\n // downstream authorize() still rejects it with RC5023. markAuthentic\n // returns a frozen member whose nested claims/arrays are the already\n // deep-frozen references from above.\n return wasAuthentic ? markAuthentic(snapshot) : snapshot;\n}\n\n/**\n * Recursively `Object.freeze` an object, walking arrays and plain\n * object values. Cycles are guarded via a visited set so a\n * self-referential principal won't blow the stack. Functions and\n * primitive values are left as-is.\n *\n * Skips `ArrayBuffer.isView` values (TypedArray, DataView, Buffer):\n * `Object.freeze` on a typed array with elements throws because the\n * indexed properties on the backing buffer cannot be made\n * non-configurable. A JWT claim that smuggles binary data (CBOR, an\n * encrypted key, raw bytes) would otherwise crash the dispatch.\n * `structuredClone` (used in `freezePrincipal` for `claims`) already\n * gives us an independent copy of any TypedArray, so the caller's\n * bytes are not shared with the snapshot; tool code that wants\n * write-protection on a binary claim should treat its read as opaque.\n *\n * @internal\n */\nfunction deepFreeze<T>(value: T, seen: WeakSet<object> = new WeakSet()): T {\n if (value === null || typeof value !== \"object\") return value;\n if (seen.has(value as object)) return value;\n if (ArrayBuffer.isView(value)) return value;\n seen.add(value as object);\n for (const key of Object.keys(value as object)) {\n const v = (value as Record<string, unknown>)[key];\n if (v !== null && typeof v === \"object\") deepFreeze(v, seen);\n }\n return Object.freeze(value);\n}\n","import {\n HeadersKeys,\n rcError,\n type CraftContext,\n type EventName,\n type Exchange,\n} from \"@routecraft/routecraft\";\nimport { callLlm, streamLlm } from \"../llm/providers/index.ts\";\nimport { resolvePrompt, resolveUserPromptDefault } from \"../llm/shared.ts\";\nimport type {\n LlmModelConfig,\n LlmResult,\n LlmToolCallSummary,\n} from \"../llm/types.ts\";\nimport { toAiOutputSpec } from \"../llm/structured-output.ts\";\nimport type { AgentDeltaListener } from \"./events.ts\";\nimport { buildVercelTools } from \"./tool-bridge.ts\";\nimport type { ResolvedTool } from \"./tools/selection.ts\";\nimport type {\n AgentOptions,\n AgentRegisteredOptions,\n AgentResult,\n} from \"./types.ts\";\n\n/**\n * Identity of the exchange driving the current dispatch. Used to emit\n * `route:<routeId>:agent:*` events on the context bus with stable\n * `exchangeId` / `correlationId` / `routeId` fields.\n *\n * @internal\n */\nexport interface AgentDispatchIdentity {\n exchangeId: string;\n correlationId: string;\n routeId: string;\n}\n\n/**\n * Extract the dispatch identity from an exchange. Returns `undefined`\n * for synthetic exchanges that have no route binding (mostly tests).\n *\n * @internal\n */\nexport function dispatchIdentityFrom(\n exchange: Exchange<unknown>,\n routeId: string | undefined,\n): AgentDispatchIdentity | undefined {\n if (routeId === undefined) return undefined;\n // The framework runtime sets `routecraft.correlation_id` on every\n // exchange that flows through a real route. Synthetic exchanges\n // (mostly tests) may lack it; fall back to the exchange id so the\n // emitted events still carry a stable, non-empty `correlationId`.\n const corr = exchange.headers[HeadersKeys.CORRELATION_ID];\n return {\n exchangeId: exchange.id,\n correlationId: typeof corr === \"string\" ? corr : exchange.id,\n routeId,\n };\n}\n\n/** Default sampling settings; aligned with the LLM destination defaults. */\nconst DEFAULT_TEMPERATURE = 0;\nconst DEFAULT_MAX_TOKENS = 1024;\nconst DEFAULT_MAX_TURNS = 20;\n\n/**\n * Resolved agent inputs ready for dispatch. Computed once by the\n * destination's `send()` method (after merging `defaultOptions`,\n * resolving the tool selection, and deriving the user prompt) and\n * passed to the session constructor.\n *\n * @internal\n */\nexport interface AgentSessionInput {\n /** Agent options after merging with `defaultOptions`. `model` resolved. */\n readonly options: AgentOptions | AgentRegisteredOptions;\n /** Provider config for the resolved model. */\n readonly modelConfig: LlmModelConfig;\n /** Provider-specific model name (after `parseProviderModel`). */\n readonly modelName: string;\n /** Resolved tool list (empty when the agent has no tools). */\n readonly tools: ResolvedTool[];\n /** Final user prompt for this dispatch. */\n readonly user: string;\n /** Final system prompt for this dispatch. */\n readonly system: string;\n /** Optional context reference passed to tool handlers. */\n readonly context: CraftContext | undefined;\n /**\n * Source exchange that triggered this dispatch. Forwarded to the\n * `validate` hook (`ctx.exchange`) so validators can correlate the\n * model's output with request-scoped state (headers, principal,\n * correlation id) when deciding whether to accept or retry.\n */\n readonly exchange: Exchange<unknown>;\n /**\n * Dispatch identity used to emit `route:<routeId>:agent:*` events\n * on the context bus. Undefined for synthetic exchanges with no\n * route binding.\n */\n readonly dispatchIdentity: AgentDispatchIdentity | undefined;\n}\n\n/**\n * Internal session that drives one agent dispatch. Encapsulates the\n * resolved tools + initial messages + provider config so the dispatch\n * path is structured around discrete units of work.\n *\n * Two execution paths are exposed:\n *\n * - {@link AgentSession.runUntilDone} calls `generateText` once with\n * the full tool list and lets the Vercel AI SDK handle the\n * multi-step tool-calling loop internally. Returns the consolidated\n * {@link AgentResult} when the loop terminates.\n * - {@link AgentSession.runStream} calls `streamText` with the same\n * setup, forwards every normalised event through the user-supplied\n * listener, and returns the same consolidated {@link AgentResult}\n * once the stream drains.\n *\n * Future hook (durable agents, #258): checkpoints the running messages\n * array between tool-call steps and lets a tool handler throw\n * `SuspendError` to pause the loop.\n *\n * @internal\n */\nexport class AgentSession {\n constructor(public readonly input: AgentSessionInput) {}\n\n /**\n * Run the synchronous tool-calling loop until the model emits a\n * final text response (or `stopWhen` fires). Returns the\n * consolidated `AgentResult`.\n *\n * When `validate` is set, runs the validation retry loop: every\n * call's result is fed to the validator, and a string return\n * triggers another model call with the validator message injected\n * as a corrective user turn. Retries share the `maxTurns` budget;\n * exhausting it with `validate` still rejecting fails the dispatch\n * with `RC5003`.\n */\n async runUntilDone(abortSignal: AbortSignal): Promise<AgentResult> {\n return this.runWithValidation(abortSignal, undefined);\n }\n\n /**\n * Run the streaming tool-calling loop. Same shape as\n * {@link AgentSession.runUntilDone}, but the dispatch goes through\n * `streamText`: each normalised token-level delta is forwarded to\n * `onDelta` while the loop runs, and the consolidated\n * {@link AgentResult} is returned once the stream drains. Coarse\n * decision events (tool-call, tool-result, finished,\n * error) flow on the context bus regardless of whether `onDelta`\n * is set; see `route:<id>:agent:*` events.\n *\n * `validate` retries follow the same loop as the sync path: each\n * retry restarts the stream with the prior history + the validator\n * message, and `onDelta` continues to fire across retries.\n *\n * Listener errors are caught and logged inside the LLM-provider\n * layer; they never abort the dispatch. Stream-level errors\n * (provider failure, network error) are surfaced both as an\n * `agent:error` context event AND propagate by rejecting this\n * promise, so callers handle failure exactly like the sync path.\n */\n async runStream(\n abortSignal: AbortSignal,\n onDelta: AgentDeltaListener,\n ): Promise<AgentResult> {\n return this.runWithValidation(abortSignal, onDelta);\n }\n\n /**\n * Shared dispatch path used by both `runUntilDone` and `runStream`.\n * Calls the model once, runs `validate` (when set), and either\n * returns the accepted result or loops with a corrective user\n * message until the validator accepts or `maxTurns` is exhausted.\n *\n * The cumulative `toolCalls` from every retry land on the final\n * `AgentResult.toolCalls`, so post-dispatch assertions like\n * \"must have called send_email\" see the agent's full tool history\n * (not just the last call's).\n *\n * @internal\n */\n private async runWithValidation(\n abortSignal: AbortSignal,\n onDelta: AgentDeltaListener | undefined,\n ): Promise<AgentResult> {\n const { options, exchange } = this.input;\n const validate = options.validate;\n const maxTurns = options.maxTurns ?? DEFAULT_MAX_TURNS;\n const prepared = await this.prepare(abortSignal);\n\n let turnsUsed = 0;\n let currentUser: string | unknown[] = this.input.user;\n let lastValidatorMsg: string | undefined;\n const accumulatedToolCalls: LlmToolCallSummary[] = [];\n\n try {\n while (true) {\n const remaining = maxTurns - turnsUsed;\n if (remaining <= 0) {\n throw rcError(\"RC5003\", undefined, {\n message: lastValidatorMsg\n ? `agent: maxTurns (${maxTurns}) reached while \"validate\" was still rejecting; last validator message: \"${lastValidatorMsg}\"`\n : `agent: maxTurns (${maxTurns}) reached.`,\n });\n }\n const result = await callOnce(\n prepared,\n currentUser,\n remaining,\n abortSignal,\n onDelta,\n );\n turnsUsed += result.stepsCount ?? 1;\n if (result.toolCalls && result.toolCalls.length > 0) {\n accumulatedToolCalls.push(...result.toolCalls);\n }\n if (!validate) {\n this.emitFinished(result);\n return toAgentResult(result, accumulatedToolCalls);\n }\n const verdict = await Promise.resolve(\n validate(toAgentResult(result, accumulatedToolCalls), {\n exchange,\n turnsUsed,\n }),\n );\n if (verdict === undefined || verdict === null) {\n this.emitFinished(result);\n return toAgentResult(result, accumulatedToolCalls);\n }\n if (typeof verdict !== \"string\" || verdict.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agent: \"validate\" returned a non-string, non-void value (${typeof verdict}). Return void to accept, a non-empty string to retry.`,\n });\n }\n lastValidatorMsg = verdict;\n currentUser = buildRetryPrompt(\n this.input.user,\n currentUser,\n result,\n verdict,\n );\n }\n } catch (err) {\n this.emitError(err);\n throw err;\n }\n }\n\n /**\n * Emit `route:<id>:agent:finished` on the context bus once the\n * dispatch returns a consolidated result. Carries finish reason\n * and total token usage so observability consumers can wire\n * dashboards / metrics / billing without subscribing to per-token\n * deltas.\n *\n * @internal\n */\n private emitFinished(result: LlmResult): void {\n const id = this.input.dispatchIdentity;\n const ctx = this.input.context;\n if (!id || !ctx) return;\n // Both runGenerate (sync) and runStreamGenerate (after awaiting\n // the SDK Promise) populate `result.finishReason` as a normalised\n // string. Falls back to \"unknown\" only when the provider didn't\n // report one.\n const finishReason = result.finishReason ?? \"unknown\";\n ctx.emit(`route:${id.routeId}:agent:finished` as EventName, {\n routeId: id.routeId,\n exchangeId: id.exchangeId,\n correlationId: id.correlationId,\n finishReason,\n ...(result.usage?.inputTokens !== undefined && {\n inputTokens: result.usage.inputTokens,\n }),\n ...(result.usage?.outputTokens !== undefined && {\n outputTokens: result.usage.outputTokens,\n }),\n ...(result.usage?.totalTokens !== undefined && {\n totalTokens: result.usage.totalTokens,\n }),\n });\n }\n\n /**\n * Emit `route:<id>:agent:error` on the context bus when the\n * dispatch promise rejects (provider failure, transport error, an\n * unhandled tool throw cascading through the SDK). The error\n * still propagates by rethrow; this just gives observability\n * subscribers a chance to record the failure without wrapping\n * every dispatch site.\n *\n * @internal\n */\n private emitError(err: unknown): void {\n const id = this.input.dispatchIdentity;\n const ctx = this.input.context;\n if (!id || !ctx) return;\n ctx.emit(`route:${id.routeId}:agent:error` as EventName, {\n routeId: id.routeId,\n exchangeId: id.exchangeId,\n correlationId: id.correlationId,\n error: err,\n });\n }\n\n /**\n * Shared setup invoked once per dispatch (not per validate retry):\n * builds the Vercel tool map and resolves the structured-output\n * spec. `stopWhen` is built per call inside the validation loop\n * so each call gets the *remaining* turn budget rather than the\n * full `maxTurns`.\n *\n * @internal\n */\n private async prepare(abortSignal: AbortSignal): Promise<{\n modelConfig: LlmModelConfig;\n modelName: string;\n system: string;\n output?: unknown;\n vercelTools: Record<string, unknown>;\n }> {\n const {\n options,\n modelConfig,\n modelName,\n tools,\n system,\n context,\n exchange,\n dispatchIdentity,\n } = this.input;\n const vercelTools = await buildVercelTools(\n tools,\n context,\n abortSignal,\n dispatchIdentity,\n exchange.principal,\n );\n const base = { modelConfig, modelName, system, vercelTools };\n return options.output !== undefined\n ? { ...base, output: toAiOutputSpec(options.output) }\n : base;\n }\n}\n\ninterface PreparedSession {\n modelConfig: LlmModelConfig;\n modelName: string;\n system: string;\n output?: unknown;\n vercelTools: Record<string, unknown>;\n}\n\n/**\n * One model call. Builds `stopWhen: stepCountIs(remainingTurns)` so a\n * later validate-retry consumes turns from the same shared budget,\n * then dispatches via `callLlm` (sync) or `streamLlm` (when an\n * `onDelta` listener is attached).\n *\n * @internal\n */\nasync function callOnce(\n prepared: PreparedSession,\n user: string | unknown[],\n remainingTurns: number,\n abortSignal: AbortSignal,\n onDelta: AgentDeltaListener | undefined,\n): Promise<LlmResult> {\n const toolExtras =\n Object.keys(prepared.vercelTools).length > 0\n ? {\n tools: prepared.vercelTools,\n stopWhen: await buildStopWhen(remainingTurns),\n }\n : {};\n const base = {\n config: prepared.modelConfig,\n modelId: prepared.modelName,\n options: {\n temperature: DEFAULT_TEMPERATURE,\n maxTokens: DEFAULT_MAX_TOKENS,\n },\n system: prepared.system,\n user,\n abortSignal,\n ...(prepared.output !== undefined ? { output: prepared.output } : {}),\n ...toolExtras,\n };\n return onDelta ? streamLlm({ ...base, onDelta }) : callLlm(base);\n}\n\nasync function buildStopWhen(maxTurns: number): Promise<unknown> {\n const { stepCountIs } = await import(\"ai\");\n return stepCountIs(maxTurns);\n}\n\n/**\n * Build the prompt array for a `validate`-triggered retry.\n *\n * Concatenates: prior user-side messages (the initial user prompt\n * promoted to a `{ role: \"user\" }` message on the first retry, or\n * the array carried over from a prior retry), the SDK's response\n * messages from the just-finished call (assistant text + any tool\n * messages), and a fresh user-role corrective `\"Validator: <msg>\"`.\n *\n * @internal\n */\nfunction buildRetryPrompt(\n initialUser: string,\n currentUser: string | unknown[],\n lastResult: LlmResult,\n validatorMsg: string,\n): unknown[] {\n const userMsgs: unknown[] =\n typeof currentUser === \"string\"\n ? [{ role: \"user\", content: initialUser }]\n : currentUser;\n const responseMessages = lastResult.responseMessages ?? [];\n return [\n ...userMsgs,\n ...responseMessages,\n { role: \"user\", content: `Validator: ${validatorMsg}` },\n ];\n}\n\nfunction toAgentResult(\n result: LlmResult,\n accumulatedToolCalls: LlmToolCallSummary[],\n): AgentResult {\n const out: AgentResult = { text: result.text };\n if (result.output !== undefined) out.output = result.output;\n if (result.reasoning !== undefined) out.reasoning = result.reasoning;\n if (result.usage) out.usage = result.usage;\n // Cumulative across all validate retries so post-dispatch assertions\n // like \"must have called X\" see the agent's full tool history rather\n // than only the last call's.\n if (accumulatedToolCalls.length > 0) {\n out.toolCalls = accumulatedToolCalls;\n }\n return out;\n}\n\n/**\n * Build the user prompt for an agent dispatch from the merged options\n * and the incoming exchange. Uses the agent's `user:` resolver when\n * present, otherwise derives a default from `exchange.body`\n * (matches the existing LLM destination behaviour).\n *\n * @internal\n */\nexport function buildUserPrompt(\n options: AgentOptions | AgentRegisteredOptions,\n exchange: Exchange<unknown>,\n): string {\n return options.user !== undefined\n ? resolvePrompt(options.user, exchange)\n : resolveUserPromptDefault(exchange);\n}\n","import type { AgentDefaultOptions, AgentRegisteredOptions } from \"./types.ts\";\n\n/**\n * Store key for the registry of agents installed by `agentPlugin`. Resolved\n * at destination dispatch time when an agent is referenced by name via\n * `agent(\"name\")`.\n * @internal\n */\nexport const ADAPTER_AGENT_REGISTRY = Symbol.for(\n \"routecraft.adapter.agent.registry\",\n);\n\n/**\n * Store key for the context-level agent defaults installed via\n * `agentPlugin({ defaultOptions: {...} })`. Agents that omit a field\n * inherit it from here at dispatch time.\n *\n * Mirrors the `llmPlugin({ defaultOptions })` pattern so the same merge\n * model carries across.\n * @internal\n */\nexport const ADAPTER_AGENT_DEFAULT_OPTIONS = Symbol.for(\n \"routecraft.adapter.agent.default-options\",\n);\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [ADAPTER_AGENT_REGISTRY]: Map<string, AgentRegisteredOptions>;\n [ADAPTER_AGENT_DEFAULT_OPTIONS]: AgentDefaultOptions;\n }\n}\n","import type { ResolveKey } from \"@routecraft/routecraft\";\n\n/**\n * Store key for the registry of skills installed by\n * `agentPlugin({ skills })`. Resolved at agent dispatch time so an\n * agent that lists `skills: [\"X\"]` gets the corresponding skill\n * content concatenated into its system prompt.\n * @internal\n */\nexport const ADAPTER_SKILL_REGISTRY = Symbol.for(\n \"routecraft.adapter.skill.registry\",\n);\n\n/**\n * A reusable, portable instruction set that an agent loads into its\n * system prompt at dispatch time. The full content is injected\n * verbatim, not exposed as a tool the agent can choose to invoke; this\n * matches the Claude subagent skills semantic (\"inject the skill\n * content, do not make it tool-callable\").\n *\n * Skills are framework-portable: any provider can consume one because\n * a skill is just text. Provider-specific hosted skills (e.g. the\n * Anthropic hosted-skills feature surfaced through `@ai-sdk/anthropic`)\n * are out of scope for this primitive and will land separately.\n */\nexport interface Skill {\n /** Unique skill name. Matches the registry key and the filename when loaded via `skills(path)`. */\n name: string;\n /** Human-readable description. Surfaces in observability and in error messages when a skill lookup fails. */\n description: string;\n /** Full skill content. Concatenated into the system prompt of every agent that references the skill by name. */\n content: string;\n}\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [ADAPTER_SKILL_REGISTRY]: Map<string, Skill>;\n }\n}\n\n/**\n * Registry for configured skills.\n *\n * Keys are skill names (matching the record keys in\n * `agentPlugin({ skills })`). Populate via declaration merging to\n * narrow `AgentOptions.skills` and `AgentRegisteredOptions.skills`\n * entries to the set of registered skill names.\n *\n * @example\n * ```typescript\n * declare module \"@routecraft/ai\" {\n * interface SkillRegistry {\n * \"web-search\": true;\n * \"cite-sources\": true;\n * }\n * }\n * ```\n */\n// biome-ignore lint/suspicious/noEmptyInterface: marker interface populated via declaration merging\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- Marker interface, populated via declaration merging\nexport interface SkillRegistry {}\n\n/**\n * Resolved skill name type. When `SkillRegistry` is populated,\n * constrains to the union of declared names. Falls back to `string`\n * when the registry is empty.\n */\nexport type RegisteredSkillName = ResolveKey<SkillRegistry>;\n","import {\n getExchangeContext,\n getExchangeRoute,\n rcError,\n type CraftContext,\n type Destination,\n type Exchange,\n type Principal,\n} from \"@routecraft/routecraft\";\nimport { resolveModel, resolvePrompt } from \"../llm/shared.ts\";\nimport {\n AgentSession,\n buildUserPrompt,\n dispatchIdentityFrom,\n} from \"./session.ts\";\nimport {\n ADAPTER_AGENT_DEFAULT_OPTIONS,\n ADAPTER_AGENT_REGISTRY,\n} from \"./store.ts\";\nimport { ADAPTER_SKILL_REGISTRY, type Skill } from \"../skill/types.ts\";\nimport type { AgentDeltaListener } from \"./events.ts\";\nimport type { ResolvedTool } from \"./tools/selection.ts\";\nimport type {\n AgentDefaultOptions,\n AgentOptions,\n AgentPrincipalRenderer,\n AgentRegisteredOptions,\n AgentResult,\n} from \"./types.ts\";\n\nconst AGENT_REGISTRY_STORE_DESCRIPTION =\n ADAPTER_AGENT_REGISTRY.description ?? \"routecraft.adapter.agent.registry\";\n\n/**\n * Per-call overrides accepted by the by-name `agent(\"name\", { ... })`\n * factory. Constrained to fields that are inherently request-scoped\n * (the SSE / WebSocket / TUI consumer for `onDelta` is not known at\n * registration time). Anything else (model, system, tools, output)\n * stays authoritative on the registered options.\n */\nexport interface AgentByNameOverrides {\n /**\n * Per-request token-delta listener. Mirrors `AgentOptions.onDelta`\n * but lives at the call site so each dispatch can stream into its\n * own consumer without cross-talk.\n */\n onDelta?: AgentDeltaListener;\n}\n\n/**\n * Discriminated state: inline options or a registry name.\n * @internal\n */\nexport type AgentBinding =\n | { kind: \"inline\"; options: AgentOptions }\n | {\n kind: \"by-name\";\n name: string;\n perCall?: AgentByNameOverrides;\n };\n\n/**\n * Agent destination adapter. Resolves agent options (inline or\n * registered), merges them with `agentPlugin({ defaultOptions })`,\n * resolves the agent's tool selection against the live context, and\n * dispatches the tool-calling loop via {@link AgentSession}. Replaces\n * the exchange body with `AgentResult { text, output?, reasoning?, usage? }`.\n *\n * Resolution: when constructed inline, uses options directly. When\n * constructed by name, resolves the registered agent from the context\n * store (`ADAPTER_AGENT_REGISTRY`) at dispatch time, throwing a clear\n * error if the name is unknown.\n */\nexport class AgentDestinationAdapter implements Destination<\n unknown,\n AgentResult\n> {\n readonly adapterId = \"routecraft.adapter.agent\";\n\n constructor(public readonly binding: AgentBinding) {}\n\n async send(exchange: Exchange<unknown>): Promise<AgentResult> {\n const context = getExchangeContext(exchange);\n const baseOptions = this.resolveOptions(context);\n const merged = mergeWithDefaults(baseOptions, context);\n\n if (merged.model === undefined) {\n throw rcError(\"RC5003\", undefined, {\n message:\n `Agent: no \"model\" supplied and no agentPlugin({ defaultOptions: { model } }) is set on this context. ` +\n `Specify \"model\" on the agent or set a context-level default.`,\n });\n }\n\n const { config, modelName } = resolveModel(merged.model, context);\n const tools = resolveAgentTools(merged, context);\n const user = buildUserPrompt(merged, exchange);\n // System accepts the same string-or-function shape as `llm({ system })`,\n // so resolve it against the exchange here. The session then receives a\n // plain string, matching what the provider layer expects.\n const baseSystem = resolvePrompt(merged.system, exchange);\n // Mirror the construction-time check (validateAgentOptions) so a\n // function-form `system` resolver can't silently drop the prompt at\n // dispatch by returning an empty string.\n if (baseSystem.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message:\n `Agent: \"system\" resolved to an empty string. ` +\n `When \"system\" is a function, it must return a non-empty string for the incoming exchange.`,\n });\n }\n const withSkills = appendSkillsToSystem(baseSystem, merged.skills, context);\n // Caller identity is appended last (after skills) so the author's own\n // prompt and any skill content frame the model first, with the\n // request-scoped \"who am I serving\" footer closest to the user turn.\n const system = appendPrincipalToSystem(\n withSkills,\n merged.principal,\n exchange.principal,\n exchange,\n );\n\n const route = getExchangeRoute(exchange);\n const dispatchIdentity = dispatchIdentityFrom(\n exchange,\n route?.definition.id,\n );\n\n const session = new AgentSession({\n options: merged,\n modelConfig: config,\n modelName,\n tools,\n user,\n system,\n context,\n exchange,\n dispatchIdentity,\n });\n\n // Thread the route's abort signal through so the agent dispatch\n // (LLM call + in-flight tool handlers) is cancelled when the\n // route or context shuts down. Falls back to a never-firing\n // signal when the exchange has no route binding (rare; mostly\n // synthetic exchanges in tests).\n const abortSignal = route?.signal ?? new AbortController().signal;\n\n // Streaming is selected by the presence of `onDelta` on the\n // merged options or as a per-call override at the by-name call\n // site. Per-call wins because it's request-scoped (e.g. a\n // specific SSE channel for THIS dispatch).\n const onDelta =\n this.binding.kind === \"by-name\"\n ? (this.binding.perCall?.onDelta ?? merged.onDelta)\n : merged.onDelta;\n // The consolidated AgentResult is returned in both paths, so\n // downstream pipeline ops are unaffected by the choice.\n if (onDelta !== undefined) {\n return await session.runStream(abortSignal, onDelta);\n }\n return await session.runUntilDone(abortSignal);\n }\n\n /** Pull the agent options for this dispatch, either inline or from the registry. */\n private resolveOptions(\n context: CraftContext | undefined,\n ): AgentOptions | AgentRegisteredOptions {\n if (this.binding.kind === \"inline\") return this.binding.options;\n\n if (!context) {\n throw rcError(\"RC5004\", undefined, {\n message:\n `Agent \"${this.binding.name}\" requires a context to resolve. ` +\n `Ensure the exchange has context (e.g. from a route) so the ` +\n `\"${AGENT_REGISTRY_STORE_DESCRIPTION}\" store can be read.`,\n });\n }\n const registry = context.getStore(\n ADAPTER_AGENT_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, AgentRegisteredOptions> | undefined;\n if (!registry) {\n throw rcError(\"RC5004\", undefined, {\n message:\n `Agent \"${this.binding.name}\" not found: no agents registered. ` +\n `Add agentPlugin({ agents: { \"${this.binding.name}\": {...} } }) to your config.`,\n });\n }\n const found = registry.get(this.binding.name);\n if (!found) {\n const known = Array.from(registry.keys()).join(\", \") || \"<none>\";\n throw rcError(\"RC5004\", undefined, {\n message: `Agent \"${this.binding.name}\" not found in registry. Known agents: ${known}.`,\n });\n }\n return found;\n }\n\n /**\n * Extract metadata from the agent result for observability. Includes the\n * resolved model (as string) and token usage when reported.\n */\n getMetadata(result: unknown): Record<string, unknown> {\n const r = result as AgentResult;\n const metadata: Record<string, unknown> = {};\n if (this.binding.kind === \"by-name\") metadata[\"agent\"] = this.binding.name;\n if (this.binding.kind === \"inline\") {\n const model = this.binding.options.model;\n if (typeof model === \"string\") metadata[\"model\"] = model;\n }\n if (r.usage?.inputTokens !== undefined) {\n metadata[\"inputTokens\"] = r.usage.inputTokens;\n }\n if (r.usage?.outputTokens !== undefined) {\n metadata[\"outputTokens\"] = r.usage.outputTokens;\n }\n return metadata;\n }\n}\n\n/**\n * Merge per-agent options with the context-level defaults registered\n * via `agentPlugin({ defaultOptions: {...} })`. Per-agent values win\n * per key; missing fields fall back to defaults (mirrors the LLM\n * destination's `mergedOptions` pattern).\n *\n * @internal\n */\nfunction mergeWithDefaults(\n base: AgentOptions | AgentRegisteredOptions,\n context: CraftContext | undefined,\n): AgentOptions | AgentRegisteredOptions {\n const defaults = context?.getStore(\n ADAPTER_AGENT_DEFAULT_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as AgentDefaultOptions | undefined;\n if (!defaults) return base;\n const out = { ...base } as AgentOptions | AgentRegisteredOptions;\n if (out.model === undefined && defaults.model !== undefined) {\n out.model = defaults.model;\n }\n if (out.tools === undefined && defaults.tools !== undefined) {\n out.tools = defaults.tools;\n }\n if (out.maxTurns === undefined && defaults.maxTurns !== undefined) {\n out.maxTurns = defaults.maxTurns;\n }\n if (out.principal === undefined && defaults.principal !== undefined) {\n out.principal = defaults.principal;\n }\n return out;\n}\n\n/**\n * Resolve the agent's `tools` selection against the live context. The\n * selection is the `ToolSelection` object built via `tools([...])`;\n * resolution walks the fn registry and direct registry to produce the\n * final `ResolvedTool[]` the runtime hands to the LLM.\n *\n * Returns an empty array when the agent has no tools field set\n * (and no context-default tools were inherited).\n *\n * @internal\n */\nfunction resolveAgentTools(\n options: AgentOptions | AgentRegisteredOptions,\n context: CraftContext | undefined,\n): ResolvedTool[] {\n if (options.tools === undefined) return [];\n if (!context) {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: cannot resolve tools without a CraftContext.`,\n });\n }\n return options.tools.resolve(context);\n}\n\n/**\n * Build the final system prompt by concatenating the resolved skill\n * content (when the agent declared `skills: [\"name\", ...]`) onto the\n * agent's own system prompt. Each skill is wrapped in a heading so the\n * model can see the skill name and its boundary in context.\n *\n * Throws `RC5003` when a referenced skill name is not registered,\n * when an agent declares `skills` but no skills are registered at all,\n * or when the agent has no live context to look up skills against.\n *\n * @internal\n */\nfunction appendSkillsToSystem(\n baseSystem: string,\n skills: string[] | undefined,\n context: CraftContext | undefined,\n): string {\n if (!skills || skills.length === 0) return baseSystem;\n if (!context) {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: cannot resolve \"skills\" without a CraftContext.`,\n });\n }\n const registry = context.getStore(\n ADAPTER_SKILL_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, Skill> | undefined;\n if (!registry || registry.size === 0) {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: declared \"skills\" (${skills.map((s) => `\"${s}\"`).join(\", \")}) but no skills are registered in this context. Install agentPlugin({ skills }) with the relevant entries.`,\n });\n }\n const parts: string[] = [baseSystem];\n for (const name of skills) {\n const skill = registry.get(name);\n if (!skill) {\n const known = [...registry.keys()].sort();\n throw rcError(\"RC5003\", undefined, {\n message:\n `Agent: unknown skill \"${name}\". ` +\n (known.length > 0\n ? `Known skill names: ${known.map((k) => `\"${k}\"`).join(\", \")}.`\n : `No skills are registered in this context.`),\n });\n }\n parts.push(`\\n\\n## Skill: ${skill.name}\\n\\n${skill.content}`);\n }\n return parts.join(\"\");\n}\n\n/**\n * Append a `## Caller` section describing the request's principal. Opt-in:\n * returns the base prompt unchanged when `principal` is omitted or `false`,\n * so existing agents are unaffected. When `principal` is a function it\n * renders the section itself (an empty return appends nothing); otherwise\n * the built-in {@link formatCallerSection} block is used.\n *\n * The section is informational context for the model (who triggered the\n * request), never an authorization gate; `.authorize()` and guards remain\n * the only enforcement points.\n *\n * @internal\n */\nfunction appendPrincipalToSystem(\n baseSystem: string,\n principalOption: boolean | AgentPrincipalRenderer | undefined,\n principal: Principal | undefined,\n exchange: Exchange<unknown>,\n): string {\n if (principalOption === undefined || principalOption === false) {\n return baseSystem;\n }\n const section =\n typeof principalOption === \"function\"\n ? principalOption(principal, exchange)\n : formatCallerSection(principal);\n if (section.trim() === \"\") return baseSystem;\n return `${baseSystem}\\n\\n${section}`;\n}\n\n/**\n * Render the built-in `## Caller` block from a principal. Surfaces only\n * the loggable identity fields (`name`, `email`, `subject`) and `roles`\n * (see `.standards/security.md` § 3); scopes, `claims`, `userinfoClaims`,\n * and the bearer token are never included. Absent fields are omitted\n * rather than printed as `undefined`. When no principal is present the\n * block states the request is unauthenticated so the model does not\n * invent an identity.\n *\n * @internal\n */\nfunction formatCallerSection(principal: Principal | undefined): string {\n if (!principal) {\n return (\n \"## Caller\\n\\n\" +\n \"The current request is not authenticated. No verified user identity \" +\n \"is available. Do not assume, infer, or invent the caller's name, \" +\n \"email, or permissions.\"\n );\n }\n const lines: string[] = [];\n if (principal.name) lines.push(`- Name: ${oneLine(principal.name)}`);\n if (principal.email) lines.push(`- Email: ${oneLine(principal.email)}`);\n lines.push(`- Subject: ${oneLine(principal.subject)}`);\n const roles = principal.roles\n ?.map((r) => oneLine(r))\n .filter((r) => r.length > 0);\n if (roles && roles.length > 0) {\n lines.push(`- Roles: ${roles.join(\", \")}`);\n }\n return `## Caller\\n\\nThe current request is authenticated.\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Collapse newlines (and surrounding whitespace) in an interpolated\n * identity field. Principal strings like `name` / `email` are\n * integrity-verified (they reached us unmodified from the IdP) but may be\n * subject-controlled at self-service IdPs; collapsing newlines pins a\n * value to its `- Label:` line so it cannot break out of the list item or\n * forge a `##` heading in the trusted system channel.\n *\n * @internal\n */\nfunction oneLine(value: string): string {\n return value.replace(/\\s*[\\r\\n]+\\s*/g, \" \").trim();\n}\n","import type { FnEntry } from \"../agent/tools/types.ts\";\n\n/**\n * Store key for the registry of fns installed by `agentPlugin`. Read by\n * the agent tool loop at dispatch time (follow-up story).\n *\n * Entries are either eagerly authored `FnOptions` or deferred\n * descriptors emitted by `directTool`. The agent runtime resolves\n * deferred entries on first dispatch when all registries are live.\n * @internal\n */\nexport const ADAPTER_FN_REGISTRY = Symbol.for(\"routecraft.adapter.fn.registry\");\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [ADAPTER_FN_REGISTRY]: Map<string, FnEntry>;\n }\n}\n","import {\n isRoutecraftError,\n loadOptionalPeer,\n rcError,\n type CraftContext,\n} from \"@routecraft/routecraft\";\nimport { buildAuthHeaders } from \"./build-auth-headers.ts\";\nimport { extractContent } from \"./extract-content.ts\";\nimport {\n ADAPTER_MCP_CLIENT_SERVERS,\n MCP_STDIO_MANAGERS,\n type McpClientAuthOptions,\n type McpClientHttpConfig,\n} from \"./types.ts\";\n\n/**\n * Dispatch an MCP tool call against a server registered via\n * `mcpPlugin({ clients })`. Used by both the `mcp(...)` destination\n * adapter and the agent `tools([...])` resolver so the same transport\n * logic backs both call sites.\n *\n * - For stdio clients (`MCP_STDIO_MANAGERS.get(serverId)`), delegates\n * to the long-lived `StdioClientManager.callTool`.\n * - For HTTP clients (`ADAPTER_MCP_CLIENT_SERVERS.get(serverId).url`),\n * opens a single MCP SDK client connection per call, dispatches,\n * and closes. The agent path is per-tool-call so latency dominates\n * over connection setup; if that becomes a problem the http\n * client cache in `mcpPlugin` can be promoted to a context store\n * in a follow-up.\n *\n * Throws `RC5003` when the server is not registered, when a stdio\n * server is registered but its manager is absent (mcpPlugin\n * teardown raced ahead, etc.), or when an HTTP call fails.\n *\n * @internal\n */\nexport async function dispatchMcpCall(\n ctx: CraftContext,\n serverId: string,\n toolName: string,\n args: Record<string, unknown>,\n): Promise<unknown> {\n const stdioManagers = ctx.getStore(MCP_STDIO_MANAGERS);\n const manager = stdioManagers?.get(serverId);\n if (manager) {\n try {\n return await manager.callTool(toolName, args);\n } catch (cause) {\n if (isRoutecraftError(cause)) throw cause;\n throw rcError(\"RC5003\", cause, {\n message: `mcp dispatch: stdio call to \"${serverId}:${toolName}\" failed.`,\n });\n }\n }\n\n const servers = ctx.getStore(ADAPTER_MCP_CLIENT_SERVERS);\n const config = servers?.get(serverId);\n if (!config) {\n throw rcError(\"RC5003\", undefined, {\n message: `mcp dispatch: server \"${serverId}\" is not registered. Register it via defineConfig.mcp / mcpPlugin({ clients }).`,\n });\n }\n if (typeof config !== \"object\" || config === null) {\n throw rcError(\"RC5003\", undefined, {\n message: `mcp dispatch: server \"${serverId}\" config is a string shorthand and cannot be called directly. Use a full HTTP config with a url.`,\n });\n }\n if (\n \"transport\" in config &&\n (config as { transport: string }).transport === \"stdio\"\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `mcp dispatch: stdio server \"${serverId}\" is registered but its client is not running. Ensure mcpPlugin started successfully.`,\n });\n }\n const http = config as McpClientHttpConfig;\n if (typeof http.url !== \"string\" || http.url.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `mcp dispatch: server \"${serverId}\" has no url. Cannot dispatch over HTTP.`,\n });\n }\n return callRemoteTool(http.url, toolName, args, http.auth);\n}\n\n/**\n * Open a one-shot MCP SDK client over Streamable HTTP, dispatch the\n * tool, then close. Used by `dispatchMcpCall` for the HTTP path and\n * by `McpDestinationAdapter` for inline-URL routes that bypass the\n * registry. Centralised here so transport setup, auth-header\n * building, and content extraction stay in one place.\n *\n * @internal\n */\nexport async function callRemoteTool(\n serverUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n auth?: McpClientAuthOptions,\n): Promise<unknown> {\n const clientModule = (await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/client/index.js\"),\n {\n adapterName: \"mcp (http client)\",\n packageName: \"@modelcontextprotocol/sdk\",\n },\n )) as unknown as {\n Client: new (\n info: { name: string; version: string },\n options?: { capabilities?: Record<string, unknown> },\n ) => unknown;\n };\n const transportModule = (await loadOptionalPeer(\n () => import(\"@modelcontextprotocol/sdk/client/streamableHttp.js\"),\n {\n adapterName: \"mcp (http client)\",\n packageName: \"@modelcontextprotocol/sdk\",\n },\n )) as unknown as {\n StreamableHTTPClientTransport: new (\n url: URL,\n options?: {\n sessionId?: string;\n requestInit?: { headers?: Record<string, string> };\n },\n ) => unknown;\n };\n\n let transport: unknown;\n let client: unknown;\n try {\n const url = new URL(serverUrl);\n const headers = await buildAuthHeaders(auth);\n const transportOptions = headers ? { requestInit: { headers } } : undefined;\n transport = new transportModule.StreamableHTTPClientTransport(\n url,\n transportOptions,\n );\n client = new clientModule.Client(\n { name: \"routecraft-mcp-client\", version: \"1.0.0\" },\n { capabilities: {} },\n );\n await (client as unknown as { connect(t: unknown): Promise<void> }).connect(\n transport,\n );\n const callTool = (\n client as unknown as {\n callTool(params: {\n name: string;\n arguments?: Record<string, unknown>;\n }): Promise<{ content?: Array<{ type: string; text?: string }> }>;\n }\n ).callTool;\n const response = await callTool.call(client, {\n name: toolName,\n arguments: args,\n });\n return extractContent(response);\n } catch (cause) {\n // Wrap SDK / transport / network errors as RC5003 with the original\n // attached as `cause`, matching the Error and Logging Policy\n // (`level 1`: throw rcError with the right framework code so the\n // dispatch boundary always surfaces an MCP-tagged error rather than\n // a bare TypeError or SDK-specific class). `RoutecraftError`s\n // thrown by called helpers pass through unchanged so caller-facing\n // error codes are preserved.\n if (isRoutecraftError(cause)) throw cause;\n throw rcError(\"RC5003\", cause, {\n message: `mcp dispatch: failed to call tool \"${toolName}\" at \"${serverUrl}\".`,\n });\n } finally {\n // `client` and `transport` may be undefined when an early step\n // inside the try block (URL parsing, auth header building,\n // transport / client construction) threw before they were\n // assigned. Guard each cleanup with a truthy check.\n if (client) {\n const clientCleanup = client as {\n close?: () => void | Promise<void>;\n disconnect?: () => void | Promise<void>;\n };\n const closeOrDisconnect = clientCleanup.close ?? clientCleanup.disconnect;\n if (typeof closeOrDisconnect === \"function\") {\n try {\n await Promise.resolve(closeOrDisconnect.call(client));\n } catch {\n // Ignore cleanup errors so original error propagates\n }\n }\n }\n if (transport) {\n const transportCleanup = transport as {\n close?: () => void | Promise<void>;\n destroy?: () => void;\n };\n const closeOrDestroy = transportCleanup.close ?? transportCleanup.destroy;\n if (typeof closeOrDestroy === \"function\") {\n try {\n await Promise.resolve(closeOrDestroy.call(transport));\n } catch {\n // Ignore cleanup errors so original error propagates\n }\n }\n }\n }\n}\n","import type { CraftContext, Tag } from \"@routecraft/routecraft\";\nimport type { FnOptions } from \"../../fn/types.ts\";\n\n/**\n * Discriminator value for {@link DeferredFn}. Plain symbol so a\n * `typeof entry === \"object\" && BRAND in entry` check is enough for\n * runtime detection without leaking implementation details.\n *\n * @internal\n */\nexport const DEFERRED_FN_BRAND = Symbol.for(\"routecraft.ai.fn.deferred\");\n\n/**\n * The kinds of underlying things `tools(...)` can wrap as a deferred\n * fn. Today only `directTool(routeId)` produces a deferred entry;\n * MCP tools are resolved directly from `MCP_TOOL_REGISTRY` at\n * selection time, and sub-agent tools are not yet supported. The\n * kind is purely informational at runtime (used for error messages\n * and the prefix-auto-resolution path in `tools()`).\n */\nexport type DeferredFnKind = \"direct\";\n\n/**\n * A fn that cannot be fully constructed at config-write time because it\n * depends on registries (direct route metadata, agent registrations,\n * MCP tool descriptors) that aren't populated until later in the\n * context lifecycle.\n *\n * Created by the builder helpers; the `agentPlugin` stores deferred\n * entries unmodified, and the agent runtime calls `.resolve(ctx, id)`\n * just before building the LLM tool list, when all registries are live.\n */\nexport interface DeferredFn {\n readonly [DEFERRED_FN_BRAND]: true;\n /** Underlying source kind. Surfaces in error messages. */\n readonly kind: DeferredFnKind;\n /**\n * The underlying registered id this wrapper targets (route id for\n * `direct`, agent id for `agent`, `<server>:<tool>` for `mcp`). Used\n * by the `tools()` resolver for tag-selector dedup so a fn-registry\n * wrapper supersedes the same route surfaced via the prefix\n * convention.\n */\n readonly targetId: string;\n /**\n * Tags supplied as an explicit override at builder time (e.g.\n * `directTool(routeId, { tags: [...] })`). When present these take\n * precedence over the underlying registry's tags for tag-selector\n * matching, so the user's override actually drives selection.\n * Undefined when no override was supplied; the resolver then peeks\n * the underlying registry's tags for the match decision.\n */\n readonly overrideTags?: readonly Tag[];\n /**\n * Resolve to a concrete `FnOptions`. Throws `RC5003` with a clear\n * message if the underlying registry entry is missing or incomplete.\n *\n * @param ctx - Live context (registries populated)\n * @param fnId - The fn id this descriptor was registered as (used in\n * error messages so the user can find the offending config entry)\n */\n readonly resolve: (ctx: CraftContext, fnId: string) => FnOptions;\n}\n\n/**\n * Type guard. Returns true when the value is a deferred fn descriptor\n * emitted by `directTool`.\n *\n * @internal\n */\nexport function isDeferredFn(value: unknown): value is DeferredFn {\n return (\n typeof value === \"object\" &&\n value !== null &&\n DEFERRED_FN_BRAND in value &&\n (value as { [DEFERRED_FN_BRAND]: unknown })[DEFERRED_FN_BRAND] === true\n );\n}\n\n/**\n * What the fn registry actually holds. Eagerly authored fns are stored\n * as `FnOptions`; entries from `directTool` are stored as `DeferredFn`\n * and resolved on first agent dispatch.\n */\nexport type FnEntry = FnOptions | DeferredFn;\n","import {\n ADAPTER_DIRECT_REGISTRY,\n DefaultExchange,\n HeadersKeys,\n getDirectChannel,\n isAuthentic,\n markAuthentic,\n rcError,\n sanitizeEndpoint,\n type CraftContext,\n type DirectRouteMetadata,\n type Exchange,\n type KnownTag,\n type Principal,\n type Tag,\n} from \"@routecraft/routecraft\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { randomUUID } from \"node:crypto\";\nimport type {\n FnHandlerContext,\n FnOptions,\n ReadonlyPrincipal,\n} from \"../../fn/types.ts\";\nimport { DEFERRED_FN_BRAND, type DeferredFn } from \"./types.ts\";\n\n/**\n * Re-hydrate a frozen `ReadonlyPrincipal` (as exposed on\n * `FnHandlerContext`) into a fresh mutable `Principal` so it can be\n * attached to a downstream `DefaultExchange`.\n *\n * Arrays are spread-cloned and `claims` is deep-cloned via\n * `structuredClone` so the downstream principal shares no references\n * with the agent's frozen snapshot.\n *\n * Authenticity is forwarded only when the principal that triggered the\n * agent was itself authentic: `isAuthentic(rp)` is true for a JWT /\n * `authenticate()` identity (the tool-bridge preserves the trusted-origin\n * signal on the frozen snapshot) and false for a self-asserted plain-object\n * principal. Re-branding restores the brand the spread strips for the\n * legitimate case; leaving it unbranded for the self-asserted case lets the\n * downstream route's `authorize()` correctly reject it with RC5023, instead\n * of laundering an unverified caller into a trusted one across the\n * agent -> tool boundary. The agent layer never mints or escalates: it only\n * forwards the identity it was handed.\n */\nfunction cloneFrozenPrincipal(rp: ReadonlyPrincipal): Principal {\n const out: Principal = { ...rp } as Principal;\n if (rp.audience) out.audience = [...rp.audience];\n if (rp.scopes) out.scopes = [...rp.scopes];\n if (rp.roles) out.roles = [...rp.roles];\n if (rp.claims)\n out.claims = structuredClone(rp.claims) as Record<string, unknown>;\n return isAuthentic(rp) ? markAuthentic(out) : out;\n}\n\n/**\n * JSON Schema describing an empty object. Closed for additional\n * properties so the LLM can't confuse models that have more fields.\n */\nconst EMPTY_OBJECT_JSON_SCHEMA = {\n type: \"object\" as const,\n properties: {},\n additionalProperties: false,\n};\n\n/**\n * Standard Schema implementation of an empty input object. Used by the\n * built-in fn factories so this module stays free of a Zod runtime dependency\n * (per CLAUDE.md \"Use Standard Schema, not Zod/Valibot directly in\n * shared code\").\n *\n * Exposes both `~standard.validate` (mandatory per the spec) and the\n * non-standard `~standard.jsonSchema.{input,output}` extension that\n * the Vercel AI SDK bridge consumes, so this hand-rolled schema can\n * back tools and structured-output specs alongside Zod / Valibot\n * schemas without special-casing.\n */\nconst emptyObjectSchema: StandardSchemaV1<unknown, Record<string, never>> = {\n \"~standard\": {\n version: 1,\n vendor: \"routecraft\",\n validate(value) {\n if (\n value === null ||\n typeof value !== \"object\" ||\n Array.isArray(value) ||\n Object.keys(value as object).length > 0\n ) {\n return {\n issues: [\n {\n message: \"Expected an empty object {}.\",\n },\n ],\n };\n }\n return { value: {} as Record<string, never> };\n },\n // Non-standard `jsonSchema` extension consumed by the AI SDK bridge.\n // Cast away from the strict StandardSchemaV1 shape since the spec\n // doesn't include this field; library schemas (Zod, Valibot) ship it\n // as an extension and the bridge looks it up defensively.\n jsonSchema: {\n input: () => EMPTY_OBJECT_JSON_SCHEMA,\n output: () => EMPTY_OBJECT_JSON_SCHEMA,\n },\n } as StandardSchemaV1<unknown, Record<string, never>>[\"~standard\"],\n};\n\n/**\n * Per-call overrides accepted by the builder helpers. Lets the caller\n * narrow the underlying tool's surface to a specific agent without\n * touching the underlying registration.\n *\n * Only the LLM-facing contract (description, input, tags) can be\n * overridden here. Guards are policy and live at the consumer:\n * attach them in `tools([{ name, guard }])` at the agent's call site.\n */\nexport interface ToolBuilderOverrides<TIn = unknown> {\n /** Replace the underlying description shown to the LLM. */\n description?: string;\n /**\n * Replace the underlying input schema. Replaces, does not merge with,\n * the underlying schema.\n */\n input?: StandardSchemaV1<unknown, TIn>;\n /**\n * Replace the underlying tags. Replaces, does not merge with, the\n * underlying tags.\n */\n tags?: Tag[];\n}\n\n/**\n * Wrap a registered direct route as a fn-shaped tool. The route's\n * `.description()`, `.input()` schema, and tags become the fn's\n * description, input, and tags by default; pass `overrides` to narrow\n * any of them for the calling agent.\n *\n * Resolution is deferred to agent dispatch time, when the direct\n * registry is populated. Errors at resolution (unknown route id,\n * missing description, missing input schema) throw `RC5003`.\n *\n * @example\n * ```ts\n * agentPlugin({\n * functions: {\n * fetchOrder: directTool(\"fetch-order\"),\n * safeFetchOrder: directTool(\"fetch-order\", {\n * description: \"Read-only order fetch.\",\n * tags: [\"read-only\"],\n * }),\n * },\n * });\n * ```\n */\nexport function directTool<TIn = unknown>(\n routeId: string,\n overrides?: ToolBuilderOverrides<TIn>,\n): DeferredFn {\n if (typeof routeId !== \"string\" || routeId.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `directTool: routeId must be a non-empty string.`,\n });\n }\n const overrideTags = normalizeOverrideTags(overrides?.tags, routeId);\n return {\n [DEFERRED_FN_BRAND]: true,\n kind: \"direct\",\n targetId: routeId,\n ...(overrideTags !== undefined ? { overrideTags } : {}),\n resolve(ctx, fnId): FnOptions {\n const route = readDirectRoute(ctx, routeId, fnId);\n const description = overrides?.description ?? route.description;\n if (typeof description !== \"string\" || description.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `directTool: route \"${routeId}\" has no .description() and no override was provided (referenced as fn \"${fnId}\").`,\n });\n }\n const input =\n overrides?.input ??\n (route.input?.body as StandardSchemaV1<unknown, TIn> | undefined);\n if (!input) {\n throw rcError(\"RC5003\", undefined, {\n message: `directTool: route \"${routeId}\" has no .input(...) schema and no override was provided (referenced as fn \"${fnId}\").`,\n });\n }\n const tags = overrideTags ?? route.tags;\n const handler = ((input, hctx) =>\n dispatchDirect(ctx, hctx, routeId, input)) as FnOptions[\"handler\"];\n return {\n description,\n input,\n ...(tags && tags.length > 0 ? { tags: [...tags] } : {}),\n handler,\n } as FnOptions;\n },\n };\n}\n\n/**\n * Trim and validate user-supplied builder override tags so they match\n * exact tag selectors and surface clear errors on misuse. Returns\n * `undefined` when no override was supplied (so the caller can omit\n * the field entirely on the descriptor).\n */\nfunction normalizeOverrideTags(\n value: Tag[] | undefined,\n routeId: string,\n): readonly Tag[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value)) {\n throw rcError(\"RC5003\", undefined, {\n message: `directTool(\"${routeId}\"): override \"tags\" must be an array of non-empty strings.`,\n });\n }\n const out: Tag[] = [];\n for (const t of value) {\n if (typeof t !== \"string\" || t.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `directTool(\"${routeId}\"): override \"tags\" must contain only non-empty strings.`,\n });\n }\n const trimmed = t.trim();\n if (!out.includes(trimmed)) out.push(trimmed);\n }\n return out;\n}\n\nfunction readDirectRoute(\n ctx: CraftContext,\n routeId: string,\n fnId: string,\n): DirectRouteMetadata {\n const registry = ctx.getStore(ADAPTER_DIRECT_REGISTRY) as\n | Map<string, DirectRouteMetadata>\n | undefined;\n // Direct sources register under the sanitised endpoint, so look up\n // by sanitised key. Reject the raw id in the error message so the\n // user can see which one they wrote.\n const endpoint = sanitizeEndpoint(routeId);\n const route = registry?.get(endpoint);\n if (!route) {\n const known = registry ? [...registry.keys()].sort() : [];\n throw rcError(\"RC5003\", undefined, {\n message:\n `directTool: unknown direct route id \"${routeId}\" (referenced as fn \"${fnId}\"). ` +\n (known.length > 0\n ? `Known route ids: ${known.join(\", \")}.`\n : `No direct routes are registered in this context.`),\n });\n }\n return route;\n}\n\nasync function dispatchDirect<TIn>(\n ctx: CraftContext,\n hctx: FnHandlerContext,\n routeId: string,\n input: TIn,\n): Promise<unknown> {\n const endpoint = sanitizeEndpoint(routeId);\n // Forward the calling principal so the downstream direct route sees\n // the same authenticated identity as the agent that invoked the\n // tool. The agent layer never lets a tool override or escalate this:\n // `principal` is deeply-readonly on FnHandlerContext (frozen at the\n // tool-bridge boundary). Hand the downstream exchange a fresh\n // mutable copy so a `.process()` step downstream may legitimately\n // attach a different principal; the tool handler's own snapshot\n // stays frozen and unaffected.\n const headers: Record<string, unknown> = {};\n if (hctx.correlationId) {\n headers[HeadersKeys.CORRELATION_ID] = hctx.correlationId;\n }\n if (hctx.principal) {\n headers[HeadersKeys.AUTH_PRINCIPAL] = cloneFrozenPrincipal(hctx.principal);\n }\n const exchange = new DefaultExchange<TIn>(ctx, {\n body: input,\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n });\n const channel = getDirectChannel<TIn>(ctx, endpoint, {});\n const result = (await channel.send(endpoint, exchange)) as Exchange<unknown>;\n return result.body;\n}\n\n/**\n * Built-in fn factory: returns the current UTC timestamp in ISO 8601\n * format. Takes no configuration. Assign it a tool name in your\n * `agentPlugin({ functions: { ... } })` config, the same way you use\n * `directTool(...)`.\n *\n * @example\n * ```ts\n * agentPlugin({\n * functions: {\n * CurrentTime: currentTime(),\n * fetchOrder: directTool(\"fetch-order\"),\n * },\n * });\n * ```\n */\nexport function currentTime(): FnOptions {\n return {\n description: \"Returns the current UTC timestamp in ISO 8601 format.\",\n input: emptyObjectSchema,\n handler: () => new Date().toISOString(),\n tags: [\"read-only\", \"idempotent\"] satisfies KnownTag[],\n };\n}\n\n/**\n * Built-in fn factory: generates a fresh random UUID v4. Takes no\n * configuration. Assign it a tool name in your\n * `agentPlugin({ functions: { ... } })` config.\n *\n * @example\n * ```ts\n * agentPlugin({ functions: { RandomUuid: randomUuid() } });\n * ```\n */\nexport function randomUuid(): FnOptions {\n return {\n description: \"Generates a fresh random UUID v4.\",\n input: emptyObjectSchema,\n handler: () => randomUUID(),\n tags: [\"read-only\"] satisfies KnownTag[],\n };\n}\n","import {\n ADAPTER_DIRECT_REGISTRY,\n rcError,\n sanitizeEndpoint,\n type CraftContext,\n type DirectRouteMetadata,\n type Tag,\n} from \"@routecraft/routecraft\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { ADAPTER_FN_REGISTRY } from \"../../fn/store.ts\";\nimport type { FnHandlerContext, FnOptions } from \"../../fn/types.ts\";\nimport { dispatchMcpCall } from \"../../mcp/dispatch.ts\";\nimport {\n MCP_TOOL_REGISTRY,\n type McpToolRegistryEntry,\n} from \"../../mcp/types.ts\";\nimport type { McpToolRegistry } from \"../../mcp/tool-registry.ts\";\nimport { directTool } from \"./builders.ts\";\nimport { isDeferredFn, type FnEntry } from \"./types.ts\";\n\n/**\n * Synchronous or async guard run after schema validation, before the\n * underlying handler. Throwing surfaces back to the LLM as a tool error\n * so the model can self-correct.\n */\nexport type ToolGuard = (\n input: unknown,\n ctx: FnHandlerContext,\n) => void | Promise<void>;\n\n/**\n * One entry in the agent's `tools([...])` list.\n *\n * - bare string: name lookup. Plain ids resolve against the fn registry;\n * `Direct(<routeId>)` wraps a direct route via `directTool`;\n * `MCP(server:tool)` / `MCP(server)` and the raw `mcp__server__tool`\n * / `mcp__server` / `mcp__server__*` forms resolve against\n * `MCP_TOOL_REGISTRY` (populated by `defineConfig.mcp` /\n * `mcpPlugin({ clients })`).\n * - `{ name, guard?, description? }`: same lookup, with optional\n * per-binding overrides. The `description` override applies only to\n * THIS binding (the registry entry stays the source of truth, so\n * other agents binding the same fn see the canonical description).\n * Use this when an agent's calling context calls for a different\n * framing of the tool than the registered description provides.\n * For an MCP whole-server ref (`{ name: \"MCP(server)\", guard }`) the\n * guard is attached to every expanded tool.\n * - `{ tagged, from?, guard? }`: select every fn / route / MCP tool\n * whose tags include any of the requested tag(s) (OR semantics).\n * `from?: string` restricts the selection to a single source:\n * `from: \"mcp__<server>\"` matches only that server's MCP tools.\n * Optional guard applies to every match.\n */\nexport type ToolsItem =\n | string\n | { name: string; guard?: ToolGuard; description?: string }\n | { tagged: Tag | Tag[]; from?: string; guard?: ToolGuard };\n\n/**\n * Brand for {@link ToolSelection}. Lets the agent runtime detect a\n * `tools(...)` value vs a plain array.\n *\n * @internal\n */\nexport const TOOL_SELECTION_BRAND = Symbol.for(\"routecraft.ai.tools.selection\");\n\n/**\n * Opaque deferred descriptor returned by `tools(...)`. Resolves at\n * agent dispatch time, when both the fn registry and the direct route\n * registry are populated.\n */\nexport interface ToolSelection {\n readonly [TOOL_SELECTION_BRAND]: true;\n /**\n * Resolve the selection against the live context. Throws RC5003 on\n * any unresolvable explicit reference (unknown name, deferred\n * resolution failure) AND on tag selectors that match zero tools,\n * so a misconfigured selector cannot silently strip every tool from\n * an agent.\n */\n readonly resolve: (ctx: CraftContext) => ResolvedTool[];\n}\n\n/**\n * A tool ready to be wired into the LLM tool list. Produced by\n * `ToolSelection.resolve()`.\n */\nexport interface ResolvedTool {\n /** Tool name presented to the LLM: the registered fn id, `direct_<routeId>` for routes, or `mcp__<server>__<tool>` for MCP tools. */\n name: string;\n /** Description shown to the LLM. */\n description: string;\n /** Standard Schema validating the LLM-supplied input. */\n input: StandardSchemaV1<unknown, unknown>;\n /** Optional tags inherited from the underlying registration. */\n tags?: Tag[];\n /** Optional guard run after validation, before the handler. */\n guard?: ToolGuard;\n /** The function the LLM ultimately invokes. */\n handler: FnOptions[\"handler\"];\n}\n\n/**\n * Type guard. Returns true when `value` is a tool selection produced\n * by `tools(...)`.\n *\n * @internal\n */\nexport function isToolSelection(value: unknown): value is ToolSelection {\n return (\n typeof value === \"object\" &&\n value !== null &&\n TOOL_SELECTION_BRAND in value &&\n (value as { [TOOL_SELECTION_BRAND]: unknown })[TOOL_SELECTION_BRAND] ===\n true\n );\n}\n\n/**\n * Build a tool selection for an agent from a flat list of references.\n *\n * Items can be bare strings, `{ name, guard? }`, or `{ tagged, guard? }`.\n * Resolution happens lazily at agent dispatch time.\n *\n * Resolution rules:\n * - Bare names look up exact matches in the fn registry first.\n * `Direct(<routeId>)` wraps a direct route via `directTool` (the\n * LLM-facing tool name stays `direct_<routeId>`). `MCP(server:tool)`\n * / `MCP(server)` and the raw `mcp__server__tool` / `mcp__server` /\n * `mcp__server__*` forms resolve against `MCP_TOOL_REGISTRY`.\n * - Tag selectors walk the fn registry, the direct route registry,\n * and the MCP tool registry, including any entry whose tags overlap\n * with the requested set. `from?: string` narrows the walk: pass\n * `from: \"mcp__<server>\"` to scope a tag selection to a single MCP\n * server.\n * - Final list is deduplicated by tool name. Explicit references win\n * over tag-selector matches regardless of position in the list.\n *\n * @example\n * ```ts\n * agent({\n * tools: tools([\n * \"CurrentTime\",\n * \"fetchOrder\",\n * \"Direct(cancel-order)\",\n * \"MCP(github:create_issue)\",\n * { name: \"sendSlack\", guard: confirmGuard },\n * { tagged: \"read-only\" },\n * ]),\n * });\n * ```\n */\nexport function tools(items: ToolsItem[]): ToolSelection {\n if (!Array.isArray(items)) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(items): items must be an array.`,\n });\n }\n return {\n [TOOL_SELECTION_BRAND]: true,\n resolve(ctx) {\n const explicit = new Map<string, ResolvedTool>();\n\n // Phase 1: explicit refs (bare strings + { name, guard }).\n for (const item of items) {\n if (typeof item === \"string\") {\n // An exact fn id always wins over the MCP-ref grammar, so a fn\n // whose id happens to start with `mcp__` stays reachable.\n if (isMcpRefName(item) && !fnRegistryHas(ctx, item)) {\n for (const tool of resolveMcpRefs(ctx, item, undefined)) {\n explicit.set(tool.name, tool);\n }\n continue;\n }\n const tool = resolveByName(ctx, item, undefined);\n explicit.set(tool.name, tool);\n continue;\n }\n if (item === null || typeof item !== \"object\") {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): each item must be a string, { name, guard?, description? }, or { tagged, from?, guard? }.`,\n });\n }\n if (\"name\" in item) {\n if (typeof item.name !== \"string\" || item.name.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): { name } must be a non-empty string.`,\n });\n }\n // MCP refs reject any description override (empty or not) so\n // users see the precise \"MCP server is the source of truth\"\n // message instead of the generic empty-string error.\n if (isMcpRefName(item.name) && !fnRegistryHas(ctx, item.name)) {\n if (item.description !== undefined) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): { name: \"${item.name}\", description } is not supported for MCP tools. The MCP server is the source of truth for description and schema; do not override.`,\n });\n }\n for (const tool of resolveMcpRefs(ctx, item.name, item.guard)) {\n explicit.set(tool.name, tool);\n }\n continue;\n }\n if (\n item.description !== undefined &&\n (typeof item.description !== \"string\" ||\n item.description.trim() === \"\")\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): { name: \"${item.name}\", description } must be a non-empty string when present.`,\n });\n }\n const base = resolveByName(ctx, item.name, item.guard);\n // Per-binding description override. The registry entry is\n // never mutated, so other agents binding the same fn still\n // see the canonical description.\n const tool: ResolvedTool =\n item.description !== undefined\n ? { ...base, description: item.description }\n : base;\n explicit.set(tool.name, tool);\n } else if (!(\"tagged\" in item)) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): each object item must include \"name\" or \"tagged\".`,\n });\n }\n }\n\n // Phase 2: tag selectors. Explicit names already in the map win.\n const out = new Map<string, ResolvedTool>(explicit);\n for (const item of items) {\n if (typeof item === \"object\" && item !== null && \"tagged\" in item) {\n const wanted = normalizeTags(item.tagged);\n if (wanted.length === 0) continue;\n const matches = resolveByTags(ctx, wanted, item.guard, item.from);\n if (matches.length === 0) {\n throw rcError(\"RC5003\", undefined, {\n message: item.from\n ? `tools(): tagged selector matched no tools (tagged: ${formatTags(wanted)}, from: \"${item.from}\").`\n : `tools(): tagged selector matched no tools (tagged: ${formatTags(wanted)}).`,\n });\n }\n for (const match of matches) {\n if (!out.has(match.name)) out.set(match.name, match);\n }\n }\n }\n\n return [...out.values()];\n },\n };\n}\n\n/**\n * True when the fn registry holds an exact entry for `name`. Used to let\n * an explicitly registered fn win over the MCP-ref grammar for bare\n * strings (so a fn id starting with `mcp__` stays reachable).\n *\n * @internal\n */\nfunction fnRegistryHas(ctx: CraftContext, name: string): boolean {\n const fnRegistry = ctx.getStore(ADAPTER_FN_REGISTRY) as\n | Map<string, FnEntry>\n | undefined;\n return fnRegistry?.has(name) ?? false;\n}\n\nfunction resolveByName(\n ctx: CraftContext,\n name: string,\n guard: ToolGuard | undefined,\n): ResolvedTool {\n if (typeof name !== \"string\" || name.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): tool name must be a non-empty string.`,\n });\n }\n const fnRegistry = ctx.getStore(ADAPTER_FN_REGISTRY) as\n | Map<string, FnEntry>\n | undefined;\n const fnEntry = fnRegistry?.get(name);\n if (fnEntry) {\n return resolveFnEntry(ctx, name, fnEntry, guard);\n }\n\n // `Direct(<routeId>)` wraps a registered direct route as a tool. The\n // LLM-facing tool name stays the valid `direct_<routeId>` form (tool\n // names cannot contain parentheses); `Direct(...)` is only the\n // reference grammar a developer writes in `tools([...])`.\n const directMatch = /^Direct\\((.*)\\)$/.exec(name);\n if (directMatch) {\n const routeId = directMatch[1]!.trim();\n if (routeId === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): \"${name}\" has an empty route id; use \"Direct(<routeId>)\".`,\n });\n }\n const toolName = `direct_${routeId}`;\n const wrapper = directTool(routeId);\n const fn = wrapper.resolve(ctx, toolName);\n return toResolvedTool(toolName, fn, guard);\n }\n\n const known = listKnownNames(ctx);\n throw rcError(\"RC5003\", undefined, {\n message:\n `tools(): unknown tool \"${name}\". ` +\n (known.length > 0\n ? `Available: ${known.join(\", \")}.`\n : `No fns or direct routes are registered in this context.`),\n });\n}\n\nfunction resolveFnEntry(\n ctx: CraftContext,\n name: string,\n entry: FnEntry,\n guard: ToolGuard | undefined,\n): ResolvedTool {\n if (isDeferredFn(entry)) {\n const fn = entry.resolve(ctx, name);\n return toResolvedTool(name, fn, guard);\n }\n return toResolvedTool(name, entry, guard);\n}\n\nfunction toResolvedTool(\n name: string,\n fn: FnOptions,\n guard: ToolGuard | undefined,\n): ResolvedTool {\n return {\n name,\n description: fn.description,\n input: fn.input as StandardSchemaV1<unknown, unknown>,\n ...(fn.tags && fn.tags.length > 0 ? { tags: fn.tags } : {}),\n ...(guard ? { guard } : {}),\n handler: fn.handler as FnOptions[\"handler\"],\n };\n}\n\n/**\n * Recognise an attempted MCP tool reference. Two accepted forms: the\n * raw flat identity `mcp__<server>__<tool>` (also `mcp__<server>` and\n * `mcp__<server>__*` for a whole server), which is what Claude Code\n * agent files carry, and the `MCP(server:tool)` / `MCP(server)` sugar.\n *\n * Callers consult the fn registry first, so an exact fn id (even one\n * starting with `mcp__`) takes precedence over this grammar.\n *\n * @internal\n */\nfunction isMcpRefName(name: string): boolean {\n if (name.startsWith(\"mcp__\")) return true;\n return name.startsWith(\"MCP(\") && name.endsWith(\")\");\n}\n\n/**\n * Parse an MCP reference into its server (client) and tool parts.\n * Accepts two forms:\n *\n * - Raw identity `mcp__<server>__<tool>`. Server and tool split on the\n * first `__` after the `mcp__` prefix (so single-underscore server\n * names like `my_company_api` are preserved). `mcp__<server>` and\n * `mcp__<server>__*` select every tool on the server. This is the\n * string Claude Code agent files carry, so they resolve unchanged.\n * - Sugar `MCP(server:tool)`. Colon-separated; `MCP(server)` and\n * `MCP(server:*)` select every tool on the server.\n *\n * A `toolName` of `*` means \"every tool on the server\". Separators\n * beyond the first split (extra `__` in the raw form, extra `:` in the\n * sugar) stay in the tool segment and are forwarded to the MCP server\n * verbatim.\n *\n * @internal\n */\nfunction parseMcpRef(ref: string): { clientName: string; toolName: string } {\n if (ref.startsWith(\"MCP(\") && ref.endsWith(\")\")) {\n const inner = ref.slice(4, -1).trim();\n const colon = inner.indexOf(\":\");\n const clientName = colon === -1 ? inner : inner.slice(0, colon).trim();\n const toolName = colon === -1 ? \"*\" : inner.slice(colon + 1).trim();\n if (clientName === \"\" || toolName === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): MCP reference \"${ref}\" must use \"MCP(server:tool)\" or \"MCP(server)\"; got an empty server or tool segment.`,\n });\n }\n return { clientName, toolName };\n }\n if (ref.startsWith(\"mcp__\")) {\n const rest = ref.slice(\"mcp__\".length);\n const sep = rest.indexOf(\"__\");\n const clientName = sep === -1 ? rest : rest.slice(0, sep);\n const toolName = sep === -1 ? \"*\" : rest.slice(sep + 2);\n if (clientName.trim() === \"\" || toolName.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): MCP reference \"${ref}\" must use \"mcp__server__tool\" or \"mcp__server\"; got an empty server or tool segment.`,\n });\n }\n return { clientName, toolName };\n }\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): MCP reference \"${ref}\" must use \"MCP(server:tool)\", \"MCP(server)\", or the raw \"mcp__server__tool\" form.`,\n });\n}\n\n/**\n * Resolve an MCP reference into one or more `ResolvedTool` entries.\n * The whole-server forms expand to every tool registered under the\n * server at dispatch time.\n *\n * Throws RC5003 when the registry is absent, the server is unknown,\n * the server is registered but has no tools, or the specific tool is\n * not registered.\n *\n * @internal\n */\nfunction resolveMcpRefs(\n ctx: CraftContext,\n ref: string,\n guard: ToolGuard | undefined,\n): ResolvedTool[] {\n const { clientName, toolName } = parseMcpRef(ref);\n const registry = ctx.getStore(MCP_TOOL_REGISTRY);\n if (!registry) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): MCP reference \"${ref}\" but no MCP_TOOL_REGISTRY is present. Install mcpPlugin (defineConfig.mcp) so external clients populate the registry.`,\n });\n }\n const clientTools = registry.getToolsByServer(clientName);\n if (clientTools.length === 0) {\n const known = listKnownMcpClients(registry);\n throw rcError(\"RC5003\", undefined, {\n message:\n `tools(): MCP reference \"${ref}\" but client \"${clientName}\" has no registered tools. ` +\n (known.length > 0\n ? `Known MCP clients: ${known.map((k) => `\"${k}\"`).join(\", \")}.`\n : `No MCP clients are registered in this context.`),\n });\n }\n if (toolName === \"*\") {\n return clientTools.map((entry) =>\n mcpEntryToResolvedTool(ctx, entry, guard),\n );\n }\n const entry = clientTools.find((t) => t.name === toolName);\n if (!entry) {\n const knownTools = clientTools.map((t) => t.name).sort();\n throw rcError(\"RC5003\", undefined, {\n message:\n `tools(): MCP reference \"${ref}\" but tool \"${toolName}\" is not registered under client \"${clientName}\". ` +\n `Known tools on \"${clientName}\": ${knownTools.map((n) => `\"${n}\"`).join(\", \")}.`,\n });\n }\n return [mcpEntryToResolvedTool(ctx, entry, guard)];\n}\n\n/**\n * Wrap an MCP registry entry as a `ResolvedTool`. The input is a\n * Standard Schema pass-through that exposes the entry's raw JSON\n * Schema to the Vercel AI SDK bridge (it consumes the\n * `~standard.jsonSchema` extension) and accepts the LLM-supplied\n * value unchanged (the MCP server is the source of truth for\n * validation; double-validating locally adds latency and divergence\n * risk).\n *\n * The handler captures the entry's `source` (client name) at\n * resolution time and dispatches via `dispatchMcpCall`, so a tool\n * call goes through the same stdio / HTTP plumbing as the `mcp(...)`\n * destination adapter.\n *\n * Auth boundary: the routecraft principal (`FnHandlerContext.principal`)\n * authenticates the caller into routecraft and is intentionally\n * NOT forwarded to the MCP server. The MCP client is authenticated\n * separately via the static credentials registered on\n * `defineConfig.mcp({ clients: { name: { auth } } })`. If the agent\n * needs to thread user-specific data into a tool call, it must do so\n * as a regular tool argument (e.g. include a `tenantId` field), never\n * by piggybacking on a credential. Two trust boundaries: principal\n * authenticates Routecraft; MCP `auth` authenticates the\n * Routecraft -> MCP hop.\n *\n * @internal\n */\nfunction mcpEntryToResolvedTool(\n ctx: CraftContext,\n entry: McpToolRegistryEntry,\n guard: ToolGuard | undefined,\n): ResolvedTool {\n const name = `mcp__${entry.source}__${entry.name}`;\n const description =\n entry.description && entry.description.trim() !== \"\"\n ? entry.description\n : `MCP tool \"${entry.name}\" on client \"${entry.source}\".`;\n const input = wrapJsonSchemaAsStandard(entry.inputSchema);\n const handler: FnOptions[\"handler\"] = async (rawInput) => {\n // MCP tools expect a JSON-object argument. Silently coercing a\n // non-object value to `{}` would discard the LLM's args and surface\n // an unrelated server-side error; fail loudly so the model sees a\n // precise correction message and can retry with the right shape.\n if (\n rawInput === null ||\n rawInput === undefined ||\n typeof rawInput !== \"object\" ||\n Array.isArray(rawInput)\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `mcp tool \"${name}\" expects an object argument; received ${rawInput === null ? \"null\" : Array.isArray(rawInput) ? \"array\" : typeof rawInput}.`,\n });\n }\n const args = rawInput as Record<string, unknown>;\n return dispatchMcpCall(ctx, entry.source, entry.name, args);\n };\n const tool: ResolvedTool = {\n name,\n description,\n input,\n handler,\n };\n if (entry.tags && entry.tags.length > 0) {\n tool.tags = [...entry.tags];\n }\n if (guard) tool.guard = guard;\n return tool;\n}\n\n/**\n * Lightweight Standard Schema wrapper around a raw JSON Schema. The\n * `~standard.validate` is a pass-through (MCP server validates); the\n * `~standard.jsonSchema` extension hands the JSON Schema to the\n * Vercel AI SDK bridge via `toAiInputSchema`. Follows the same shape\n * `emptyObjectSchema` in `builders.ts` uses so the bridge code stays\n * uniform.\n *\n * @internal\n */\nfunction wrapJsonSchemaAsStandard(\n schema: Record<string, unknown>,\n): StandardSchemaV1<unknown, unknown> {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"routecraft\",\n validate(value) {\n return { value };\n },\n jsonSchema: {\n input: () => schema,\n output: () => schema,\n },\n } as StandardSchemaV1<unknown, unknown>[\"~standard\"],\n };\n}\n\nfunction listKnownMcpClients(registry: McpToolRegistry): string[] {\n const set = new Set<string>();\n for (const entry of registry.getTools()) set.add(entry.source);\n return [...set].sort();\n}\n\n/**\n * Parsed `from` scope filter. `kind: \"all\"` means walk every source\n * (default when `from` is unset). `kind: \"mcp\"` narrows to a single\n * MCP client.\n *\n * @internal\n */\ninterface FromScope {\n kind: \"all\" | \"mcp\";\n mcpClient?: string;\n}\n\nfunction parseFromScope(from: string | undefined): FromScope {\n if (from === undefined) return { kind: \"all\" };\n if (typeof from !== \"string\" || from.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): \"from\" must be a non-empty string when present.`,\n });\n }\n if (from.startsWith(\"mcp__\")) {\n const client = from.slice(\"mcp__\".length);\n if (client.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): from \"${from}\" has an empty server name; use \"mcp__<server>\".`,\n });\n }\n return { kind: \"mcp\", mcpClient: client };\n }\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): from \"${from}\" is not a supported source filter. Use \"mcp__<server>\".`,\n });\n}\n\nfunction resolveByTags(\n ctx: CraftContext,\n wanted: Tag[],\n guard: ToolGuard | undefined,\n from: string | undefined,\n): ResolvedTool[] {\n const wantedSet = new Set(wanted);\n const scope = parseFromScope(from);\n const out: ResolvedTool[] = [];\n const seenNames = new Set<string>();\n // Track route ids already surfaced via a fn-registry directTool wrapper\n // **that actually contributed** so the direct-registry walk doesn't\n // double-include them. Wrappers that didn't match the wanted tag set\n // are NOT added here -- the underlying route may still match by its\n // own tags and is allowed to surface under its direct_<routeId> name.\n // MCP entries are walked separately at the end of this function via\n // MCP_TOOL_REGISTRY (not the fn-registry deferred path), so they\n // sit outside this dedup set.\n const coveredRouteIds = new Set<string>();\n\n // fn registry and direct registry walks only run when scope is\n // unrestricted (\"all\"). A scoped selector like\n // `{ tagged: \"read-only\", from: \"mcp__Nuclino\" }` deliberately\n // excludes fns and routes.\n if (scope.kind === \"all\") {\n // Walk the fn registry first so explicit fn-side tags (incl. directTool\n // wrappers) take precedence over a parallel direct-registry walk.\n // Skip non-direct deferred entries entirely (none exist today now that\n // `agentTool` is gone, but the guard is kept so future deferred kinds\n // do not silently surface here without an explicit by-name ref).\n const fnRegistry = ctx.getStore(ADAPTER_FN_REGISTRY) as\n | Map<string, FnEntry>\n | undefined;\n if (fnRegistry) {\n for (const [name, entry] of fnRegistry) {\n if (isDeferredFn(entry)) {\n if (entry.kind !== \"direct\") continue;\n // Use the wrapper's explicit `overrides.tags` when present so a\n // `directTool(routeId, { tags: [...] })` wrapper actually drives\n // selection. Fall back to peeking the underlying route's tags\n // when no override was supplied.\n const candidateTags =\n entry.overrideTags ?? peekDirectTags(ctx, entry.targetId);\n if (!candidateTags.some((t) => wantedSet.has(t))) continue;\n const fn = entry.resolve(ctx, name);\n out.push(toResolvedTool(name, fn, guard));\n seenNames.add(name);\n // Direct routes register under their sanitised endpoint, but\n // `directTool` wrappers carry the user-supplied raw id. Store the\n // sanitised form so the direct-registry walk below (which\n // iterates the registry by its sanitised key) dedups correctly\n // even when the route id contains URL-special chars like \"/\".\n coveredRouteIds.add(sanitizeEndpoint(entry.targetId));\n continue;\n }\n const tags = entry.tags ?? [];\n if (tags.some((t) => wantedSet.has(t))) {\n out.push(toResolvedTool(name, entry, guard));\n seenNames.add(name);\n }\n }\n }\n\n // Walk the direct registry for routes not already surfaced via a\n // fn-registry wrapper. Registry keys are the sanitised endpoint;\n // `coveredRouteIds` is also keyed by the sanitised form so the\n // dedup works for raw ids containing URL-special characters.\n const directRegistry = ctx.getStore(ADAPTER_DIRECT_REGISTRY) as\n | Map<string, DirectRouteMetadata>\n | undefined;\n if (directRegistry) {\n for (const [routeId, meta] of directRegistry) {\n if (coveredRouteIds.has(routeId)) continue;\n const tags = meta.tags ?? [];\n if (!tags.some((t) => wantedSet.has(t))) continue;\n const conventionName = `direct_${routeId}`;\n if (seenNames.has(conventionName)) continue;\n // Only include if the route is fully tool-shaped (has description\n // and input schema). Routes that are missing those silently skip\n // tag-selector inclusion -- explicit refs would still throw.\n if (\n typeof meta.description !== \"string\" ||\n meta.description.trim() === \"\"\n ) {\n continue;\n }\n if (!meta.input?.body) continue;\n const wrapper = directTool(routeId);\n const fn = wrapper.resolve(ctx, conventionName);\n out.push(toResolvedTool(conventionName, fn, guard));\n seenNames.add(conventionName);\n }\n }\n }\n\n // Walk the MCP registry. Under \"all\" scope every client is in\n // scope; under \"mcp\" scope only the named client contributes.\n const mcpRegistry = ctx.getStore(MCP_TOOL_REGISTRY);\n if (mcpRegistry) {\n let entries: McpToolRegistryEntry[];\n if (scope.kind === \"mcp\") {\n entries = mcpRegistry.getToolsByServer(scope.mcpClient as string);\n if (entries.length === 0) {\n const known = listKnownMcpClients(mcpRegistry);\n throw rcError(\"RC5003\", undefined, {\n message:\n `tools(): from \"mcp__${scope.mcpClient}\" has no registered tools. ` +\n (known.length > 0\n ? `Known MCP clients: ${known.map((k) => `\"${k}\"`).join(\", \")}.`\n : `No MCP clients are registered in this context.`),\n });\n }\n } else {\n entries = mcpRegistry.getTools();\n }\n for (const entry of entries) {\n const tags = entry.tags ?? [];\n if (!tags.some((t) => wantedSet.has(t))) continue;\n const tool = mcpEntryToResolvedTool(ctx, entry, guard);\n if (seenNames.has(tool.name)) continue;\n out.push(tool);\n seenNames.add(tool.name);\n }\n } else if (scope.kind === \"mcp\") {\n // Asked for a specific MCP client but the registry isn't installed.\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): from \"mcp__${scope.mcpClient}\" but no MCP_TOOL_REGISTRY is present. Install mcpPlugin (defineConfig.mcp).`,\n });\n }\n\n return out;\n}\n\nfunction formatTags(tags: Tag[]): string {\n return tags.length === 1\n ? `\"${tags[0]}\"`\n : `[${tags.map((t) => `\"${t}\"`).join(\", \")}]`;\n}\n\nfunction peekDirectTags(ctx: CraftContext, routeId: string): Tag[] {\n const directRegistry = ctx.getStore(ADAPTER_DIRECT_REGISTRY) as\n | Map<string, DirectRouteMetadata>\n | undefined;\n // Routes register under the sanitised endpoint; look up the same way.\n return directRegistry?.get(sanitizeEndpoint(routeId))?.tags ?? [];\n}\n\nfunction normalizeTags(value: Tag | Tag[]): Tag[] {\n return (Array.isArray(value) ? value : [value]).filter(\n (t): t is Tag => typeof t === \"string\" && t.trim() !== \"\",\n );\n}\n\nfunction listKnownNames(ctx: CraftContext): string[] {\n const fnNames = [\n ...(\n (ctx.getStore(ADAPTER_FN_REGISTRY) as Map<string, FnEntry> | undefined) ??\n new Map()\n ).keys(),\n ];\n const routeNames = [\n ...(\n (ctx.getStore(ADAPTER_DIRECT_REGISTRY) as\n | Map<string, DirectRouteMetadata>\n | undefined) ?? new Map()\n ).keys(),\n ].map((id) => `Direct(${id})`);\n return [...fnNames, ...routeNames].sort();\n}\n","import {\n type Destination,\n factoryArgs,\n rcError,\n tagAdapter,\n} from \"@routecraft/routecraft\";\nimport { parseProviderModel } from \"../llm/shared.ts\";\nimport {\n AgentDestinationAdapter,\n type AgentByNameOverrides,\n} from \"./destination.ts\";\nimport { isToolSelection } from \"./tools/selection.ts\";\nimport type { AgentOptions, AgentResult } from \"./types.ts\";\n\n/**\n * Validate the LLM-config shape of agent options. Run at construction so\n * misconfiguration surfaces immediately rather than at first dispatch.\n *\n * @internal\n */\nexport function validateAgentOptions(options: AgentOptions): void {\n // `system` accepts the same string-or-function shape as `llm({ system })`.\n // For the static form, require non-empty so misconfiguration (\"\" or\n // missing) surfaces at construction. The function form is validated at\n // dispatch (its return value flows through `resolvePrompt`).\n if (typeof options.system === \"string\") {\n if (options.system.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"system\" is required and must be a non-empty string (or a function that returns one).`,\n });\n }\n } else if (typeof options.system !== \"function\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"system\" must be a string or a function (exchange) => string.`,\n });\n }\n if (\n options.user !== undefined &&\n typeof options.user !== \"string\" &&\n typeof options.user !== \"function\"\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"user\" must be a string or a function (exchange) => string when present.`,\n });\n }\n // `model` is optional: inheritable from agentPlugin({ defaultOptions:\n // { model } }) at dispatch time. Validate the shape only when present.\n if (options.model !== undefined) {\n if (typeof options.model !== \"string\" || options.model.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"model\" must be a non-empty \"providerId:modelName\" string when present.`,\n });\n }\n try {\n parseProviderModel(options.model);\n } catch {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"model\" string must be in \"providerId:modelName\" form (e.g. ollama:llama3). Got: \"${options.model}\"`,\n });\n }\n }\n if (options.tools !== undefined && !isToolSelection(options.tools)) {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"tools\" must be the result of tools([...]).`,\n });\n }\n if (\n options.principal !== undefined &&\n typeof options.principal !== \"boolean\" &&\n typeof options.principal !== \"function\"\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"principal\" must be a boolean or a function (principal, exchange) => string when present.`,\n });\n }\n if (options.output !== undefined) {\n if (options.output === null || typeof options.output !== \"object\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"output\" must be a Standard Schema (Zod/Valibot/ArkType/etc.).`,\n });\n }\n const standard = (\n options.output as { [\"~standard\"]?: { validate?: unknown } }\n )[\"~standard\"];\n if (typeof standard?.validate !== \"function\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: \"output\" must be a Standard Schema (Zod/Valibot/ArkType/etc.).`,\n });\n }\n }\n}\n\n/**\n * Create an agent destination.\n *\n * Two forms:\n *\n * - **Inline**: `agent({ model, system, user? })` -- destination constructed\n * from inline options. Identity and description come from the enclosing\n * route (`.id()`, `.description()`).\n * - **By name**: `agent(\"name\")` -- destination resolved at dispatch time\n * against agents registered via `agentPlugin({ agents: { name: {...} } })`.\n * Registered agents carry their own description.\n *\n * @example Inline (identity on the route)\n * ```typescript\n * craft()\n * .id(\"zoe\")\n * .description(\"A helpful assistant\")\n * .from(direct())\n * .to(agent({\n * model: \"anthropic:claude-opus-4-7\",\n * system: readFileSync(\"./prompts/zoe.md\", \"utf-8\"),\n * }))\n * .to(direct(\"reply\"));\n * ```\n *\n * @example By name (agent registered in the plugin)\n * ```typescript\n * agentPlugin({\n * agents: {\n * summariser: {\n * description: \"Summarises documents\",\n * model: \"anthropic:claude-opus-4-7\",\n * system: \"Be concise.\",\n * },\n * },\n * });\n *\n * craft()\n * .id(\"caller\")\n * .from(timer({ intervalMs: 60_000 }))\n * .to(agent(\"summariser\"))\n * .to(direct(\"reply\"));\n * ```\n */\nexport function agent(options: AgentOptions): Destination<unknown, AgentResult>;\nexport function agent(name: string): Destination<unknown, AgentResult>;\nexport function agent(\n name: string,\n perCall: AgentByNameOverrides,\n): Destination<unknown, AgentResult>;\nexport function agent(\n arg: AgentOptions | string,\n perCall?: AgentByNameOverrides,\n): Destination<unknown, AgentResult> {\n if (typeof arg === \"string\") {\n if (arg.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Agent: name must be a non-empty string.`,\n });\n }\n return tagAdapter(\n new AgentDestinationAdapter({\n kind: \"by-name\",\n name: arg,\n ...(perCall ? { perCall } : {}),\n }),\n agent,\n // Preserve both args so `mockAdapter()` and other testing-hook\n // introspection see the per-call overrides supplied at the\n // call site (e.g. a per-request `onDelta`).\n perCall ? factoryArgs(arg, perCall) : factoryArgs(arg),\n );\n }\n validateAgentOptions(arg);\n return tagAdapter(\n new AgentDestinationAdapter({ kind: \"inline\", options: arg }),\n agent,\n factoryArgs(arg),\n );\n}\n","import { rcError } from \"@routecraft/routecraft\";\nimport type { FnOptions } from \"./types.ts\";\n\n/**\n * Validate a fn's config shape. Run at context init (not at authoring\n * time) so authoring `{ ... } satisfies FnOptions` stays ergonomic and\n * misconfiguration surfaces with a helpful RC5003 error at startup.\n *\n * @internal\n */\nexport function validateFnOptions(id: string, options: FnOptions): void {\n if (options === null || typeof options !== \"object\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn \"${id}\" entry must be an object with description, input, and handler.`,\n });\n }\n if (\n typeof options.description !== \"string\" ||\n options.description.trim() === \"\"\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn \"${id}\" is missing a non-empty \"description\".`,\n });\n }\n if (\n options.input === null ||\n typeof options.input !== \"object\" ||\n typeof (options.input as { [\"~standard\"]?: unknown })[\"~standard\"] !==\n \"object\"\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn \"${id}\" \"input\" is required and must be a Standard Schema value (Zod/Valibot/ArkType/etc.).`,\n });\n }\n const standard = (\n options.input as { [\"~standard\"]?: { validate?: unknown } }\n )[\"~standard\"];\n if (typeof standard?.validate !== \"function\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn \"${id}\" \"input\" must be a Standard Schema with a callable validate.`,\n });\n }\n if (typeof options.handler !== \"function\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn \"${id}\" \"handler\" is required and must be a function.`,\n });\n }\n if (options.tags !== undefined) {\n if (!Array.isArray(options.tags)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn \"${id}\" \"tags\" must be an array of non-empty strings.`,\n });\n }\n for (let i = 0; i < options.tags.length; i++) {\n const t = options.tags[i];\n if (typeof t !== \"string\" || t.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn \"${id}\" \"tags\" must contain only non-empty strings.`,\n });\n }\n // Normalise: trim surrounding whitespace so exact selectors match.\n options.tags[i] = t.trim();\n }\n }\n}\n","import {\n rcError,\n type CraftContext,\n type CraftPlugin,\n} from \"@routecraft/routecraft\";\nimport { validateAgentOptions } from \"./agent.ts\";\nimport {\n ADAPTER_AGENT_DEFAULT_OPTIONS,\n ADAPTER_AGENT_REGISTRY,\n} from \"./store.ts\";\nimport { validateFnOptions } from \"../fn/fn.ts\";\nimport { ADAPTER_FN_REGISTRY } from \"../fn/store.ts\";\nimport { parseProviderModel } from \"../llm/shared.ts\";\nimport { ADAPTER_SKILL_REGISTRY, type Skill } from \"../skill/types.ts\";\nimport type { AgentDefaultOptions, AgentRegisteredOptions } from \"./types.ts\";\nimport { isDeferredFn, type FnEntry } from \"./tools/types.ts\";\nimport { isToolSelection } from \"./tools/selection.ts\";\n\nexport interface AgentPluginOptions {\n /**\n * Agents available for by-name lookup via `agent(\"id\")`. Keyed by the\n * agent id; each entry provides the agent's description, optional\n * model, system, and optional user-prompt override. Duplicate ids\n * across multiple `agentPlugin` installs throw at context init.\n */\n agents?: Record<string, AgentRegisteredOptions>;\n\n /**\n * Ad-hoc in-process functions available to agents (via `tools: [...]`\n * in follow-up stories). Keyed by the fn id; each entry is either an\n * eagerly-authored `FnOptions` (description, input, handler) or a\n * deferred descriptor emitted by a builder helper such as\n * `directTool(routeId)`.\n * Deferred descriptors resolve at agent dispatch time when all\n * registries are populated.\n *\n * Duplicate ids across multiple `agentPlugin` installs throw at\n * context init.\n *\n * For tests, exercise registered fn handlers via `testFn` from\n * `@routecraft/testing` rather than dispatching through the plugin.\n */\n functions?: Record<string, FnEntry>;\n\n /**\n * Skills available to agents via `AgentOptions.skills: [\"name\", ...]`.\n * Keyed by skill name; each entry's `content` is concatenated into\n * the system prompt of any agent that lists the name.\n *\n * Spread the `Record<string, Skill>` returned by `skills(path)` to\n * load skills from markdown files.\n *\n * Duplicate skill names across multiple `agentPlugin` installs throw\n * at context init.\n */\n skills?: Record<string, Skill>;\n\n /**\n * Context-level defaults applied to any agent that doesn't override\n * them. Mirrors the `llmPlugin({ defaultOptions })` pattern:\n *\n * - `model` (`LlmModelId` string) is used by agents that omit `model`.\n * Requires `llmPlugin` to be installed with the relevant provider.\n * - `tools` (`ToolSelection` from `tools([...])`) is used by agents\n * that omit `tools`. Override-not-extend: an explicit `tools:` on\n * an agent replaces this default entirely.\n *\n * Multiple `agentPlugin` installs that each set the same default\n * field throw at context init.\n */\n defaultOptions?: AgentDefaultOptions;\n}\n\nfunction validateRegisteredAgent(\n id: string,\n options: AgentRegisteredOptions,\n): void {\n if (\n typeof options.description !== \"string\" ||\n options.description.trim() === \"\"\n ) {\n throw rcError(\"RC5003\", undefined, {\n message:\n `agentPlugin: agent \"${id}\" is missing a non-empty \"description\". ` +\n `Registered agents carry their own description because they are not ` +\n `backed by a route.`,\n });\n }\n validateAgentOptions(options);\n}\n\n/**\n * Agent plugin: registers agents and functions in the context store so\n * routes can reference agents by name via `agent(\"id\")` and so fns are\n * available to tool-using agents (the agent tool loop dispatches them\n * directly; there is no public dispatch API). Throws on duplicate id\n * (within agents, within fns, or across multiple plugin installs) at\n * context init.\n *\n * @example\n * ```typescript\n * import { agentPlugin } from \"@routecraft/ai\";\n * import { z } from \"zod\";\n *\n * agentPlugin({\n * agents: {\n * summariser: {\n * description: \"Summarises documents into bullet points\",\n * model: \"anthropic:claude-opus-4-7\",\n * system: \"You are a summariser. Be concise.\",\n * },\n * },\n * functions: {\n * CurrentTime: {\n * description: \"Current UTC timestamp in ISO 8601\",\n * input: z.object({}),\n * handler: async () => new Date().toISOString(),\n * },\n * },\n * });\n * ```\n */\nexport function agentPlugin(options: AgentPluginOptions = {}): CraftPlugin {\n const agents = options.agents ?? {};\n const functions = options.functions ?? {};\n const skillsMap = options.skills ?? {};\n const defaultOptions = validatePluginDefaults(options.defaultOptions);\n return {\n apply(ctx: CraftContext) {\n // Merge into an existing registry when present so multiple\n // `agentPlugin({...})` entries compose instead of overwriting.\n const existingAgents = ctx.getStore(\n ADAPTER_AGENT_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, AgentRegisteredOptions> | undefined;\n const agentMap =\n existingAgents ?? new Map<string, AgentRegisteredOptions>();\n for (const [id, entry] of Object.entries(agents)) {\n if (id.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: agent id must be a non-empty string.`,\n });\n }\n if (entry === null || typeof entry !== \"object\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: agent \"${id}\" entry must be an object with description, model, and system.`,\n });\n }\n if (entry.tools !== undefined && !isToolSelection(entry.tools)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: agent \"${id}\" \"tools\" must be the result of tools([...]).`,\n });\n }\n validateRegisteredAgent(id, entry);\n if (agentMap.has(id)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: duplicate agent id \"${id}\". Each agent id must be unique within a context.`,\n });\n }\n agentMap.set(id, entry);\n }\n if (!existingAgents) {\n ctx.setStore(\n ADAPTER_AGENT_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n agentMap,\n );\n }\n\n const existingFns = ctx.getStore(\n ADAPTER_FN_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, FnEntry> | undefined;\n const fnMap = existingFns ?? new Map<string, FnEntry>();\n for (const [id, entry] of Object.entries(functions)) {\n if (id.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn id must be a non-empty string.`,\n });\n }\n if (entry === null || typeof entry !== \"object\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn \"${id}\" entry must be an object with description, input, and handler.`,\n });\n }\n if (!isDeferredFn(entry)) {\n validateFnOptions(id, entry);\n }\n if (fnMap.has(id)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: duplicate fn id \"${id}\". Each fn id must be unique within a context.`,\n });\n }\n fnMap.set(id, entry);\n }\n if (!existingFns) {\n ctx.setStore(\n ADAPTER_FN_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n fnMap,\n );\n }\n\n const existingSkills = ctx.getStore(\n ADAPTER_SKILL_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, Skill> | undefined;\n const skillMap = existingSkills ?? new Map<string, Skill>();\n for (const [name, skill] of Object.entries(skillsMap)) {\n if (typeof name !== \"string\" || name.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: skill name must be a non-empty string.`,\n });\n }\n if (skill === null || typeof skill !== \"object\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: skill \"${name}\" entry must be an object with name, description, and content.`,\n });\n }\n if (skill.name !== name) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: skill key \"${name}\" does not match its \"name\" field \"${String(skill.name)}\". Keys and names must match so the registry has one canonical id per skill.`,\n });\n }\n if (\n typeof skill.description !== \"string\" ||\n skill.description.trim() === \"\"\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: skill \"${name}\" is missing a non-empty \"description\".`,\n });\n }\n if (typeof skill.content !== \"string\" || skill.content.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: skill \"${name}\" is missing non-empty \"content\". Skills inject their content into the agent's system prompt; an empty content would not change behaviour.`,\n });\n }\n if (skillMap.has(name)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: duplicate skill name \"${name}\". Each skill name must be unique within a context.`,\n });\n }\n skillMap.set(name, skill);\n }\n if (!existingSkills && skillMap.size > 0) {\n ctx.setStore(\n ADAPTER_SKILL_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n skillMap,\n );\n }\n\n if (defaultOptions !== undefined) {\n const existing = ctx.getStore(\n ADAPTER_AGENT_DEFAULT_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as AgentDefaultOptions | undefined;\n const merged = mergePluginDefaults(existing, defaultOptions);\n ctx.setStore(\n ADAPTER_AGENT_DEFAULT_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n merged,\n );\n }\n },\n };\n}\n\n/**\n * Validate the shape of `agentPlugin({ defaultOptions: ... })` at\n * plugin-construction time. Returns the validated value (with no\n * mutations) or undefined when no defaults were supplied.\n *\n * @internal\n */\nfunction validatePluginDefaults(\n raw: AgentDefaultOptions | undefined,\n): AgentDefaultOptions | undefined {\n if (raw === undefined) return undefined;\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"defaultOptions\" must be an object with optional \"model\" / \"tools\".`,\n });\n }\n if (raw.model !== undefined) {\n if (typeof raw.model !== \"string\" || raw.model.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"defaultOptions.model\" must be a non-empty \"providerId:modelName\" string.`,\n });\n }\n try {\n parseProviderModel(raw.model);\n } catch {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"defaultOptions.model\" must be in \"providerId:modelName\" form (e.g. anthropic:claude-opus-4-7). Got: \"${raw.model}\"`,\n });\n }\n }\n if (raw.tools !== undefined && !isToolSelection(raw.tools)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"defaultOptions.tools\" must be the result of tools([...]).`,\n });\n }\n return raw;\n}\n\n/**\n * Merge a freshly-supplied `defaultOptions` into the value already\n * stored by a previous `agentPlugin` install. Per-field conflicts\n * throw so a context cannot accidentally end up with two competing\n * defaults for the same field.\n *\n * @internal\n */\nfunction mergePluginDefaults(\n existing: AgentDefaultOptions | undefined,\n next: AgentDefaultOptions,\n): AgentDefaultOptions {\n if (!existing) return { ...next };\n if (next.model !== undefined && existing.model !== undefined) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"defaultOptions.model\" is already set on this context. A context can have only one default model.`,\n });\n }\n if (next.tools !== undefined && existing.tools !== undefined) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"defaultOptions.tools\" is already set on this context. Combine selectors into a single tools([...]) call.`,\n });\n }\n return {\n ...existing,\n ...(next.model !== undefined ? { model: next.model } : {}),\n ...(next.tools !== undefined ? { tools: next.tools } : {}),\n };\n}\n","import { registerConfigApplier } from \"@routecraft/routecraft\";\nimport { llmPlugin } from \"./llm/plugin.ts\";\nimport { mcpPlugin } from \"./mcp/plugin.ts\";\nimport { embeddingPlugin } from \"./embedding/plugin.ts\";\nimport { agentPlugin } from \"./agent/plugin.ts\";\nimport type { LlmPluginOptions } from \"./llm/types.ts\";\nimport type { McpPluginOptions } from \"./mcp/types.ts\";\nimport type { EmbeddingPluginOptions } from \"./embedding/types.ts\";\nimport type { AgentPluginOptions } from \"./agent/plugin.ts\";\n\n/**\n * Promote AI ecosystem plugins to first-class keys on `CraftConfig`. Once\n * `@routecraft/ai` is imported, users can write:\n *\n * ```typescript\n * import { defineConfig } from \"@routecraft/routecraft\";\n * import \"@routecraft/ai\";\n *\n * export default defineConfig({\n * llm: { providers: { openai: { apiKey: \"...\" } } },\n * mcp: { clients: { ... } },\n * embedding: { providers: { ... } },\n * agent: { agents: { ... }, functions: { ... } },\n * });\n * ```\n *\n * Each key carries the same options as the corresponding plugin factory and\n * participates in the standard plugin lifecycle (registered/starting/started\n * /stopping/stopped events; teardown on shutdown).\n *\n * The existing `llmPlugin`, `mcpPlugin`, `embeddingPlugin`, and `agentPlugin`\n * factories remain available for use via `plugins: [...]` (e.g. for shared\n * plugin instances or programmatic composition).\n */\ndeclare module \"@routecraft/routecraft\" {\n interface CraftConfig {\n /** LLM provider configuration. Equivalent to `plugins: [llmPlugin(...)]`. */\n llm?: LlmPluginOptions;\n /** MCP server / client configuration. Equivalent to `plugins: [mcpPlugin(...)]`. */\n mcp?: McpPluginOptions;\n /** Embedding provider configuration. Equivalent to `plugins: [embeddingPlugin(...)]`. */\n embedding?: EmbeddingPluginOptions;\n /** Agent and tool registry. Equivalent to `plugins: [agentPlugin(...)]`. */\n agent?: AgentPluginOptions;\n }\n}\n\nregisterConfigApplier(\"llm\", (options) => llmPlugin(options));\nregisterConfigApplier(\"mcp\", (options) => mcpPlugin(options));\nregisterConfigApplier(\"embedding\", (options) => embeddingPlugin(options));\nregisterConfigApplier(\"agent\", (options) => agentPlugin(options));\n","/**\n * Cross-instance identity for @routecraft/ai: Symbol.for() keys and type guards.\n * Shared across all copies of @routecraft/ai (and multiple routecraft versions) in a process.\n */\n\nexport const BRAND = {\n McpAdapter: Symbol.for(\"routecraft.ai.McpAdapter\"),\n} as const;\n\nfunction isBranded(obj: unknown, key: symbol): boolean {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n (obj as Record<symbol, unknown>)[key] === true\n );\n}\n\nexport function isMcpAdapter(obj: unknown): boolean {\n return isBranded(obj, BRAND.McpAdapter);\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport {\n getExchangeContext,\n type CraftContext,\n type Destination,\n type Exchange,\n type MergedOptions,\n} from \"@routecraft/routecraft\";\nimport { callLlm } from \"./providers/index.ts\";\nimport {\n parseProviderModel,\n resolveModel,\n resolvePrompt,\n resolveUserPromptDefault,\n} from \"./shared.ts\";\nimport { toAiOutputSpec } from \"./structured-output.ts\";\nimport type {\n LlmOptions,\n LlmOptionsMerged,\n LlmResultWithOutput,\n} from \"./types.ts\";\nimport { ADAPTER_LLM_OPTIONS } from \"./types.ts\";\n\n/**\n * When the AI SDK doesn't set result.output (e.g. it threw on the getter), try to\n * parse result.text as JSON and validate with the output schema. Returns the\n * parsed value or undefined. Handles both sync and async Standard Schema validate().\n */\nasync function parseStructuredTextFallback(\n text: string,\n schema: StandardSchemaV1,\n): Promise<unknown> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return undefined;\n }\n const standard = (schema as unknown as Record<string, unknown>)[\n \"~standard\"\n ] as\n | {\n validate: (\n value: unknown,\n ) =>\n | { value?: unknown; issues?: unknown }\n | Promise<{ value?: unknown; issues?: unknown }>;\n }\n | undefined;\n if (!standard?.validate) return undefined;\n let result = standard.validate(parsed);\n if (result instanceof Promise) result = await result;\n if (\n result &&\n typeof result === \"object\" &&\n \"issues\" in result &&\n result.issues\n )\n return undefined;\n return result && typeof result === \"object\" && \"value\" in result\n ? result.value\n : undefined;\n}\n\nconst DEFAULT_TEMPERATURE = 0;\nconst DEFAULT_MAX_TOKENS = 1024;\n\n/**\n * LLM destination adapter. Expects model id as \"providerId:modelName\" (e.g. ollama:lfm2.5-thinking),\n * resolves the provider from the plugin store, merges options, and calls the provider with the model name.\n * Use with .enrich(llm(\"providerId:modelName\", options)) or .to(llm(...)).\n *\n * @template S - Output schema type when an `output` schema is provided; narrows result.output for downstream typing.\n */\nexport class LlmDestinationAdapter<\n S extends StandardSchemaV1 | undefined = undefined,\n>\n implements\n Destination<unknown, LlmResultWithOutput<S>>,\n MergedOptions<LlmOptionsMerged>\n{\n readonly adapterId = \"routecraft.adapter.llm\";\n\n constructor(\n private readonly modelId: string,\n options: LlmOptions = {},\n ) {\n this.options = options as Partial<LlmOptionsMerged>;\n }\n\n public options: Partial<LlmOptionsMerged>;\n\n mergedOptions(context: CraftContext): LlmOptionsMerged {\n const store = context.getStore(\n ADAPTER_LLM_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Partial<LlmOptionsMerged> | undefined;\n return {\n temperature: DEFAULT_TEMPERATURE,\n maxTokens: DEFAULT_MAX_TOKENS,\n ...store,\n ...this.options,\n } as LlmOptionsMerged;\n }\n\n async send(exchange: Exchange<unknown>): Promise<LlmResultWithOutput<S>> {\n const context = getExchangeContext(exchange);\n const { config, modelName } = resolveModel(this.modelId, context);\n const merged = this.mergedOptions(context!);\n\n const system = resolvePrompt(merged.system, exchange);\n const user =\n resolvePrompt(merged.user, exchange) ||\n resolveUserPromptDefault(exchange);\n\n const opts: Parameters<typeof callLlm>[0][\"options\"] = {\n temperature: merged.temperature,\n maxTokens: merged.maxTokens,\n };\n if (merged.topP !== undefined) opts.topP = merged.topP;\n if (merged.frequencyPenalty !== undefined)\n opts.frequencyPenalty = merged.frequencyPenalty;\n if (merged.presencePenalty !== undefined)\n opts.presencePenalty = merged.presencePenalty;\n\n const output =\n merged.output !== undefined ? toAiOutputSpec(merged.output) : undefined;\n\n const result = await callLlm({\n config,\n modelId: modelName,\n options: opts,\n system,\n user,\n output,\n });\n\n if (\n result.output === undefined &&\n result.text &&\n merged.output !== undefined\n ) {\n const fallback = await parseStructuredTextFallback(\n result.text,\n merged.output,\n );\n if (fallback !== undefined) result.output = fallback;\n }\n\n return result as LlmResultWithOutput<S>;\n }\n\n /**\n * Extract metadata from LLM result for observability.\n * Includes model, provider, and token usage.\n */\n getMetadata(result: unknown): Record<string, unknown> {\n const llmResult = result as LlmResultWithOutput<S>;\n const { providerId } = parseProviderModel(this.modelId);\n\n const metadata: Record<string, unknown> = {\n model: this.modelId,\n provider: providerId,\n };\n\n if (llmResult.usage) {\n if (llmResult.usage[\"inputTokens\"] !== undefined) {\n metadata[\"inputTokens\"] = llmResult.usage[\"inputTokens\"];\n }\n if (llmResult.usage[\"outputTokens\"] !== undefined) {\n metadata[\"outputTokens\"] = llmResult.usage[\"outputTokens\"];\n }\n }\n\n return metadata;\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { Destination } from \"@routecraft/routecraft\";\nimport { LlmDestinationAdapter } from \"./destination.ts\";\nimport type { LlmOptions, LlmResultWithOutput } from \"./types.ts\";\nimport type { RegisteredLlmModelId } from \"../registry.ts\";\n\n/**\n * Creates an LLM destination that calls a provider with a model. Use with .enrich() or .to().\n * Pass model id as \"providerId:modelName\" (e.g. ollama:lfm2.5-thinking). The provider must be\n * registered via llmPlugin({ providers: { ollama: { provider: \"ollama\" }, ... } }).\n * When options.output is provided, the result type narrows so body.output is typed downstream.\n *\n * @param modelId - \"providerId:modelName\"; the provider is resolved from the plugin, the model name is sent to the provider.\n * @param options - Optional overrides (system, user, temperature, maxTokens, output, etc.). User prompt defaults to exchange.body.\n */\nexport function llm<S extends StandardSchemaV1 | undefined = undefined>(\n modelId: RegisteredLlmModelId,\n options?: LlmOptions & { output?: S },\n): Destination<unknown, LlmResultWithOutput<S>> {\n return new LlmDestinationAdapter<S>(modelId, options);\n}\n","/**\n * Brand symbol for MCP adapter type checking.\n * Used internally to identify MCP adapters.\n * @internal\n */\nexport const BRAND_MCP_ADAPTER = Symbol.for(\"routecraft.mcp.adapter\");\n","import {\n rcError,\n type CraftContext,\n type Exchange,\n type ExchangeHeaders,\n type OnParseError,\n type Principal,\n type Source,\n type SourceMeta,\n} from \"@routecraft/routecraft\";\nimport {\n MCP_LOCAL_TOOL_REGISTRY,\n MCP_PLUGIN_REGISTERED,\n type McpLocalToolEntry,\n type McpServerOptions,\n} from \"../../types.ts\";\nimport type { McpMessage } from \"./types.ts\";\nimport { BRAND_MCP_ADAPTER } from \"./shared.ts\";\n\n/**\n * Characters allowed in an MCP tool name. Matches OpenAI's function-calling\n * constraint (the strictest mainstream LLM client), which all major MCP\n * client implementations respect: ASCII letters, digits, underscore, and\n * hyphen, with a 1-64 length bound. Keeping tool names in this set ensures\n * the `tool.name` field survives `tools/list` -> LLM function-calling\n * without further mangling.\n */\nconst MCP_TOOL_NAME_RE = /^[A-Za-z0-9_-]{1,64}$/;\n\nfunction assertValidMcpToolName(endpoint: string): void {\n if (!MCP_TOOL_NAME_RE.test(endpoint)) {\n throw rcError(\"RC5003\", undefined, {\n message: `Invalid MCP tool name \"${endpoint}\"`,\n suggestion:\n \"MCP tool names must match /^[A-Za-z0-9_-]{1,64}$/ for client interoperability (OpenAI, Anthropic, etc.). Use alphanumerics, underscore, or hyphen in the route's .id().\",\n });\n }\n}\n\n/**\n * McpSourceAdapter exposes a route as an MCP tool.\n *\n * The tool name is the route id (validated against the MCP protocol name\n * regex). The tool's title / description / input / output schemas come\n * from the route's discovery bundle (`.title()` / `.description()` /\n * `.input()` / `.output()`); framework-level input validation is applied\n * before the route handler runs. Adapter options hold only MCP-protocol\n * extras (annotations, icons).\n *\n * Maintains its own registry ({@link MCP_LOCAL_TOOL_REGISTRY}) so MCP and\n * direct routes stay fully isolated: a shared endpoint string does not\n * collide, and direct routes never leak into MCP `tools/list`.\n */\nexport class McpSourceAdapter implements Source<McpMessage<undefined>> {\n readonly adapterId: string = \"routecraft.adapter.mcp\";\n\n private options: McpServerOptions;\n\n constructor(options: McpServerOptions = {}) {\n (this as unknown as Record<symbol, boolean>)[BRAND_MCP_ADAPTER] = true;\n this.options = options;\n }\n\n async subscribe(\n context: CraftContext,\n handler: (\n message: McpMessage<undefined>,\n headers?: ExchangeHeaders,\n parse?: (raw: unknown) => unknown | Promise<unknown>,\n parseFailureMode?: OnParseError,\n principal?: Principal | undefined,\n ) => Promise<Exchange>,\n abortController: AbortController,\n onReady?: () => void,\n meta?: SourceMeta,\n ): Promise<void> {\n if (!meta?.routeId) {\n throw rcError(\"RC5003\", undefined, {\n message:\n \"McpSourceAdapter requires a route id from the engine (missing SourceMeta.routeId)\",\n suggestion:\n \"MCP source adapters take their tool name from the route id. Call .id('tool-name') on the route before .from(mcp(...)).\",\n });\n }\n\n const endpoint = meta.routeId;\n assertValidMcpToolName(endpoint);\n\n const discovery = meta.discovery;\n const description = discovery?.description;\n if (typeof description !== \"string\" || description.length === 0) {\n throw rcError(\"RC5003\", undefined, {\n message: `MCP route \"${endpoint}\" requires a description`,\n suggestion:\n \"Set .description('...') on the route builder before .from(mcp()); the MCP protocol requires a non-empty description for each tool.\",\n });\n }\n\n const registered = context.getStore(\n MCP_PLUGIN_REGISTERED as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as boolean | undefined;\n if (registered !== true) {\n throw new Error(\n \"MCP plugin required: routes using .from(mcp(...)) require the MCP plugin. Add mcpPlugin() to your config: plugins: [mcpPlugin()].\",\n );\n }\n\n let registry = context.getStore(\n MCP_LOCAL_TOOL_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, McpLocalToolEntry> | undefined;\n if (!registry) {\n registry = new Map<string, McpLocalToolEntry>();\n context.setStore(\n MCP_LOCAL_TOOL_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n registry,\n );\n }\n\n if (registry.has(endpoint)) {\n throw rcError(\"RC5003\", undefined, {\n message: `Duplicate MCP tool endpoint \"${endpoint}\": another .from(mcp(...)) route already registered this endpoint in the same context`,\n suggestion:\n \"Each MCP tool endpoint must be unique within a context. Rename one of the mcp() routes to a different route id.\",\n });\n }\n\n // The engine applies input validation before the handler runs, so the\n // MCP adapter just hands the exchange body / headers through. The\n // principal (set by the MCP server when auth is configured) rides\n // through as the 5th argument so the route's exchange surfaces the\n // same identity.\n const entryHandler = async (exchange: Exchange): Promise<Exchange> => {\n return handler(\n exchange.body as McpMessage<undefined>,\n exchange.headers,\n undefined,\n undefined,\n exchange.principal,\n ) as Promise<Exchange>;\n };\n\n const entry: McpLocalToolEntry = {\n endpoint,\n description,\n handler: entryHandler,\n };\n if (discovery?.title !== undefined) entry.title = discovery.title;\n if (discovery?.input !== undefined) entry.input = discovery.input;\n if (discovery?.output !== undefined) entry.output = discovery.output;\n if (this.options.annotations !== undefined) {\n entry.annotations = this.options.annotations;\n }\n if (this.options.icons !== undefined) entry.icons = this.options.icons;\n\n // Register the cleanup listener before the insert. Any abort from now on\n // (including one dispatched synchronously from inside addEventListener if\n // the signal is already aborted) will run the cleanup, so the entry never\n // outlives its teardown handler.\n abortController.signal.addEventListener(\n \"abort\",\n () => {\n const current = context.getStore(\n MCP_LOCAL_TOOL_REGISTRY as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, McpLocalToolEntry> | undefined;\n current?.delete(endpoint);\n },\n { once: true },\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n\n registry.set(endpoint, entry);\n\n onReady?.();\n\n await new Promise<void>((resolve) => {\n if (abortController.signal.aborted) {\n resolve();\n return;\n }\n abortController.signal.addEventListener(\"abort\", () => resolve(), {\n once: true,\n });\n });\n }\n}\n","import type { Exchange, Destination } from \"@routecraft/routecraft\";\nimport { getExchangeContext } from \"@routecraft/routecraft\";\nimport type {\n McpClientOptions,\n McpArgsExtractor,\n McpClientAuthOptions,\n McpClientHttpConfig,\n} from \"../../types.ts\";\nimport { ADAPTER_MCP_CLIENT_SERVERS } from \"../../types.ts\";\nimport { BRAND_MCP_ADAPTER } from \"./shared.ts\";\nimport { callRemoteTool, dispatchMcpCall } from \"../../dispatch.ts\";\n\n/** Ensure inline url is HTTP(S) only. Stdio clients are reached via dispatchMcpCall. */\nfunction assertHttpUrl(url: string): void {\n const trimmed = url.trim().toLowerCase();\n if (!trimmed.startsWith(\"http://\") && !trimmed.startsWith(\"https://\")) {\n throw new Error(\n `MCP client: url must be HTTP or HTTPS. Stdio is not supported in routes; register stdio clients via mcpPlugin({ clients: { name: { command, args } } }). Got: \"${url.slice(0, 50)}${url.length > 50 ? \"...\" : \"\"}\"`,\n );\n }\n}\n\n/**\n * Look up the registered server config from the context store.\n * Returns undefined when no context or no matching serverId.\n * Backward-compat: store value may be a plain string (url only).\n */\nfunction resolveServerConfig(\n options: McpClientOptions,\n context: ReturnType<typeof getExchangeContext>,\n): McpClientHttpConfig | string | undefined {\n if (!options.serverId || !context) return undefined;\n const servers = context.getStore(ADAPTER_MCP_CLIENT_SERVERS);\n const cfg = servers?.get(options.serverId);\n if (cfg && typeof cfg === \"object\" && \"transport\" in cfg) {\n // stdio configs surface through dispatchMcpCall; resolveConnection only\n // needs the http variant for the inline-URL or http-serverId fall-through.\n return undefined;\n }\n return cfg as McpClientHttpConfig | string | undefined;\n}\n\n/**\n * Resolves the URL and auth for the MCP server from options or context (serverId).\n * Returns both in a single lookup to avoid duplicate store reads.\n */\nfunction resolveConnection(\n options: McpClientOptions,\n context: ReturnType<typeof getExchangeContext>,\n): { url: string; auth?: McpClientAuthOptions | undefined } {\n if (options.url) {\n assertHttpUrl(options.url);\n return { url: options.url, auth: options.auth };\n }\n if (options.serverId && !context) {\n throw new Error(\n `MCP client: serverId \"${options.serverId}\" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store \"${String(ADAPTER_MCP_CLIENT_SERVERS)}\" can be read.`,\n );\n }\n if (options.serverId && context) {\n const config = resolveServerConfig(options, context);\n if (!config) {\n throw new Error(\n `MCP client: serverId \"${options.serverId}\" not found in context store. Register it with context store key \"${String(ADAPTER_MCP_CLIENT_SERVERS)}\".`,\n );\n }\n const url = typeof config === \"string\" ? config : config.url;\n const auth =\n options.auth ??\n (typeof config === \"object\" && \"auth\" in config\n ? config.auth\n : undefined);\n return { url, auth };\n }\n throw new Error(\n \"MCP client: either url or serverId must be provided in McpClientOptions.\",\n );\n}\n\n/**\n * Default args extractor: use exchange body as tool arguments.\n * If body is a non-null object, use it as the args; otherwise use { input: body }.\n */\nexport const defaultArgs: McpArgsExtractor = (exchange) =>\n typeof exchange.body === \"object\" && exchange.body !== null\n ? (exchange.body as Record<string, unknown>)\n : { input: exchange.body };\n\n/**\n * McpDestinationAdapter implements the Destination interface for the MCP adapter.\n *\n * This adapter is used when mcp() is called with client options:\n * - `mcp({ url, tool })` - Direct HTTP URL\n * - `mcp({ serverId, tool })` - Server registered via mcpPlugin\n * - `mcp('server:tool')` - Shorthand for serverId:tool\n *\n * It makes HTTP calls to remote MCP servers using the MCP SDK.\n */\nexport class McpDestinationAdapter implements Destination<unknown, unknown> {\n readonly adapterId: string = \"routecraft.adapter.mcp\";\n\n constructor(private readonly options: McpClientOptions) {\n (this as unknown as Record<symbol, boolean>)[BRAND_MCP_ADAPTER] = true;\n\n // Validate client options\n if (!options.url && !options.serverId) {\n throw new Error(\n \"MCP client: either url or serverId must be provided in McpClientOptions.\",\n );\n }\n\n if (options.url && options.serverId) {\n throw new Error(\n \"MCP client: cannot provide both url and serverId. Use either url for direct HTTP or serverId for registered servers.\",\n );\n }\n }\n\n async send(exchange: Exchange<unknown>): Promise<unknown> {\n const context = getExchangeContext(exchange);\n const toolName =\n this.options.tool ??\n (typeof exchange.body === \"object\" &&\n exchange.body !== null &&\n \"tool\" in exchange.body &&\n typeof (exchange.body as { tool: string }).tool === \"string\"\n ? (exchange.body as { tool: string }).tool\n : undefined);\n if (!toolName) {\n throw new Error(\n \"MCP client: tool name required. Set options.tool or exchange.body.tool.\",\n );\n }\n const argsExtractor = this.options.args ?? defaultArgs;\n const args = argsExtractor(exchange);\n\n // serverId path -> registered MCP client (stdio or http). Delegates\n // to `dispatchMcpCall` so transport selection (stdio manager vs\n // one-shot HTTP client), missing-client diagnostics, and resource\n // cleanup all live in one place shared with the agent\n // `tools([...])` resolver.\n if (this.options.serverId) {\n if (!context) {\n throw new Error(\n `MCP client: serverId \"${this.options.serverId}\" requires a context to resolve. Ensure the exchange has context (e.g. from a route).`,\n );\n }\n const transport = resolveServerTransport(context, this.options.serverId);\n const result = await dispatchMcpCall(\n context,\n this.options.serverId,\n toolName,\n args,\n );\n if (result && typeof result === \"object\") {\n (result as Record<string, unknown>)[\"metadata\"] = {\n toolName,\n transport,\n serverId: this.options.serverId,\n };\n }\n return result;\n }\n\n // Inline-URL path -> direct HTTP call without going through the\n // registry. Uses the shared `callRemoteTool` helper so transport\n // setup, auth-header building, and cleanup stay aligned with\n // `dispatchMcpCall`.\n const { url, auth } = resolveConnection(this.options, context);\n const result = await callRemoteTool(url, toolName, args, auth);\n if (result && typeof result === \"object\") {\n (result as Record<string, unknown>)[\"metadata\"] = {\n toolName,\n url,\n transport: \"http\",\n };\n }\n return result;\n }\n\n /**\n * Extract metadata from MCP adapter execution.\n * Reads metadata from the result object to avoid race conditions with concurrent exchanges.\n */\n getMetadata(result: unknown): Record<string, unknown> {\n if (result && typeof result === \"object\" && \"metadata\" in result) {\n return (result as { metadata: Record<string, unknown> }).metadata;\n }\n return {\n toolName: \"unknown\",\n transport: \"unknown\",\n };\n }\n}\n\n/**\n * Look up the transport label for a registered MCP server so the\n * destination's metadata reflects what `dispatchMcpCall` actually\n * used. Falls back to `\"http\"` because that's the default for\n * registered clients without an explicit transport tag (stdio configs\n * carry `transport: \"stdio\"` explicitly).\n */\nfunction resolveServerTransport(\n context: NonNullable<ReturnType<typeof getExchangeContext>>,\n serverId: string,\n): \"stdio\" | \"http\" {\n const servers = context.getStore(ADAPTER_MCP_CLIENT_SERVERS);\n const cfg = servers?.get(serverId);\n if (\n cfg &&\n typeof cfg === \"object\" &&\n \"transport\" in cfg &&\n (cfg as { transport: string }).transport === \"stdio\"\n ) {\n return \"stdio\";\n }\n return \"http\";\n}\n","import {\n rcError,\n tagAdapter,\n factoryArgs,\n type Source,\n type Destination,\n} from \"@routecraft/routecraft\";\nimport type {\n McpArgsExtractor,\n McpClientOptions,\n McpServerOptions,\n} from \"../../types.ts\";\nimport type { RegisteredMcpShorthand } from \"../../../registry.ts\";\nimport { McpSourceAdapter } from \"./source.ts\";\nimport { McpDestinationAdapter } from \"./destination.ts\";\nimport type { McpMessage } from \"./types.ts\";\n\n/**\n * Creates an MCP adapter.\n *\n * - **Source (for `.from()`):** Call with no arguments or with MCP-protocol\n * options (`annotations`, `icons`). The tool name is the route id; the\n * description, title, and input / output schemas come from the route\n * builder (`.description()`, `.title()`, `.input()`, `.output()`) and a\n * non-empty `.description()` is required. Requires `mcpPlugin()`.\n *\n * - **Destination (for `.to()` / `.tap()`):** Call with client options:\n * - `mcp({ url, tool })` - Direct HTTP URL to remote MCP server\n * - `mcp({ serverId, tool })` - Server ID registered via mcpPlugin({ clients })\n * - `mcp('server:tool', { args? })` - Shorthand for serverId:tool with optional args extractor\n *\n * @example\n * ```ts\n * // Source route (tool name = route id)\n * craft()\n * .id(\"search\")\n * .description(\"Search documents\")\n * .input({ body: mySchema })\n * .from(mcp({ annotations: { readOnlyHint: true } }))\n *\n * // Destination (call remote MCP server)\n * .to(mcp({ url: 'http://localhost:3001/mcp', tool: 'search' }))\n * .to(mcp({ serverId: 'my-server', tool: 'search' }))\n * .to(mcp('my-server:search'))\n * .to(mcp('my-server:search', { args: (ex) => ex.body.params }))\n * ```\n */\nexport function mcp(options?: McpServerOptions): Source<McpMessage<undefined>>;\nexport function mcp(\n clientOptions: McpClientOptions,\n): Destination<unknown, unknown>;\nexport function mcp(\n shorthand: RegisteredMcpShorthand,\n options?: { args?: McpArgsExtractor },\n): Destination<unknown, unknown>;\nexport function mcp(\n arg?: McpServerOptions | McpClientOptions | RegisteredMcpShorthand,\n options?: { args?: McpArgsExtractor },\n): Source<McpMessage<undefined>> | Destination<unknown, unknown> {\n // Client (object): url or serverId present\n if (\n typeof arg === \"object\" &&\n arg !== null &&\n (\"url\" in arg || \"serverId\" in arg)\n ) {\n const clientOpts = arg as McpClientOptions;\n if (typeof clientOpts.auth?.token === \"string\") {\n if (clientOpts.auth.token.trim().length === 0) {\n throw new TypeError(\n \"mcp(): auth.token must be a non-empty string when provided\",\n );\n }\n }\n if (Array.isArray(clientOpts.auth?.token)) {\n if (clientOpts.auth.token.length === 0) {\n throw new TypeError(\"mcp(): auth.token array must not be empty\");\n }\n for (let i = 0; i < clientOpts.auth.token.length; i++) {\n const entry = clientOpts.auth.token[i];\n if (typeof entry !== \"string\" || entry.trim().length === 0) {\n throw new TypeError(\n `mcp(): auth.token[${i}] must be a non-empty string`,\n );\n }\n }\n }\n return tagAdapter(\n new McpDestinationAdapter(clientOpts),\n mcp,\n factoryArgs(arg, options),\n );\n }\n\n // Client: \"server:tool\" shorthand string\n if (typeof arg === \"string\" && arg.includes(\":\")) {\n const colonIndex = arg.indexOf(\":\");\n const serverId = arg.slice(0, colonIndex);\n const tool = arg.slice(colonIndex + 1);\n const clientOptions: McpClientOptions = { serverId, tool };\n if (\n options !== undefined &&\n typeof options === \"object\" &&\n \"args\" in options &&\n options.args !== undefined\n ) {\n clientOptions.args = options.args as McpArgsExtractor;\n }\n return tagAdapter(\n new McpDestinationAdapter(clientOptions),\n mcp,\n factoryArgs(arg, options),\n );\n }\n\n // A bare string without a colon is not a valid call: it is neither\n // a client shorthand (requires \"server:tool\") nor a source options\n // object. Point users at the right overload.\n if (typeof arg === \"string\") {\n throw rcError(\"RC5003\", undefined, {\n message: `mcp(${JSON.stringify(arg)}) is not a valid call: a bare string without \":\" is neither a client shorthand nor source options`,\n suggestion:\n \"Use .from(mcp()) for a source (tool name comes from .id()), .to(mcp({ url, tool })) for a remote server, .to(mcp('server:tool')) for a registered shorthand, or direct('name') for in-process dispatch.\",\n });\n }\n\n // Source: undefined or server options (annotations / icons)\n return tagAdapter(\n new McpSourceAdapter((arg as McpServerOptions) ?? {}),\n mcp,\n factoryArgs(arg, options),\n );\n}\n\n// Re-export types for public API\nexport type {\n McpMessage,\n McpArgsExtractor,\n McpClientHttpConfig,\n} from \"./types\";\nexport { BRAND_MCP_ADAPTER } from \"./shared\";\nexport { defaultArgs } from \"./destination\";\n","import type {\n OAuthPrincipal,\n OAuthTokenVerifier,\n OAuthValidatorAuthOptions,\n} from \"@routecraft/routecraft\";\nimport type {\n OAuthAuthOptions,\n OAuthClientInfo,\n OAuthProxyEndpoints,\n} from \"./types.ts\";\n\n/**\n * Supplier for a registered OAuth client.\n *\n * Called **per request** by the MCP SDK's proxy provider during the OAuth\n * flow (authorize, token exchange, revoke) with the incoming `client_id`.\n * Return the matching {@link OAuthClientInfo} or `undefined` to reject the\n * client with a standard OAuth error.\n *\n * Avoid blocking I/O on the hot path when possible. Cache database reads or\n * load the registry at boot.\n */\nexport type OAuthClientSupplier = (\n clientId: string,\n) => Promise<OAuthClientInfo | undefined> | OAuthClientInfo | undefined;\n\n/**\n * The `verify` option accepted by `oauth()`.\n *\n * Pass:\n * - An `OAuthValidatorAuthOptions` (output of `jwt()` or `jwks()`) to compose\n * a validator-based verifier, or\n * - A raw `OAuthTokenVerifier` function for custom logic.\n *\n * Both shapes guarantee an {@link OAuthPrincipal} with `expiresAt`, which the\n * MCP SDK's bearer middleware requires. The type system rejects verifiers\n * that do not uphold that contract -- no more runtime surprises from a\n * well-typed verifier that forgot to populate `expiresAt`.\n */\nexport type OAuthVerifier = OAuthValidatorAuthOptions | OAuthTokenVerifier;\n\n/**\n * Options for the `oauth()` factory.\n */\nexport interface OAuthFactoryOptions {\n /** Base URL for OAuth endpoints (defaults to the resolved resource URL). */\n baseUrl?: string | URL;\n /** Upstream OAuth provider endpoints to proxy. */\n endpoints: OAuthProxyEndpoints;\n /**\n * Token verifier for access tokens arriving at `/mcp`.\n *\n * Accept:\n * - `jwks({ jwksUrl, issuer, audience })` -- JWKS-backed verification (the common case)\n * - `jwt({ secret, issuer, audience })` -- static-key verification (rare)\n * - A raw `(token) => Principal | Promise<Principal>` function -- custom logic\n *\n * The verifier is called on every authenticated request.\n */\n verify: OAuthVerifier;\n /**\n * Registered OAuth client(s). Accepts either:\n * - a static {@link OAuthClientInfo} for the single-client case (matched on\n * `client_id`; unknown IDs are rejected), or\n * - an {@link OAuthClientSupplier} `(clientId) => OAuthClientInfo | undefined`\n * for dynamic lookup (database, registry, etc.).\n *\n * The supplier is invoked **per request** by the MCP SDK's proxy provider\n * during every authorize/token/revoke call; treat it as a hot path.\n */\n client: OAuthClientInfo | OAuthClientSupplier;\n /** Scopes required on every request to `/mcp`. Enforcement policy, not metadata. */\n requiredScopes?: string[];\n}\n\n/**\n * Normalise the factory-level `client` option into the `(clientId) =>\n * Promise<OAuthClientInfo | undefined>` shape expected by the MCP SDK's\n * `ProxyOAuthServerProvider`.\n *\n * When a static {@link OAuthClientInfo} is supplied, the returned lookup\n * accepts only requests whose `clientId` matches the object's `client_id`;\n * unknown IDs are rejected so an accidental single-client setup cannot\n * silently authorize other clients.\n */\nfunction normaliseClientSupplier(\n input: OAuthClientInfo | OAuthClientSupplier,\n): (clientId: string) => Promise<OAuthClientInfo | undefined> {\n if (typeof input === \"function\") {\n return async (clientId) => input(clientId);\n }\n const staticClient = input;\n return async (clientId) =>\n clientId === staticClient.client_id ? staticClient : undefined;\n}\n\n/**\n * Normalise the `verify` option into a `(token) => Promise<OAuthPrincipal>`\n * callback.\n */\nfunction buildVerifier(\n verify: OAuthVerifier,\n): (token: string) => Promise<OAuthPrincipal> {\n if (!verify) {\n throw new TypeError(\n \"oauth: `verify` is required. Pass jwks(...), jwt(...), or a custom (token) => OAuthPrincipal function.\",\n );\n }\n if (typeof verify === \"function\") {\n return async (token) => verify(token);\n }\n return async (token) => verify.validator(token);\n}\n\n/**\n * Built-in OAuth authentication helper for MCP HTTP servers.\n * Configures a full OAuth 2.1 server flow that proxies to an upstream identity\n * provider using the MCP SDK's `ProxyOAuthServerProvider` and `mcpAuthRouter`.\n *\n * Returns an {@link OAuthAuthOptions} that can be passed directly to\n * `mcpPlugin({ auth: oauth({ ... }) })`.\n *\n * The server will mount OAuth endpoints (`/.well-known/oauth-authorization-server`,\n * `/authorize`, `/token`, `/revoke`) alongside the `/mcp` transport endpoint.\n *\n * @example JWKS-backed OAuth (e.g. Clerk)\n * ```ts\n * import { mcpPlugin, oauth, jwks } from \"@routecraft/ai\";\n *\n * mcpPlugin({\n * transport: \"http\",\n * resource: { url: \"https://mcp.example.com\" },\n * auth: oauth({\n * endpoints: {\n * authorizationUrl: \"https://idp.example.com/authorize\",\n * tokenUrl: \"https://idp.example.com/token\",\n * },\n * verify: jwks({\n * jwksUrl: \"https://idp.example.com/.well-known/jwks.json\",\n * issuer: \"https://idp.example.com\",\n * audience: \"https://mcp.example.com\",\n * }),\n * client: {\n * client_id: \"my-mcp-server\",\n * redirect_uris: [\"http://localhost:3000/callback\"],\n * },\n * }),\n * });\n * ```\n *\n * @example Dynamic client lookup (e.g. DCR, database-backed registry)\n * ```ts\n * oauth({\n * // ...\n * client: async (clientId) => await db.clients.findByClientId(clientId),\n * })\n * ```\n *\n * @example Custom verification (opaque tokens, introspection, etc.)\n * ```ts\n * oauth({\n * endpoints: { authorizationUrl: \"...\", tokenUrl: \"...\" },\n * verify: async (token) => {\n * const principal = await myIntrospectionCall(token);\n * return {\n * kind: \"custom\",\n * scheme: \"bearer\",\n * subject: principal.userId,\n * clientId: principal.clientId,\n * expiresAt: principal.exp,\n * };\n * },\n * client: { ... },\n * });\n * ```\n */\nexport function oauth(options: OAuthFactoryOptions): OAuthAuthOptions {\n if (!options.verify) {\n throw new TypeError(\n \"oauth: `verify` is required. Pass jwks(...), jwt(...), or a custom (token) => OAuthPrincipal function.\",\n );\n }\n const verifyAccessToken = buildVerifier(options.verify);\n const getClient = normaliseClientSupplier(options.client);\n\n // Surface the IdP issuer from the verify helper so the server can resolve\n // the OIDC Discovery document for plugin-level `userinfo: true`. Principal\n // enrichment itself lives on `mcpPlugin({ userinfo })`, orthogonal to the\n // auth mode (mirrors how `resource` was promoted off `oauth()`).\n const verifyIssuer =\n typeof options.verify === \"function\" ? undefined : options.verify.issuer;\n\n const result: OAuthAuthOptions = {\n provider: \"oauth\",\n endpoints: options.endpoints,\n verifyAccessToken,\n getClient,\n ...(verifyIssuer !== undefined && { issuer: verifyIssuer }),\n ...(options.baseUrl !== undefined && { baseUrl: options.baseUrl }),\n ...(options.requiredScopes !== undefined && {\n requiredScopes: options.requiredScopes,\n }),\n };\n\n return result;\n}\n","import { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join, resolve, basename, extname } from \"node:path\";\nimport { rcError } from \"@routecraft/routecraft\";\n\n/**\n * Parsed markdown document: front matter as a plain object plus the\n * remaining body. Returned by {@link readMarkdownFile}.\n *\n * @internal\n */\nexport interface ParsedMarkdown {\n /** Path the document was read from. */\n path: string;\n /** Filename without extension. Matches the agent / skill `name` after validation. */\n filename: string;\n /** Parsed YAML front matter. Empty object when no front matter is present. */\n frontmatter: Record<string, unknown>;\n /** Trimmed body (everything after the front-matter block). */\n body: string;\n}\n\n/**\n * YAML parser shape we depend on. Lazy-loaded the first time a\n * markdown loader runs so the `yaml` package can be an optional peer\n * dependency: callers that never invoke `agents()` / `skills()` do\n * not need to install it, and it stays out of `@routecraft/ai`'s\n * static import graph (size-limit is enforced on the entry bundle).\n *\n * @internal\n */\ntype YamlParse = (text: string) => unknown;\nlet cachedParseYaml: YamlParse | undefined;\n\nasync function loadYamlParse(): Promise<YamlParse> {\n if (cachedParseYaml) return cachedParseYaml;\n try {\n const mod = (await import(\"yaml\")) as { parse: YamlParse };\n cachedParseYaml = mod.parse;\n return cachedParseYaml;\n } catch (err) {\n if (\n err instanceof Error &&\n (err.message.includes(\"ERR_MODULE_NOT_FOUND\") ||\n err.message.includes(\"Cannot find module\") ||\n err.message.includes(\"Cannot find package\")) &&\n err.message.includes(\"yaml\")\n ) {\n throw new Error(\n `The markdown loaders (agents()/skills()) require the \"yaml\" package. Install it with: bun add yaml`,\n );\n }\n throw err;\n }\n}\n\n/**\n * Strip a `--- ... ---` YAML front-matter block from the start of the\n * file and return the parsed object plus the body. Files without a\n * leading `---` are treated as having no front matter (frontmatter is\n * `{}` and body is the full content).\n *\n * @internal\n */\nasync function splitFrontmatter(\n raw: string,\n path: string,\n): Promise<ParsedMarkdown> {\n const filename = basename(path, extname(path));\n if (!raw.startsWith(\"---\")) {\n return {\n path,\n filename,\n frontmatter: {},\n body: raw.trim(),\n };\n }\n const end = raw.indexOf(\"\\n---\", 3);\n if (end === -1) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${path}\": opened a YAML front-matter block with \"---\" but never closed it. Add a closing \"---\" line before the body.`,\n });\n }\n const yamlText = raw.slice(3, end).trim();\n const body = raw.slice(end + 4).trim();\n let parsed: unknown;\n try {\n if (yamlText) {\n const parseYaml = await loadYamlParse();\n parsed = parseYaml(yamlText);\n } else {\n parsed = {};\n }\n } catch (err) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${path}\": YAML front matter failed to parse. ${(err as Error).message}`,\n });\n }\n if (parsed !== null && typeof parsed !== \"object\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${path}\": YAML front matter must parse to an object (got ${typeof parsed}).`,\n });\n }\n return {\n path,\n filename,\n frontmatter: (parsed as Record<string, unknown> | null) ?? {},\n body,\n };\n}\n\n/**\n * Read a single markdown file from disk and split into front matter +\n * body. Resolves the path against `process.cwd()` so callers can pass\n * relative locations (`\"./agents/researcher.md\"`).\n *\n * @internal\n */\nexport async function readMarkdownFile(path: string): Promise<ParsedMarkdown> {\n const abs = resolve(process.cwd(), path);\n let raw: string;\n try {\n raw = readFileSync(abs, \"utf-8\");\n } catch (err) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${path}\" could not be read: ${(err as Error).message}`,\n });\n }\n return splitFrontmatter(raw, abs);\n}\n\n/**\n * Options controlling how {@link readMarkdownDir} discovers entries.\n *\n * @internal\n */\nexport interface ReadMarkdownDirOptions {\n /**\n * When set, subdirectories of `dir` are also inspected. If a\n * subdirectory contains a file with this exact name (e.g.\n * `\"SKILL.md\"`), it is yielded as a single `ParsedMarkdown` whose\n * `filename` is the **subdirectory name**, not the sentinel stem.\n * This matches the Claude Code skill convention\n * (`<name>/SKILL.md`), where the directory name is the identity and\n * the folder can also bundle supporting assets. Subdirectories\n * without the sentinel are silently skipped.\n */\n sentinelFilename?: string;\n}\n\n/**\n * Read markdown documents from `dir` and return one `ParsedMarkdown`\n * entry per discovered file.\n *\n * - Flat `.md` files directly under `dir` are always loaded.\n * - When `sentinelFilename` is set, subdirectories containing that\n * exact file are loaded too, keyed by the **subdirectory name**.\n *\n * Subdirectories without the configured sentinel (or any\n * subdirectories at all when the option is absent) are silently\n * skipped, so a `node_modules`-style folder mixed in with real skills\n * does not produce noise.\n *\n * @internal\n */\nexport async function readMarkdownDir(\n dir: string,\n options: ReadMarkdownDirOptions = {},\n): Promise<ParsedMarkdown[]> {\n const abs = resolve(process.cwd(), dir);\n let stats;\n try {\n stats = statSync(abs);\n } catch (err) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown directory \"${dir}\" could not be opened: ${(err as Error).message}`,\n });\n }\n if (!stats.isDirectory()) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown directory \"${dir}\" is not a directory. Pass a path to a directory containing .md files.`,\n });\n }\n const out: ParsedMarkdown[] = [];\n for (const entry of readdirSync(abs, { withFileTypes: true })) {\n if (entry.isFile()) {\n if (extname(entry.name).toLowerCase() !== \".md\") continue;\n out.push(\n await splitFrontmatter(\n readFileSync(join(abs, entry.name), \"utf-8\"),\n join(abs, entry.name),\n ),\n );\n continue;\n }\n if (entry.isDirectory() && options.sentinelFilename) {\n const sentinelPath = join(abs, entry.name, options.sentinelFilename);\n let sentinelStats;\n try {\n sentinelStats = statSync(sentinelPath);\n } catch {\n continue;\n }\n if (!sentinelStats.isFile()) continue;\n const parsed = await splitFrontmatter(\n readFileSync(sentinelPath, \"utf-8\"),\n sentinelPath,\n );\n // The subdirectory name is the identity, not the sentinel stem.\n parsed.filename = entry.name;\n out.push(parsed);\n }\n }\n // Sort so file order is deterministic regardless of filesystem\n // listing order. Useful for stable tests and reproducible builds.\n out.sort((a, b) => a.filename.localeCompare(b.filename));\n return out;\n}\n\n/**\n * Validate that `value` is a non-empty string and return it; otherwise\n * throw RC5003 quoting the field name and source path.\n *\n * @internal\n */\nexport function requireString(\n value: unknown,\n field: string,\n source: string,\n): string {\n if (typeof value !== \"string\" || value.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter field \"${field}\" must be a non-empty string.`,\n });\n }\n return value;\n}\n\n/**\n * Validate that `value` is an array of non-empty strings (or\n * undefined) and return it; otherwise throw RC5003.\n *\n * @internal\n */\nexport function optionalStringArray(\n value: unknown,\n field: string,\n source: string,\n): string[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value)) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter field \"${field}\" must be an array of strings.`,\n });\n }\n for (const v of value) {\n if (typeof v !== \"string\" || v.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter field \"${field}\" must contain only non-empty strings.`,\n });\n }\n }\n return value as string[];\n}\n\n/**\n * Validate that `value` is a boolean (or undefined) and return it;\n * otherwise throw RC5003. Use for frontmatter flags that map to a\n * boolean option; the function-form variant of an option (a closure)\n * cannot be expressed in YAML and must be set in code instead.\n *\n * @internal\n */\nexport function optionalBoolean(\n value: unknown,\n field: string,\n source: string,\n): boolean | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== \"boolean\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter field \"${field}\" must be a boolean (true or false).`,\n });\n }\n return value;\n}\n\n/**\n * Validate that `value` is a finite positive integer (or undefined)\n * and return it; otherwise throw RC5003.\n *\n * @internal\n */\nexport function optionalPositiveInt(\n value: unknown,\n field: string,\n source: string,\n): number | undefined {\n if (value === undefined) return undefined;\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n !Number.isInteger(value) ||\n value < 1\n ) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter field \"${field}\" must be a positive integer.`,\n });\n }\n return value;\n}\n","import { rcError } from \"@routecraft/routecraft\";\nimport {\n optionalBoolean,\n optionalPositiveInt,\n optionalStringArray,\n readMarkdownDir,\n readMarkdownFile,\n requireString,\n} from \"../skill/markdown.ts\";\nimport { tools } from \"./tools/index.ts\";\nimport type { LlmModelId } from \"../llm/types.ts\";\nimport type { AgentRegisteredOptions } from \"./types.ts\";\n\n/**\n * Frontmatter fields supported today. Claude's subagent schema covers\n * many more (`disallowedTools`, `permissionMode`, `mcpServers`,\n * `hooks`, `memory`, `background`, `effort`, `isolation`, `color`,\n * `initialPrompt`, ...) which we will add incrementally as the\n * underlying features land. Any other key in the frontmatter throws\n * `RC5003` \"not yet supported\" at load so a misspelt key never silently\n * disappears.\n */\nconst SUPPORTED_AGENT_KEYS = new Set([\n \"name\",\n \"description\",\n \"model\",\n \"maxTurns\",\n \"tools\",\n \"skills\",\n \"principal\",\n]);\n\n/**\n * Per-agent override layered on top of the markdown frontmatter. Only\n * the fields that make sense to override at config time are exposed\n * here. Lifecycle fields like `validate` and `onDelta` belong in code\n * (markdown frontmatter cannot express closures) so set those on the\n * agent at the call site or via `agentPlugin({ defaultOptions })`.\n *\n * `principal` accepts the full {@link AgentRegisteredOptions.principal}\n * shape here (`boolean | AgentPrincipalRenderer`). Frontmatter can only\n * carry the boolean form; reach for the override (or\n * `agentPlugin({ defaultOptions })`) when an agent needs the\n * function-renderer form that YAML cannot express.\n */\nexport interface AgentMarkdownOverride extends Partial<\n Pick<\n AgentRegisteredOptions,\n \"description\" | \"model\" | \"maxTurns\" | \"tools\" | \"skills\" | \"principal\"\n >\n> {\n /**\n * Replace the system prompt loaded from the markdown body. Useful\n * when a deployment wants to swap a tone or constraint without\n * editing the source file.\n */\n system?: string;\n}\n\n/**\n * Convert a parsed markdown file into an `AgentRegisteredOptions`.\n * Validates that frontmatter `name` matches the filename so the\n * registry id is unambiguous; throws on unsupported frontmatter\n * fields and on empty body so an agent never lands with a hollow\n * system prompt.\n *\n * @internal\n */\nfunction toAgent(\n filename: string,\n frontmatter: Record<string, unknown>,\n body: string,\n source: string,\n): { name: string; agent: AgentRegisteredOptions } {\n for (const key of Object.keys(frontmatter)) {\n if (!SUPPORTED_AGENT_KEYS.has(key)) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter field \"${key}\" is not yet supported. Currently supported fields: ${[...SUPPORTED_AGENT_KEYS].sort().join(\", \")}.`,\n });\n }\n }\n const name = requireString(frontmatter[\"name\"], \"name\", source);\n if (name !== filename) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter \"name\" (\"${name}\") must match the filename (\"${filename}\"). Rename one or the other.`,\n });\n }\n const description = requireString(\n frontmatter[\"description\"],\n \"description\",\n source,\n );\n if (body.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": agent body is empty. The body becomes the agent's system prompt; an empty system prompt is rejected at dispatch.`,\n });\n }\n const modelRaw = frontmatter[\"model\"];\n if (modelRaw !== undefined && typeof modelRaw !== \"string\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter \"model\" must be a string of the form \"provider:model\" (e.g. \"anthropic:claude-sonnet-4-6\").`,\n });\n }\n if (typeof modelRaw === \"string\" && !modelRaw.includes(\":\")) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter \"model\" (\"${modelRaw}\") must use the full \"provider:model\" form. Bare model aliases like \"sonnet\" / \"opus\" / \"haiku\" are not yet supported by the markdown loader.`,\n });\n }\n const maxTurns = optionalPositiveInt(\n frontmatter[\"maxTurns\"],\n \"maxTurns\",\n source,\n );\n const toolNames = optionalStringArray(frontmatter[\"tools\"], \"tools\", source);\n const skillNames = optionalStringArray(\n frontmatter[\"skills\"],\n \"skills\",\n source,\n );\n // Frontmatter carries only the boolean form; the function-renderer\n // form is a closure YAML cannot express and is supplied via the\n // override map or agentPlugin({ defaultOptions }).\n const principal = optionalBoolean(\n frontmatter[\"principal\"],\n \"principal\",\n source,\n );\n const agent: AgentRegisteredOptions = {\n description,\n system: body,\n };\n if (modelRaw) agent.model = modelRaw as LlmModelId;\n if (maxTurns !== undefined) agent.maxTurns = maxTurns;\n if (toolNames !== undefined) agent.tools = tools(toolNames);\n if (skillNames !== undefined) agent.skills = skillNames;\n if (principal !== undefined) agent.principal = principal;\n return { name, agent };\n}\n\n/**\n * Apply caller-supplied overrides on top of the agent loaded from\n * markdown. Replaces, never extends: an explicit `tools` override\n * replaces the markdown's tool list entirely (matches the\n * agent-level tool inheritance contract).\n *\n * @internal\n */\nfunction applyOverride(\n agent: AgentRegisteredOptions,\n override: AgentMarkdownOverride | undefined,\n): AgentRegisteredOptions {\n if (!override) return agent;\n const out: AgentRegisteredOptions = { ...agent };\n if (override.description !== undefined)\n out.description = override.description;\n if (override.model !== undefined) out.model = override.model;\n if (override.maxTurns !== undefined) out.maxTurns = override.maxTurns;\n if (override.tools !== undefined) out.tools = override.tools;\n if (override.skills !== undefined) out.skills = override.skills;\n if (override.principal !== undefined) out.principal = override.principal;\n if (override.system !== undefined) out.system = override.system;\n return out;\n}\n\n/**\n * Load agents from a markdown file or directory.\n *\n * - If `path` points to a directory, every `.md` file directly under\n * it becomes one agent. The filename (without `.md`) is the agent\n * name and must match the frontmatter `name`.\n * - If `path` points to a single `.md` file, the file becomes one\n * agent keyed by its filename.\n *\n * Frontmatter mirrors a deliberately narrow subset of Claude's\n * subagent schema:\n *\n * | Field | Required | Maps to |\n * | ------------- | -------- | -------------------------------------- |\n * | `name` | yes | record key + agent id |\n * | `description` | yes | `AgentRegisteredOptions.description` |\n * | `model` | no | `AgentRegisteredOptions.model` (full |\n * | | | `provider:model` form only) |\n * | `maxTurns` | no | `AgentRegisteredOptions.maxTurns` |\n * | `tools` | no | `tools(stringArray)` |\n * | `skills` | no | `AgentRegisteredOptions.skills` |\n * | `principal` | no | `AgentRegisteredOptions.principal` |\n * | | | (boolean only; renderer via override) |\n *\n * Body of the file becomes `system`. Other Claude subagent fields\n * (`disallowedTools`, `permissionMode`, `mcpServers`, `hooks`,\n * `memory`, `background`, `effort`, `isolation`, `color`,\n * `initialPrompt`, ...) throw `RC5003` \"not yet supported\" at load\n * and will land in follow-up stories as the runtime gains the\n * underlying features.\n *\n * Pass `overrides` keyed by agent name to replace any of\n * `description` / `model` / `maxTurns` / `tools` / `skills` /\n * `system` per agent without editing the markdown source.\n *\n * Returns a `Record<name, AgentRegisteredOptions>` ready to spread\n * into `agentPlugin({ agents: agents(\"./agents\") })`.\n *\n * @example\n * ```ts\n * agentPlugin({\n * agents: agents(\"./agents\", {\n * researcher: { maxTurns: 30 },\n * }),\n * });\n * ```\n */\nexport async function agents(\n path: string,\n overrides: Record<string, AgentMarkdownOverride> = {},\n): Promise<Record<string, AgentRegisteredOptions>> {\n const out: Record<string, AgentRegisteredOptions> = {};\n const docs = path.endsWith(\".md\")\n ? [await readMarkdownFile(path)]\n : await readMarkdownDir(path);\n for (const doc of docs) {\n const { name, agent } = toAgent(\n doc.filename,\n doc.frontmatter,\n doc.body,\n doc.path,\n );\n out[name] = applyOverride(agent, overrides[name]);\n }\n for (const name of Object.keys(overrides)) {\n if (!(name in out)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agents(\"${path}\"): override for \"${name}\" but no agent with that name was loaded from disk.`,\n });\n }\n }\n return out;\n}\n","/**\n * Signal raised by a fn handler when it cannot complete synchronously\n * and the agent's tool-loop should pause until an external event (a\n * human reply, a webhook, a long-running batch result) supplies the\n * answer.\n *\n * **Stub today.** This type is exported so user code that wants to be\n * forward-compatible with the durable-agents epic can throw it, but no\n * runtime path catches it yet. When the durable epic lands, the agent\n * runtime will catch this error, persist the message thread, and\n * return `{ status: \"suspended\", checkpointId }` to the calling route\n * instead of an `AgentResult`. See the durable-agents tracking issue\n * for the full design.\n *\n * Until then, throwing this is a normal error and behaves like any\n * other tool failure (feeds back to the model for self-correction).\n *\n * For human-in-the-loop flows where waits are short (seconds to\n * minutes), the recommended pattern is to write a tool handler that\n * blocks on the answer (`await pollUntilReply(...)`); the agent's\n * await chain holds the loop in memory until the tool resolves.\n *\n * @example\n * ```ts\n * import { SuspendError } from \"@routecraft/ai\"\n *\n * const askApproval: FnOptions = {\n * description: \"Ask a human for approval via email\",\n * input: z.object({ question: z.string() }),\n * handler: async (input, ctx) => {\n * await sendApprovalRequest({\n * question: input.question,\n * callbackUrl: `${baseUrl}/resume/${ctx.checkpointId}`,\n * })\n * throw new SuspendError({ reason: \"awaiting-human-approval\" })\n * },\n * }\n * ```\n */\nexport class SuspendError extends Error {\n /** Discriminator for runtime detection. */\n override readonly name = \"SuspendError\";\n /**\n * Optional reason string surfaced in telemetry and the eventual\n * suspended-agent record. Free-form; pick whatever your product\n * vocabulary uses (\"awaiting-human-approval\", \"waiting-for-webhook\",\n * etc.).\n */\n readonly reason?: string;\n /**\n * Optional channel hint indicating how the agent will be resumed.\n * Surfaces in telemetry and lets the surrounding route decide how\n * to react (e.g. return `202 Accepted` to the HTTP client).\n */\n readonly resumeChannel?: string;\n\n constructor(opts?: { reason?: string; resumeChannel?: string }) {\n super(\n opts?.reason\n ? `Agent suspended: ${opts.reason}`\n : \"Agent suspended pending external resumption.\",\n );\n if (opts?.reason !== undefined) this.reason = opts.reason;\n if (opts?.resumeChannel !== undefined) {\n this.resumeChannel = opts.resumeChannel;\n }\n }\n}\n\n/**\n * Type guard for `SuspendError`. Used by the runtime to detect\n * suspension signals without importing the concrete class everywhere.\n *\n * @internal\n */\nexport function isSuspendError(value: unknown): value is SuspendError {\n return value instanceof SuspendError;\n}\n","import { rcError } from \"@routecraft/routecraft\";\nimport {\n readMarkdownDir,\n readMarkdownFile,\n requireString,\n} from \"./markdown.ts\";\nimport type { Skill } from \"./types.ts\";\n\n/**\n * Per-skill override applied on top of the markdown frontmatter.\n */\nexport interface SkillOverride {\n description?: string;\n content?: string;\n}\n\n/**\n * Convert a parsed markdown file into a `Skill`. Validates that\n * frontmatter `name`, when present, matches the directory or\n * filename so the registry id is unambiguous, and that body is\n * non-empty so the agent never injects a hollow skill into its\n * system prompt.\n *\n * Unknown top-level frontmatter keys are silently accepted: Claude\n * Code's full skill frontmatter schema (`allowed-tools`,\n * `argument-hint`, `disable-model-invocation`, `when_to_use`, etc.)\n * is much wider than routecraft consumes, and tooling commonly\n * layers further metadata on top. Keys other than `name` and\n * `description` are ignored by the runtime; only those two are\n * validated.\n *\n * @internal\n */\nfunction toSkill(\n filename: string,\n frontmatter: Record<string, unknown>,\n body: string,\n source: string,\n): Skill {\n const name = requireString(frontmatter[\"name\"], \"name\", source);\n if (name !== filename) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter \"name\" (\"${name}\") must match the filename (\"${filename}\"). Rename one or the other.`,\n });\n }\n const description = requireString(\n frontmatter[\"description\"],\n \"description\",\n source,\n );\n if (body.trim() === \"\") {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": skill body is empty. The body becomes the injected skill content; an empty body would not change the agent's behaviour.`,\n });\n }\n return { name, description, content: body };\n}\n\n/**\n * Load skills from a markdown file or directory.\n *\n * Two directory layouts are supported and may coexist in the same\n * folder, matching the [Claude Code skill convention](https://code.claude.com/docs/en/skills):\n *\n * - **Flat:** a `.md` file directly under the directory. The filename\n * (without `.md`) is the skill name and must match frontmatter\n * `name`.\n * - **Nested:** a `<name>/SKILL.md` file inside a subdirectory. The\n * subdirectory name is the skill name and must match frontmatter\n * `name`. The folder can also bundle supporting assets (scripts,\n * templates, examples); the loader only consumes `SKILL.md`.\n *\n * Subdirectories without a `SKILL.md` sentinel are silently skipped.\n *\n * If `path` points to a single `.md` file, the file becomes one\n * skill keyed by its filename.\n *\n * Frontmatter requires `name` and `description`. Any other keys\n * (including Claude Code fields like `allowed-tools`, `when_to_use`,\n * `argument-hint`, `disable-model-invocation`, or arbitrary metadata\n * blocks added by other tooling) are silently accepted and ignored.\n *\n * Body of the file becomes `Skill.content` and is concatenated into\n * the system prompt of any agent that lists the skill name in its\n * `skills` array.\n *\n * Pass `overrides` keyed by skill name to replace `description` or\n * `content` per skill without editing the markdown source.\n *\n * Returns a `Record<name, Skill>` ready to spread into\n * `agentPlugin({ skills: skills(\"./skills\") })`.\n *\n * @example\n * ```ts\n * agentPlugin({\n * skills: skills(\"./skills\"),\n * agents: agents(\"./agents\"),\n * });\n * ```\n */\nexport async function skills(\n path: string,\n overrides: Record<string, SkillOverride> = {},\n): Promise<Record<string, Skill>> {\n const out: Record<string, Skill> = {};\n const sources = new Map<string, string>();\n const docs = path.endsWith(\".md\")\n ? [await readMarkdownFile(path)]\n : await readMarkdownDir(path, { sentinelFilename: \"SKILL.md\" });\n for (const doc of docs) {\n const skill = toSkill(doc.filename, doc.frontmatter, doc.body, doc.path);\n // Flat `foo.md` and nested `foo/SKILL.md` can both resolve to the\n // same skill name. Reject explicitly so the conflict is visible\n // at load time instead of silently last-write-wins.\n const previousSource = sources.get(skill.name);\n if (previousSource) {\n throw rcError(\"RC5003\", undefined, {\n message: `skills(\"${path}\"): duplicate skill name \"${skill.name}\" loaded from both \"${previousSource}\" and \"${doc.path}\". Each skill name must be unique within a directory; rename or remove one source.`,\n });\n }\n sources.set(skill.name, doc.path);\n const override = overrides[skill.name];\n out[skill.name] = override ? { ...skill, ...override } : skill;\n }\n // Surface override entries that didn't match any loaded skill so a\n // typo in the override key doesn't silently no-op.\n for (const name of Object.keys(overrides)) {\n if (!(name in out)) {\n throw rcError(\"RC5003\", undefined, {\n message: `skills(\"${path}\"): override for \"${name}\" but no skill with that name was loaded from disk.`,\n });\n }\n }\n return out;\n}\n","import {\n getExchangeContext,\n type CraftContext,\n type Destination,\n type Exchange,\n type MergedOptions,\n} from \"@routecraft/routecraft\";\nimport { callEmbedding } from \"./providers/index.ts\";\nimport type {\n EmbeddingModelConfig,\n EmbeddingOptions,\n EmbeddingResult,\n} from \"./types.ts\";\nimport {\n ADAPTER_EMBEDDING_OPTIONS,\n ADAPTER_EMBEDDING_PROVIDERS,\n} from \"./types.ts\";\n\nfunction parseProviderModel(id: string): {\n providerId: string;\n modelName: string;\n} {\n const colon = id.indexOf(\":\");\n if (colon < 1 || colon === id.length - 1) {\n throw new Error(\n `Embedding adapter: model id must be \"providerId:modelName\" (e.g. huggingface:all-MiniLM-L6-v2). Got: \"${id}\"`,\n );\n }\n return {\n providerId: id.slice(0, colon),\n modelName: id.slice(colon + 1),\n };\n}\n\nfunction resolveProviderAndModel(\n modelId: string,\n context: CraftContext | undefined,\n): { config: EmbeddingModelConfig; modelName: string } {\n if (!context) {\n throw new Error(\n `Embedding adapter: model id \"${modelId}\" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so embedding providers can be read.`,\n );\n }\n const store = context.getStore(\n ADAPTER_EMBEDDING_PROVIDERS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Map<string, EmbeddingModelConfig> | undefined;\n if (!store) {\n throw new Error(\n \"Embedding provider not found: no providers registered. Add embeddingPlugin({ providers: { huggingface: {} } }) to your config.\",\n );\n }\n const { providerId, modelName } = parseProviderModel(modelId);\n const config = store.get(providerId);\n if (!config) {\n throw new Error(\n `Embedding provider \"${providerId}\" not found. Register it with embeddingPlugin({ providers: { \"${providerId}\": {} } }).`,\n );\n }\n return { config, modelName };\n}\n\nfunction buildText<T>(\n using: (exchange: Exchange<T>) => string | string[],\n): (exchange: Exchange<T>) => string {\n return (exchange: Exchange<T>) => {\n const value = using(exchange);\n return Array.isArray(value) ? value.filter(Boolean).join(\" | \") : value;\n };\n}\n\n/**\n * Embedding destination adapter. Expects model id as \"providerId:modelName\"\n * (e.g. huggingface:all-MiniLM-L6-v2), resolves the provider from the plugin store,\n * and returns { embedding: number[] }. Use with .enrich(embedding(\"provider:model\", { using: ... })).\n */\nexport class EmbeddingDestinationAdapter<T = unknown>\n implements Destination<T, EmbeddingResult>, MergedOptions<EmbeddingOptions>\n{\n readonly adapterId = \"routecraft.adapter.embedding\";\n\n constructor(\n private readonly modelId: string,\n options: EmbeddingOptions<T>,\n ) {\n this.options = options as Partial<EmbeddingOptions>;\n }\n\n public options: Partial<EmbeddingOptions>;\n\n mergedOptions(context: CraftContext): EmbeddingOptions {\n const store = context.getStore(\n ADAPTER_EMBEDDING_OPTIONS as keyof import(\"@routecraft/routecraft\").StoreRegistry,\n ) as Partial<EmbeddingOptions> | undefined;\n return { ...store, ...this.options } as EmbeddingOptions;\n }\n\n async send(exchange: Exchange<T>): Promise<EmbeddingResult> {\n const context = getExchangeContext(exchange);\n const { config, modelName } = resolveProviderAndModel(\n this.modelId,\n context,\n );\n const merged = this.mergedOptions(context!);\n\n const getText = buildText(\n merged.using as (e: Exchange<unknown>) => string | string[],\n );\n const text = getText(exchange as Exchange<unknown>);\n\n const embedding = await callEmbedding({ config, modelName, text });\n return { embedding };\n }\n}\n","import type { Destination } from \"@routecraft/routecraft\";\nimport { EmbeddingDestinationAdapter } from \"./destination.ts\";\nimport type {\n EmbeddingModelId,\n EmbeddingOptions,\n EmbeddingResult,\n} from \"./types.ts\";\n\n/**\n * Creates an embedding destination that computes a vector for the given text.\n * Use with .enrich(). Pass model id as \"providerId:modelName\" (e.g. huggingface:all-MiniLM-L6-v2).\n * The provider must be registered via embeddingPlugin({ providers: { huggingface: {} } }).\n *\n * @param modelId - \"providerId:modelName\"; the provider is resolved from the plugin.\n * @param options - using(exchange) returns the string (or string[]) to embed.\n */\nexport function embedding<T = unknown>(\n modelId: EmbeddingModelId,\n options: EmbeddingOptions<T>,\n): Destination<T, EmbeddingResult> {\n return new EmbeddingDestinationAdapter<T>(modelId, options);\n}\n"]}
|