@routecraft/ai 0.6.0-canary.9 → 0.6.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/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +949 -405
- package/dist/index.d.ts +949 -405
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/package.json +27 -22
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/llm/types.ts","../src/llm/providers/llm-utils.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/block/client.ts","../src/block/resolve.ts","../src/llm/shared.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/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/block/markdown.ts","../src/agent/loader.ts","../src/agent/suspend.ts","../src/block/builders.ts","../src/embedding/destination.ts","../src/embedding/embedding.ts"],"names":["ADAPTER_LLM_PROVIDERS","ADAPTER_LLM_OPTIONS","PROVIDER_DEFAULTS","assertLanguageModelShape","model","providerName","modelId","m","toLlmUsage","u","getStructuredOutput","result","readReasoning","r","collectToolCalls","steps","out","step","calls","results","call","c","toolCallId","toolName","input","summary","match","buildExtras","params","buildSdkParams","options","system","user","extras","PROVIDERS","isProvider","s","validateLlmPluginOptions","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","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","createUserinfoUrlResolver","option","issuer","url","base","discoveryUrl","cachedUrl","cachedUntil","inFlight","fetchAndCache","response","cause","rcError","doc","resolved","ttl","fetchUserinfo","mergeEnrichment","principal","merged","liftOidcClaims","payload","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","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","names","exposedDetail","registry","entries","toolsFilter","e","entry","tool","schema","standard","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","getHuggingFacePipeline","pipe","run","text","previewForError","toNumberArray","d","callEmbedding","vec","i","output","ADAPTER_EMBEDDING_PROVIDERS","ADAPTER_EMBEDDING_OPTIONS","embeddingPlugin","makeBlockClient","route","getExchangeRoute","BLOCK_NAME_SEPARATOR","BLOCK_LOADER_TOOL","BLOCK_RESERVED_PREFIX","BLOCK_LOADER_PREFIX","isBlockLoaderTool","resolveBlocks","blocks","flat","flattenBlocks","parts","loaderTools","resolveOnce","buildLoaderTool","isBlockGroup","BLOCK_TOOL_NAME_CHARSET","TOOL_NAME_MAX_LENGTH","blockCollisionError","qualified","blockCycleError","prefix","walkBlocks","seen","LIFETIME_CACHE","invokeResolver","EMPTY_OBJECT_JSON_SCHEMA","EMPTY_OBJECT_SCHEMA","handler","summariseBlockLoads","toolCalls","tc","isBlockLoaderCall","parseProviderModel","id","colon","resolveModel","isCustomInstance","store","resolvePrompt","resolveUserPromptDefault","resolveLanguageModel","resolveOpenAI","resolveAnthropic","resolveGemini","resolveOpenRouter","resolveOllama","resolveLmStudio","resolveCustom","_","mod","settings","openrouter","resolvedId","rawModel","ollama","lmstudio","normalizeStreamDelta","part","p","readString","obj","streamLlm","onDelta","runStreamGenerate","streamText","delta","frameworkLogger","usage","safeAwait","reasoning","structured","finishReason","callLlm","runGenerate","generateText","responseMessages","toAiSchema","direction","errorContext","primary","jsonSchemaObj","validate","jsonSchema","toAiInputSchema","toAiOutputSpec","aiSchema","Output","buildVercelTools","abortSignal","dispatchIdentity","guard","baseCtx","makeFnHandlerContext","isLoader","blockName","callOpts","callCtx","randomUUID","start","freezePrincipal","wasAuthentic","isAuthentic","snapshot","deepFreeze","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","userCalls","blockCalls","buildUserPrompt","ADAPTER_AGENT_REGISTRY","ADAPTER_AGENT_DEFAULT_OPTIONS","AGENT_REGISTRY_STORE_DESCRIPTION","AgentDestinationAdapter","binding","getExchangeContext","baseOptions","mergeWithDefaults","userTools","resolveAgentTools","baseSystem","systemAppend","mergeUserAndLoaderTools","withBlocks","appendPrincipalToSystem","found","known","defaults","mergeBlocks","agent","override","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","emptyObjectSchema","directTool","overrides","fnId","readDirectRoute","hctx","dispatchDirect","ADAPTER_DIRECT_REGISTRY","endpoint","sanitizeEndpoint","getDirectChannel","currentTime","randomUuid","TOOL_SELECTION_BRAND","isToolSelection","arg","items","runBuilder","buildCatalog","isMcpRefName","fnRegistryHas","resolveMcpRefs","resolveByName","fns","fnRegistry","routes","directRegistry","meta","rawId","mcp","mcpRegistry","builder","catalog","fnEntry","resolveFnEntry","directMatch","toResolvedTool","listKnownNames","parseMcpRef","ref","inner","clientName","sep","clientTools","listKnownMcpClients","mcpEntryToResolvedTool","knownTools","n","wrapJsonSchemaAsStandard","rawInput","set","fnNames","routeNames","validateAgentOptions","validateBlocks","defaultsLabel","state","validateBlocksLevel","leafCount","maybeValue","childLeaves","b","perCall","tagAdapter","factoryArgs","validateFnOptions","validateRegisteredAgent","agentPlugin","agents","functions","defaultOptions","validatePluginDefaults","existingAgents","agentMap","existingFns","fnMap","mergePluginDefaults","raw","mergedBlocks","registerConfigApplier","BRAND","isBranded","isMcpAdapter","parseStructuredTextFallback","LlmDestinationAdapter","llmResult","llm","BRAND_MCP_ADAPTER","MCP_TOOL_NAME_RE","assertValidMcpToolName","McpSourceAdapter","abortController","onReady","discovery","assertHttpUrl","trimmed","resolveServerConfig","cfg","resolveConnection","defaultArgs","McpDestinationAdapter","resolveServerTransport","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","requireString","field","optionalStringArray","optionalBoolean","optionalPositiveInt","SUPPORTED_AGENT_KEYS","toAgent","frontmatter","modelRaw","toolNames","applyOverride","docs","SuspendError","skills","mode","lifetime","sources","prior","fromFile","resolvePath","readFile","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 * A model object the active LLM engine can drive (today an AI SDK\n * `LanguageModel`), or anything else a future engine accepts. Deliberately\n * `unknown` so no engine-specific type reaches the public surface: every other\n * provider is addressed by a `\"provider:model\"` string and the framework's own\n * `LlmOptions`/`LlmResult` types, so swapping the underlying SDK does not break\n * consumers. The `custom` provider is the one engine-bound escape hatch, and we\n * keep that binding a runtime contract (validated by `assertLanguageModelShape`)\n * rather than a compile-time coupling.\n */\nexport type CustomLanguageModel = unknown;\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 | \"lmstudio\"\n | \"custom\";\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 interface LlmModelConfigLmStudio {\n provider: \"lmstudio\";\n /**\n * LM Studio server URL. Optional: defaults to http://localhost:1234/v1.\n * Only set when LM Studio runs on a non-default host or port.\n */\n baseURL?: string;\n /**\n * API key sent to LM Studio. Optional: LM Studio ignores authentication,\n * so this defaults to a placeholder. Set it only if you front LM Studio\n * with a proxy that enforces a key.\n */\n apiKey?: string;\n /**\n * Override model name sent to LM Studio. Optional: defaults to the model\n * from the llm(\"lmstudio:model\") call (the part after the colon).\n */\n modelId?: string;\n}\n\nexport interface LlmModelConfigCustom {\n provider: \"custom\";\n /**\n * A pre-built AI SDK language model, or a factory that builds one from the\n * model name (the part after the colon in llm(\"custom:name\")). This is the\n * escape hatch for running an agent or llm() step against an in-process or\n * otherwise unsupported model with no API key and no network.\n */\n model: CustomLanguageModel | ((modelId: string) => CustomLanguageModel);\n /**\n * Optional model name. Only needed when using an inline config object with\n * a factory; the string form llm(\"custom:name\") supplies it directly.\n */\n modelId?: string;\n}\n\nexport type LlmModelConfig =\n | LlmModelConfigOpenAI\n | LlmModelConfigAnthropic\n | LlmModelConfigOpenRouter\n | LlmModelConfigOllama\n | LlmModelConfigGemini\n | LlmModelConfigLmStudio\n | LlmModelConfigCustom;\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}\nexport interface LlmLmStudioProviderOptions {\n baseURL?: string;\n apiKey?: string;\n modelId?: string;\n}\nexport interface LlmCustomProviderOptions {\n model: CustomLanguageModel | ((modelId: string) => CustomLanguageModel);\n modelId?: string;\n}\n\nexport interface LlmPluginProviders {\n ollama?: LlmOllamaProviderOptions;\n openai?: LlmOpenAIProviderOptions;\n anthropic?: LlmAnthropicProviderOptions;\n openrouter?: LlmOpenRouterProviderOptions;\n gemini?: LlmGeminiProviderOptions;\n lmstudio?: LlmLmStudioProviderOptions;\n custom?: LlmCustomProviderOptions;\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 // LM Studio (local; ids are whatever model you have loaded)\n | \"lmstudio:qwen2.5-7b-instruct\"\n | \"lmstudio:llama-3.2-3b-instruct\"\n | \"lmstudio:phi-4\"\n | \"lmstudio:mistral-nemo-instruct-2407\"\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 {\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 lmstudio: {\n baseURL: \"http://localhost:1234/v1\",\n },\n} as const;\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 { assertLanguageModelShape } from \"./providers/llm-utils.ts\";\nimport type { LlmPluginOptions, LlmProviderType } from \"./types.ts\";\n\nconst PROVIDERS: LlmProviderType[] = [\n \"openai\",\n \"anthropic\",\n \"openrouter\",\n \"ollama\",\n \"gemini\",\n \"lmstudio\",\n \"custom\",\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 case \"lmstudio\":\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 if (\n providerId === \"lmstudio\" &&\n (opts as { apiKey?: string }).apiKey !== undefined &&\n typeof (opts as { apiKey?: string }).apiKey !== \"string\"\n ) {\n throw new TypeError(\n `llmPlugin: providers[\"lmstudio\"].apiKey must be a string when provided`,\n );\n }\n break;\n case \"custom\": {\n const model = (opts as { model?: unknown }).model;\n // A factory is only invoked at dispatch, so its return shape cannot be\n // checked eagerly; a concrete instance can, so assert it now and fail\n // at plugin apply rather than at first dispatch.\n if (typeof model === \"function\") break;\n if (model === null || typeof model !== \"object\") {\n throw new TypeError(\n `llmPlugin: providers[\"custom\"].model must be an AI SDK language model or a factory function`,\n );\n }\n assertLanguageModelShape(model, \"custom\", \"(custom)\");\n break;\n }\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 \"lmstudio\",\n \"custom\",\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 // Cast via `unknown`: the `custom` provider carries a function-typed\n // `model`, so a direct assertion is not comparable across the union.\n return { provider: providerId, ...opts } as unknown 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; surfaced on `ToolsCatalog.mcp[].tags` for the builder\n * form of `tools((catalog) => ...)` so MCP tools can be filtered\n * 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=\"200\" height=\"200\" viewBox=\"0 0 200 200\" fill=\"${fill}\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M125 175H75V125L125 175ZM175 175H125V125L175 175ZM125 25C152.614 25 175 47.3858 175 75C175 102.614 152.614 125 125 125V75H75L125 125H75L25 75V25H125Z\" /></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` shape\n * (visible on `ToolsCatalog.mcp[].tags` for the builder form of\n * `tools()`, and on the resolved tool's `tags` for downstream\n * inspection).\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 { loadOptionalPeer } from \"@routecraft/routecraft\";\nimport 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\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 const mod = (await loadOptionalPeer(\n () => import(\"@huggingface/transformers\"),\n {\n adapterName: \"Hugging Face embedding\",\n packageName: \"@huggingface/transformers\",\n },\n )) as {\n pipeline: (\n task: string,\n model: string,\n opts?: { dtype?: string },\n ) => Promise<unknown>;\n };\n const pipe = (await mod.pipeline(\"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 getExchangeRoute,\n rcError,\n type Exchange,\n type ForwardFn,\n} from \"@routecraft/routecraft\";\nimport type { BlockClient } from \"./types.ts\";\n\n/**\n * Build the {@link BlockClient} handed to a block resolver function.\n *\n * Wraps the same {@link ForwardFn} that route `.error()` handlers\n * receive: resolves the dispatch's bound route via\n * `getExchangeRoute(exchange).getForward()`. When the exchange has no\n * route binding (synthetic exchanges in tests), `forward` rejects\n * with RC5025 so a resolver does not silently no-op and downstream\n * `.error()` handlers can pattern-match on the failure mode.\n *\n * @internal\n */\nexport function makeBlockClient(exchange: Exchange<unknown>): BlockClient {\n const route = getExchangeRoute(exchange);\n const forward: ForwardFn = route\n ? route.getForward()\n : async () => {\n throw rcError(\"RC5025\", undefined, {\n message:\n \"Block resolver: client.forward() called but the exchange has no bound route. \" +\n \"Block resolvers can only forward when invoked through a real route dispatch.\",\n });\n };\n return { forward };\n}\n","import {\n rcError,\n type CraftContext,\n type Exchange,\n} from \"@routecraft/routecraft\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { FnOptions } from \"../fn/types.ts\";\nimport type { ResolvedTool } from \"../agent/tools/selection.ts\";\nimport { makeBlockClient } from \"./client.ts\";\nimport type {\n AgentBlockLoadSummary,\n BlockBody,\n BlockClient,\n Blocks,\n} from \"./types.ts\";\n\n/**\n * Separator joining nested {@link Blocks} group names into the single\n * canonical block name used for the system-prompt heading, the\n * synthetic loader tool name, and the `blocksLoaded` summary. A leaf\n * `onboarding` under group `skills` flattens to `skills__onboarding`.\n *\n * `__` rather than `/` because loader tool names reach the provider\n * unsanitised and must match `^[a-zA-Z0-9_-]{1,64}$`. Using one\n * canonical flattened name everywhere keeps the slice-based\n * {@link summariseBlockLoads} / {@link isBlockLoaderCall} logic intact.\n *\n * @internal\n */\nexport const BLOCK_NAME_SEPARATOR = \"__\";\n\n/**\n * Symbol stamped on `ResolvedTool` entries produced by\n * {@link resolveBlocks} for `mode: \"progressive\"` blocks. Lets the\n * tool bridge route their telemetry to `agent:block:loaded` events\n * (and the session to partition them out of `AgentResult.toolCalls`)\n * without sniffing on the tool name.\n *\n * @internal\n */\nexport const BLOCK_LOADER_TOOL = Symbol.for(\"routecraft.ai.block.loader-tool\");\n\n/**\n * Reserved name prefix for the block surface. User tools (fns, direct\n * routes, MCP tools) and block names that start with this prefix\n * collide with the framework's synthetic surface and are rejected at\n * construction (block names via `validateBlocks`) or dispatch\n * (resolved tool names via `mergeUserAndLoaderTools`) with RC5026.\n *\n * The framework reserves the broader `_block_` namespace (not just\n * `_block_load_`) so future synthetic-tool kinds (e.g. unloaders or\n * state probes) can land without a separate breaking reservation.\n *\n * @internal\n */\nexport const BLOCK_RESERVED_PREFIX = \"_block_\";\n\n/**\n * Concrete prefix used to generate synthetic loader-tool names today.\n * Always starts with {@link BLOCK_RESERVED_PREFIX}; user names are\n * validated against the broader reservation, not this specific kind.\n *\n * @internal\n */\nexport const BLOCK_LOADER_PREFIX = \"_block_load_\";\n\n/**\n * Internal extension carried on a synthetic loader-tool `ResolvedTool`.\n * The session reads it to assemble `AgentResult.blocksLoaded` after a\n * dispatch.\n *\n * @internal\n */\nexport interface BlockLoaderToolMeta {\n [BLOCK_LOADER_TOOL]: true;\n blockName: string;\n}\n\n/** A `ResolvedTool` known to be a synthetic block loader. @internal */\nexport type BlockLoaderTool = ResolvedTool & BlockLoaderToolMeta;\n\n/**\n * Type guard for {@link BlockLoaderTool}. Used by the session and tool\n * bridge to differentiate user tools from framework-synthesised loaders.\n *\n * @internal\n */\nexport function isBlockLoaderTool(tool: ResolvedTool): tool is BlockLoaderTool {\n return (tool as { [BLOCK_LOADER_TOOL]?: true })[BLOCK_LOADER_TOOL] === true;\n}\n\n/**\n * Result of resolving a list of {@link Block}s for one agent dispatch.\n * `systemAppend` is the string to concatenate onto the agent's\n * `system` prompt (already includes per-block `## <name>` headings).\n * `loaderTools` is the list of synthetic tools to merge into the\n * agent's `ResolvedTool[]` before handing it to the LLM.\n *\n * @internal\n */\nexport interface ResolvedBlocks {\n systemAppend: string;\n loaderTools: BlockLoaderTool[];\n}\n\n/**\n * Resolve every block on an agent for one dispatch.\n *\n * - `mode: \"inject\"` blocks: run the resolver (respecting `lifetime`)\n * and append the result to `systemAppend` as `## <name>\\n\\n<body>`.\n * - `mode: \"progressive\"` blocks: emit one synthetic\n * `_block_load_<name>` tool whose handler runs the resolver on\n * demand against the captured exchange and context.\n *\n * Caching for `lifetime: \"context\"` is keyed by the block object\n * identity on a `WeakMap<CraftContext, Map<Block, string>>`. Two\n * declarations of the same logical block in separate agents are\n * therefore independent caches.\n *\n * Throws RC5025 when an inject-mode resolver throws or returns a\n * non-string. Progressive-mode resolver failures surface back to the\n * model as a loader-tool error so the model can self-correct rather\n * than aborting the dispatch.\n *\n * @internal\n */\nexport async function resolveBlocks(\n blocks: Blocks | undefined,\n exchange: Exchange<unknown>,\n context: CraftContext | undefined,\n): Promise<ResolvedBlocks> {\n if (!blocks) return { systemAppend: \"\", loaderTools: [] };\n const flat = flattenBlocks(blocks);\n if (flat.size === 0) {\n return { systemAppend: \"\", loaderTools: [] };\n }\n const client = makeBlockClient(exchange);\n const parts: string[] = [];\n const loaderTools: BlockLoaderTool[] = [];\n for (const [name, body] of flat) {\n if (body.mode === \"inject\") {\n const value = await resolveOnce(name, body, exchange, context, client);\n parts.push(`\\n\\n## ${name}\\n\\n${value}`);\n continue;\n }\n loaderTools.push(buildLoaderTool(name, body, exchange, context, client));\n }\n return { systemAppend: parts.join(\"\"), loaderTools };\n}\n\n/**\n * Discriminate a {@link Blocks} record value: a leaf {@link BlockBody}\n * carries a string `mode` (always `\"inject\"` or `\"progressive\"`); any\n * other object value is a nested group. Keying on `mode` being a\n * string is unambiguous for well-formed input because a group's\n * members are always objects (`BlockBody`/`Blocks`) or `false`, never a\n * bare string, so a group can never accidentally present a string\n * `mode` at its own level, even when a member happens to be named\n * `mode`. A malformed leaf that omits `mode` is caught separately by\n * `validateBlocks` (which reports the missing mode) rather than being\n * silently treated as a group. `false` removal sentinels are filtered\n * out before this is called.\n *\n * @internal\n */\nexport function isBlockGroup(value: BlockBody | Blocks): value is Blocks {\n return typeof (value as Partial<BlockBody>).mode !== \"string\";\n}\n\n/**\n * Provider tool-name charset. Synthetic loader names are\n * `_block_load_<flattenedName>` and are sent to the model provider\n * verbatim, which constrains them to `^[A-Za-z0-9_-]{1,64}$`. The\n * flattened block name must therefore satisfy {@link\n * BLOCK_TOOL_NAME_CHARSET} and stay within {@link TOOL_NAME_MAX_LENGTH}\n * once the loader prefix is added. Validated at construction so an\n * unsafe name fails at `agent()` rather than at the provider on the\n * first dispatch.\n *\n * @internal\n */\nexport const BLOCK_TOOL_NAME_CHARSET = /^[A-Za-z0-9_-]+$/;\n\n/** Maximum provider tool-name length. @internal */\nexport const TOOL_NAME_MAX_LENGTH = 64;\n\n/**\n * RC5026 error for two blocks whose names collapse to the same\n * flattened canonical name. Shared by the construction-time validator\n * ({@link validateBlocks}) and the dispatch-time flattener ({@link\n * flattenBlocks}) so the code and message cannot drift between the two\n * walkers, which must stay behaviourally identical.\n *\n * @internal\n */\nexport function blockCollisionError(\n qualified: string,\n): ReturnType<typeof rcError> {\n return rcError(\"RC5026\", undefined, {\n message: `Agent block \"${qualified}\": two blocks resolve to the same name after flattening nested groups. Rename one of them.`,\n });\n}\n\n/**\n * RC5026 error for a blocks tree that contains a cycle (a group that\n * directly or transitively contains itself). Shared by the validator\n * and the flattener for the same reason as {@link blockCollisionError}.\n *\n * @internal\n */\nexport function blockCycleError(prefix: string): ReturnType<typeof rcError> {\n return rcError(\"RC5026\", undefined, {\n message: `Agent block \"${prefix}\": blocks form a cycle (a group contains itself). Block trees must be finite.`,\n });\n}\n\n/**\n * Flatten a {@link Blocks} tree depth-first into an ordered map keyed\n * by the canonical name (group names joined by {@link\n * BLOCK_NAME_SEPARATOR}). Insertion order is preserved so inject\n * blocks keep their author-declared system-prompt order. `false`\n * entries are skipped (they are removal sentinels handled at merge\n * time, a no-op here). Two blocks that collapse to the same flattened\n * name throw RC5026 so a silent override cannot happen. This runs on\n * the post-merge record at dispatch, so it is the authoritative guard\n * for collisions that only arise once defaults and per-agent blocks\n * are combined; within-record collisions are already caught earlier by\n * `validateBlocks` at construction.\n *\n * @internal\n */\nexport function flattenBlocks(blocks: Blocks): Map<string, BlockBody> {\n const out = new Map<string, BlockBody>();\n walkBlocks(blocks, \"\", out, new WeakSet());\n return out;\n}\n\nfunction walkBlocks(\n blocks: Blocks,\n prefix: string,\n out: Map<string, BlockBody>,\n // Ancestors on the current recursion path; guards against a group\n // that (directly or transitively) contains itself, which would\n // otherwise recurse without bound. Added before descending and\n // removed after, so a group legitimately reused on two sibling\n // branches is not mistaken for a cycle.\n seen: WeakSet<object>,\n): void {\n if (seen.has(blocks)) throw blockCycleError(prefix);\n seen.add(blocks);\n for (const [name, body] of Object.entries(blocks)) {\n if (body === false) continue;\n const qualified = prefix ? `${prefix}${BLOCK_NAME_SEPARATOR}${name}` : name;\n if (isBlockGroup(body)) {\n walkBlocks(body, qualified, out, seen);\n continue;\n }\n if (out.has(qualified)) throw blockCollisionError(qualified);\n out.set(qualified, body);\n }\n seen.delete(blocks);\n}\n\n/**\n * Per-context, per-block resolution cache. Keyed by `CraftContext`\n * identity at the outer layer and by `BlockBody` object identity at\n * the inner layer. Stores the in-flight promise rather than the\n * resolved string so concurrent dispatches against the same\n * `context`-lifetime block share one resolution instead of racing\n * into N parallel invocations. WeakMap on the outer key so a disposed\n * context does not pin block content in memory.\n *\n * @internal\n */\nconst LIFETIME_CACHE = new WeakMap<\n CraftContext,\n Map<BlockBody, Promise<string>>\n>();\n\n/**\n * Run a block's resolver, honouring `lifetime`. For\n * `lifetime: \"dispatch\"` (default) the resolver runs every call. For\n * `lifetime: \"context\"` the resolver runs once per `CraftContext`\n * and the cached value (or in-flight promise) is reused for\n * subsequent calls in that context.\n *\n * @internal\n */\nasync function resolveOnce(\n name: string,\n body: BlockBody,\n exchange: Exchange<unknown>,\n context: CraftContext | undefined,\n client: BlockClient,\n): Promise<string> {\n const lifetime = body.lifetime ?? \"dispatch\";\n if (lifetime === \"context\" && context) {\n let cache = LIFETIME_CACHE.get(context);\n if (cache?.has(body)) return cache.get(body) as Promise<string>;\n if (!cache) {\n cache = new Map<BlockBody, Promise<string>>();\n LIFETIME_CACHE.set(context, cache);\n }\n const pending = invokeResolver(name, body, exchange, context, client);\n cache.set(body, pending);\n // On rejection, evict so a subsequent dispatch can retry rather\n // than being permanently stuck on the cached failure.\n pending.catch(() => cache!.delete(body));\n return pending;\n }\n return invokeResolver(name, body, exchange, context, client);\n}\n\n/**\n * Invoke a block's `value` resolver and validate its return shape.\n * Throws RC5025 on any failure so callers can decide whether to abort\n * the dispatch (inject mode) or report the error back to the model\n * (progressive mode).\n *\n * @internal\n */\nasync function invokeResolver(\n name: string,\n body: BlockBody,\n exchange: Exchange<unknown>,\n context: CraftContext | undefined,\n client: BlockClient,\n): Promise<string> {\n const { value } = body;\n if (typeof value === \"string\") return value;\n if (typeof value !== \"function\") {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${name}\": \"value\" must be a string or a function returning a string.`,\n });\n }\n if (!context) {\n throw rcError(\"RC5025\", undefined, {\n message: `Agent block \"${name}\": resolver function requires a CraftContext but the exchange has no bound context.`,\n });\n }\n let resolved: unknown;\n try {\n resolved = await Promise.resolve(value(exchange, context, [], client));\n } catch (cause) {\n throw rcError(\"RC5025\", cause, {\n message: `Agent block \"${name}\": resolver function threw: ${(cause as Error)?.message ?? String(cause)}`,\n });\n }\n if (typeof resolved !== \"string\") {\n throw rcError(\"RC5025\", undefined, {\n message: `Agent block \"${name}\": resolver function must return a string (got ${typeof resolved}).`,\n });\n }\n return resolved;\n}\n\n/**\n * JSON Schema describing an empty object. The loader tools accept no\n * input from the model (the block's content is fixed by the resolver,\n * not parameterised), so the schema is closed for additional properties\n * to match the bridge's expectations.\n *\n * @internal\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 for loader\n * tools. Mirrors the shape used by `currentTime` / `randomUuid` so the\n * AI SDK bridge's JSON-schema lookup works uniformly.\n *\n * @internal\n */\nconst EMPTY_OBJECT_SCHEMA: 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: [{ message: \"Expected an empty object {}.\" }],\n };\n }\n return { value: {} as Record<string, never> };\n },\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 * Build the synthetic `_block_load_<name>` tool for a progressive\n * block. The handler closes over the dispatch's exchange / context /\n * client so the resolver runs against live per-dispatch state when\n * the model invokes the loader. Errors are rethrown so the standard\n * tool-bridge error path reports them as a tool error the model can\n * self-correct from.\n *\n * @internal\n */\nfunction buildLoaderTool(\n name: string,\n body: BlockBody,\n exchange: Exchange<unknown>,\n context: CraftContext | undefined,\n client: BlockClient,\n): BlockLoaderTool {\n const description =\n typeof body.description === \"string\" && body.description.trim() !== \"\"\n ? body.description\n : `Load the \"${name}\" block.`;\n const handler: FnOptions[\"handler\"] = async () =>\n resolveOnce(name, body, exchange, context, client);\n return {\n name: `${BLOCK_LOADER_PREFIX}${name}`,\n description,\n input: EMPTY_OBJECT_SCHEMA,\n handler,\n [BLOCK_LOADER_TOOL]: true,\n blockName: name,\n };\n}\n\n/**\n * Build the `AgentBlockLoadSummary[]` from accumulated tool calls.\n * Filters the dispatched tool-call list to entries whose name carries\n * the reserved loader prefix and maps them onto the public summary\n * shape consumed by `AgentResult.blocksLoaded`.\n *\n * @internal\n */\nexport function summariseBlockLoads(\n toolCalls: ReadonlyArray<{\n toolCallId: string;\n toolName: string;\n output?: unknown;\n error?: unknown;\n }>,\n): AgentBlockLoadSummary[] {\n const out: AgentBlockLoadSummary[] = [];\n for (const tc of toolCalls) {\n if (!tc.toolName.startsWith(BLOCK_LOADER_PREFIX)) continue;\n const blockName = tc.toolName.slice(BLOCK_LOADER_PREFIX.length);\n const summary: AgentBlockLoadSummary = {\n blockName,\n toolName: tc.toolName,\n toolCallId: tc.toolCallId,\n };\n if (tc.output !== undefined) summary.output = tc.output;\n if (tc.error !== undefined) summary.error = tc.error;\n out.push(summary);\n }\n return out;\n}\n\n/**\n * Predicate matching the tool-call summaries that came from synthetic\n * block loaders. Used by the session to partition the cumulative\n * tool-call list before populating `AgentResult.toolCalls` vs\n * `AgentResult.blocksLoaded`.\n *\n * @internal\n */\nexport function isBlockLoaderCall(toolName: string): boolean {\n return toolName.startsWith(BLOCK_LOADER_PREFIX);\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 // A custom provider carrying a concrete model instance needs no model name\n // (only the factory form consumes one), so it is exempt from the guard.\n const isCustomInstance =\n model.provider === \"custom\" &&\n typeof (model as { model?: unknown }).model !== \"function\";\n if (modelName.trim() === \"\" && !isCustomInstance) {\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.`,\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 { loadOptionalPeer } from \"@routecraft/routecraft\";\nimport { assertLanguageModelShape, PROVIDER_DEFAULTS } 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 *\n * Provider SDKs are optional peer dependencies, loaded lazily through\n * `loadOptionalPeer` so a missing package surfaces as `RC5017` with an\n * install hint (see `.standards/ci-cd.md` § 6).\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 case \"lmstudio\":\n return resolveLmStudio(config, modelId);\n case \"custom\":\n return resolveCustom(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 const mod = (await loadOptionalPeer(() => import(\"@ai-sdk/openai\"), {\n adapterName: \"OpenAI LLM\",\n packageName: \"@ai-sdk/openai\",\n })) as {\n createOpenAI: (s: {\n apiKey: string;\n baseURL?: string;\n }) => (m: string) => unknown;\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 = mod.createOpenAI(settings);\n return openai(modelId);\n}\n\nasync function resolveAnthropic(\n config: import(\"../types.ts\").LlmModelConfigAnthropic,\n modelId: string,\n): Promise<unknown> {\n const mod = (await loadOptionalPeer(() => import(\"@ai-sdk/anthropic\"), {\n adapterName: \"Anthropic LLM\",\n packageName: \"@ai-sdk/anthropic\",\n })) as {\n createAnthropic: (s: { apiKey: string }) => (m: string) => unknown;\n };\n const anthropic = mod.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 const mod = (await loadOptionalPeer(() => import(\"@ai-sdk/google\"), {\n adapterName: \"Gemini LLM\",\n packageName: \"@ai-sdk/google\",\n })) as {\n createGoogleGenerativeAI: (s: { apiKey: string }) => (m: string) => unknown;\n };\n const google = mod.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 const mod = (await loadOptionalPeer(\n () => import(\"@openrouter/ai-sdk-provider\"),\n {\n adapterName: \"OpenRouter LLM\",\n packageName: \"@openrouter/ai-sdk-provider\",\n },\n )) as {\n createOpenRouter: (s: { apiKey: string }) => {\n chat: (id: string) => unknown;\n };\n };\n const openrouter = mod.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 const mod = (await loadOptionalPeer(() => import(\"ollama-ai-provider-v2\"), {\n adapterName: \"Ollama LLM\",\n packageName: \"ollama-ai-provider-v2\",\n })) as {\n createOllama: (s: { baseURL?: string }) => (name: string) => unknown;\n };\n const ollama = mod.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\nasync function resolveLmStudio(\n config: import(\"../types.ts\").LlmModelConfigLmStudio,\n modelId: string,\n): Promise<unknown> {\n const mod = (await loadOptionalPeer(\n () => import(\"@ai-sdk/openai-compatible\"),\n { adapterName: \"LM Studio LLM\", packageName: \"@ai-sdk/openai-compatible\" },\n )) as {\n createOpenAICompatible: (s: {\n name: string;\n baseURL: string;\n apiKey?: string;\n includeUsage?: boolean;\n }) => (id: string) => unknown;\n };\n // LM Studio serves an OpenAI-compatible chat-completions API. We use Vercel's\n // dedicated openai-compatible provider (not @ai-sdk/openai) so the adapter is\n // not tied to OpenAI-specific behaviour such as the Responses API. The\n // provider's default model is the chat-completions model, and `includeUsage`\n // makes LM Studio report token usage on streaming responses too.\n const settings: {\n name: string;\n baseURL: string;\n apiKey?: string;\n includeUsage: boolean;\n } = {\n name: \"lmstudio\",\n baseURL: config.baseURL ?? PROVIDER_DEFAULTS.lmstudio.baseURL,\n includeUsage: true,\n };\n // Only send an Authorization header when a key is configured; LM Studio\n // ignores auth, so we do not invent a placeholder bearer token.\n if (config.apiKey !== undefined) settings.apiKey = config.apiKey;\n const lmstudio = mod.createOpenAICompatible(settings);\n const name = config.modelId ?? modelId;\n const rawModel = lmstudio(name);\n assertLanguageModelShape(rawModel, \"LM Studio\", name);\n return rawModel;\n}\n\nfunction resolveCustom(\n config: import(\"../types.ts\").LlmModelConfigCustom,\n modelId: string,\n): unknown {\n const { model } = config;\n const resolved =\n typeof model === \"function\"\n ? (model as (id: string) => unknown)(modelId)\n : model;\n assertLanguageModelShape(resolved, \"Custom\", modelId || \"(custom)\");\n return resolved;\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 { isBlockLoaderTool } from \"../block/resolve.ts\";\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 }])`).\n * Throwing inside the guard surfaces back to the model as a tool\n * error so the model can self-correct; the wrapper emits\n * `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 // Block-loader synthetic tools emit `agent:block:loaded` /\n // `agent:block:error` events instead of the user-tool family so\n // observability consumers can wire framework bookkeeping separately\n // from the agent's user-tool usage.\n const isLoader = isBlockLoaderTool(r);\n const blockName = isLoader\n ? (r as { blockName?: string }).blockName\n : undefined;\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 (!isLoader && 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 if (isLoader) {\n ctx.emit(\n `route:${dispatchIdentity.routeId}:agent:block:loaded` as EventName,\n {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n blockName,\n output,\n duration: Date.now() - start,\n },\n );\n } else {\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 }\n return output;\n } catch (err) {\n if (ctx && dispatchIdentity) {\n if (isLoader) {\n ctx.emit(\n `route:${dispatchIdentity.routeId}:agent:block:error` as EventName,\n {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n blockName,\n error: err,\n duration: Date.now() - start,\n },\n );\n } else {\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 }\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 { isBlockLoaderCall, summariseBlockLoads } from \"../block/resolve.ts\";\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. Synthetic block-loader invocations are\n // partitioned out into `blocksLoaded` so user-tool assertions stay\n // clean.\n const userCalls: LlmToolCallSummary[] = [];\n const blockCalls: LlmToolCallSummary[] = [];\n for (const call of accumulatedToolCalls) {\n if (isBlockLoaderCall(call.toolName)) {\n blockCalls.push(call);\n } else {\n userCalls.push(call);\n }\n }\n if (userCalls.length > 0) out.toolCalls = userCalls;\n if (blockCalls.length > 0) out.blocksLoaded = summariseBlockLoads(blockCalls);\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 {\n getExchangeContext,\n getExchangeRoute,\n rcError,\n type CraftContext,\n type Destination,\n type Exchange,\n type Principal,\n} from \"@routecraft/routecraft\";\nimport { BLOCK_RESERVED_PREFIX, resolveBlocks } from \"../block/resolve.ts\";\nimport type { BlockBody, Blocks } from \"../block/types.ts\";\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 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 userTools = 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 { systemAppend, loaderTools } = await resolveBlocks(\n merged.blocks,\n exchange,\n context,\n );\n const tools = mergeUserAndLoaderTools(userTools, loaderTools);\n const withBlocks = `${baseSystem}${systemAppend}`;\n // Caller identity is appended last (after blocks) so the author's own\n // prompt and any block 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 withBlocks,\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 if (defaults.blocks !== undefined) {\n out.blocks = mergeBlocks(defaults.blocks, base.blocks);\n }\n return out;\n}\n\n/**\n * Merge default blocks with the agent's own. The per-agent record is\n * applied on top of the defaults by name: a key in both records picks\n * the per-agent body (overrides only that entry); non-colliding\n * defaults still apply; per-agent keys with new names extend the\n * record. A per-agent value of `false` removes the matching default;\n * a `false` for a name absent from defaults is a no-op so adding or\n * removing defaults later cannot break the agent definition.\n *\n * Insertion order is preserved by walking defaults first, then any\n * per-agent keys that didn't override a default. Inject blocks appear\n * in the system prompt in this order, which matters because the model\n * is sensitive to earlier system-prompt content.\n *\n * Merge is by top-level name only. When a name's value is a nested\n * group, a per-agent entry replaces the whole group (not a per-member\n * merge), and `false` removes the whole group. Per-member merge inside\n * a group is intentionally unsupported; see the agentPlugin reference.\n *\n * @internal\n */\nfunction mergeBlocks(\n defaults: { [name: string]: BlockBody | Blocks },\n agent: Blocks | undefined,\n): Blocks {\n // Null-prototype accumulator so a block name like `__proto__` cannot\n // mutate Object.prototype via `out[name] = body`. Block-name validation\n // (validateBlocks / validatePluginDefaults) already rejects the\n // reserved `_block_` prefix and empty strings, but `__proto__` is\n // outside both rules, so this is defence-in-depth.\n const out = Object.create(null) as Blocks;\n if (!agent) {\n for (const [name, body] of Object.entries(defaults)) out[name] = body;\n return out;\n }\n for (const [name, body] of Object.entries(defaults)) {\n if (Object.prototype.hasOwnProperty.call(agent, name)) {\n const override = agent[name];\n // `false` removes the default for this agent; an undefined value\n // shouldn't reach here under the Blocks type, but guard anyway.\n if (override === false || override === undefined) continue;\n out[name] = override;\n } else {\n out[name] = body;\n }\n }\n for (const [name, body] of Object.entries(agent)) {\n if (Object.prototype.hasOwnProperty.call(out, name)) continue;\n if (body === false) continue;\n out[name] = body;\n }\n return out;\n}\n\n/**\n * Merge user tools (from `tools([...])`) with synthetic block-loader\n * tools produced by {@link resolveBlocks}. Rejects (RC5026) any user\n * tool whose resolved name starts with the reserved `_block_` prefix,\n * so a misconfigured registry cannot shadow the framework's surface.\n *\n * @internal\n */\nfunction mergeUserAndLoaderTools(\n userTools: ResolvedTool[],\n loaderTools: ResolvedTool[],\n): ResolvedTool[] {\n for (const tool of userTools) {\n if (tool.name.startsWith(BLOCK_RESERVED_PREFIX)) {\n throw rcError(\"RC5026\", undefined, {\n message: `Agent tool \"${tool.name}\": names starting with \"${BLOCK_RESERVED_PREFIX}\" are reserved for synthetic block tools. Rename the fn or route.`,\n });\n }\n }\n return [...userTools, ...loaderTools];\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 * 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 } 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`). Surfaced in error messages so authors can find the\n * offending registration when resolution fails.\n */\n readonly targetId: string;\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} 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 `description` and `input` may be overridden. Guards are policy\n * and live at the consumer (attach them in `tools([{ name, guard }])`\n * at the agent's call site). Tags were previously overridable to\n * influence the removed tag-based selector; without that selector the\n * override has no effect at runtime, so the field is gone.\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\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 * `description` or `input` 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 * }),\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 return {\n [DEFERRED_FN_BRAND]: true,\n kind: \"direct\",\n targetId: routeId,\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 = 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\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 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 */\nexport type ToolsItem =\n | string\n | { name: string; guard?: ToolGuard; description?: string };\n\n/**\n * Read-only snapshot of every tool registered in the live context,\n * handed to the function form of `tools()`. Lets a builder filter or\n * compose a list without baking selector languages into the framework\n * (a \"give me all read-only fns\" predicate is the user's `.filter()`\n * call, not a framework-blessed primitive).\n *\n * Walking the snapshot is the explicit, code-visible way to extend an\n * agent's tool surface across registrations: a future fn whose tags\n * match the predicate will silently extend the surface the next time\n * `resolve()` runs. The function form makes that visible at the call\n * site, where a `.filter()` is the obvious signal that the set is\n * dynamic.\n */\nexport interface ToolsCatalog {\n /**\n * Plain fn entries from `agentPlugin({ functions })`. Deferred\n * wrappers (e.g. `directTool(routeId)`) appear here too with their\n * canonical name and the override tags supplied at builder time.\n */\n readonly fns: ReadonlyArray<{\n readonly name: string;\n readonly description?: string;\n readonly tags?: readonly Tag[];\n }>;\n /**\n * Direct routes registered in `ADAPTER_DIRECT_REGISTRY`. Reference\n * them in a `ToolsItem` as `\"Direct(<id>)\"`.\n */\n readonly routes: ReadonlyArray<{\n readonly id: string;\n readonly description?: string;\n readonly tags?: readonly Tag[];\n }>;\n /**\n * MCP tools populated by `mcpPlugin({ clients })`. Reference them in\n * a `ToolsItem` as `\"MCP(<server>:<tool>)\"` or\n * `\"mcp__<server>__<tool>\"`.\n */\n readonly mcp: ReadonlyArray<{\n readonly server: string;\n readonly tool: string;\n readonly description?: string;\n readonly tags?: readonly Tag[];\n }>;\n}\n\n/**\n * Builder form of `tools()`. Receives a snapshot of the registered\n * tools and returns the list of references to expose. Same return\n * shape as the array form, so the rest of resolution is identical.\n */\nexport type ToolsBuilder = (catalog: ToolsCatalog) => ToolsItem[];\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).\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.\n *\n * Two forms:\n *\n * - **Array**: `tools([...])` -- explicit enumeration of references.\n * Resolution happens lazily at agent dispatch time. Items are bare\n * strings or `{ name, guard?, description? }` objects.\n * - **Builder**: `tools((catalog) => [...])` -- programmatic selection.\n * Receives a snapshot of the live fn / route / MCP registries and\n * returns the same shape the array form accepts. Use this as the\n * escape hatch when explicit enumeration is impractical (e.g. \"give\n * me every read-only fn\"); the predicate lives in your code so the\n * implicit-extension behaviour is visible at the call site.\n *\n * Resolution rules:\n *\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 * - Final list is deduplicated by tool name; later refs to the same\n * name win (so a user's builder can override a tag-derived entry\n * simply by listing it explicitly).\n *\n * @example Array form\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 * ]),\n * });\n * ```\n *\n * @example Builder form\n * ```ts\n * agent({\n * tools: tools((catalog) => [\n * \"fetchOrder\",\n * ...catalog.fns\n * .filter((f) => f.tags?.includes(\"read-only\"))\n * .map((f) => f.name),\n * ]),\n * });\n * ```\n */\nexport function tools(items: ToolsItem[]): ToolSelection;\nexport function tools(builder: ToolsBuilder): ToolSelection;\nexport function tools(arg: ToolsItem[] | ToolsBuilder): ToolSelection {\n if (typeof arg !== \"function\" && !Array.isArray(arg)) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): argument must be an array of ToolsItem or a (catalog) => ToolsItem[] builder.`,\n });\n }\n return {\n [TOOL_SELECTION_BRAND]: true,\n resolve(ctx) {\n const items =\n typeof arg === \"function\" ? runBuilder(arg, buildCatalog(ctx)) : arg;\n const out = new Map<string, ResolvedTool>();\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 out.set(tool.name, tool);\n }\n continue;\n }\n const tool = resolveByName(ctx, item, undefined);\n out.set(tool.name, tool);\n continue;\n }\n if (item === null || typeof item !== \"object\" || !(\"name\" in item)) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): each item must be a string or { name, guard?, description? }.`,\n });\n }\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 out.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 out.set(tool.name, tool);\n }\n return [...out.values()];\n },\n };\n}\n\n/**\n * Build a {@link ToolsCatalog} snapshot from the live context's\n * registries. Each entry and its `tags` array are frozen so the\n * interface's `readonly` modifiers match runtime behaviour: a builder\n * cannot mutate an entry's name / description / tags in place and have\n * it silently affect the rest of resolution. Freeze cost is negligible\n * for a per-dispatch snapshot of a handful of registry entries.\n *\n * @internal\n */\nfunction buildCatalog(ctx: CraftContext): ToolsCatalog {\n const fns: ToolsCatalog[\"fns\"][number][] = [];\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 // Deferred wrappers don't carry their own description/tags in\n // the registry; users who want to filter on those should walk\n // catalog.routes for the underlying route, then reference it\n // as `Direct(<routeId>)` in the returned items list.\n fns.push(Object.freeze({ name }));\n } else {\n const tags =\n entry.tags && entry.tags.length > 0\n ? Object.freeze([...entry.tags])\n : undefined;\n fns.push(\n Object.freeze({\n name,\n description: entry.description,\n ...(tags !== undefined ? { tags } : {}),\n }),\n );\n }\n }\n }\n\n const routes: ToolsCatalog[\"routes\"][number][] = [];\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 const tags =\n meta.tags && meta.tags.length > 0\n ? Object.freeze([...meta.tags])\n : undefined;\n // The direct registry is keyed by the sanitised (URL-encoded)\n // endpoint, but `Direct(<routeId>)` consumers want the raw id\n // they passed to `.id(...)`. Round-trip through\n // `decodeURIComponent` so a builder that does\n // `Direct(${r.id})` resolves cleanly for ids containing `/`,\n // `:`, etc. (without the decode, the resolver would\n // double-encode at lookup time).\n const rawId = decodeURIComponent(routeId);\n routes.push(\n Object.freeze({\n id: rawId,\n ...(meta.description ? { description: meta.description } : {}),\n ...(tags !== undefined ? { tags } : {}),\n }),\n );\n }\n }\n\n const mcp: ToolsCatalog[\"mcp\"][number][] = [];\n const mcpRegistry = ctx.getStore(MCP_TOOL_REGISTRY);\n if (mcpRegistry) {\n for (const entry of mcpRegistry.getTools()) {\n const tags =\n entry.tags && entry.tags.length > 0\n ? Object.freeze([...entry.tags])\n : undefined;\n mcp.push(\n Object.freeze({\n server: entry.source,\n tool: entry.name,\n ...(entry.description ? { description: entry.description } : {}),\n ...(tags !== undefined ? { tags } : {}),\n }),\n );\n }\n }\n\n return Object.freeze({\n fns: Object.freeze(fns),\n routes: Object.freeze(routes),\n mcp: Object.freeze(mcp),\n });\n}\n\n/**\n * Invoke a user-supplied tools builder safely and surface failures as\n * RC5003 with the original error chained. Validates that the return\n * is an array so a confused builder doesn't silently produce nothing.\n *\n * @internal\n */\nfunction runBuilder(builder: ToolsBuilder, catalog: ToolsCatalog): ToolsItem[] {\n let items: unknown;\n try {\n items = builder(catalog);\n } catch (cause) {\n throw rcError(\"RC5003\", cause, {\n message: `tools(builder): builder threw: ${(cause as Error)?.message ?? String(cause)}`,\n });\n }\n if (!Array.isArray(items)) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(builder): builder must return an array of ToolsItem (got ${typeof items}).`,\n });\n }\n return items as ToolsItem[];\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\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 {\n BLOCK_LOADER_PREFIX,\n BLOCK_NAME_SEPARATOR,\n BLOCK_RESERVED_PREFIX,\n BLOCK_TOOL_NAME_CHARSET,\n blockCollisionError,\n blockCycleError,\n isBlockGroup,\n TOOL_NAME_MAX_LENGTH,\n} from \"../block/resolve.ts\";\nimport type { BlockBody, Blocks } from \"../block/types.ts\";\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 if (options.blocks !== undefined) {\n validateBlocks(options.blocks);\n }\n}\n\n/**\n * Validate the shape of every entry on an agent's `blocks` record.\n * Throws RC5027 on individual block misconfiguration and RC5026 on\n * reserved-prefix collisions or empty names. Runs at construction so\n * misconfigured blocks surface immediately, not at first dispatch.\n *\n * Duplicate keys are impossible by construction (object literal); a\n * value of `false` is permitted and means \"remove this block from\n * defaults\" -- the validator only checks the body shape for non-`false`\n * entries. Empty-string keys are rejected because they round-trip as\n * an unloadable block name.\n *\n * Exported (`@internal`) so `agentPlugin({ defaultOptions: { blocks } })`\n * can reuse the same checks. Pass `defaultsLabel` from the defaults\n * path: it switches `false` from \"allowed (per-agent removal sentinel)\"\n * to \"rejected with RC5003\" at every nesting level, because defaults\n * cannot sensibly remove themselves, and names the offending entry\n * with that label.\n *\n * Validation is authoritative at construction: alongside the per-leaf\n * structural checks it enforces the flattened-name rules a synthetic\n * loader tool depends on (reserved `_block_` namespace, provider\n * charset and length, no two blocks collapsing to one name) so those\n * surface at `agent()` rather than at the provider on first dispatch.\n *\n * @internal\n */\nexport function validateBlocks(blocks: unknown, defaultsLabel?: string): void {\n const state: BlockValidationState = {\n seenNames: new Set<string>(),\n seenObjects: new WeakSet<object>(),\n // Only set when present: `exactOptionalPropertyTypes` forbids an\n // explicit `undefined` for the optional `defaultsLabel`.\n ...(defaultsLabel !== undefined ? { defaultsLabel } : {}),\n };\n validateBlocksLevel(blocks, \"\", state);\n}\n\ninterface BlockValidationState {\n /** Flattened leaf names seen so far, for collision detection. */\n readonly seenNames: Set<string>;\n /** Groups on the current recursion path, for cycle detection. */\n readonly seenObjects: WeakSet<object>;\n /** Defaults label; when set, `false` is rejected (see {@link validateBlocks}). */\n readonly defaultsLabel?: string;\n}\n\n/**\n * Recursive worker for {@link validateBlocks}. Validates one level of a\n * {@link Blocks} tree, recursing into nested groups. `prefix` carries\n * the flattened-name path (joined by {@link BLOCK_NAME_SEPARATOR}) so\n * error messages name the offending block the way it resolves at\n * dispatch. A record value is a leaf or a nested group per {@link\n * isBlockGroup}.\n *\n * @internal\n */\nfunction validateBlocksLevel(\n blocks: unknown,\n prefix: string,\n state: BlockValidationState,\n): number {\n if (blocks === null || typeof blocks !== \"object\" || Array.isArray(blocks)) {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent: \"blocks\" must be a Record<string, BlockBody | Blocks | false>.`,\n });\n }\n if (state.seenObjects.has(blocks)) throw blockCycleError(prefix);\n state.seenObjects.add(blocks);\n // Count of leaves at this level and below. A nested group that\n // produces zero leaves (empty `{}` or only `false` members) is an\n // author mistake the strict-at-construction contract should surface,\n // so the caller rejects it; the top-level record is allowed to be\n // empty (an agent with no blocks).\n let leafCount = 0;\n for (const [name, body] of Object.entries(blocks as Blocks)) {\n const qualified = prefix ? `${prefix}${BLOCK_NAME_SEPARATOR}${name}` : name;\n if (name.trim() === \"\") {\n throw rcError(\"RC5026\", undefined, {\n message: `Agent block: block name must be a non-empty string.`,\n });\n }\n // Reject reserved-prefix segments and any combination whose\n // flattened name lands in the reserved namespace (e.g. a group\n // \"_block\" with a leaf \"x\" flattens to \"_block__x\").\n if (\n name.startsWith(BLOCK_RESERVED_PREFIX) ||\n qualified.startsWith(BLOCK_RESERVED_PREFIX)\n ) {\n throw rcError(\"RC5026\", undefined, {\n message: `Agent block \"${qualified}\": names starting with \"${BLOCK_RESERVED_PREFIX}\" are reserved for synthetic block tools. Rename the block or a parent group.`,\n });\n }\n if (body === false) {\n if (state.defaultsLabel !== undefined) {\n throw rcError(\"RC5003\", undefined, {\n message:\n `agentPlugin: \"${state.defaultsLabel}.${qualified}\" cannot be false. ` +\n `\"false\" is the per-agent removal sentinel; defaults cannot remove themselves. ` +\n `Drop the entry or replace it with a BlockBody.`,\n });\n }\n continue;\n }\n if (body === null || typeof body !== \"object\") {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": value must be a BlockBody object (with mode and value), a nested Blocks group, or \"false\" to remove a default.`,\n });\n }\n if (isBlockGroup(body)) {\n // A value with no string `mode` is normally a nested group. But a\n // BlockBody-shaped `value` (string or function) is a strong signal\n // the author meant a leaf and forgot or mistyped `mode`; report\n // that precisely instead of recursing and blaming a phantom\n // `<name>__value` block. A real group's members are objects, so\n // this never misfires on a member that merely happens to be named\n // `value`.\n const maybeValue = (body as Partial<BlockBody>).value;\n if (typeof maybeValue === \"string\" || typeof maybeValue === \"function\") {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": \"mode\" must be \"inject\" or \"progressive\" (got ${JSON.stringify((body as Partial<BlockBody>).mode)}).`,\n });\n }\n const childLeaves = validateBlocksLevel(body, qualified, state);\n if (childLeaves === 0) {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": a nested group must contain at least one block (got an empty group or only \"false\" members).`,\n });\n }\n leafCount += childLeaves;\n continue;\n }\n if (state.seenNames.has(qualified)) throw blockCollisionError(qualified);\n state.seenNames.add(qualified);\n leafCount += 1;\n const b = body as BlockBody;\n if (b.mode !== \"inject\" && b.mode !== \"progressive\") {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": \"mode\" must be \"inject\" or \"progressive\" (got ${JSON.stringify(b.mode)}).`,\n });\n }\n if (\n b.mode === \"progressive\" &&\n (typeof b.description !== \"string\" || b.description.trim() === \"\")\n ) {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": progressive-mode blocks require a non-empty \"description\" so the model can decide whether to load.`,\n });\n }\n // Progressive blocks become the synthetic loader tool\n // `_block_load_<flattenedName>`, which the provider constrains to\n // `^[A-Za-z0-9_-]{1,64}$`. Check the flattened name here so an\n // unsafe or over-long name fails at construction, not at the\n // provider on first dispatch.\n if (b.mode === \"progressive\") {\n if (!BLOCK_TOOL_NAME_CHARSET.test(qualified)) {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": a progressive block becomes the loader tool \"${BLOCK_LOADER_PREFIX}${qualified}\", so its flattened name must match ${BLOCK_TOOL_NAME_CHARSET.source} (letters, digits, \"_\", \"-\"). Rename the block or its parent group.`,\n });\n }\n const toolName = `${BLOCK_LOADER_PREFIX}${qualified}`;\n if (toolName.length > TOOL_NAME_MAX_LENGTH) {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": the loader tool name \"${toolName}\" is ${toolName.length} characters, over the provider limit of ${TOOL_NAME_MAX_LENGTH}. Shorten the block name or its parent group.`,\n });\n }\n }\n if (\n b.lifetime !== undefined &&\n b.lifetime !== \"dispatch\" &&\n b.lifetime !== \"context\"\n ) {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": \"lifetime\" must be \"dispatch\" or \"context\" when present (got ${JSON.stringify(b.lifetime)}).`,\n });\n }\n if (typeof b.value !== \"string\" && typeof b.value !== \"function\") {\n throw rcError(\"RC5027\", undefined, {\n message: `Agent block \"${qualified}\": \"value\" must be a string or a function returning a string.`,\n });\n }\n }\n state.seenObjects.delete(blocks);\n return leafCount;\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, validateBlocks } 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 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 * 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 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 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 if (raw.blocks !== undefined) {\n // Run the same validation as AgentOptions.blocks (blank names, the\n // reserved `_block_` namespace, provider-unsafe / over-long loader\n // names, flatten collisions, malformed BlockBody values) at plugin\n // construction rather than at agent dispatch. The `defaultsLabel`\n // argument additionally rejects `false` at every nesting level,\n // because defaults are the base layer and cannot remove themselves;\n // the error names the offending entry by its flattened path.\n validateBlocks(raw.blocks, \"defaultOptions.blocks\");\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 // Blocks merge additively across multiple `agentPlugin` installs:\n // each install contributes named entries, and a name set in two\n // installs throws so we never silently pick one. This differs from\n // `model` / `tools` (single-valued) and matches how blocks compose\n // per-agent: independent named contributions.\n let mergedBlocks: typeof existing.blocks | undefined;\n if (existing.blocks !== undefined || next.blocks !== undefined) {\n mergedBlocks = { ...(existing.blocks ?? {}) };\n if (next.blocks !== undefined) {\n for (const [name, body] of Object.entries(next.blocks)) {\n if (Object.prototype.hasOwnProperty.call(mergedBlocks, name)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"defaultOptions.blocks\" already contains \"${name}\" from a previous install. Each block name may be defined once across all installs.`,\n });\n }\n mergedBlocks[name] = body;\n }\n }\n }\n return {\n ...existing,\n ...(next.model !== undefined ? { model: next.model } : {}),\n ...(next.tools !== undefined ? { tools: next.tools } : {}),\n ...(mergedBlocks !== undefined ? { blocks: mergedBlocks } : {}),\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 or block `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()` or `skills()`\n * do 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 \"../block/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 \"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\" | \"principal\" | \"blocks\"\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 // 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 (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.principal !== undefined) out.principal = override.principal;\n if (override.blocks !== undefined) out.blocks = override.blocks;\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 * | `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` / `blocks` /\n * `principal` / `system` per agent without editing the markdown\n * source. `blocks` is override-only because YAML cannot express the\n * function-form resolvers a block may carry.\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 // Null-prototype map so a frontmatter `name` like `__proto__` or\n // `toString` cannot collide with Object.prototype (the `in` check\n // below would otherwise pass for keys that were never loaded, and\n // an assignment to `__proto__` would mutate the prototype).\n const out = Object.create(null) as 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 (!Object.prototype.hasOwnProperty.call(out, name)) {\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 { readFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\nimport {\n rcError,\n type CraftContext,\n type Exchange,\n} from \"@routecraft/routecraft\";\nimport {\n readMarkdownDir,\n readMarkdownFile,\n requireString,\n} from \"./markdown.ts\";\nimport type {\n BlockBody,\n BlockClient,\n BlockLifetime,\n BlockMode,\n Blocks,\n} from \"./types.ts\";\n\n/**\n * Options for {@link skills}. Loads markdown skills from disk and\n * returns one {@link BlockBody} per skill, keyed by skill name, so\n * the agent picks them up via its `blocks: { ... }` record.\n */\nexport interface SkillsOptions {\n /**\n * Path to a single `.md` file or a directory containing skill\n * markdown files. Directories support the Claude Code convention:\n * flat `.md` files and nested `<name>/SKILL.md` folders may\n * coexist.\n */\n source: string;\n /**\n * How skills are surfaced to the model. Defaults to `\"progressive\"`\n * so the model sees each skill's name + description in the system\n * prompt and only loads the body via a tool call when relevant\n * (matches Claude Code's default progressive-disclosure behaviour).\n * Pass `\"inject\"` to concatenate every skill's full body into the\n * system prompt on every dispatch.\n */\n mode?: BlockMode;\n /**\n * Per-block lifetime applied to every loaded skill. Defaults to\n * `\"dispatch\"`. Pass `\"context\"` to read each skill file once per\n * `CraftContext` and reuse the parsed content across dispatches.\n */\n lifetime?: BlockLifetime;\n}\n\n/**\n * Load markdown skills from disk and return them as a {@link Blocks}\n * record ready to spread into an agent's `blocks: { ... }` map.\n *\n * Two layouts are supported and may coexist in the same folder:\n *\n * - **Flat**: `<dir>/<name>.md` -- filename (without `.md`) is the\n * skill name and must match the frontmatter `name`.\n * - **Nested**: `<dir>/<name>/SKILL.md` -- the subdirectory name is\n * the skill name and must match the frontmatter `name`. The folder\n * can also bundle supporting assets; only `SKILL.md` is consumed.\n *\n * The `description` frontmatter becomes the block's description (used\n * verbatim when `mode: \"progressive\"` so the model can decide whether\n * to load); the markdown body becomes the block's static `value`.\n *\n * @example\n * ```ts\n * agent({\n * model: \"anthropic:claude-sonnet-4-6\",\n * system: \"You are an analyst.\",\n * blocks: {\n * ...(await skills({ source: \"./skills\" })),\n * },\n * });\n * ```\n */\nexport async function skills(options: SkillsOptions): Promise<Blocks> {\n if (!options || typeof options !== \"object\") {\n throw rcError(\"RC5027\", undefined, {\n message: `skills: options must be an object with at least { source }.`,\n });\n }\n const { source, mode = \"progressive\", lifetime } = options;\n if (typeof source !== \"string\" || source.trim() === \"\") {\n throw rcError(\"RC5027\", undefined, {\n message: `skills: \"source\" must be a non-empty path to a markdown file or directory.`,\n });\n }\n if (mode !== \"inject\" && mode !== \"progressive\") {\n throw rcError(\"RC5027\", undefined, {\n message: `skills: \"mode\" must be \"inject\" or \"progressive\" (got ${JSON.stringify(mode)}).`,\n });\n }\n if (\n lifetime !== undefined &&\n lifetime !== \"dispatch\" &&\n lifetime !== \"context\"\n ) {\n throw rcError(\"RC5027\", undefined, {\n message: `skills: \"lifetime\" must be \"dispatch\" or \"context\" when present (got ${JSON.stringify(lifetime)}).`,\n });\n }\n const docs = source.endsWith(\".md\")\n ? [await readMarkdownFile(source)]\n : await readMarkdownDir(source, { sentinelFilename: \"SKILL.md\" });\n const sources = new Map<string, string>();\n const out: Record<string, BlockBody> = {};\n for (const doc of docs) {\n const name = requireString(doc.frontmatter[\"name\"], \"name\", doc.path);\n if (name !== doc.filename) {\n throw rcError(\"RC5027\", undefined, {\n message: `skills: markdown file \"${doc.path}\": frontmatter \"name\" (\"${name}\") must match the filename (\"${doc.filename}\"). Rename one or the other.`,\n });\n }\n const description = requireString(\n doc.frontmatter[\"description\"],\n \"description\",\n doc.path,\n );\n if (doc.body.trim() === \"\") {\n throw rcError(\"RC5027\", undefined, {\n message: `skills: markdown file \"${doc.path}\": skill body is empty. The body becomes the block's content; an empty body would not change the agent's behaviour.`,\n });\n }\n const prior = sources.get(name);\n if (prior) {\n throw rcError(\"RC5026\", undefined, {\n message: `skills(\"${source}\"): duplicate skill name \"${name}\" loaded from both \"${prior}\" and \"${doc.path}\". Each skill name must be unique within a source; rename or remove one.`,\n });\n }\n sources.set(name, doc.path);\n const body: BlockBody = { description, mode, value: doc.body };\n if (lifetime !== undefined) body.lifetime = lifetime;\n out[name] = body;\n }\n return out;\n}\n\n/**\n * Return a function-form resolver that reads a UTF-8 text file at\n * dispatch (or context-init) time. Useful when a block's content\n * lives on disk and may be edited without restarting the process.\n *\n * Resolves the path against `process.cwd()` so relative paths\n * (`\"./prompts/identity.md\"`) work the same way the markdown loaders\n * do.\n *\n * @example\n * ```ts\n * agent({\n * model: \"anthropic:claude-sonnet-4-6\",\n * system: \"You are Zoe.\",\n * blocks: {\n * identity: {\n * mode: \"inject\",\n * lifetime: \"context\",\n * value: fromFile(\"./prompts/identity.md\"),\n * },\n * },\n * });\n * ```\n */\nexport function fromFile(\n path: string,\n): (\n exchange: Exchange<unknown>,\n context: CraftContext,\n events: readonly unknown[],\n client: BlockClient,\n) => Promise<string> {\n if (typeof path !== \"string\" || path.trim() === \"\") {\n throw rcError(\"RC5027\", undefined, {\n message: `fromFile: \"path\" must be a non-empty string.`,\n });\n }\n return async () => {\n const abs = resolvePath(process.cwd(), path);\n try {\n // Async read so the resolver does not block the event loop on\n // every dispatch (default lifetime is `\"dispatch\"`, so this can\n // fire often under concurrent agent traffic).\n return await readFile(abs, \"utf-8\");\n } catch (cause) {\n throw rcError(\"RC5025\", cause, {\n message: `fromFile(\"${path}\"): could not read file: ${(cause as Error)?.message ?? String(cause)}`,\n });\n }\n };\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"]}
|
|
1
|
+
{"version":3,"sources":["../src/llm/types.ts","../src/llm/providers/llm-utils.ts","../src/llm/validate-options.ts","../src/llm/plugin.ts","../src/tool-name.ts","../src/mcp/types.ts","../package.json","../src/mcp/build-auth-headers.ts","../src/mcp/sdk.ts","../src/mcp/extract-content.ts","../src/mcp/dispatch.ts","../src/fn/handler-context.ts","../src/mcp/annotation-tags.ts","../src/mcp/proxy.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/http-client-cache.ts","../src/mcp/validate-options.ts","../src/mcp/stdio-client-manager.ts","../src/mcp/tool-registry.ts","../src/mcp/plugin.ts","../src/embedding/providers/index.ts","../src/embedding/types.ts","../src/embedding/plugin.ts","../src/block/client.ts","../src/block/resolve.ts","../src/llm/shared.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/agent/tools/policy.ts","../src/agent/enricher.ts","../src/fn/store.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/errors.ts","../src/brand.ts","../src/llm/enricher.ts","../src/llm/llm.ts","../src/mcp/adapters/mcp/shared.ts","../src/mcp/adapters/mcp/source.ts","../src/mcp/adapters/mcp/enricher.ts","../src/mcp/adapters/mcp/index.ts","../src/mcp/oauth.ts","../src/block/markdown.ts","../src/agent/loader.ts","../src/agent/suspend.ts","../src/block/builders.ts","../src/embedding/enricher.ts","../src/embedding/embedding.ts"],"names":["ADAPTER_LLM_PROVIDERS","ADAPTER_LLM_OPTIONS","PROVIDER_DEFAULTS","assertLanguageModelShape","model","providerName","modelId","m","toLlmUsage","u","getStructuredOutput","result","readReasoning","r","collectToolCalls","steps","out","step","calls","results","call","c","toolCallId","toolName","input","summary","match","buildExtras","params","buildSdkParams","options","system","user","extras","PROVIDERS","isProvider","s","validateLlmPluginOptions","providerId","opts","PROVIDER_IDS","toModelConfig","llmPlugin","ctx","map","TOOL_NAME_CHARACTER_CLASS","TOOL_NAME_CHARACTER","TOOL_NAME_CHARSET","TOOL_NAME_MAX_LENGTH","TOOL_NAME_PATTERN","TOOL_NAME_PATTERN_SOURCE","TOOL_NAME_SEPARATOR","isSplittableNameHead","segment","separatorHalf","describeToolNameViolation","name","MCP_TOOL_NAME_PATTERN","MCP_PLUGIN_REGISTERED","ADAPTER_MCP_CLIENT_SERVERS","MCP_TOOL_REGISTRY","MCP_STDIO_MANAGERS","MCP_LOCAL_TOOL_REGISTRY","McpHeadersKeys","version","rrIndexes","resolveToken","token","idx","buildAuthHeaders","auth","headers","customHeaders","authorizationOverride","resolved","value","loadMcpServerSdk","adapterName","loadOptionalPeer","loadMcpServerStdioSdk","loadMcpNodeSdk","loadMcpClientSdk","loadMcpClientStdioSdk","MCP_VERSION_NEGOTIATION","MCP_CLIENT_INFO","connectMcpHttpClient","url","Client","StreamableHTTPClientTransport","transport","init","merged","client","cause","extractContent","response","content","item","dispatchMcpCall","serverId","args","dispatchMcpCallRaw","manager","isRoutecraftError","rcError","http","resolveHttpConfig","callRemoteToolRaw","config","callRemoteTool","serverUrl","connection","makeFnHandlerContext","abortSignal","principal","frameworkLogger","freezePrincipal","wasAuthentic","isAuthentic","snapshot","deepFreeze","markAuthentic","seen","key","v","mergeAnnotations","base","overrides","TAG_ANNOTATION_HINTS","deriveAnnotationsFromTags","tags","derived","tag","hint","deriveTagsFromAnnotations","annotations","parseProxyRef","ref","normalizeProxyEntries","proxy","entry","exposedNameFor","remoteToolName","resolveProxiedTools","warn","registry","add","isExact","exposedName","existing","clientTools","t","proxiedToolToMcpTool","proxied","tool","description","ALLOW_METHODS","EXPOSE_HEADERS","LOOPBACK_HOSTS","defaultLoopbackOriginResolver","requestOrigin","parsed","resolveCorsOptions","origin","allowed","safeResolveOrigin","cors","buildCorsHeaders","preflight","applyCorsHeaders","res","Vary","rest","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","expiresAt","compute","hashToken","cached","pending","promise","enrichment","err","oldest","createHash","parseMaxAge","headerValue","createUserinfoUrlResolver","option","issuer","discoveryUrl","cachedUrl","cachedUntil","inFlight","fetchAndCache","doc","ttl","fetchUserinfo","mergeEnrichment","liftOidcClaims","payload","buildEnrichedVerifier","baseVerifier","userinfo","cache","resolveUserinfoUrl","responseSub","isExpiredTokenError","JOSE_INFRASTRUCTURE_CODES","NETWORK_ERROR_CODES","isInfrastructureError","current","depth","code","classifyRejectionReason","NEVER_ABORTED","isPlainObject","normalizeToolArgs","toolErrorLogMessage","error","toolErrorUserMessage","logMsg","McpServer","context","fallback","info","websiteUrl","icons","instructions","explicit","msg","serveStdio","Server","server","tools","request","createMcpHandler","toNodeHandler","handler","nodeHandler","req","host","port","metadata","resource","metadataUrl","required","granted","scope","serve","createServer","rawOrigin","originValue","resolvedResourceUrl","ownedPaths","authenticated","missing","detail","resolve","reject","boundPort","listenDetail","authInfo","stashed","addr","authOptions","verifier","rawHeader","schemeMatch","successDetail","nowSeconds","clockToleranceSec","expired","reason","srv","names","exposedDetail","entries","localNames","e","toolsFilter","message","schema","standard","body","HeadersKeys","exchange","DefaultExchange","resultExchange","resultText","guard","guardCtx","raw","createConnectionCache","create","onError","SCOPE_TOKEN","validateMcpPluginOptions","requiredScopes","salvaged","suggested","seenRefs","seenNames","isString","isObject","isWildcard","refKey","exposed","validateWithSchema","formatSchemaIssues","StdioClientManager","logger","onEvent","onToolsUpdated","clientMod","stdioMod","command","env","cwd","data","transportWithClose","maxRestarts","restartDelayMs","restartBackoffMultiplier","delay","stableMs","McpToolRegistry","source","sourceMap","derivedTags","fingerprint","isStdioConfig","mcpPlugin","stdioManagers","httpClients","httpRefreshTimers","toolRegistry","clientEntries","k","startStdioClient","httpConfig","listHttpClientTools","setupHttpToolRefresh","timer","managerOpts","event","details","_serverId","getOrCreateHttpClient","rawClient","typed","interval","pipelineCache","disposeEmbeddingPipelineCache","resolveHuggingFaceModel","modelName","getHuggingFacePipeline","pipe","run","text","previewForError","toNumberArray","d","callEmbedding","vec","output","ADAPTER_EMBEDDING_PROVIDERS","ADAPTER_EMBEDDING_OPTIONS","embeddingPlugin","makeBlockClient","route","getExchangeRoute","BLOCK_NAME_SEPARATOR","BLOCK_LOADER_TOOL","BLOCK_RESERVED_PREFIX","BLOCK_LOADER_PREFIX","isBlockLoaderTool","resolveBlocks","blocks","flat","flattenBlocks","parts","loaderTools","resolveOnce","buildLoaderTool","isBlockGroup","BLOCK_TOOL_NAME_CHARSET","blockCollisionError","qualified","blockCycleError","prefix","walkBlocks","LIFETIME_CACHE","invokeResolver","EMPTY_OBJECT_JSON_SCHEMA","EMPTY_OBJECT_SCHEMA","summariseBlockLoads","toolCalls","tc","isBlockLoaderCall","parseProviderModel","id","colon","resolveModel","isCustomInstance","store","resolvePrompt","resolveUserPromptDefault","resolveLanguageModel","resolveOpenAI","resolveAnthropic","resolveGemini","resolveOpenRouter","resolveOllama","resolveLmStudio","resolveCustom","_","keyedSettings","settings","openrouter","resolvedId","rawModel","ollama","mod","lmstudio","normalizeStreamDelta","part","p","readString","obj","streamLlm","onDelta","runStreamGenerate","streamText","delta","usage","safeAwait","reasoning","structured","finishReason","callLlm","runGenerate","generateText","responseMessages","toAiSchema","direction","errorContext","primary","jsonSchemaObj","validate","jsonSchema","toAiInputSchema","toAiOutputSpec","aiSchema","Output","buildVercelTools","dispatchIdentity","baseCtx","isLoader","blockName","callOpts","callCtx","randomUUID","start","errorName","dispatchIdentityFrom","routeId","corr","DEFAULT_TEMPERATURE","DEFAULT_MAX_TOKENS","DEFAULT_MAX_TURNS","AgentSession","maxTurns","turnsUsed","currentUser","lastValidatorMsg","accumulatedToolCalls","prepared","remaining","callOnce","toAgentResult","verdict","buildRetryPrompt","agentName","identity","modelConfig","vercelTools","remainingTurns","toolExtras","buildStopWhen","stepCountIs","initialUser","lastResult","validatorMsg","userMsgs","userCalls","blockCalls","buildUserPrompt","ADAPTER_AGENT_REGISTRY","ADAPTER_AGENT_DEFAULT_OPTIONS","ADAPTER_AGENT_TOOL_POLICIES","AGENT_TOOL_POLICY_KIND_PRESENCE","AGENT_TOOL_POLICY_KINDS","isGovernableToolKind","kind","ruleAdmits","rule","onRuleError","reported","policiesAdmit","policies","policy","AGENT_REGISTRY_STORE_DESCRIPTION","AgentEnricherAdapter","binding","getExchangeContext","baseOptions","mergeWithDefaults","userTools","resolveAgentTools","baseSystem","systemAppend","mergeUserAndLoaderTools","withBlocks","appendPrincipalToSystem","session","found","known","defaults","mergeBlocks","agent","override","agentId","applyToolPolicy","policyContext","admitted","emitDenied","toolKind","messageOf","descriptor","toDescriptor","meta","principalOption","section","formatCallerSection","lines","oneLine","roles","ADAPTER_FN_REGISTRY","DEFERRED_FN_BRAND","isDeferredFn","cloneFrozenPrincipal","rp","emptyObjectSchema","directTool","fnId","readDirectRoute","hctx","dispatchDirect","capabilities","CraftClient","currentTime","randomUuid","DIRECT_TOOL_PREFIX","MCP_TOOL_PREFIX","assertValidDirectToolName","violation","TOOL_SELECTION_BRAND","isToolSelection","arg","items","runBuilder","buildCatalog","isMcpRefName","fnRegistryHas","resolveMcpRefs","resolveByName","fns","fnRegistry","routes","mcp","mcpRegistry","builder","catalog","fnEntry","resolveFnEntry","directMatch","fn","toResolvedTool","listKnownNames","exhaustive","parseMcpRef","inner","clientName","sep","listKnownMcpClients","mcpEntryToResolvedTool","knownTools","n","dropOnce","wrapJsonSchemaAsStandard","rawInput","set","fnNames","routeNames","validateAgentOptions","validateBlocks","defaultsLabel","state","validateBlocksLevel","leafCount","maybeValue","childLeaves","b","perCall","tagAdapter","factoryArgs","validateFnOptions","i","validateRegisteredAgent","agentPlugin","agents","functions","defaultOptions","validatePluginDefaults","toolPolicy","validateToolPolicy","existingAgents","agentMap","existingFns","fnMap","idViolation","mergePluginDefaults","existingPolicies","emitRegistrations","agentEntries","fnEntries","eager","next","mergedBlocks","registerConfigApplier","DOCS_BASE","registerErrorCodes","BRAND","isBranded","isMcpAdapter","parseStructuredTextFallback","LlmEnricherAdapter","llmResult","llm","BRAND_MCP_ADAPTER","assertValidMcpToolName","endpoint","McpSourceAdapter","sub","discovery","assertHttpUrl","trimmed","resolveServerConfig","cfg","resolveConnection","defaultArgs","McpEnricherAdapter","resolveServerTransport","clientOpts","colonIndex","clientOptions","isNonEmptyIssuer","buildVerifier","verify","oauth","cachedParseYaml","loadYamlParse","splitFrontmatter","path","filename","basename","extname","end","yamlText","parseYaml","readMarkdownFile","abs","readFileSync","readMarkdownDir","dir","stats","statSync","readdirSync","join","sentinelPath","sentinelStats","a","requireString","field","optionalStringArray","optionalBoolean","optionalPositiveInt","SUPPORTED_AGENT_KEYS","OVERRIDE_ONLY_AGENT_KEYS","toAgent","frontmatter","modelRaw","toolNames","applyOverride","docs","SuspendError","skills","mode","lifetime","sources","prior","fromFile","resolvePath","readFile","resolveProviderAndModel","buildText","using","EmbeddingEnricherAdapter","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 * A model object the active LLM engine can drive (today an AI SDK\n * `LanguageModel`), or anything else a future engine accepts. Deliberately\n * `unknown` so no engine-specific type reaches the public surface: every other\n * provider is addressed by a `\"provider:model\"` string and the framework's own\n * `LlmOptions`/`LlmResult` types, so swapping the underlying SDK does not break\n * consumers. The `custom` provider is the one engine-bound escape hatch, and we\n * keep that binding a runtime contract (validated by `assertLanguageModelShape`)\n * rather than a compile-time coupling.\n */\nexport type CustomLanguageModel = unknown;\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 | \"lmstudio\"\n | \"custom\";\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 * Anthropic API URL. Optional: the SDK default applies when unset.\n * Set it to route through a gateway or proxy. Configuring it here wins\n * over the ambient `ANTHROPIC_BASE_URL` environment variable, which the\n * SDK falls back to when no explicit URL is passed.\n */\n baseURL?: 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 * Gemini API URL. Optional: the SDK default applies when unset.\n * Set it to route through a gateway or proxy.\n */\n baseURL?: string;\n}\n\nexport interface LlmModelConfigLmStudio {\n provider: \"lmstudio\";\n /**\n * LM Studio server URL. Optional: defaults to http://localhost:1234/v1.\n * Only set when LM Studio runs on a non-default host or port.\n */\n baseURL?: string;\n /**\n * API key sent to LM Studio. Optional: LM Studio ignores authentication,\n * so this defaults to a placeholder. Set it only if you front LM Studio\n * with a proxy that enforces a key.\n */\n apiKey?: string;\n /**\n * Override model name sent to LM Studio. Optional: defaults to the model\n * from the llm(\"lmstudio:model\") call (the part after the colon).\n */\n modelId?: string;\n}\n\nexport interface LlmModelConfigCustom {\n provider: \"custom\";\n /**\n * A pre-built AI SDK language model, or a factory that builds one from the\n * model name (the part after the colon in llm(\"custom:name\")). This is the\n * escape hatch for running an agent or llm() step against an in-process or\n * otherwise unsupported model with no API key and no network.\n */\n model: CustomLanguageModel | ((modelId: string) => CustomLanguageModel);\n /**\n * Optional model name. Only needed when using an inline config object with\n * a factory; the string form llm(\"custom:name\") supplies it directly.\n */\n modelId?: string;\n}\n\nexport type LlmModelConfig =\n | LlmModelConfigOpenAI\n | LlmModelConfigAnthropic\n | LlmModelConfigOpenRouter\n | LlmModelConfigOllama\n | LlmModelConfigGemini\n | LlmModelConfigLmStudio\n | LlmModelConfigCustom;\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 baseURL?: string;\n}\nexport interface LlmOpenRouterProviderOptions {\n apiKey: string;\n modelId?: string;\n}\nexport interface LlmGeminiProviderOptions {\n apiKey: string;\n baseURL?: string;\n}\nexport interface LlmLmStudioProviderOptions {\n baseURL?: string;\n apiKey?: string;\n modelId?: string;\n}\nexport interface LlmCustomProviderOptions {\n model: CustomLanguageModel | ((modelId: string) => CustomLanguageModel);\n modelId?: string;\n}\n\nexport interface LlmPluginProviders {\n ollama?: LlmOllamaProviderOptions;\n openai?: LlmOpenAIProviderOptions;\n anthropic?: LlmAnthropicProviderOptions;\n openrouter?: LlmOpenRouterProviderOptions;\n gemini?: LlmGeminiProviderOptions;\n lmstudio?: LlmLmStudioProviderOptions;\n custom?: LlmCustomProviderOptions;\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 | ((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 reported by the provider. Mirrors the Vercel AI SDK\n * `LanguageModelUsage` shape so result.usage can be used interchangeably\n * with `generateText()` return values.\n *\n * Cache fields are populated only when the provider reports them (currently\n * Anthropic with prompt caching enabled). Absent when the provider does not\n * support caching or caching was not active for the call.\n */\nexport interface LlmUsage {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n /** Cached input tokens read from the provider's cache (e.g. Anthropic prompt caching). */\n cacheReadTokens?: number;\n /** Input tokens written to the provider's cache for future calls. */\n cacheWriteTokens?: 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 // LM Studio (local; ids are whatever model you have loaded)\n | \"lmstudio:qwen2.5-7b-instruct\"\n | \"lmstudio:llama-3.2-3b-instruct\"\n | \"lmstudio:phi-4\"\n | \"lmstudio:mistral-nemo-instruct-2407\"\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 {\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 lmstudio: {\n baseURL: \"http://localhost:1234/v1\",\n },\n} as const;\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 into LlmUsage, including cache token details when present. */\nexport function toLlmUsage(u: {\n inputTokens?: number | undefined;\n outputTokens?: number | undefined;\n totalTokens?: number | undefined;\n inputTokenDetails?:\n | {\n cacheReadTokens?: number | undefined;\n cacheWriteTokens?: number | undefined;\n }\n | 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 ...(u.inputTokenDetails?.cacheReadTokens !== undefined && {\n cacheReadTokens: u.inputTokenDetails.cacheReadTokens,\n }),\n ...(u.inputTokenDetails?.cacheWriteTokens !== undefined && {\n cacheWriteTokens: u.inputTokenDetails.cacheWriteTokens,\n }),\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 { assertLanguageModelShape } from \"./providers/llm-utils.ts\";\nimport type { LlmPluginOptions, LlmProviderType } from \"./types.ts\";\n\nconst PROVIDERS: LlmProviderType[] = [\n \"openai\",\n \"anthropic\",\n \"openrouter\",\n \"ollama\",\n \"gemini\",\n \"lmstudio\",\n \"custom\",\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 // openrouter has no baseURL option; the other keyed providers do.\n if (\n providerId !== \"openrouter\" &&\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 break;\n case \"ollama\":\n case \"lmstudio\":\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 if (\n providerId === \"lmstudio\" &&\n (opts as { apiKey?: string }).apiKey !== undefined &&\n typeof (opts as { apiKey?: string }).apiKey !== \"string\"\n ) {\n throw new TypeError(\n `llmPlugin: providers[\"lmstudio\"].apiKey must be a string when provided`,\n );\n }\n break;\n case \"custom\": {\n const model = (opts as { model?: unknown }).model;\n // A factory is only invoked at dispatch, so its return shape cannot be\n // checked eagerly; a concrete instance can, so assert it now and fail\n // at plugin apply rather than at first dispatch.\n if (typeof model === \"function\") break;\n if (model === null || typeof model !== \"object\") {\n throw new TypeError(\n `llmPlugin: providers[\"custom\"].model must be an AI SDK language model or a factory function`,\n );\n }\n assertLanguageModelShape(model, \"custom\", \"(custom)\");\n break;\n }\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 \"lmstudio\",\n \"custom\",\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 // Cast via `unknown`: the `custom` provider carries a function-typed\n // `model`, so a direct assertion is not comparable across the union.\n return { provider: providerId, ...opts } as unknown 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(ADAPTER_LLM_PROVIDERS, map);\n if (\n options.defaultOptions &&\n Object.keys(options.defaultOptions).length > 0\n ) {\n ctx.setStore(ADAPTER_LLM_OPTIONS, options.defaultOptions);\n }\n },\n };\n}\n","/**\n * The single definition of what a tool name may look like once it\n * reaches a model provider.\n *\n * Every LLM-facing name this package generates is constrained by the\n * same rule: the fn id, the `direct__<routeId>` form for capabilities,\n * the `mcp__<server>__<tool>` form for client tools, the\n * `_block__load__<name>` form for synthetic block loaders, and the route\n * ids the `mcp()` source exposes as tools. The constraint comes from\n * OpenAI's function-calling charset, the strictest of the mainstream\n * clients, which the other providers and MCP implementations respect.\n *\n * These constants previously existed in three independent copies (the\n * MCP types module, the MCP source adapter, the block resolver). They\n * live here so a change to the provider contract is one edit rather\n * than three, and so no generation path can drift out of agreement with\n * the paths that validate.\n */\n\n/**\n * The one place the permitted characters are written down. Everything\n * else in this module composes from it, so raising the limit or\n * widening the set is a single edit rather than several that a reviewer\n * has to notice are related.\n *\n * @internal\n */\nconst TOOL_NAME_CHARACTER_CLASS = \"[A-Za-z0-9_-]\";\n\n/**\n * Matches a single permitted character. Used to name the offending\n * characters in {@link describeToolNameViolation}. Stateless (no `g`\n * flag), so repeated `.test` calls do not carry `lastIndex` between\n * them.\n *\n * @internal\n */\nconst TOOL_NAME_CHARACTER = new RegExp(TOOL_NAME_CHARACTER_CLASS);\n\n/**\n * Characters permitted in a provider-facing tool name: ASCII letters,\n * digits, underscore, and hyphen. Unanchored to a length so callers\n * that build a name in parts can check the charset of a segment\n * separately from the length of the whole.\n *\n * @internal\n */\nexport const TOOL_NAME_CHARSET = new RegExp(`^${TOOL_NAME_CHARACTER_CLASS}+$`);\n\n/**\n * Maximum provider-facing tool-name length.\n *\n * @internal\n */\nexport const TOOL_NAME_MAX_LENGTH = 64;\n\n/**\n * The full constraint: charset plus length, anchored. Built from\n * {@link TOOL_NAME_CHARSET}'s character class and\n * {@link TOOL_NAME_MAX_LENGTH} rather than restating either, so the\n * three cannot disagree.\n *\n * @internal\n */\nexport const TOOL_NAME_PATTERN = new RegExp(\n `^${TOOL_NAME_CHARACTER_CLASS}{1,${TOOL_NAME_MAX_LENGTH}}$`,\n);\n\n/**\n * The constraint rendered for error messages and suggestions, in the\n * anchored `/.../` form a developer would recognise as a regex.\n *\n * Derived so an error can never instruct someone to satisfy a rule the\n * validator has stopped enforcing.\n *\n * @internal\n */\nexport const TOOL_NAME_PATTERN_SOURCE = `/${TOOL_NAME_PATTERN.source}/`;\n\n/**\n * The sole structural separator in a synthetic tool name.\n *\n * Every name this package composes from parts joins them with `__`:\n * `direct__<routeId>`, `mcp__<server>__<tool>`,\n * `_block__load__<name>`. A single underscore is therefore never a\n * boundary, which is what makes a name with an underscore inside a\n * segment (a server called `my_company_api`, a route called\n * `fetch_order`) unambiguous against the prefix that precedes it.\n *\n * Prefixes must not contain `__` internally, or the boundary they are\n * supposed to mark stops being findable.\n *\n * @internal\n */\nexport const TOOL_NAME_SEPARATOR = \"__\";\n\n/**\n * True when `segment` can be the leading part of a composed name that\n * a reader splits at the FIRST separator, `mcp__<server>__<tool>` being\n * the one such name today.\n *\n * Three shapes break that split, and the two that are not obvious are\n * the reason this is a function rather than an inline `includes`:\n *\n * - an internal `__` moves the boundary left (`a__b` + `c` composes\n * `mcp__a__b__c`, read back as server `a`, tool `b__c`)\n * - a TRAILING single `_` does the same, because the segment's own\n * underscore joins the separator (`foo_` + `bar` composes\n * `mcp__foo___bar`, read back as server `foo`, tool `_bar`). Worse,\n * that is the name `foo` + `_bar` composes, so two distinct pairs\n * collapse onto one and whichever resolves last wins\n * - an empty segment leaves nothing between the separators\n *\n * Testing the segment with one separator-half appended catches the\n * first two in a single condition.\n *\n * Deliberately NOT a general \"is this a valid name segment\" predicate.\n * `_block__load__<name>` is composed from the same separator but is\n * never split this way (the prefix is fixed and everything after it is\n * the block name), so block names may and do contain `__`. Only names\n * whose reader searches for the first separator are in scope.\n *\n * Callers choose their own reaction: `mcpPlugin({ clients })` throws\n * RC5003, because the name is chosen locally and can be fixed; agent\n * resolution drops the tool with a warning, because the registry can be\n * populated without going through the plugin.\n *\n * @internal\n */\nexport function isSplittableNameHead(segment: string): boolean {\n if (segment === \"\") return false;\n const separatorHalf = TOOL_NAME_SEPARATOR.slice(\n 0,\n TOOL_NAME_SEPARATOR.length / 2,\n );\n return !`${segment}${separatorHalf}`.includes(TOOL_NAME_SEPARATOR);\n}\n\n/**\n * True when `name` is usable as a provider-facing tool name, both in\n * charset and in length.\n *\n * @internal\n */\nexport function isValidToolName(name: string): boolean {\n return TOOL_NAME_PATTERN.test(name);\n}\n\n/**\n * Explain why `name` is not a usable tool name, or return `undefined`\n * when it is fine. Callers embed the reason in their own error so the\n * message names the thing the developer actually wrote (a route id, a\n * block name) rather than the derived tool name alone.\n *\n * Length is reported before charset when both are wrong, because a name\n * that is too long is usually a structural problem (a deeply nested\n * block group) while a bad character is usually a typo.\n *\n * @internal\n */\nexport function describeToolNameViolation(name: string): string | undefined {\n if (name.length === 0) return \"it is empty\";\n if (name.length > TOOL_NAME_MAX_LENGTH) {\n return `it is ${name.length} characters, over the provider limit of ${TOOL_NAME_MAX_LENGTH}`;\n }\n if (!TOOL_NAME_CHARSET.test(name)) {\n // Iterate code points, not UTF-16 units: `split(\"\")` would tear a\n // non-BMP character into two lone surrogates and report them as two\n // separate mystery characters rather than the one the author typed.\n const offending = [\n ...new Set([...name].filter((c) => !TOOL_NAME_CHARACTER.test(c))),\n ];\n return `it contains ${offending.map((c) => `\"${c}\"`).join(\", \")}, outside the allowed set of letters, digits, \"_\", and \"-\"`;\n }\n return undefined;\n}\n","import type { Exchange, Tag } from \"@routecraft/routecraft\";\nimport type { Principal, ValidatorAuthOptions } from \"@routecraft/routecraft\";\nimport type { ToolGuard } from \"../fn/types.ts\";\nimport { TOOL_NAME_PATTERN } from \"../tool-name.ts\";\nimport type { McpCorsOptions } from \"./cors.ts\";\nimport type { McpToolRegistry } from \"./tool-registry.ts\";\nimport type { UserinfoOption } from \"./userinfo.ts\";\n\n/**\n * Characters allowed in an MCP tool name. Enforced on route ids by the\n * `mcp()` source and on exposed proxied-tool names by the proxy\n * resolver.\n *\n * An alias for the package-wide {@link TOOL_NAME_PATTERN}: the MCP\n * surface and the agent surface answer to the same provider constraint,\n * so they share one definition rather than restating it. Kept under the\n * MCP name because it is part of this module's published surface.\n */\nexport const MCP_TOOL_NAME_PATTERN = TOOL_NAME_PATTERN;\n\n/**\n * The tool-calling surface of a managed stdio client, as stored under\n * {@link MCP_STDIO_MANAGERS}. `callTool` returns extracted content;\n * `callToolRaw` returns the raw MCP result for verbatim passthrough.\n */\nexport interface McpStdioToolCaller {\n callTool(name: string, args: Record<string, unknown>): Promise<unknown>;\n callToolRaw(\n name: string,\n args: Record<string, unknown>,\n ): Promise<McpRawToolResult>;\n}\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<string, McpStdioToolCaller>;\n }\n\n interface RoutecraftHeaders {\n /** The MCP tool name that triggered this exchange. */\n \"routecraft.mcp.tool\"?: string;\n /** Correlation id for the single MCP request that produced this exchange. */\n \"routecraft.mcp.request\"?: 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 /** Correlation id for the single MCP request that produced this exchange. */\n REQUEST = \"routecraft.mcp.request\",\n}\n\n/**\n * Protected-resource (RFC 9728) metadata for the MCP server.\n *\n * Used by every auth helper 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 the IdP issuer surfaced by\n * `jwks()` / `jwt()` / `oauth()`.\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 * Authentication options for the MCP HTTP server.\n * Only applies when `transport` is `\"http\"`. Ignored for stdio.\n *\n * The MCP server is an OAuth 2.0 **Resource Server**: it verifies bearer\n * tokens and advertises its Authorization Server via RFC 9728 metadata, so\n * clients run the OAuth flow directly against the IdP. Build the options with\n * `jwks()`, `jwt()`, a custom validator, or the `oauth()` helper (which layers\n * `requiredScopes` and issuer advertisement over any of those).\n */\nexport type McpHttpAuthOptions = ValidatorAuthOptions & {\n /**\n * IdP issuer(s) advertised as `authorization_servers` in the RFC 9728\n * protected-resource metadata, and used to resolve the OIDC Discovery\n * document for plugin-level `mcpPlugin({ userinfo: true })`. Surfaced\n * automatically by `jwks()` / `jwt()` / `oauth()`.\n */\n issuer?: string | string[];\n /**\n * Scopes required on every request to `/mcp`. A token missing any of them\n * is refused with `403 insufficient_scope` (RFC 6750 §3.1), distinct from\n * the `401` an unauthenticated or invalid token receives.\n *\n * Enforcement policy, not metadata: advertise the scopes a client may ask\n * for via `mcpPlugin({ resource: { scopesSupported } })`.\n */\n requiredScopes?: string[];\n /**\n * Clock skew allowed when the server re-checks the verified principal's\n * `expiresAt`. Surfaced automatically by `jwks()` / `jwt()` / `oauth()` from\n * the tolerance the verifier itself applied, so the gate does not refuse a\n * token the verifier accepted within skew. Defaults to `0`, matching\n * `authorize({ clockToleranceSec })`.\n */\n clockToleranceSec?: number;\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 every\n * auth helper; 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 * Proxy selected tools from registered `clients` through this MCP server,\n * without writing a route per tool. Each entry is either a ref string or a\n * config object with per-tool overrides:\n *\n * - `\"server:tool\"` -- proxy one tool from a registered client.\n * - `\"server:*\"` or `\"server\"` -- proxy every tool the client advertises.\n * - `{ ref: \"server:tool\", name?, description?, annotations? }` -- proxy one\n * tool with overrides (exact refs only; wildcards cannot be renamed).\n *\n * Proxied tools appear in `tools/list` under their original name (or the\n * `name` override) with the remote schema, description, and annotations\n * passed through. `tools/call` dispatches over the client's registered\n * transport and auth, and the remote result (content, structuredContent,\n * isError) is returned verbatim.\n *\n * Selection resolves against the live tool registry, so wildcard entries\n * follow tool refresh and stdio restarts. An exact ref and a wildcard\n * covering the same remote tool compose: the exact entry's overrides and\n * guard win regardless of config order. Collisions between different\n * remote tools on one exposed name are deterministic: a local\n * `.from(mcp())` route always wins over a proxied tool, and earlier\n * `proxy` entries win over later ones (a warning is logged either way;\n * use the `name` override to disambiguate). Exposed names must match\n * `[A-Za-z0-9_-]{1,64}`; a remote tool whose own name does not conform\n * is skipped with a warning unless renamed via an exact entry's `name`.\n *\n * Trust boundary: the caller's authenticated principal is NOT forwarded to\n * the remote server; the Routecraft -> MCP hop authenticates with the\n * client's registered `auth`. Route-scope guardrails (`authorize()`, input\n * validation, throttling) do not run for proxied calls, but a per-entry\n * `guard` can reject a call by caller identity before it dispatches (same\n * contract as the agent's `tools([{ name, guard }])`). Proxy simple,\n * read-only tools, guard the ones that need an identity check, and put\n * anything needing stateful guardrails behind a `.from(mcp())` route.\n */\n proxy?: Array<string | McpProxyToolConfig>;\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 * Config-object form of an `mcpPlugin({ proxy })` entry. Proxies one tool\n * from a registered client with optional overrides for how it is exposed.\n */\nexport interface McpProxyToolConfig {\n /**\n * Tool reference: `\"server:tool\"` for one tool, or `\"server:*\"` / `\"server\"`\n * for every tool the client advertises. `server` must be a key of\n * `mcpPlugin({ clients })`.\n */\n ref: string;\n /**\n * Exposed tool name override. Defaults to the remote tool's own name.\n * Must match `[A-Za-z0-9_-]{1,64}` and is invalid on wildcard refs.\n */\n name?: string;\n /**\n * Description override shown in `tools/list`. Defaults to the remote\n * tool's description. Invalid on wildcard refs.\n */\n description?: string;\n /**\n * Annotation overrides merged over the remote tool's annotations\n * (per-key; an override key wins over the remote value).\n */\n annotations?: McpToolAnnotations;\n /**\n * Guard run before the call is dispatched to the remote server. Same\n * contract as the agent's `tools([{ name, guard }])`: receives the raw\n * tool arguments and a handler context carrying the MCP caller's\n * read-only `principal` (when the HTTP transport authenticated one);\n * throw to reject the call, which surfaces to the client as an\n * `isError` result. On a wildcard ref the guard is attached to every\n * expanded tool.\n */\n guard?: ToolGuard;\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 display title reported by the source server. */\n title?: string;\n /** Human-readable description of the tool. */\n description?: string;\n /** JSON Schema for tool input. */\n inputSchema: Record<string, unknown>;\n /** JSON Schema for tool output, when the source server reports one. */\n outputSchema?: Record<string, unknown>;\n /** Icons reported by the source server. */\n icons?: McpIcon[];\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; surfaced on `ToolsCatalog.mcp[].tags` for the builder\n * form of `tools((catalog) => ...)` so MCP tools can be filtered\n * 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 * Raw MCP `tools/call` result as returned by the SDK, before any content\n * extraction. Used by the raw dispatch path so proxied tool calls can pass\n * the remote result through verbatim (content array of any spec type,\n * structured content, and the error flag).\n */\nexport interface McpRawToolResult {\n content?: Array<{\n type: string;\n text?: string;\n data?: string;\n [key: string]: unknown;\n }>;\n structuredContent?: Record<string, unknown>;\n isError?: boolean;\n [key: string]: unknown;\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 \"name\": \"@routecraft/ai\",\n \"version\": \"0.6.0\",\n \"description\": \"AI and MCP integrations for Routecraft\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup src/index.ts --format esm,cjs --dts\",\n \"test\": \"vitest\",\n \"test:coverage\": \"vitest --coverage\",\n \"prepublishOnly\": \"bun run build\"\n },\n \"dependencies\": {\n \"@standard-schema/spec\": \"^1.1.0\",\n \"ai\": \"^6.0.246\"\n },\n \"devDependencies\": {\n \"@ai-sdk/anthropic\": \"^3.0.107\",\n \"@ai-sdk/google\": \"^3.0.104\",\n \"@ai-sdk/openai\": \"^3.0.91\",\n \"@ai-sdk/openai-compatible\": \"^1.0.47\",\n \"@huggingface/transformers\": \"^3.8.1\",\n \"@modelcontextprotocol/client\": \"^2.0.0\",\n \"@modelcontextprotocol/node\": \"^2.0.0\",\n \"@modelcontextprotocol/server\": \"^2.0.0\",\n \"@openrouter/ai-sdk-provider\": \"^2.10.0\",\n \"@routecraft/routecraft\": \"workspace:*\",\n \"@sinonjs/fake-timers\": \"^11.3.1\",\n \"@types/sinonjs__fake-timers\": \"^15.0.1\",\n \"jose\": \"^6.2.8\",\n \"ollama-ai-provider-v2\": \"^3.6.0\",\n \"vitest\": \"^4.1.10\",\n \"yaml\": \"^2.9.0\",\n \"zod\": \"^4.4.3\"\n },\n \"peerDependencies\": {\n \"@ai-sdk/anthropic\": \"^3.0.50\",\n \"@ai-sdk/google\": \"^3.0.34\",\n \"@ai-sdk/openai\": \"^3.0.37\",\n \"@ai-sdk/openai-compatible\": \"^1.0.46\",\n \"@huggingface/transformers\": \"^3.8.1\",\n \"@modelcontextprotocol/client\": \"^2.0.0\",\n \"@modelcontextprotocol/node\": \"^2.0.0\",\n \"@modelcontextprotocol/server\": \"^2.0.0\",\n \"@openrouter/ai-sdk-provider\": \"^2.2.3\",\n \"@routecraft/routecraft\": \">=0.6.0 <1.0.0\",\n \"ollama-ai-provider-v2\": \"^3.3.1\",\n \"yaml\": \"^2.8.0\"\n },\n \"keywords\": [\n \"routecraft\",\n \"ai\",\n \"mcp\",\n \"tools\",\n \"llm\"\n ],\n \"author\": \"routecraftjs\",\n \"license\": \"Apache-2.0\",\n \"homepage\": \"https://routecraft.dev\",\n \"bugs\": \"https://github.com/routecraftjs/routecraft/issues\",\n \"repository\": \"https://github.com/routecraftjs/routecraft\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"peerDependenciesMeta\": {\n \"@ai-sdk/anthropic\": {\n \"optional\": true\n },\n \"@ai-sdk/google\": {\n \"optional\": true\n },\n \"@ai-sdk/openai\": {\n \"optional\": true\n },\n \"@ai-sdk/openai-compatible\": {\n \"optional\": true\n },\n \"@huggingface/transformers\": {\n \"optional\": true\n },\n \"@modelcontextprotocol/client\": {\n \"optional\": true\n },\n \"@modelcontextprotocol/node\": {\n \"optional\": true\n },\n \"@modelcontextprotocol/server\": {\n \"optional\": true\n },\n \"@openrouter/ai-sdk-provider\": {\n \"optional\": true\n },\n \"ollama-ai-provider-v2\": {\n \"optional\": true\n },\n \"yaml\": {\n \"optional\": true\n }\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","/**\n * Optional-peer loaders for the MCP TypeScript SDK v2.\n *\n * The v1 SDK shipped as a single `@modelcontextprotocol/sdk` package with deep\n * sub-path imports (`/server/index.js`, `/client/streamableHttp.js`, ...). v2\n * splits it into role packages with flat entry points, so every load site\n * resolves through a helper here rather than restating the `loadOptionalPeer`\n * incantation with its own package name and adapter label.\n *\n * Centralising the loads also keeps the install hints correct: a consumer using\n * only outbound MCP clients is told to install `@modelcontextprotocol/client`,\n * not the whole SDK.\n *\n * @see https://modelcontextprotocol.io/specification/2026-07-28\n */\nimport { loadOptionalPeer } from \"@routecraft/routecraft\";\nimport { version as packageVersion } from \"../../package.json\";\nimport { buildAuthHeaders } from \"./build-auth-headers.ts\";\nimport type { McpClientAuthOptions } from \"./types.ts\";\n\n/** The v2 server package: `createMcpHandler`, `Server`, bearer auth, OAuth metadata. */\nexport function loadMcpServerSdk(\n adapterName: string,\n): Promise<typeof import(\"@modelcontextprotocol/server\")> {\n return loadOptionalPeer(() => import(\"@modelcontextprotocol/server\"), {\n adapterName,\n packageName: \"@modelcontextprotocol/server\",\n });\n}\n\n/** The v2 server stdio entry: `serveStdio`. */\nexport function loadMcpServerStdioSdk(\n adapterName: string,\n): Promise<typeof import(\"@modelcontextprotocol/server/stdio\")> {\n return loadOptionalPeer(() => import(\"@modelcontextprotocol/server/stdio\"), {\n adapterName,\n packageName: \"@modelcontextprotocol/server\",\n });\n}\n\n/** The v2 Node adapter: `toNodeHandler` bridges a web-standard handler to `node:http`. */\nexport function loadMcpNodeSdk(\n adapterName: string,\n): Promise<typeof import(\"@modelcontextprotocol/node\")> {\n return loadOptionalPeer(() => import(\"@modelcontextprotocol/node\"), {\n adapterName,\n packageName: \"@modelcontextprotocol/node\",\n });\n}\n\n/** The v2 client package: `Client`, `StreamableHTTPClientTransport`. */\nexport function loadMcpClientSdk(\n adapterName: string,\n): Promise<typeof import(\"@modelcontextprotocol/client\")> {\n return loadOptionalPeer(() => import(\"@modelcontextprotocol/client\"), {\n adapterName,\n packageName: \"@modelcontextprotocol/client\",\n });\n}\n\n/** The v2 client stdio entry: `StdioClientTransport`. */\nexport function loadMcpClientStdioSdk(\n adapterName: string,\n): Promise<typeof import(\"@modelcontextprotocol/client/stdio\")> {\n return loadOptionalPeer(() => import(\"@modelcontextprotocol/client/stdio\"), {\n adapterName,\n packageName: \"@modelcontextprotocol/client\",\n });\n}\n\n/**\n * Protocol negotiation applied to every outbound Routecraft MCP client.\n *\n * `auto` probes with `server/discover` and speaks the 2026-07-28 stateless\n * revision when the remote offers it, falling back to the 2025 `initialize`\n * handshake otherwise. Routecraft cannot know which revision a configured\n * remote speaks, so pinning either era would strand half the ecosystem.\n */\nexport const MCP_VERSION_NEGOTIATION = {\n mode: \"auto\",\n} as const;\n\n/**\n * Client identity Routecraft presents on every outbound MCP connection.\n *\n * The version is the real package version, not a constant: remote servers log\n * and branch on `clientInfo.version`, so a frozen value would make every\n * Routecraft client indistinguishable in their telemetry.\n */\nexport const MCP_CLIENT_INFO = {\n name: \"routecraft-mcp-client\",\n version: packageVersion,\n} as const;\n\n/**\n * Open one outbound MCP client over Streamable HTTP.\n *\n * Every caller that talks to a remote MCP server over HTTP goes through here,\n * so negotiation mode, client identity and auth headers cannot drift between\n * the one-shot dispatch path and the plugin's cached clients. A failed\n * handshake closes the transport rather than orphaning its socket.\n *\n * The stdio manager deliberately does not use this: it builds a stdio\n * transport and registers a `listChanged` handler, and folding both shapes\n * into one helper would need a transport-kind flag. It shares the loaders and\n * constants above instead.\n */\nexport async function connectMcpHttpClient(\n url: URL,\n auth?: McpClientAuthOptions,\n): Promise<{\n client: InstanceType<Awaited<ReturnType<typeof loadMcpClientSdk>>[\"Client\"]>;\n transport: InstanceType<\n Awaited<\n ReturnType<typeof loadMcpClientSdk>\n >[\"StreamableHTTPClientTransport\"]\n >;\n}> {\n const { Client, StreamableHTTPClientTransport } =\n await loadMcpClientSdk(\"mcp (http client)\");\n\n // Auth headers are resolved per request through the transport's fetch hook,\n // not baked into `requestInit` once at connect. `McpClientTokenProvider` is\n // documented as \"called on every request\", and a token array round-robins\n // per request; a client cached across many calls (mcpPlugin's clients) would\n // otherwise pin whichever token was current when it connected and keep\n // presenting it after expiry.\n const transport = new StreamableHTTPClientTransport(url, {\n fetch: async (input, init) => {\n const headers = await buildAuthHeaders(auth);\n if (!headers) return fetch(input, init);\n const merged = new Headers(init?.headers);\n for (const [name, value] of Object.entries(headers)) {\n merged.set(name, value);\n }\n return fetch(input, { ...init, headers: merged });\n },\n });\n const client = new Client(MCP_CLIENT_INFO, {\n capabilities: {},\n versionNegotiation: MCP_VERSION_NEGOTIATION,\n });\n\n try {\n await client.connect(transport);\n } catch (cause) {\n await transport.close().catch(() => {});\n throw cause;\n }\n\n return { client, transport };\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 {\n isRoutecraftError,\n rcError,\n type CraftContext,\n} from \"@routecraft/routecraft\";\nimport { connectMcpHttpClient } from \"./sdk.ts\";\nimport { extractContent } from \"./extract-content.ts\";\nimport {\n ADAPTER_MCP_CLIENT_SERVERS,\n MCP_STDIO_MANAGERS,\n type McpClientAuthOptions,\n type McpClientHttpConfig,\n type McpRawToolResult,\n} from \"./types.ts\";\n\n/**\n * Dispatch an MCP tool call against a server registered via\n * `mcpPlugin({ clients })` and extract the result content. Used by both\n * the `mcp(...)` destination adapter and the agent `tools([...])`\n * resolver. Thin wrapper over {@link dispatchMcpCallRaw} so the two\n * dispatch flavours (raw for the proxy, extracted here) can never drift.\n *\n * - For stdio clients (`MCP_STDIO_MANAGERS.get(serverId)`), delegates\n * to the long-lived `StdioClientManager.callToolRaw`.\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 return extractContent(\n await dispatchMcpCallRaw(ctx, serverId, toolName, args),\n );\n}\n\n/**\n * Dispatch an MCP tool call like {@link dispatchMcpCall} but return the raw\n * MCP `tools/call` result (content array, structuredContent, isError) without\n * content extraction. Used by the MCP server's proxy path so remote results\n * pass through to the calling client verbatim.\n *\n * Throws `RC5003` under the same conditions as {@link dispatchMcpCall}.\n *\n * @internal\n */\nexport async function dispatchMcpCallRaw(\n ctx: CraftContext,\n serverId: string,\n toolName: string,\n args: Record<string, unknown>,\n): Promise<McpRawToolResult> {\n const stdioManagers = ctx.getStore(MCP_STDIO_MANAGERS);\n const manager = stdioManagers?.get(serverId);\n if (manager) {\n try {\n return await manager.callToolRaw(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 http = resolveHttpConfig(ctx, serverId);\n return callRemoteToolRaw(http.url, toolName, args, http.auth);\n}\n\n/**\n * Resolve the HTTP config for a registered server id, throwing `RC5003` when\n * the server is unknown, is a string shorthand, is a stdio server whose\n * manager is absent, or has no url.\n */\nfunction resolveHttpConfig(\n ctx: CraftContext,\n serverId: string,\n): McpClientHttpConfig {\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 http;\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 `McpEnricherAdapter` 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 return extractContent(\n await callRemoteToolRaw(serverUrl, toolName, args, auth),\n );\n}\n\n/**\n * Like {@link callRemoteTool} but returns the raw MCP `tools/call` result\n * without content extraction. Used by the MCP server's proxy path.\n *\n * @internal\n */\nexport async function callRemoteToolRaw(\n serverUrl: string,\n toolName: string,\n args: Record<string, unknown>,\n auth?: McpClientAuthOptions,\n): Promise<McpRawToolResult> {\n let connection: Awaited<ReturnType<typeof connectMcpHttpClient>> | undefined;\n try {\n connection = await connectMcpHttpClient(new URL(serverUrl), auth);\n return (await connection.client.callTool({\n name: toolName,\n arguments: args,\n })) as McpRawToolResult;\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 // `connection` stays undefined when URL parsing or the handshake threw;\n // a failed handshake already closed its own transport. Cleanup errors are\n // swallowed so the original failure propagates.\n try {\n await connection?.client.close();\n } catch {\n // Ignore cleanup errors so original error propagates\n }\n try {\n await connection?.transport.close();\n } catch {\n // Ignore cleanup errors so original error propagates\n }\n }\n}\n","import {\n logger as frameworkLogger,\n isAuthentic,\n markAuthentic,\n type Principal,\n} from \"@routecraft/routecraft\";\nimport type { FnHandlerContext } from \"./types.ts\";\n\n/**\n * Construct the synthetic `FnHandlerContext` handed to a tool's guard\n * and handler. Used by the agent tool bridge for every tool invocation\n * and by the MCP server for proxied-tool guards. Mirrors the shape\n * `testFn` provides: `logger`, `abortSignal`, optional `principal`\n * (carried over from the dispatching exchange or the MCP caller so\n * guards can authorise without re-reading the source request),\n * optional `correlationId` (not yet populated by the runtime), and\n * optional `checkpointId` (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 *\n * @internal\n */\nexport function 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 resolved tool at `buildVercelTools` time (each tool's\n * handler context holds its own frozen snapshot, reused across that\n * tool's invocations in the dispatch) and once per guarded proxied MCP\n * tool call. Do not rely on reference equality of `ctx.principal` across\n * different tools of one dispatch.\n *\n * @internal\n */\nexport function 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 // Clone userinfoClaims for the same reason as claims: without it, the\n // shallow spread shares the live principal's object and deepFreeze would\n // freeze the caller's (and the userinfo enrichment cache's) copy in place.\n if (snapshot.userinfoClaims) {\n snapshot.userinfoClaims = structuredClone(snapshot.userinfoClaims);\n }\n // Clone the delegation fields for the same reason: `actor` is a nested\n // Principal chain and `mayAct` an array of matcher objects, both shared\n // by the shallow spread. delegate() output arrives already frozen (so\n // freezing in place would be harmless there), but a principal assembled\n // by a .process() step is mutable and must not have its chain frozen as\n // a side effect of a tool dispatch.\n if (snapshot.actor) snapshot.actor = structuredClone(snapshot.actor);\n if (snapshot.mayAct) snapshot.mayAct = structuredClone(snapshot.mayAct);\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 // re-clones and freezes the policy-bearing structures (actor chain,\n // mayAct, roles/scopes/audience); claims and userinfoClaims stay the\n // already 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 type { KnownTag, Tag } from \"@routecraft/routecraft\";\nimport type { McpToolAnnotations } from \"./types.ts\";\n\n/**\n * Merge a base set of annotation hints with per-key overrides. Override\n * values win per-key. Returns `undefined` when neither source contributes\n * anything, so callers omit `annotations` entirely rather than carrying an\n * empty object onto the `tools/list` wire. Shared by the `mcp()` source\n * adapter (tag-derived + explicit) and the proxy path (remote + config\n * overrides) so the merge policy lives once.\n *\n * @internal\n */\nexport function mergeAnnotations(\n base: McpToolAnnotations | undefined,\n overrides: McpToolAnnotations | undefined,\n): McpToolAnnotations | undefined {\n const merged: McpToolAnnotations = { ...base, ...overrides };\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\n/**\n * The canonical correspondence between the well-known route tags and the MCP\n * tool annotation hints they describe. Both directions derive from this single\n * table, so the four pairs are declared once: `deriveAnnotationsFromTags`\n * (tag -> hint) and `deriveTagsFromAnnotations` (hint -> tag) stay exact\n * inverses, and adding a fifth correspondence is a one-line edit here rather\n * than two functions plus prose drifting apart.\n *\n * @internal\n */\nexport const TAG_ANNOTATION_HINTS = [\n [\"read-only\", \"readOnlyHint\"],\n [\"destructive\", \"destructiveHint\"],\n [\"idempotent\", \"idempotentHint\"],\n [\"open-world\", \"openWorldHint\"],\n] as const satisfies ReadonlyArray<\n readonly [KnownTag, keyof McpToolAnnotations]\n>;\n\n/**\n * Derive the MCP tool annotation hints implied by a route's tags. Only the\n * well-known tags carry MCP meaning; any other tag is ignored here (it still\n * drives `tools()` selectors). Returns only the hints present as tags so the\n * result can merge under explicit annotations without clobbering unrelated\n * keys.\n *\n * @internal\n */\nexport function deriveAnnotationsFromTags(\n tags: readonly string[] | undefined,\n): McpToolAnnotations {\n if (!tags || tags.length === 0) return {};\n const derived: McpToolAnnotations = {};\n for (const [tag, hint] of TAG_ANNOTATION_HINTS) {\n if (tags.includes(tag)) derived[hint] = true;\n }\n return derived;\n}\n\n/**\n * Derive capability tags from MCP `annotations` hints so MCP tools surface\n * alongside fns and direct routes under the same `Tag` shape (visible on\n * `ToolsCatalog.mcp[].tags` for the builder form of `tools()`, and on the\n * resolved tool's `tags` for downstream inspection). Returns an empty array\n * (omitted from the entry) when no hints apply.\n *\n * @internal\n */\nexport function deriveTagsFromAnnotations(\n annotations: McpToolAnnotations | undefined,\n): Tag[] {\n if (!annotations) return [];\n const tags: Tag[] = [];\n for (const [tag, hint] of TAG_ANNOTATION_HINTS) {\n if (annotations[hint]) tags.push(tag);\n }\n return tags;\n}\n","import type { CraftContext } from \"@routecraft/routecraft\";\nimport { mergeAnnotations } from \"./annotation-tags.ts\";\nimport { TOOL_NAME_PATTERN_SOURCE } from \"../tool-name.ts\";\nimport { MCP_TOOL_NAME_PATTERN, MCP_TOOL_REGISTRY } from \"./types.ts\";\nimport type {\n McpProxyToolConfig,\n McpTool,\n McpToolRegistryEntry,\n} from \"./types.ts\";\n\n/** Parsed `mcpPlugin({ proxy })` ref. `toolName` is `\"*\"` for wildcards. */\nexport interface McpProxyRef {\n serverId: string;\n toolName: string;\n}\n\n/**\n * Parse a proxy ref string: `\"server:tool\"`, `\"server:*\"`, or bare\n * `\"server\"` (equivalent to `\"server:*\"`, matching the agent's\n * whole-server `MCP(server)` form). Colons beyond the first split stay in\n * the tool segment, matching the agent ref grammar (`parseMcpRef`), so a\n * remote tool named `ns:tool` is addressable as `\"server:ns:tool\"`. Such\n * a name needs a `name` override to be exposed (exposed names must match\n * {@link MCP_TOOL_NAME_PATTERN}).\n *\n * Throws `TypeError` on malformed refs so both option validation and\n * runtime resolution fail with the same message.\n *\n * @internal\n */\nexport function parseProxyRef(ref: string): McpProxyRef {\n if (typeof ref !== \"string\" || ref.trim() === \"\") {\n throw new TypeError(\n 'mcpPlugin: proxy ref must be a non-empty string like \"server:tool\", \"server:*\", or \"server\"',\n );\n }\n const idx = ref.indexOf(\":\");\n if (idx === -1) {\n return { serverId: ref, toolName: \"*\" };\n }\n const serverId = ref.slice(0, idx);\n const toolName = ref.slice(idx + 1);\n if (serverId === \"\" || toolName === \"\") {\n throw new TypeError(\n `mcpPlugin: proxy ref \"${ref}\" is malformed. Use \"server:tool\", \"server:*\", or \"server\".`,\n );\n }\n return { serverId, toolName };\n}\n\n/**\n * Normalize a `proxy` option array to config-object form (`string` entries\n * become `{ ref }`).\n *\n * @internal\n */\nexport function normalizeProxyEntries(\n proxy: Array<string | McpProxyToolConfig>,\n): McpProxyToolConfig[] {\n return proxy.map((entry) =>\n typeof entry === \"string\" ? { ref: entry } : entry,\n );\n}\n\n/**\n * The name a proxy entry exposes a remote tool under: the entry's `name`\n * override when set, otherwise the remote tool's own name. Shared by\n * static validation and runtime resolution so the two can never disagree.\n *\n * @internal\n */\nexport function exposedNameFor(\n config: McpProxyToolConfig,\n remoteToolName: string,\n): string {\n return config.name ?? remoteToolName;\n}\n\n/**\n * A client tool selected for proxying, resolved against the live tool\n * registry. Carries everything `tools/list` and `tools/call` need.\n */\nexport interface McpProxiedTool {\n /** Name this server exposes the tool under (override or remote name). */\n exposedName: string;\n /** Registered client the tool dispatches to. */\n serverId: string;\n /** Tool name on the remote server (dispatch target). */\n toolName: string;\n /** The registry entry the tool resolved from. */\n entry: McpToolRegistryEntry;\n /** Per-entry config overrides (description, annotations, guard). */\n config: McpProxyToolConfig;\n}\n\n/**\n * Resolve the `proxy` selection against the current MCP tool registry.\n *\n * Resolution follows the live registry (the server memoizes per registry\n * version, so this runs when the registry changes, not per request).\n * Entries that do not resolve (client not yet listed, tool gone after\n * refresh) are skipped via `warn` rather than thrown, because client\n * availability is transient by design (the plugin already tolerates a\n * failed initial listing).\n *\n * Collision policy:\n * - Two entries covering the SAME remote tool (an exact ref overlapping a\n * wildcard) compose rather than collide: the exact entry's config\n * (overrides, guard) wins regardless of config order, so a wildcard can\n * never silently strip an explicitly configured guard.\n * - Two DIFFERENT remote tools mapping to one exposed name are first-wins\n * in config order; the loser is reported through `warn`.\n * - Exposed names must match {@link MCP_TOOL_NAME_PATTERN}; non-conforming\n * remote names are skipped via `warn` unless renamed. Collisions with\n * local route tools are the caller's concern (the server checks its\n * local registry).\n *\n * @internal\n */\nexport function resolveProxiedTools(\n ctx: CraftContext,\n proxy: Array<string | McpProxyToolConfig>,\n warn: (key: string, message: string) => void,\n): Map<string, McpProxiedTool> {\n const resolved = new Map<string, McpProxiedTool>();\n const registry = ctx.getStore(MCP_TOOL_REGISTRY);\n if (!registry) {\n warn(\n \"proxy:no-registry\",\n \"mcpPlugin proxy: no MCP tool registry present; proxied tools are unavailable.\",\n );\n return resolved;\n }\n\n const add = (\n entry: McpToolRegistryEntry,\n config: McpProxyToolConfig,\n isExact: boolean,\n ): void => {\n const exposedName = exposedNameFor(config, entry.name);\n if (!MCP_TOOL_NAME_PATTERN.test(exposedName)) {\n warn(\n `proxy:invalid-name:${exposedName}`,\n `mcpPlugin proxy: remote tool \"${entry.source}:${entry.name}\" has a name that does not match ${TOOL_NAME_PATTERN_SOURCE} and is skipped. Proxy it with an exact ref and a \"name\" override to expose it.`,\n );\n return;\n }\n const existing = resolved.get(exposedName);\n if (existing) {\n const sameRemoteTool =\n existing.serverId === entry.source && existing.toolName === entry.name;\n if (!sameRemoteTool) {\n warn(\n `proxy:conflict:${exposedName}`,\n `mcpPlugin proxy: tool name \"${exposedName}\" from \"${config.ref}\" collides with \"${existing.serverId}:${existing.toolName}\"; first entry wins. Use a name override to expose both.`,\n );\n return;\n }\n // Exact and wildcard entries covering the same remote tool compose:\n // the exact entry's config is the operator's specific intent (its\n // guard and overrides must never be dropped by a broader wildcard),\n // so specific-wins regardless of config order.\n if (!isExact) return;\n }\n resolved.set(exposedName, {\n exposedName,\n serverId: entry.source,\n toolName: entry.name,\n entry,\n config,\n });\n };\n\n for (const config of normalizeProxyEntries(proxy)) {\n const { serverId, toolName } = parseProxyRef(config.ref);\n const clientTools = registry.getToolsByServer(serverId);\n if (clientTools.length === 0) {\n warn(\n `proxy:unresolved:${serverId}`,\n `mcpPlugin proxy: client \"${serverId}\" has no registered tools (not yet listed, or listing failed); its proxy entries are skipped until tools appear.`,\n );\n continue;\n }\n if (toolName === \"*\") {\n for (const entry of clientTools) add(entry, config, false);\n continue;\n }\n const entry = clientTools.find((t) => t.name === toolName);\n if (!entry) {\n warn(\n `proxy:unresolved:${config.ref}`,\n `mcpPlugin proxy: tool \"${toolName}\" is not registered under client \"${serverId}\". Known tools: ${clientTools\n .map((t) => `\"${t.name}\"`)\n .sort()\n .join(\", \")}.`,\n );\n continue;\n }\n add(entry, config, true);\n }\n\n return resolved;\n}\n\n/**\n * Convert a resolved proxied tool to the MCP `tools/list` wire shape.\n * Remote schema, title, description, and annotations pass through;\n * per-entry `description` overrides replace and `annotations` overrides\n * merge over the remote values. Icons are NOT set here: the server applies\n * the same inheritance rule it applies to local tools (`entry.icons ??`\n * server icons, omitted when empty), reading the tri-state (unset / [] /\n * set) off `proxied.entry.icons`.\n *\n * @internal\n */\nexport function proxiedToolToMcpTool(proxied: McpProxiedTool): McpTool {\n const { entry, config } = proxied;\n const tool: McpTool = {\n name: proxied.exposedName,\n inputSchema: entry.inputSchema as McpTool[\"inputSchema\"],\n };\n const description = config.description ?? entry.description;\n if (description !== undefined) {\n tool.description = description;\n }\n if (entry.title !== undefined) {\n tool.title = entry.title;\n }\n if (entry.outputSchema !== undefined) {\n tool.outputSchema = entry.outputSchema as NonNullable<\n McpTool[\"outputSchema\"]\n >;\n }\n const annotations = mergeAnnotations(entry.annotations, config.annotations);\n if (annotations !== undefined) {\n tool.annotations = annotations;\n }\n return tool;\n}\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. Only `WWW-Authenticate` (the\n * RFC 9728 `resource_metadata` hint on a 401) qualifies: protocol revision\n * 2026-07-28 removed both `Mcp-Session-Id` (no protocol-level sessions) and\n * SSE resumability (`Last-Event-ID`), and the stateless serving of 2025-era\n * traffic mints neither, so nothing else is ever emitted to read.\n *\n * @internal\n */\nconst ALLOW_METHODS = \"GET, POST, OPTIONS\";\nconst ALLOW_HEADERS = \"*\";\nconst EXPOSE_HEADERS = \"WWW-Authenticate\";\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 from `resource.url` so a\n * non-default resource path still answers at the URL RFC 9728 §3 tells a\n * client to probe, preserving the \"identical JSON at every advertised URL\"\n * promise in `.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=\"200\" height=\"200\" viewBox=\"0 0 200 200\" fill=\"${fill}\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M125 175H75V125L125 175ZM175 175H125V125L175 175ZM125 25C152.614 25 175 47.3858 175 75C175 102.614 152.614 125 125 125V75H75L125 125H75L25 75V25H125Z\" /></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 with every auth helper. 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 every auth\n * helper (`jwks()` / `jwt()` / a custom `{ validator }` / `oauth()`); the\n * caller supplies the base verifier and the IdP `issuer` (needed only for\n * `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","import { isRoutecraftError } from \"@routecraft/routecraft\";\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\n/**\n * Bounded vocabulary for the `auth:rejected` event `reason` field.\n *\n * @internal\n */\nexport type AuthRejectionReason =\n \"expired\" | \"infrastructure\" | \"invalid_token\";\n\n/**\n * Map a token-verification error to the bounded `auth:rejected` reason\n * vocabulary. Never derived from the raw error message: a custom verifier\n * controls that message and could embed the bearer token, leaking a secret\n * into an aggregator-indexed event field (see `.standards/security.md`\n * sections 4 and 10). The full error stays operator-only via the structured\n * `{ err }` log binding.\n *\n * `infrastructure` mirrors the predicate the OAuth path uses for its 500\n * rethrow (framework errors and JWKS infrastructure failures), so the event\n * payload always matches the HTTP status the client receives.\n *\n * @internal\n */\nexport function classifyRejectionReason(err: unknown): AuthRejectionReason {\n if (isExpiredTokenError(err)) return \"expired\";\n if (isRoutecraftError(err) || isInfrastructureError(err)) {\n return \"infrastructure\";\n }\n return \"invalid_token\";\n}\n","import type { CraftContext } from \"@routecraft/routecraft\";\nimport {\n DefaultExchange,\n HeadersKeys,\n isRoutecraftError,\n markAuthentic,\n} from \"@routecraft/routecraft\";\nimport { createServer } from \"node:http\";\nimport type { IncomingMessage } from \"node:http\";\nimport type {\n AuthInfo,\n CallToolResult,\n ListToolsResult,\n McpHttpHandler,\n McpRequestContext,\n Server as SdkServer,\n} from \"@modelcontextprotocol/server\";\nimport type { NodeIncomingMessageLike } from \"@modelcontextprotocol/node\";\nimport type { StdioServerHandle } from \"@modelcontextprotocol/server/stdio\";\nimport type {\n OAuthValidatorAuthOptions,\n Principal,\n ValidatorAuthOptions,\n} from \"@routecraft/routecraft\";\nimport {\n MCP_LOCAL_TOOL_REGISTRY,\n MCP_TOOL_REGISTRY,\n McpHeadersKeys,\n} from \"./types.ts\";\nimport type {\n McpIcon,\n McpLocalToolEntry,\n McpPluginOptions,\n McpRawToolResult,\n McpTool,\n} from \"./types.ts\";\nimport { dispatchMcpCallRaw } from \"./dispatch.ts\";\nimport { makeFnHandlerContext } from \"../fn/handler-context.ts\";\nimport {\n proxiedToolToMcpTool,\n resolveProxiedTools,\n type McpProxiedTool,\n} from \"./proxy.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 { classifyRejectionReason, isExpiredTokenError } from \"./auth-errors.ts\";\nimport {\n loadMcpNodeSdk,\n loadMcpServerSdk,\n loadMcpServerStdioSdk,\n} from \"./sdk.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 * A Node request after the auth gate has run. The gate stashes the verified\n * {@link SdkAuthInfo} here because `toNodeHandler` forwards `req.auth` to the\n * handler as its pass-through `authInfo` -- which is how the principal reaches\n * a per-request server instance without ambient state.\n */\ntype AuthenticatedRequest = IncomingMessage & { auth?: SdkAuthInfo };\n\n/**\n * Outcome of the HTTP auth gate.\n *\n * A refusal carries the status it deserves: `401` when the caller's credential\n * is missing, malformed, expired or rejected, and `500` when verification\n * itself could not be completed (an unreachable JWKS endpoint, a failed\n * `userinfo` fetch). Collapsing the two would tell a client to discard a token\n * that is probably fine.\n */\ntype AuthGateResult =\n | { ok: true; principal: Principal; token: string }\n | { ok: false; status: 500 }\n | { ok: false; status: 401; presented: boolean };\n\n/**\n * Shared never-aborted signal for guard contexts on the proxied-call path,\n * where no per-request abort signal exists. Mirrors the agent runtime's\n * fallback when no route signal is available, without allocating a fresh\n * AbortController per call.\n */\nconst NEVER_ABORTED = new AbortController().signal;\n\n/** True for a plain, non-array, non-null object. */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Normalize `tools/call` arguments to a plain object. The MCP SDK may deliver\n * a parsed object or a raw JSON string; MCP tool arguments are always a JSON\n * object, so a primitive, array, or null is coerced to the safe fallback\n * shape (`{ input: <string> }` for a raw non-object string, `{}` otherwise)\n * before any guard or remote dispatch consumes it.\n */\nfunction normalizeToolArgs(args: unknown): Record<string, unknown> {\n if (typeof args === \"string\") {\n try {\n const parsed: unknown = JSON.parse(args);\n return isPlainObject(parsed) ? parsed : { input: args };\n } catch {\n return { input: args };\n }\n }\n return isPlainObject(args) ? args : {};\n}\n\n/** Wire shape returned by `tools/call` handlers (local and proxied). */\ntype McpToolCallResult = {\n content: Array<{ type: string; [key: string]: unknown }>;\n structuredContent?: Record<string, unknown>;\n isError?: boolean;\n};\n\n/**\n * Log-safe message for a failed tool call: the RC meta message for\n * RoutecraftErrors, the error message otherwise.\n */\nfunction toolErrorLogMessage(error: unknown): string {\n return isRoutecraftError(error)\n ? (error as unknown as { meta: { message: string } }).meta.message\n : error instanceof Error\n ? error.message\n : String(error);\n}\n\n/**\n * Client-facing message for a failed tool call: includes the RC cause\n * (e.g. schema field errors) but never stack traces or internal details.\n */\nfunction toolErrorUserMessage(error: unknown, logMsg: string): string {\n if (isRoutecraftError(error)) {\n const cause = (error as { cause?: Error }).cause;\n if (cause?.message) {\n return `${logMsg}: ${cause.message}`;\n }\n }\n return logMsg;\n}\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 | \"proxy\"\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/**\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\n * infrastructure. It reads the MCP route registry lazily (on first `tools/list`\n * request) to ensure routes have subscribed.\n *\n * Serving follows protocol revision 2026-07-28: both transports build a fresh\n * server instance per serving unit and hold no state between them, so the HTTP\n * transport scales horizontally with no session affinity. 2025-era clients are\n * still served, through the SDK's stateless fallback.\n *\n * The SDK is loaded through `loadOptionalPeer` (see `./sdk.ts`) because it is\n * an optional peer dependency, not because of any type incompatibility.\n */\nexport class McpServer {\n private context: CraftContext;\n private options: McpServerResolvedOptions;\n /**\n * Node HTTP server when transport is http; used to listen on port and close\n * on stop.\n */\n private httpServer: ReturnType<typeof createServer> | null = null;\n /**\n * The web-standard MCP handler backing the HTTP transport. Holds no\n * per-client state: it builds a fresh server instance per request from\n * {@link createServerInstance}. `null` until the HTTP transport starts.\n */\n private mcpHandler: McpHttpHandler | null = null;\n /** Handle for the stdio transport, used to await shutdown. `null` on HTTP. */\n private stdioHandle: StdioServerHandle | null = null;\n /**\n * Per-request factory inputs, resolved once by {@link prepareServerFactory}\n * so {@link createServerInstance} stays off the dynamic-import path.\n */\n private sdkServerCtor: typeof SdkServer | null = null;\n private serverInfo: SdkServerInfo | null = null;\n private serverOptions: SdkServerOptions | null = null;\n private running = false;\n private toolsListLogged = false;\n /**\n * Deduplication keys for proxy-resolution warnings, scoped to a registry\n * version: each distinct condition (unresolved ref, name collision) logs\n * once per resolution epoch instead of per request, and re-logs if it\n * recurs after the client tool registry actually changes (a client that\n * recovers and then degrades again is not silenced by its first outage).\n */\n private proxyWarnings = new Set<string>();\n\n /** Registry version the memoized proxy resolution was computed against. */\n private proxyResolvedVersion = -1;\n\n /** Memoized proxy resolution; recomputed only when the registry changes. */\n private proxyResolved: Map<string, McpProxiedTool> = new Map();\n /**\n * Validator-mode token verifier, optionally wrapped with `userinfo`\n * enrichment. Built eagerly in `startHttp` so a misconfigured\n * `userinfo: true` (no issuer) fails at startup rather than on first\n * request. `null` until the HTTP transport 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 * `serveStdio` calls the factory once per connection, and once more for a\n * discarded `server/discover` probe when a negotiating client checks which\n * protocol revision this server speaks. stdio carries no HTTP credentials,\n * so the instance is always built without a principal.\n */\n private async startStdio(): Promise<void> {\n const { serveStdio } = await loadMcpServerStdioSdk(\"mcp (stdio)\");\n await this.prepareServerFactory();\n this.stdioHandle = serveStdio(() => this.createServerInstance(undefined));\n }\n\n /**\n * Resolve everything the per-request factory needs, once, at startup.\n *\n * {@link createServerInstance} runs on every request, so the SDK import and\n * the identity/capability objects are hoisted out of that path: they depend\n * only on `this.options` and would otherwise be recomputed per request on\n * the axis this transport is meant to scale along.\n */\n private async prepareServerFactory(): Promise<void> {\n const { Server } = await loadMcpServerSdk(\"mcp\");\n this.sdkServerCtor = Server;\n this.serverInfo = this.buildServerInfo();\n this.serverOptions = this.buildServerOptions();\n }\n\n /**\n * Build one MCP `Server` instance bound to a single serving unit: one HTTP\n * request under `createMcpHandler`, or one connection under `serveStdio`.\n *\n * The authenticated principal is closed over rather than read from ambient\n * request-scoped storage. Under the 2026-07-28 stateless model a request is\n * self-describing and its instance is never reused, so the principal is\n * simply a construction parameter -- which is also what makes the handler\n * safe to run on any replica.\n */\n private createServerInstance(principal: Principal | undefined): SdkServer {\n if (!this.sdkServerCtor || !this.serverInfo || !this.serverOptions) {\n throw new Error(\n \"mcp: server factory used before prepareServerFactory() ran\",\n );\n }\n const server = new this.sdkServerCtor(this.serverInfo, this.serverOptions);\n\n // Each handler casts only the member whose type is deliberately looser\n // than the SDK's generated schema: `McpTool.inputSchema.properties` is a\n // `Record<string, unknown>` because it comes from an arbitrary Standard\n // Schema, and `content` blocks are assembled by route code. The\n // surrounding result envelope stays structurally checked, so a future\n // required field on either result is a compile error rather than a\n // protocol error at a client.\n server.setRequestHandler(\"tools/list\", () => {\n const tools = this.getAvailableTools();\n this.logExposedToolsOnce();\n return { tools: tools as unknown as ListToolsResult[\"tools\"] };\n });\n\n server.setRequestHandler(\"tools/call\", async (request) => {\n const result = await this.handleToolCall(\n request.params.name,\n request.params.arguments ?? {},\n principal,\n );\n return {\n ...result,\n content: result.content as unknown as CallToolResult[\"content\"],\n };\n });\n\n return server;\n }\n\n /**\n * Build the stateless web-standard MCP handler shared by both HTTP paths.\n *\n * Under protocol revision 2026-07-28 there is no `initialize` handshake and\n * no `Mcp-Session-Id`: every request is self-describing, so the handler\n * builds a fresh server instance per request and holds nothing between them.\n * That is what lets a Routecraft MCP server run as N replicas behind a plain\n * round-robin load balancer, with no sticky sessions and no shared store.\n *\n * `legacy: \"stateless\"` (the SDK default) keeps 2025-era clients working:\n * a request that carries no per-request `_meta` envelope is answered by the\n * established stateless 2025 idiom from the same factory. Existing clients\n * therefore keep working unchanged, they simply do not get the new\n * revision's features.\n */\n private async buildHttpHandler(): Promise<{\n handler: McpHttpHandler;\n serve: (\n req: AuthenticatedRequest,\n res: import(\"node:http\").ServerResponse,\n ) => void;\n }> {\n const { createMcpHandler } = await loadMcpServerSdk(\"mcp (http)\");\n const { toNodeHandler } = await loadMcpNodeSdk(\"mcp (http)\");\n await this.prepareServerFactory();\n\n const handler = createMcpHandler(\n (ctx: McpRequestContext) =>\n this.createServerInstance(this.authInfoToPrincipal(ctx.authInfo)),\n {\n onerror: (error: Error) => {\n this.context.logger.error({ err: error }, \"MCP handler error\");\n },\n },\n );\n\n const nodeHandler = toNodeHandler(handler, {\n onerror: (error: Error) => {\n this.context.logger.error({ err: error }, \"MCP HTTP request error\");\n },\n });\n\n // `IncomingMessage.method` is `string | undefined` while the adapter's\n // duck-typed shape declares `method?: string`; under\n // `exactOptionalPropertyTypes` those differ statically but not at runtime.\n //\n // The adapter's own try/catch covers request conversion and `fetch`, but\n // not the `res.writeHead`/`res.end` that follow it, so a response already\n // committed upstream (CORS, bearer middleware) surfaces as a rejection\n // here. Left unhandled it would take the process down under Node's\n // default `--unhandled-rejections=throw`, turning one bad request into a\n // replica outage.\n const serve = (\n req: AuthenticatedRequest,\n res: import(\"node:http\").ServerResponse,\n ): void => {\n void nodeHandler(req as NodeIncomingMessageLike, res).catch(\n (err: unknown) => {\n this.context.logger.error({ err }, \"MCP HTTP request failed\");\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal Server Error\" }));\n } else if (!res.writableEnded) {\n res.end();\n }\n },\n );\n };\n\n return { handler, serve };\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. Call it after `.listen()` so the bound port is known:\n * nothing registers middleware that closes over the URL beforehand, so an\n * ephemeral `port: 0` resolves to the real port rather than baking `:0`\n * into the discovery document and the 401 headers.\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 * The four RFC 9728 / RFC 6750 helpers below are deliberately hand-rolled\n * rather than taken from `@modelcontextprotocol/server`, which exports\n * `buildOAuthProtectedResourceMetadata`, `getOAuthProtectedResourceMetadataUrl`,\n * `oauthMetadataResponse` and `bearerAuthChallengeResponse`.\n *\n * Two of those are web-standard shaped (`oauthMetadataResponse(request:\n * Request): Response`, `bearerAuthChallengeResponse(): Response`), but the\n * metadata and 401 paths are answered on raw Node `IncomingMessage` /\n * `ServerResponse` before anything reaches `toNodeHandler`, so adopting them\n * would mean bridging Request/Response for the two endpoints least able to\n * afford an extra translation layer. `bearerAuthChallengeResponse` also\n * derives the challenge from a thrown error, whereas the gate derives it\n * from a classified outcome (missing credential, rejected token,\n * insufficient scope); routing our policy back through errors it recognises\n * is the coupling that dropping `requireBearerAuth` removed.\n *\n * The remaining two are pure builders whose output is a security-surface\n * wire format we already pin with tests. Swapping them would re-pin the same\n * bytes against a dependency that can change them in a minor release, for no\n * user-visible gain. Revisit only if the SDK starts emitting a field the\n * spec requires and these do not.\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 && \"issuer\" in auth) {\n const issuer: OAuthValidatorAuthOptions[\"issuer\"] = auth.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 rejected request, with an\n * absolute `resource_metadata` URL per RFC 9728 §5.1.\n *\n * `params` carries the RFC 6750 §3 attributes for the specific refusal: a\n * bare challenge on a `401`, or `error=\"insufficient_scope\"` plus the\n * `scope` the client would need on a `403`.\n */\n private buildWwwAuthenticateHeader(\n params: Record<string, string> = {},\n ): string {\n const metadataUrl = this.resolveResourceMetadataUrl();\n const attributes = [\n `realm=\"mcp\"`,\n ...Object.entries(params).map(([key, value]) => `${key}=\"${value}\"`),\n `resource_metadata=\"${metadataUrl}\"`,\n ];\n return `Bearer ${attributes.join(\", \")}`;\n }\n\n /**\n * Required scopes the principal does not carry, in configuration order.\n * Empty when no `requiredScopes` are configured or all are satisfied.\n */\n private missingScopes(principal: Principal): string[] {\n const required = this.options.auth?.requiredScopes;\n if (!required || required.length === 0) return [];\n const granted = new Set(principal.scopes ?? []);\n return required.filter((scope) => !granted.has(scope));\n }\n\n /**\n * Serve the RFC 9728 protected-resource metadata document.\n *\n * 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 the HTTP transport on a raw Node `http.createServer`.\n */\n private async startHttp(): Promise<void> {\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 { handler, serve } = await this.buildHttpHandler();\n this.mcpHandler = handler;\n\n this.httpServer = createServer(async (req: AuthenticatedRequest, 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 if (this.options.auth) {\n const authenticated = await this.validateAuth(req);\n if (!authenticated.ok) {\n if (authenticated.status === 500) {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Internal Server Error\" }));\n return;\n }\n // RFC 6750 §3: a request that carried no credential gets a bare\n // challenge. Claiming `invalid_token` there would tell the MCP\n // discovery probe its credential was rejected when it never sent\n // one, and clients branch on that.\n res.writeHead(401, {\n \"Content-Type\": \"application/json\",\n \"WWW-Authenticate\": this.buildWwwAuthenticateHeader(\n authenticated.presented ? { error: \"invalid_token\" } : {},\n ),\n });\n res.end(JSON.stringify({ error: \"Unauthorized\" }));\n return;\n }\n\n // A valid token that lacks a required scope is a 403, not a 401\n // (RFC 6750 §3.1): the identity is good, the grant is too narrow, and\n // re-authenticating with the same scopes would not help. The\n // `scope` parameter tells the client what to ask for on a step-up.\n const missing = this.missingScopes(authenticated.principal);\n if (missing.length > 0) {\n const detail = {\n reason: \"insufficient_scope\",\n scheme: \"bearer\",\n source: \"mcp\",\n };\n this.context.logger.warn(detail, \"Auth rejected: insufficient scope\");\n this.context.emit(\"auth:rejected\", detail);\n res.writeHead(403, {\n \"Content-Type\": \"application/json\",\n \"WWW-Authenticate\": this.buildWwwAuthenticateHeader({\n error: \"insufficient_scope\",\n scope: missing.join(\" \"),\n }),\n });\n res.end(JSON.stringify({ error: \"insufficient_scope\" }));\n return;\n }\n\n // `toNodeHandler` forwards `req.auth` to the handler's pass-through\n // `authInfo`, which the per-request factory reads back into the\n // principal. This is the stateless replacement for the\n // AsyncLocalStorage the sessionful transport needed.\n req.auth = this.principalToAuthInfo(\n authenticated.principal,\n authenticated.token,\n );\n }\n\n serve(req, res);\n });\n\n await this.listenHttp(port, host);\n }\n\n /**\n * Bind the HTTP server to the configured port and host.\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 SDK `AuthInfo` carried on a request back into the Routecraft\n * {@link Principal} for the exchange headers.\n *\n * {@link principalToAuthInfo} stashes the fully-populated principal in\n * `authInfo.extra.principal`, so the round trip is lossless. The fallback\n * covers an `AuthInfo` this server did not mint, which can only reach here\n * if the SDK handler is driven directly: it reconstructs what the SDK-level\n * shape can express and nothing more, rather than dropping the identity.\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 * Wrap a verified {@link Principal} as the SDK `AuthInfo` the handler passes\n * through to the per-request factory, stashing the full principal in `extra`\n * so {@link authInfoToPrincipal} recovers it losslessly on the way back out.\n *\n * The principal travels as a construction parameter of the per-request\n * server instance rather than through ambient storage: revision 2026-07-28\n * builds a fresh instance per request, so the identity can be closed over at\n * construction and there is no session for an `AsyncLocalStorage` to key on.\n *\n * `token` carries the verified bearer the caller presented. Every auth\n * helper must agree on it: the SDK hands one `AuthInfo` to every\n * per-request instance, and a consumer reading `authInfo.token` must not see\n * a real credential under `oauth()` and a placeholder under `jwt()`.\n */\n private principalToAuthInfo(\n principal: Principal,\n token: string,\n ): SdkAuthInfo {\n const authInfo: SdkAuthInfo = {\n token,\n clientId: principal.clientId ?? principal.subject,\n scopes: principal.scopes ?? [],\n extra: { principal },\n };\n if (principal.expiresAt !== undefined) {\n authInfo.expiresAt = principal.expiresAt;\n }\n return authInfo;\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>) | null {\n const authOptions = this.options.auth as\n (ValidatorAuthOptions & { issuer?: string | string[] }) | 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 *\n * This is the single auth gate: `jwt()`, `jwks()`, `oauth()` and a custom\n * `{ validator }` all converge here, which is why `requireBearerAuth` was\n * dropped in favour of owning the 401/403/500 mapping locally.\n *\n * Returns the authenticated principal and the bearer it was derived from on\n * success. The token rides along so {@link principalToAuthInfo} can present\n * it as `AuthInfo.token` whichever helper produced the principal.\n */\n private async validateAuth(req: IncomingMessage): Promise<AuthGateResult> {\n const authOptions = this.options.auth as ValidatorAuthOptions | undefined;\n const verifier =\n authOptions && \"validator\" in authOptions\n ? (this.validatorVerifier ?? this.buildValidatorVerifier())\n : null;\n if (!verifier) {\n // `auth` is configured but yields no verifier, so every request is\n // refused. Unreachable through `mcpPlugin`, which rejects auth without a\n // `validator` at construction, but `McpServer` can be built directly.\n // Refusing is right; refusing silently is not, because a blanket 401 with\n // no log and no event looks identical to a server nobody has a token for.\n const detail = {\n reason: \"no_verifier\",\n scheme: \"bearer\",\n source: \"mcp\",\n };\n this.context.logger.error(\n detail,\n \"Auth rejected: auth is configured but resolved no verifier; every request will be refused\",\n );\n this.context.emit(\"auth:rejected\", detail);\n return { ok: false, status: 401, presented: false };\n }\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 { ok: false, status: 401, presented: false };\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 { ok: false, status: 401, presented: false };\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 // `debug`, not `info`: auth is re-verified on every request under the\n // stateless revision, so an `info` line per tool call would put a\n // subject identifier in the log stream at agent-loop rates. The event\n // still fires for metrics and audit sinks.\n // A verified principal whose expiry has already passed must not\n // authenticate. `jwt()` / `jwks()` reject an expired token themselves,\n // but a custom validator may not, and the gate is the last checkpoint\n // before the route runs. Absent `expiresAt` is left alone: a credential\n // with no expiry concept (an API key) is a legitimate validator result.\n //\n // The tolerance is the one the verifier itself applied (surfaced by\n // `jwks()` / `jwt()` / `oauth()`), so the gate cannot refuse a token the\n // verifier just accepted within skew. Non-finite inputs fail closed for\n // the same reason `authorize()` does: a comparison against NaN is always\n // false, which would turn the check into a no-op.\n if (result.expiresAt !== undefined) {\n // Floored and inclusive, matching `authorize()`, `jwt()` and jose's\n // `exp <= now - tolerance`. A fractional `now` would put the gate's\n // boundary ahead of the verifier's; an exclusive `>` would put it\n // behind, honouring a token for a second past its stated expiry.\n const nowSeconds = Math.floor(Date.now() / 1000);\n const clockToleranceSec = this.options.auth?.clockToleranceSec ?? 0;\n if (\n !Number.isFinite(result.expiresAt) ||\n !Number.isFinite(clockToleranceSec) ||\n nowSeconds >= result.expiresAt + clockToleranceSec\n ) {\n const detail = {\n reason: \"expired\",\n scheme: \"bearer\",\n source: \"mcp\",\n };\n this.context.logger.debug(\n detail,\n \"Auth rejected: principal expiry has passed\",\n );\n this.context.emit(\"auth:rejected\", detail);\n return { ok: false, status: 401, presented: true };\n }\n }\n\n this.context.logger.debug(successDetail, \"Auth succeeded\");\n this.context.emit(\"auth:success\", successDetail);\n return { ok: true, principal: result, token };\n } catch (err) {\n const expired = isExpiredTokenError(err);\n const reason = classifyRejectionReason(err);\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 (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 fault (RC5021 userinfo/discovery fetch, RC5022 sub\n // mismatch, or a JWKS endpoint that is unreachable, slow, or answers\n // badly) is not the caller's token being wrong: answer 500 so the client\n // retries later rather than discarding a credential that may be valid.\n return reason === \"infrastructure\"\n ? { ok: false, status: 500 }\n : { ok: false, status: 401, presented: true };\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 // Tear down the modern leg: aborts in-flight 2026-era exchanges and\n // closes their per-request instances. There are no sessions to drain.\n // Per the SDK contract this does NOT reach the 2025-era stateless\n // fallback, so a legacy exchange in flight is ended by the socket\n // close below rather than drained.\n if (this.mcpHandler) {\n // Isolated: a rejection here must not skip the listener teardown\n // below, or the port stays bound and `running` stays true.\n try {\n await this.mcpHandler.close();\n } catch (error) {\n this.context.logger.error(\n { err: error },\n \"Failed to close MCP handler; continuing shutdown\",\n );\n } finally {\n this.mcpHandler = null;\n }\n }\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.stdioHandle) {\n await this.stdioHandle.close();\n this.stdioHandle = null;\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: local `.from(mcp())`\n * route tools (after the `tools` filter) plus tools proxied from\n * registered clients via `proxy`. Reads the MCP local tool registry lazily\n * so routes have time to subscribe before the first `tools/list` request.\n *\n * On a name collision the local route tool wins and the proxied tool is\n * skipped with a once-per-name warning.\n */\n getAvailableTools(): McpTool[] {\n const entries = this.getExposedLocalEntries();\n const tools = entries.map((entry) => this.entryToMcpTool(entry));\n\n const localNames = new Set(entries.map((e) => e.endpoint));\n for (const proxied of this.resolveProxied().values()) {\n if (localNames.has(proxied.exposedName)) {\n this.warnProxyOnce(\n `proxy:local-conflict:${proxied.exposedName}`,\n `mcpPlugin proxy: tool name \"${proxied.exposedName}\" from \"${proxied.serverId}:${proxied.toolName}\" collides with a local mcp() route; the route wins. Use a name override to expose both.`,\n );\n continue;\n }\n const tool = proxiedToolToMcpTool(proxied);\n // Same icon-inheritance rule as entryToMcpTool: the tool's own icons\n // when set, the server icons when unset, nothing when explicitly [].\n const icons = proxied.entry.icons ?? this.resolveServerIcons();\n if (icons.length > 0) {\n tool.icons = icons;\n }\n tools.push(tool);\n }\n return tools;\n }\n\n /**\n * Whether a local tool entry passes the `tools` filter. Shared by the\n * list path (filter the whole registry) and the call path (check the one\n * looked-up entry) so a filtered-out tool is consistently invisible.\n */\n private passesToolsFilter(entry: McpLocalToolEntry): boolean {\n const toolsFilter = this.options.tools;\n if (!toolsFilter) return true;\n if (Array.isArray(toolsFilter)) return toolsFilter.includes(entry.endpoint);\n return toolsFilter(entry);\n }\n\n /**\n * Local route tool entries after the `tools` filter, for `tools/list`.\n */\n private getExposedLocalEntries(): McpLocalToolEntry[] {\n const registry = this.context.getStore(MCP_LOCAL_TOOL_REGISTRY) as\n Map<string, McpLocalToolEntry> | undefined;\n\n if (!registry) {\n return [];\n }\n\n return Array.from(registry.values()).filter((e) =>\n this.passesToolsFilter(e),\n );\n }\n\n /**\n * Look up one local tool entry by name for `tools/call`, honoring the\n * `tools` filter (a filtered-out tool is not callable).\n */\n private lookupLocalEntry(toolName: string): McpLocalToolEntry | undefined {\n const registry = this.context.getStore(MCP_LOCAL_TOOL_REGISTRY) as\n Map<string, McpLocalToolEntry> | undefined;\n const entry = registry?.get(toolName);\n if (!entry || !this.passesToolsFilter(entry)) return undefined;\n return entry;\n }\n\n /**\n * Resolve the `proxy` selection against the live client tool registry,\n * memoized on the registry's change version: wildcard entries follow\n * tool refresh and stdio restarts (any change re-resolves), while\n * steady-state requests reuse the cached resolution. A version change\n * also opens a new warning epoch so a condition that recurs after the\n * registry recovered is logged again rather than silenced forever.\n */\n private resolveProxied(): Map<string, McpProxiedTool> {\n if (!this.options.proxy || this.options.proxy.length === 0) {\n return new Map();\n }\n const registry = this.context.getStore(MCP_TOOL_REGISTRY);\n const version = registry?.version ?? -1;\n if (registry && version === this.proxyResolvedVersion) {\n return this.proxyResolved;\n }\n // Open a new warning epoch only when a registry is actually present and\n // its version advanced. Clearing unconditionally would re-warn on every\n // request while the registry is still missing (proxyResolvedVersion never\n // advances to -1), flooding the log with the same \"no registry\" message.\n if (registry) {\n this.proxyWarnings.clear();\n }\n const resolved = resolveProxiedTools(\n this.context,\n this.options.proxy,\n (key, msg) => this.warnProxyOnce(key, msg),\n );\n if (registry) {\n this.proxyResolvedVersion = version;\n this.proxyResolved = resolved;\n }\n return resolved;\n }\n\n /** Log a proxy-resolution warning once per dedup key. */\n private warnProxyOnce(key: string, message: string): void {\n if (this.proxyWarnings.has(key)) return;\n this.proxyWarnings.add(key);\n this.context.logger.warn({}, message);\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. Resolves local route tools first\n * (after the `tools` filter, so a filtered-out tool is not callable),\n * then tools proxied from registered clients.\n */\n private async handleToolCall(\n toolName: string,\n args: Record<string, unknown>,\n principal: Principal | undefined,\n ): Promise<McpToolCallResult> {\n try {\n // Normalize args once for both the local and proxied paths (the SDK\n // may pass a parsed object or a raw JSON string). MCP tool arguments\n // are always a JSON object; a primitive, array, or null (however it\n // arrives) is coerced to the safe fallback shape before any guard or\n // remote dispatch consumes it, so downstream code can trust a record.\n const body = normalizeToolArgs(args);\n\n const entry = this.lookupLocalEntry(toolName);\n if (!entry) {\n const proxied = this.resolveProxied().get(toolName);\n if (proxied) {\n return await this.handleProxiedToolCall(proxied, body, principal);\n }\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 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 (jwt/jwks/\n // custom validator and `oauth()`) 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 headers: Record<string, unknown> = {\n [McpHeadersKeys.TOOL]: toolName,\n [McpHeadersKeys.REQUEST]: crypto.randomUUID(),\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 // Deep snapshot: the live body is handed to the route handler next\n // and may be mutated (including nested values) after emission.\n args: structuredClone(body),\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 // A tool that advertises an outputSchema (the route declares .output())\n // MUST return structuredContent per the MCP spec; spec-compliant clients\n // reject the response otherwise. The text block stays alongside it for\n // non-structured clients, as the spec recommends. Only a plain object\n // body qualifies: the spec requires outputSchema (and therefore the\n // structured result) to be an object, so a primitive or array body from\n // a mismatched .output() declaration falls back to text-only.\n const result: {\n content: Array<{ type: \"text\"; text: string }>;\n structuredContent?: Record<string, unknown>;\n } = {\n content: [{ type: \"text\", text: resultText }],\n };\n if (\n entry.output?.body !== undefined &&\n typeof resultExchange.body === \"object\" &&\n resultExchange.body !== null &&\n !Array.isArray(resultExchange.body)\n ) {\n result.structuredContent = resultExchange.body as Record<\n string,\n unknown\n >;\n }\n return result;\n } catch (error) {\n const logMsg = toolErrorLogMessage(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 return {\n content: [\n {\n type: \"text\",\n text: `Error: ${toolErrorUserMessage(error, logMsg)}`,\n },\n ],\n isError: true,\n };\n }\n }\n\n /**\n * Dispatch a proxied tool call to its registered client and pass the raw\n * MCP result (content, structuredContent, isError) through verbatim.\n *\n * Trust boundary: the caller's authenticated principal is NOT forwarded;\n * the Routecraft -> MCP hop authenticates with the client's registered\n * `auth` (same posture as the agent's MCP tool dispatch). Route-scope\n * guardrails do not run here; a per-entry `guard` (run before dispatch,\n * with the caller's read-only principal on its context) covers identity\n * checks, and tools needing stateful guardrails belong behind a\n * `.from(mcp())` route.\n *\n * Guard rejections and dispatch failures are handled here (not in\n * `handleToolCall`'s catch) so the `plugin:mcp:tool:failed` event always\n * carries the proxied/serverId/remoteTool fields the events reference\n * documents, keeping called/failed pairs correlatable per client.\n */\n private async handleProxiedToolCall(\n proxied: McpProxiedTool,\n args: Record<string, unknown>,\n principal: Principal | undefined,\n ): Promise<McpToolCallResult> {\n const detail = {\n tool: proxied.exposedName,\n proxied: true as const,\n serverId: proxied.serverId,\n remoteTool: proxied.toolName,\n };\n // Deep snapshot: the live args object is handed to the guard and remote\n // dispatch next and may be mutated (including nested values) after emission.\n this.context.emit(`plugin:mcp:tool:called`, {\n ...detail,\n args: structuredClone(args),\n });\n\n try {\n const guard = proxied.config.guard;\n if (guard) {\n const guardCtx = makeFnHandlerContext(\n proxied.exposedName,\n NEVER_ABORTED,\n principal,\n );\n await guard(args, guardCtx);\n }\n\n const raw: McpRawToolResult = await dispatchMcpCallRaw(\n this.context,\n proxied.serverId,\n proxied.toolName,\n args,\n );\n\n if (raw.isError) {\n this.context.emit(`plugin:mcp:tool:failed`, {\n ...detail,\n error: \"Remote tool returned an error result\",\n });\n } else {\n this.context.emit(`plugin:mcp:tool:completed`, detail);\n }\n\n return {\n ...raw,\n content: Array.isArray(raw.content)\n ? (raw.content as McpToolCallResult[\"content\"])\n : [],\n };\n } catch (error) {\n const logMsg = toolErrorLogMessage(error);\n this.context.logger.error({ ...detail, err: error }, logMsg);\n this.context.emit(`plugin:mcp:tool:failed`, { ...detail, error: logMsg });\n\n // A framework error here is a dispatch/transport failure (RC5003),\n // whose message and cause can carry the configured upstream URL,\n // host:port, or a subprocess path. Those go to the log and the failed\n // event (operator-facing) but never to the MCP caller; the client gets\n // a generic message. A non-framework throw is the guard's own rejection\n // (the author wrote it for the caller), so its message passes through.\n const clientText = isRoutecraftError(error)\n ? `Proxied tool \"${proxied.exposedName}\" could not be called.`\n : logMsg;\n\n return {\n content: [{ type: \"text\", text: `Error: ${clientText}` }],\n isError: true,\n };\n }\n }\n}\n","/**\n * Keyed cache of long-lived connections that are expensive to establish and\n * must be disposed exactly once.\n *\n * Caching the resolved value is not enough. Establishing a connection is\n * asynchronous, so a cache that stores the result leaves a window between the\n * miss and the write in which a second caller also misses, also connects, and\n * whose write replaces the first entry. The displaced connection is then\n * unreachable and never disposed, leaking it and its transport. Storing the\n * in-flight promise closes the window: the second caller joins the first.\n *\n * A rejected attempt evicts itself, so a transient failure does not poison the\n * key for the process lifetime.\n */\nexport interface DisposableEntry {\n dispose(): Promise<void>;\n}\n\n/** Keyed promise cache with identity-checked eviction. */\nexport interface ConnectionCache<T extends DisposableEntry> {\n /**\n * Return the in-flight or settled promise for `key`, starting one with\n * `create` on a miss. Concurrent callers for the same key share one promise.\n */\n getOrCreate(key: string, create: () => Promise<T>): Promise<T>;\n /**\n * Evict `key` only when it still holds `pending`, and dispose that entry.\n *\n * The identity check matters because attempts can overlap: a caller whose\n * own attempt failed must not evict and dispose the healthy connection a\n * concurrent caller has since cached under the same key.\n */\n evict(key: string, pending: Promise<T>): Promise<void>;\n /** Dispose every cached entry and empty the cache. */\n disposeAll(onError: (error: unknown, key: string) => void): Promise<void>;\n}\n\nexport function createConnectionCache<\n T extends DisposableEntry,\n>(): ConnectionCache<T> {\n const entries = new Map<string, Promise<T>>();\n\n return {\n getOrCreate(key, create) {\n const existing = entries.get(key);\n if (existing) return existing;\n\n const pending = create();\n entries.set(key, pending);\n // A failed attempt must not stay cached, or every later call replays the\n // same rejection. Evicting here rather than at the call site keeps the\n // cache consistent even for callers that never inspect the rejection.\n void pending.catch(() => {\n if (entries.get(key) === pending) entries.delete(key);\n });\n return pending;\n },\n\n async evict(key, pending) {\n // Removal and disposal are one step, not two. Callers share a single\n // promise, so overlapping failures arrive here with the same `pending`;\n // disposing outside this guard would close the same connection once per\n // failing caller. Exactly one caller removes a given entry, so exactly\n // one disposes it.\n if (entries.get(key) !== pending) return;\n entries.delete(key);\n // A rejected attempt has nothing to dispose, and its rejection is\n // already the failure the caller is handling.\n await pending.then(\n (entry) => entry.dispose(),\n () => undefined,\n );\n },\n\n async disposeAll(onError) {\n for (const [key, pending] of entries) {\n try {\n const entry = await pending;\n await entry.dispose();\n } catch (error) {\n onError(error, key);\n }\n }\n entries.clear();\n },\n };\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { formatSchemaIssues, rcError } from \"@routecraft/routecraft\";\nimport { exposedNameFor, parseProxyRef } from \"./proxy.ts\";\nimport { MCP_TOOL_NAME_PATTERN } from \"./types.ts\";\nimport type { McpPluginOptions } from \"./types.ts\";\nimport {\n isSplittableNameHead,\n TOOL_NAME_PATTERN_SOURCE,\n TOOL_NAME_SEPARATOR,\n} from \"../tool-name.ts\";\n\n/** Standard Schema validate result: success has value, failure has issues. */\ntype ValidateResult<T = unknown> =\n { value: T; issues?: never } | { 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 */\n/** RFC 6749 §3.3 scope-token: visible ASCII except space, `\"` and `\\`. */\nconst SCOPE_TOKEN = /^[\\x21\\x23-\\x5B\\x5D-\\x7E]+$/;\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 const auth = options.auth as unknown as Record<string, unknown>;\n\n // The pre-2026 authorization-server-proxy shape. It has no `validator`, so\n // it would otherwise start cleanly and then refuse every request with 401.\n // Fail at construction with the migration instead.\n if (\n \"provider\" in auth ||\n \"endpoints\" in auth ||\n \"verifyAccessToken\" in auth ||\n \"getClient\" in auth\n ) {\n throw new TypeError(\n \"mcpPlugin: auth uses the removed OAuth authorization-server proxy shape \" +\n \"({ provider, endpoints, verifyAccessToken, getClient }). The MCP server is \" +\n \"now a resource server: use oauth({ verify, issuer, requiredScopes }) and \" +\n \"point clients at your IdP's own authorization and token endpoints, which \" +\n \"they discover from the protected-resource metadata.\",\n );\n }\n\n if (\"validator\" in auth) {\n if (typeof 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 a 'validator' function. \" +\n \"Use jwt(), jwks(), oauth(), or a custom { validator } object.\",\n );\n }\n\n // Required scopes are reflected into a `WWW-Authenticate` challenge, whose\n // grammar (RFC 6749 §3.3) excludes quotes, backslashes and spaces. Reject\n // them here so a misconfiguration surfaces at startup rather than as a\n // corrupted header on the first refusal.\n const requiredScopes = auth[\"requiredScopes\"];\n if (requiredScopes !== undefined) {\n if (!Array.isArray(requiredScopes)) {\n throw new TypeError(\n \"mcpPlugin: auth.requiredScopes must be an array of scope strings\",\n );\n }\n for (const scope of requiredScopes as unknown[]) {\n if (typeof scope !== \"string\" || !SCOPE_TOKEN.test(scope)) {\n throw new TypeError(\n `mcpPlugin: auth.requiredScopes contains an invalid scope ${JSON.stringify(scope)}. ` +\n \"A scope token is one or more visible ASCII characters excluding space, \" +\n \"double quote and backslash (RFC 6749 §3.3).\",\n );\n }\n }\n }\n\n // The expiry gate fails closed on a non-finite tolerance, so a NaN or\n // negative value would refuse every request at runtime. Say so at startup.\n const clockToleranceSec = auth[\"clockToleranceSec\"];\n if (\n clockToleranceSec !== undefined &&\n (typeof clockToleranceSec !== \"number\" ||\n !Number.isFinite(clockToleranceSec) ||\n clockToleranceSec < 0)\n ) {\n throw new TypeError(\n \"mcpPlugin: auth.clockToleranceSec must be a finite, non-negative number of seconds\",\n );\n }\n }\n\n // Validate stdio client configs\n if (options.clients) {\n for (const [name, config] of Object.entries(options.clients)) {\n // A client name is one segment of the `mcp__<server>__<tool>` wire\n // name an agent sees, and resolution splits that at the FIRST\n // separator after the prefix. A client called `a__b` exposing `c`\n // therefore generates `mcp__a__b__c`, which reads back as server\n // `a`, tool `b__c`: a valid-looking name pointing at nothing, and\n // two distinct pairs could collapse onto one name.\n //\n // Rejected here rather than only at resolution because this is\n // the half we own. Client names are chosen locally in this very\n // option; tool names come from the remote. Resolution still drops\n // such tools with a warning for a registry populated directly,\n // but reaching that path through `mcpPlugin` meant every tool on\n // the client vanished at dispatch with nothing failing at\n // startup. Constraining the server alone is enough to make the\n // grammar unambiguous, so a remote may keep using `__` in its own\n // tool names freely.\n //\n // The exact shapes that break the split, and why a trailing\n // underscore is one of them, live with the separator in\n // `isSplittableNameHead`. Both this throw and the resolution-time\n // drop in `agent/tools/selection.ts` call it, so the two layers\n // cannot disagree about what they reject.\n if (!isSplittableNameHead(name)) {\n // Collapse runs and trim the edges, so the name offered back is\n // one the check above actually accepts. Naively splitting on\n // the separator does not: `a____b` would yield `a__b` and `a__`\n // would yield `a_`, both rejected again by the very error that\n // suggested them. A name with nothing left after trimming\n // (`\"\"`, `\"___\"`) still gets a concrete placeholder, so every\n // rejection carries something copyable.\n const salvaged = name.replace(/_+/g, \"_\").replace(/^_+|_+$/g, \"\");\n const suggested = salvaged === \"\" ? \"client\" : salvaged;\n throw rcError(\"RC5003\", undefined, {\n message: `mcpPlugin: client name \"${name}\" must not be empty, contain \"${TOOL_NAME_SEPARATOR}\", or end with \"_\". It becomes the server segment of the generated \"mcp__<server>__<tool>\" tool name, which is split at the first \"${TOOL_NAME_SEPARATOR}\" after the prefix, so any of those makes the name ambiguous or collides with another client.`,\n suggestion: `Rename the client to something without \"${TOOL_NAME_SEPARATOR}\" (a single underscore inside the name is fine, e.g. \"${suggested}\").`,\n });\n }\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 proxy selection. Refs must parse, reference a registered client,\n // and produce statically unique exposed names; wildcard refs cannot carry\n // name/description overrides (they fan out to many tools).\n if (options.proxy !== undefined) {\n if (!Array.isArray(options.proxy)) {\n throw new TypeError(\n \"mcpPlugin: proxy must be an array of ref strings or { ref, ... } configs\",\n );\n }\n const seenRefs = new Set<string>();\n const seenNames = new Set<string>();\n for (const raw of options.proxy) {\n const isString = typeof raw === \"string\";\n const isObject =\n typeof raw === \"object\" && raw !== null && !Array.isArray(raw);\n if (!isString && !isObject) {\n throw new TypeError(\n \"mcpPlugin: each proxy entry must be a ref string or a { ref, ... } config object\",\n );\n }\n const entry = isString ? { ref: raw } : raw;\n const { serverId, toolName } = parseProxyRef(entry.ref);\n // Own-property check: `serverId in options.clients` would accept\n // inherited keys (constructor, toString, ...) that client setup, which\n // iterates `Object.entries`, never registers, leaving the ref\n // permanently unresolved at runtime.\n if (!options.clients || !Object.hasOwn(options.clients, serverId)) {\n throw new TypeError(\n `mcpPlugin: proxy ref \"${entry.ref}\" references unknown client \"${serverId}\". Register it under clients.`,\n );\n }\n const isWildcard = toolName === \"*\";\n if (\n isWildcard &&\n (entry.name !== undefined || entry.description !== undefined)\n ) {\n throw new TypeError(\n `mcpPlugin: proxy ref \"${entry.ref}\" is a wildcard and cannot set name or description overrides`,\n );\n }\n // Guard the type at runtime too: RegExp.test coerces a non-string\n // (e.g. a number from untyped JS) to a string, which would pass the\n // pattern and then surface as a non-string tool name on tools/list.\n if (\n entry.name !== undefined &&\n (typeof entry.name !== \"string\" ||\n !MCP_TOOL_NAME_PATTERN.test(entry.name))\n ) {\n throw new TypeError(\n `mcpPlugin: proxy name override \"${String(entry.name)}\" must be a string matching ${TOOL_NAME_PATTERN_SOURCE}`,\n );\n }\n if (entry.guard !== undefined && typeof entry.guard !== \"function\") {\n throw new TypeError(\n `mcpPlugin: proxy guard for \"${entry.ref}\" must be a function (throw inside it to reject a call)`,\n );\n }\n const refKey = `${serverId}:${toolName}`;\n if (seenRefs.has(refKey)) {\n throw new TypeError(\n `mcpPlugin: duplicate proxy ref \"${entry.ref}\" (resolves to \"${refKey}\")`,\n );\n }\n seenRefs.add(refKey);\n if (!isWildcard) {\n const exposed = exposedNameFor(entry, toolName);\n if (seenNames.has(exposed)) {\n throw new TypeError(\n `mcpPlugin: proxy entries expose the tool name \"${exposed}\" more than once. Use name overrides to disambiguate.`,\n );\n }\n seenNames.add(exposed);\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 { McpRawToolResult, McpTool } from \"./types.ts\";\nimport { extractContent } from \"./extract-content.ts\";\nimport {\n loadMcpClientSdk,\n loadMcpClientStdioSdk,\n MCP_CLIENT_INFO,\n MCP_VERSION_NEGOTIATION,\n} from \"./sdk.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<McpRawToolResult>;\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 loadMcpClientSdk(\"mcp (stdio client)\");\n const stdioMod = await loadMcpClientStdioSdk(\"mcp (stdio client)\");\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(MCP_CLIENT_INFO, {\n capabilities: {},\n versionNegotiation: MCP_VERSION_NEGOTIATION,\n listChanged: {\n tools: {\n onChanged: (error: unknown, tools: unknown) => {\n if (tools && Array.isArray((tools as { tools: unknown[] }).tools)) {\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\n // manually. Log the cause so a persistently broken push path is\n // distinguishable from a healthy one that simply re-lists.\n this.logger.debug(\n { err: error, serverId },\n \"listChanged delivered no tools; re-listing manually\",\n );\n void this.refreshTools();\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 return extractContent(await this.callToolRaw(name, args));\n }\n\n /**\n * Call a tool on the remote MCP server and return the raw MCP result\n * (content array, structuredContent, isError) without content extraction.\n * Used by the proxy path so remote results pass through verbatim.\n *\n * @param name - Tool name to invoke\n * @param args - Arguments passed to the tool\n * @returns The raw MCP `tools/call` result\n */\n async callToolRaw(\n name: string,\n args: Record<string, unknown>,\n ): Promise<McpRawToolResult> {\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 return await this.client.callTool({\n name,\n arguments: args,\n });\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\";\nimport { deriveTagsFromAnnotations } from \"./annotation-tags.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 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 /** Monotonic change counter; bumped on every observable mutation. */\n private changeVersion = 0;\n\n /** Per-source fingerprint of the last stored tool list. */\n private fingerprints = new Map<string, string>();\n\n /** Keys already reported by a consumer for {@link reportedVersion}. */\n private reported = new Set<string>();\n\n /** Registry version {@link reported} was accumulated against. */\n private reportedVersion = -1;\n\n /**\n * Monotonically increasing version, bumped whenever a source's tools\n * actually change (a periodic re-listing that returns the same tools does\n * not bump it). Lets consumers (e.g. the MCP server's proxy resolution)\n * memoize derived state and recompute only when the registry changed,\n * instead of on every read or refresh tick.\n */\n get version(): number {\n return this.changeVersion;\n }\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.title !== undefined) {\n entry.title = tool.title;\n }\n if (tool.description !== undefined) {\n entry.description = tool.description;\n }\n if (tool.outputSchema !== undefined) {\n entry.outputSchema = tool.outputSchema as Record<string, unknown>;\n }\n if (tool.icons !== undefined) {\n entry.icons = tool.icons;\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 // Only bump the change version when the source's tools actually\n // differ from what was stored, so periodic HTTP re-listings with an\n // unchanged tool set do not invalidate memoized consumers.\n const fingerprint = JSON.stringify([transport, tools]);\n if (this.fingerprints.get(source) !== fingerprint) {\n this.fingerprints.set(source, fingerprint);\n this.changeVersion++;\n }\n }\n\n /**\n * Claim the right to report `key` once for the registry's current\n * {@link version}. Returns true the first time a key is claimed and\n * false for every later claim, until the registry actually changes.\n *\n * For consumers that diagnose a persistent property of a registered\n * tool rather than an event of the call they are serving. The agent\n * tool resolver is the motivating case: it runs per dispatch, so a\n * remote tool whose name cannot be used as a provider tool name would\n * otherwise log the same warning on every dispatch of every agent\n * bound to that server, forever.\n *\n * Scoped to the version rather than to the registry's lifetime so a\n * condition that survives a refresh is re-reported rather than\n * silenced by its first occurrence. A periodic re-listing that\n * returns an unchanged tool set does not bump the version, so it does\n * not re-open the reports either.\n *\n * @param key - Stable identity of the condition being reported\n * @returns Whether the caller should report it\n * @internal\n */\n shouldReport(key: string): boolean {\n if (this.reportedVersion !== this.changeVersion) {\n this.reportedVersion = this.changeVersion;\n this.reported.clear();\n }\n if (this.reported.has(key)) return false;\n this.reported.add(key);\n return true;\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 if (this.tools.delete(source)) {\n this.fingerprints.delete(source);\n this.changeVersion++;\n }\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 { connectMcpHttpClient } from \"./sdk.ts\";\nimport { createConnectionCache } from \"./http-client-cache.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 McpStdioToolCaller,\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\";\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 = createConnectionCache<{\n listTools(): Promise<{ tools: McpTool[] }>;\n /** Close the client AND its transport; closing the client alone leaks the socket. */\n dispose(): Promise<void>;\n }>();\n const httpRefreshTimers: ReturnType<typeof setInterval>[] = [];\n let toolRegistry: McpToolRegistry | null = null;\n\n return {\n async apply(ctx: CraftContext) {\n ctx.setStore(MCP_PLUGIN_REGISTERED, true);\n\n // Create and store tool registry\n toolRegistry = new McpToolRegistry();\n ctx.setStore(MCP_TOOL_REGISTRY, toolRegistry);\n\n // Store stdio managers map so destination adapter can call tools on stdio clients\n ctx.setStore(\n MCP_STDIO_MANAGERS,\n stdioManagers as Map<string, McpStdioToolCaller>,\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(ADAPTER_MCP_CLIENT_SERVERS, map);\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 await httpClients.disposeAll((error, serverId) => {\n ctx.logger.error(\n { err: error, serverId, operation: \"close\" },\n \"Failed to close HTTP client\",\n );\n });\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 function getOrCreateHttpClient(\n serverId: string,\n url: string,\n auth?: McpClientHttpConfig[\"auth\"],\n ): Promise<{\n listTools(): Promise<{ tools: McpTool[] }>;\n dispose(): Promise<void>;\n }> {\n return httpClients.getOrCreate(serverId, async () => {\n const { client: rawClient, transport } = await connectMcpHttpClient(\n new URL(url),\n auth,\n );\n const typed = rawClient as unknown as {\n close(): Promise<void>;\n listTools(): Promise<{ tools: McpTool[] }>;\n };\n\n // Both handles are retained: closing the client does not close its\n // transport, so a cache that kept only the client would leak a socket\n // per entry on teardown and per failed refresh.\n return {\n listTools: () => typed.listTools(),\n dispose: async (): Promise<void> => {\n try {\n await typed.close();\n } catch {\n // Ignore cleanup errors\n }\n try {\n await transport.close();\n } catch {\n // Ignore cleanup errors\n }\n },\n };\n });\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 let pending: ReturnType<typeof getOrCreateHttpClient> | undefined;\n try {\n pending = getOrCreateHttpClient(serverId, url, auth);\n const client = await pending;\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 the next attempt\n // reconnects, and dispose it so an unreachable remote does not leak a\n // client and a transport per refresh interval. `evict` drops the entry\n // only when it is still the one THIS refresh used, because overlapping\n // refreshes are possible (the interval can fire while a previous run is\n // still in flight) and evicting by key alone would let a failing run\n // dispose the healthy client a concurrent run had just cached.\n if (pending) await httpClients.evict(serverId, pending);\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 { loadOptionalPeer } from \"@routecraft/routecraft\";\nimport 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\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 const mod = (await loadOptionalPeer(\n () => import(\"@huggingface/transformers\"),\n {\n adapterName: \"Hugging Face embedding\",\n packageName: \"@huggingface/transformers\",\n },\n )) as {\n pipeline: (\n task: string,\n model: string,\n opts?: { dtype?: string },\n ) => Promise<unknown>;\n };\n const pipe = (await mod.pipeline(\"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\" | \"ollama\" | \"openai\" | \"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(ADAPTER_EMBEDDING_PROVIDERS, map);\n if (\n options.defaultOptions &&\n Object.keys(options.defaultOptions).length > 0\n ) {\n ctx.setStore(ADAPTER_EMBEDDING_OPTIONS, options.defaultOptions);\n }\n },\n async teardown() {\n await disposeEmbeddingPipelineCache();\n },\n };\n}\n","import {\n getExchangeRoute,\n rcError,\n type Exchange,\n type ForwardFn,\n} from \"@routecraft/routecraft\";\nimport type { BlockClient } from \"./types.ts\";\n\n/**\n * Build the {@link BlockClient} handed to a block resolver function.\n *\n * Wraps the same {@link ForwardFn} that route `.error()` handlers\n * receive: resolves the dispatch's bound route via\n * `getExchangeRoute(exchange).getForward()`. When the exchange has no\n * route binding (synthetic exchanges in tests), `forward` rejects\n * with AI1001 so a resolver does not silently no-op and downstream\n * `.error()` handlers can pattern-match on the failure mode.\n *\n * @internal\n */\nexport function makeBlockClient(exchange: Exchange<unknown>): BlockClient {\n const route = getExchangeRoute(exchange);\n const forward: ForwardFn = route\n ? route.getForward()\n : async () => {\n throw rcError(\"AI1001\", undefined, {\n message:\n \"Block resolver: client.forward() called but the exchange has no bound route. \" +\n \"Block resolvers can only forward when invoked through a real route dispatch.\",\n });\n };\n return { forward };\n}\n","import {\n rcError,\n type CraftContext,\n type Exchange,\n} from \"@routecraft/routecraft\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { FnOptions } from \"../fn/types.ts\";\nimport type { ResolvedTool } from \"../agent/tools/selection.ts\";\nimport { TOOL_NAME_CHARSET, TOOL_NAME_SEPARATOR } from \"../tool-name.ts\";\nimport { makeBlockClient } from \"./client.ts\";\nimport type {\n AgentBlockLoadSummary,\n BlockBody,\n BlockClient,\n Blocks,\n} from \"./types.ts\";\n\n/**\n * Separator joining nested {@link Blocks} group names into the single\n * canonical block name used for the system-prompt heading, the\n * synthetic loader tool name, and the `blocksLoaded` summary. A leaf\n * `onboarding` under group `skills` flattens to `skills__onboarding`.\n *\n * `__` rather than `/` because loader tool names reach the provider\n * unsanitised and must match `^[a-zA-Z0-9_-]{1,64}$`. Using one\n * canonical flattened name everywhere keeps the slice-based\n * {@link summariseBlockLoads} / {@link isBlockLoaderCall} logic intact.\n *\n * @internal\n */\nexport const BLOCK_NAME_SEPARATOR = TOOL_NAME_SEPARATOR;\n\n/**\n * Symbol stamped on `ResolvedTool` entries produced by\n * {@link resolveBlocks} for `mode: \"progressive\"` blocks. Lets the\n * tool bridge route their telemetry to `agent:block:loaded` events\n * (and the session to partition them out of `AgentResult.toolCalls`)\n * without sniffing on the tool name.\n *\n * @internal\n */\nexport const BLOCK_LOADER_TOOL = Symbol.for(\"routecraft.ai.block.loader-tool\");\n\n/**\n * Reserved name prefix for the block surface. User tools (fns, direct\n * routes, MCP tools) and block names that start with this prefix\n * collide with the framework's synthetic surface and are rejected at\n * construction (block names via `validateBlocks`) or dispatch\n * (resolved tool names via `mergeUserAndLoaderTools`) with AI1002.\n *\n * The framework reserves the broader `_block_` namespace (not just\n * `_block__load__`) so future synthetic-tool kinds (e.g. unloaders or\n * state probes) can land without a separate breaking reservation.\n *\n * Deliberately kept at the single-underscore `_block_`, one character\n * shorter than the `_block__` that today's names actually start with.\n * The reservation is about what users may not claim, so the wider net\n * is the right one: it also catches names in the pre-`__` shape, which\n * would otherwise become claimable the moment the loader prefix moved.\n *\n * @internal\n */\nexport const BLOCK_RESERVED_PREFIX = \"_block_\";\n\n/**\n * Concrete prefix used to generate synthetic loader-tool names today.\n * Always starts with {@link BLOCK_RESERVED_PREFIX}; user names are\n * validated against the broader reservation, not this specific kind.\n *\n * Shaped as `_<namespace>__<kind>__`, so the generated name is\n * `_block__load__<name>`: `__` is the only structural separator, and\n * the leading `_` marks the framework-reserved namespace. The kind\n * segment leaves room for future synthetic tools (unloaders, state\n * probes) under the same namespace without another breaking rename.\n *\n * @internal\n */\nexport const BLOCK_LOADER_PREFIX = `_block${TOOL_NAME_SEPARATOR}load${TOOL_NAME_SEPARATOR}`;\n\n/**\n * Internal extension carried on a synthetic loader-tool `ResolvedTool`.\n * The session reads it to assemble `AgentResult.blocksLoaded` after a\n * dispatch.\n *\n * @internal\n */\nexport interface BlockLoaderToolMeta {\n [BLOCK_LOADER_TOOL]: true;\n blockName: string;\n}\n\n/** A `ResolvedTool` known to be a synthetic block loader. @internal */\nexport type BlockLoaderTool = ResolvedTool & BlockLoaderToolMeta;\n\n/**\n * Type guard for {@link BlockLoaderTool}. Used by the session and tool\n * bridge to differentiate user tools from framework-synthesised loaders.\n *\n * @internal\n */\nexport function isBlockLoaderTool(tool: ResolvedTool): tool is BlockLoaderTool {\n return (tool as { [BLOCK_LOADER_TOOL]?: true })[BLOCK_LOADER_TOOL] === true;\n}\n\n/**\n * Result of resolving a list of {@link Block}s for one agent dispatch.\n * `systemAppend` is the string to concatenate onto the agent's\n * `system` prompt (already includes per-block `## <name>` headings).\n * `loaderTools` is the list of synthetic tools to merge into the\n * agent's `ResolvedTool[]` before handing it to the LLM.\n *\n * @internal\n */\nexport interface ResolvedBlocks {\n systemAppend: string;\n loaderTools: BlockLoaderTool[];\n}\n\n/**\n * Resolve every block on an agent for one dispatch.\n *\n * - `mode: \"inject\"` blocks: run the resolver (respecting `lifetime`)\n * and append the result to `systemAppend` as `## <name>\\n\\n<body>`.\n * - `mode: \"progressive\"` blocks: emit one synthetic\n * `_block__load__<name>` tool whose handler runs the resolver on\n * demand against the captured exchange and context.\n *\n * Caching for `lifetime: \"context\"` is keyed by the block object\n * identity on a `WeakMap<CraftContext, Map<Block, string>>`. Two\n * declarations of the same logical block in separate agents are\n * therefore independent caches.\n *\n * Throws AI1001 when an inject-mode resolver throws or returns a\n * non-string. Progressive-mode resolver failures surface back to the\n * model as a loader-tool error so the model can self-correct rather\n * than aborting the dispatch.\n *\n * @internal\n */\nexport async function resolveBlocks(\n blocks: Blocks | undefined,\n exchange: Exchange<unknown>,\n context: CraftContext | undefined,\n): Promise<ResolvedBlocks> {\n if (!blocks) return { systemAppend: \"\", loaderTools: [] };\n const flat = flattenBlocks(blocks);\n if (flat.size === 0) {\n return { systemAppend: \"\", loaderTools: [] };\n }\n const client = makeBlockClient(exchange);\n const parts: string[] = [];\n const loaderTools: BlockLoaderTool[] = [];\n for (const [name, body] of flat) {\n if (body.mode === \"inject\") {\n const value = await resolveOnce(name, body, exchange, context, client);\n parts.push(`\\n\\n## ${name}\\n\\n${value}`);\n continue;\n }\n loaderTools.push(buildLoaderTool(name, body, exchange, context, client));\n }\n return { systemAppend: parts.join(\"\"), loaderTools };\n}\n\n/**\n * Discriminate a {@link Blocks} record value: a leaf {@link BlockBody}\n * carries a string `mode` (always `\"inject\"` or `\"progressive\"`); any\n * other object value is a nested group. Keying on `mode` being a\n * string is unambiguous for well-formed input because a group's\n * members are always objects (`BlockBody`/`Blocks`) or `false`, never a\n * bare string, so a group can never accidentally present a string\n * `mode` at its own level, even when a member happens to be named\n * `mode`. A malformed leaf that omits `mode` is caught separately by\n * `validateBlocks` (which reports the missing mode) rather than being\n * silently treated as a group. `false` removal sentinels are filtered\n * out before this is called.\n *\n * @internal\n */\nexport function isBlockGroup(value: BlockBody | Blocks): value is Blocks {\n return typeof (value as Partial<BlockBody>).mode !== \"string\";\n}\n\n/**\n * Provider tool-name charset. Synthetic loader names are\n * `_block__load__<flattenedName>` and are sent to the model provider\n * verbatim, so the flattened block name must satisfy {@link\n * BLOCK_TOOL_NAME_CHARSET} and stay within the provider length limit\n * once the loader prefix is added. Validated at construction so an\n * unsafe name fails at `agent()` rather than at the provider on the\n * first dispatch.\n *\n * Aliases of the package-wide constants in `tool-name.ts`; the block\n * surface answers to the same provider contract as every other tool\n * name, so it consumes that definition rather than restating it.\n *\n * @internal\n */\nexport const BLOCK_TOOL_NAME_CHARSET = TOOL_NAME_CHARSET;\n\n/**\n * AI1002 error for two blocks whose names collapse to the same\n * flattened canonical name. Shared by the construction-time validator\n * ({@link validateBlocks}) and the dispatch-time flattener ({@link\n * flattenBlocks}) so the code and message cannot drift between the two\n * walkers, which must stay behaviourally identical.\n *\n * @internal\n */\nexport function blockCollisionError(\n qualified: string,\n): ReturnType<typeof rcError> {\n return rcError(\"AI1002\", undefined, {\n message: `Agent block \"${qualified}\": two blocks resolve to the same name after flattening nested groups. Rename one of them.`,\n });\n}\n\n/**\n * AI1002 error for a blocks tree that contains a cycle (a group that\n * directly or transitively contains itself). Shared by the validator\n * and the flattener for the same reason as {@link blockCollisionError}.\n *\n * @internal\n */\nexport function blockCycleError(prefix: string): ReturnType<typeof rcError> {\n return rcError(\"AI1002\", undefined, {\n message: `Agent block \"${prefix}\": blocks form a cycle (a group contains itself). Block trees must be finite.`,\n });\n}\n\n/**\n * Flatten a {@link Blocks} tree depth-first into an ordered map keyed\n * by the canonical name (group names joined by {@link\n * BLOCK_NAME_SEPARATOR}). Insertion order is preserved so inject\n * blocks keep their author-declared system-prompt order. `false`\n * entries are skipped (they are removal sentinels handled at merge\n * time, a no-op here). Two blocks that collapse to the same flattened\n * name throw AI1002 so a silent override cannot happen. This runs on\n * the post-merge record at dispatch, so it is the authoritative guard\n * for collisions that only arise once defaults and per-agent blocks\n * are combined; within-record collisions are already caught earlier by\n * `validateBlocks` at construction.\n *\n * @internal\n */\nexport function flattenBlocks(blocks: Blocks): Map<string, BlockBody> {\n const out = new Map<string, BlockBody>();\n walkBlocks(blocks, \"\", out, new WeakSet());\n return out;\n}\n\nfunction walkBlocks(\n blocks: Blocks,\n prefix: string,\n out: Map<string, BlockBody>,\n // Ancestors on the current recursion path; guards against a group\n // that (directly or transitively) contains itself, which would\n // otherwise recurse without bound. Added before descending and\n // removed after, so a group legitimately reused on two sibling\n // branches is not mistaken for a cycle.\n seen: WeakSet<object>,\n): void {\n if (seen.has(blocks)) throw blockCycleError(prefix);\n seen.add(blocks);\n for (const [name, body] of Object.entries(blocks)) {\n if (body === false) continue;\n const qualified = prefix ? `${prefix}${BLOCK_NAME_SEPARATOR}${name}` : name;\n if (isBlockGroup(body)) {\n walkBlocks(body, qualified, out, seen);\n continue;\n }\n if (out.has(qualified)) throw blockCollisionError(qualified);\n out.set(qualified, body);\n }\n seen.delete(blocks);\n}\n\n/**\n * Per-context, per-block resolution cache. Keyed by `CraftContext`\n * identity at the outer layer and by `BlockBody` object identity at\n * the inner layer. Stores the in-flight promise rather than the\n * resolved string so concurrent dispatches against the same\n * `context`-lifetime block share one resolution instead of racing\n * into N parallel invocations. WeakMap on the outer key so a disposed\n * context does not pin block content in memory.\n *\n * @internal\n */\nconst LIFETIME_CACHE = new WeakMap<\n CraftContext,\n Map<BlockBody, Promise<string>>\n>();\n\n/**\n * Run a block's resolver, honouring `lifetime`. For\n * `lifetime: \"dispatch\"` (default) the resolver runs every call. For\n * `lifetime: \"context\"` the resolver runs once per `CraftContext`\n * and the cached value (or in-flight promise) is reused for\n * subsequent calls in that context.\n *\n * @internal\n */\nasync function resolveOnce(\n name: string,\n body: BlockBody,\n exchange: Exchange<unknown>,\n context: CraftContext | undefined,\n client: BlockClient,\n): Promise<string> {\n const lifetime = body.lifetime ?? \"dispatch\";\n if (lifetime === \"context\" && context) {\n let cache = LIFETIME_CACHE.get(context);\n if (cache?.has(body)) return cache.get(body) as Promise<string>;\n if (!cache) {\n cache = new Map<BlockBody, Promise<string>>();\n LIFETIME_CACHE.set(context, cache);\n }\n const pending = invokeResolver(name, body, exchange, context, client);\n cache.set(body, pending);\n // On rejection, evict so a subsequent dispatch can retry rather\n // than being permanently stuck on the cached failure.\n pending.catch(() => cache!.delete(body));\n return pending;\n }\n return invokeResolver(name, body, exchange, context, client);\n}\n\n/**\n * Invoke a block's `value` resolver and validate its return shape.\n * Throws AI1003 when the `value` shape itself is invalid (neither string\n * nor function) and AI1001 for every resolution failure, so callers can\n * decide whether to abort the dispatch (inject mode) or report the error\n * back to the model (progressive mode).\n *\n * @internal\n */\nasync function invokeResolver(\n name: string,\n body: BlockBody,\n exchange: Exchange<unknown>,\n context: CraftContext | undefined,\n client: BlockClient,\n): Promise<string> {\n const { value } = body;\n if (typeof value === \"string\") return value;\n if (typeof value !== \"function\") {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${name}\": \"value\" must be a string or a function returning a string.`,\n });\n }\n if (!context) {\n throw rcError(\"AI1001\", undefined, {\n message: `Agent block \"${name}\": resolver function requires a CraftContext but the exchange has no bound context.`,\n });\n }\n let resolved: unknown;\n try {\n resolved = await Promise.resolve(value(exchange, context, [], client));\n } catch (cause) {\n throw rcError(\"AI1001\", cause, {\n message: `Agent block \"${name}\": resolver function threw: ${(cause as Error)?.message ?? String(cause)}`,\n });\n }\n if (typeof resolved !== \"string\") {\n throw rcError(\"AI1001\", undefined, {\n message: `Agent block \"${name}\": resolver function must return a string (got ${typeof resolved}).`,\n });\n }\n return resolved;\n}\n\n/**\n * JSON Schema describing an empty object. The loader tools accept no\n * input from the model (the block's content is fixed by the resolver,\n * not parameterised), so the schema is closed for additional properties\n * to match the bridge's expectations.\n *\n * @internal\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 for loader\n * tools. Mirrors the shape used by `currentTime` / `randomUuid` so the\n * AI SDK bridge's JSON-schema lookup works uniformly.\n *\n * @internal\n */\nconst EMPTY_OBJECT_SCHEMA: 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: [{ message: \"Expected an empty object {}.\" }],\n };\n }\n return { value: {} as Record<string, never> };\n },\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 * Build the synthetic `_block__load__<name>` tool for a progressive\n * block. The handler closes over the dispatch's exchange / context /\n * client so the resolver runs against live per-dispatch state when\n * the model invokes the loader. Errors are rethrown so the standard\n * tool-bridge error path reports them as a tool error the model can\n * self-correct from.\n *\n * @internal\n */\nfunction buildLoaderTool(\n name: string,\n body: BlockBody,\n exchange: Exchange<unknown>,\n context: CraftContext | undefined,\n client: BlockClient,\n): BlockLoaderTool {\n const description =\n typeof body.description === \"string\" && body.description.trim() !== \"\"\n ? body.description\n : `Load the \"${name}\" block.`;\n const handler: FnOptions[\"handler\"] = async () =>\n resolveOnce(name, body, exchange, context, client);\n return {\n name: `${BLOCK_LOADER_PREFIX}${name}`,\n description,\n input: EMPTY_OBJECT_SCHEMA,\n // Loader tools declare their provenance like every other resolved\n // tool, but are never shown to `toolPolicy`: they are merged in\n // after policy evaluation, because assembling context is not the\n // same act as granting reach.\n source: { kind: \"block\", name },\n handler,\n [BLOCK_LOADER_TOOL]: true,\n blockName: name,\n };\n}\n\n/**\n * Build the `AgentBlockLoadSummary[]` from accumulated tool calls.\n * Filters the dispatched tool-call list to entries whose name carries\n * the reserved loader prefix and maps them onto the public summary\n * shape consumed by `AgentResult.blocksLoaded`.\n *\n * @internal\n */\nexport function summariseBlockLoads(\n toolCalls: ReadonlyArray<{\n toolCallId: string;\n toolName: string;\n output?: unknown;\n error?: unknown;\n }>,\n): AgentBlockLoadSummary[] {\n const out: AgentBlockLoadSummary[] = [];\n for (const tc of toolCalls) {\n if (!tc.toolName.startsWith(BLOCK_LOADER_PREFIX)) continue;\n const blockName = tc.toolName.slice(BLOCK_LOADER_PREFIX.length);\n const summary: AgentBlockLoadSummary = {\n blockName,\n toolName: tc.toolName,\n toolCallId: tc.toolCallId,\n };\n if (tc.output !== undefined) summary.output = tc.output;\n if (tc.error !== undefined) summary.error = tc.error;\n out.push(summary);\n }\n return out;\n}\n\n/**\n * Predicate matching the tool-call summaries that came from synthetic\n * block loaders. Used by the session to partition the cumulative\n * tool-call list before populating `AgentResult.toolCalls` vs\n * `AgentResult.blocksLoaded`.\n *\n * @internal\n */\nexport function isBlockLoaderCall(toolName: string): boolean {\n return toolName.startsWith(BLOCK_LOADER_PREFIX);\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 // A custom provider carrying a concrete model instance needs no model name\n // (only the factory form consumes one), so it is exempt from the guard.\n const isCustomInstance =\n model.provider === \"custom\" &&\n typeof (model as { model?: unknown }).model !== \"function\";\n if (modelName.trim() === \"\" && !isCustomInstance) {\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.`,\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(ADAPTER_LLM_PROVIDERS);\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 { loadOptionalPeer } from \"@routecraft/routecraft\";\nimport { assertLanguageModelShape, PROVIDER_DEFAULTS } 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 *\n * Provider SDKs are optional peer dependencies, loaded lazily through\n * `loadOptionalPeer` so a missing package surfaces as `RC5017` with an\n * install hint (see `.standards/ci-cd.md` § 6).\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 case \"lmstudio\":\n return resolveLmStudio(config, modelId);\n case \"custom\":\n return resolveCustom(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\n/**\n * Settings shared by the keyed cloud providers (OpenAI, Anthropic, Gemini):\n * a required API key plus an optional API URL override.\n */\ninterface KeyedProviderSettings {\n apiKey: string;\n baseURL?: string;\n}\n\n/**\n * Build the SDK factory settings for a keyed provider. `baseURL` is omitted\n * entirely when unset (rather than passed as `undefined`) so the settings\n * object mirrors the user's config and the SDK's own default and env-var\n * resolution applies untouched.\n */\nfunction keyedSettings(config: KeyedProviderSettings): KeyedProviderSettings {\n const settings: KeyedProviderSettings = { apiKey: config.apiKey };\n if (config.baseURL !== undefined) settings.baseURL = config.baseURL;\n return settings;\n}\n\nasync function resolveOpenAI(\n config: import(\"../types.ts\").LlmModelConfigOpenAI,\n modelId: string,\n): Promise<unknown> {\n const mod = (await loadOptionalPeer(() => import(\"@ai-sdk/openai\"), {\n adapterName: \"OpenAI LLM\",\n packageName: \"@ai-sdk/openai\",\n })) as {\n createOpenAI: (s: KeyedProviderSettings) => (m: string) => unknown;\n };\n const openai = mod.createOpenAI(keyedSettings(config));\n return openai(modelId);\n}\n\nasync function resolveAnthropic(\n config: import(\"../types.ts\").LlmModelConfigAnthropic,\n modelId: string,\n): Promise<unknown> {\n const mod = (await loadOptionalPeer(() => import(\"@ai-sdk/anthropic\"), {\n adapterName: \"Anthropic LLM\",\n packageName: \"@ai-sdk/anthropic\",\n })) as {\n createAnthropic: (s: KeyedProviderSettings) => (m: string) => unknown;\n };\n const anthropic = mod.createAnthropic(keyedSettings(config));\n return anthropic(modelId);\n}\n\nasync function resolveGemini(\n config: import(\"../types.ts\").LlmModelConfigGemini,\n modelId: string,\n): Promise<unknown> {\n const mod = (await loadOptionalPeer(() => import(\"@ai-sdk/google\"), {\n adapterName: \"Gemini LLM\",\n packageName: \"@ai-sdk/google\",\n })) as {\n createGoogleGenerativeAI: (\n s: KeyedProviderSettings,\n ) => (m: string) => unknown;\n };\n const google = mod.createGoogleGenerativeAI(keyedSettings(config));\n return google(modelId);\n}\n\nasync function resolveOpenRouter(\n config: import(\"../types.ts\").LlmModelConfigOpenRouter,\n modelId: string,\n): Promise<unknown> {\n const mod = (await loadOptionalPeer(\n () => import(\"@openrouter/ai-sdk-provider\"),\n {\n adapterName: \"OpenRouter LLM\",\n packageName: \"@openrouter/ai-sdk-provider\",\n },\n )) as {\n createOpenRouter: (s: { apiKey: string }) => {\n chat: (id: string) => unknown;\n };\n };\n const openrouter = mod.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 const mod = (await loadOptionalPeer(() => import(\"ollama-ai-provider-v2\"), {\n adapterName: \"Ollama LLM\",\n packageName: \"ollama-ai-provider-v2\",\n })) as {\n createOllama: (s: { baseURL?: string }) => (name: string) => unknown;\n };\n const ollama = mod.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\nasync function resolveLmStudio(\n config: import(\"../types.ts\").LlmModelConfigLmStudio,\n modelId: string,\n): Promise<unknown> {\n const mod = (await loadOptionalPeer(\n () => import(\"@ai-sdk/openai-compatible\"),\n { adapterName: \"LM Studio LLM\", packageName: \"@ai-sdk/openai-compatible\" },\n )) as {\n createOpenAICompatible: (s: {\n name: string;\n baseURL: string;\n apiKey?: string;\n includeUsage?: boolean;\n }) => (id: string) => unknown;\n };\n // LM Studio serves an OpenAI-compatible chat-completions API. We use Vercel's\n // dedicated openai-compatible provider (not @ai-sdk/openai) so the adapter is\n // not tied to OpenAI-specific behaviour such as the Responses API. The\n // provider's default model is the chat-completions model, and `includeUsage`\n // makes LM Studio report token usage on streaming responses too.\n const settings: {\n name: string;\n baseURL: string;\n apiKey?: string;\n includeUsage: boolean;\n } = {\n name: \"lmstudio\",\n baseURL: config.baseURL ?? PROVIDER_DEFAULTS.lmstudio.baseURL,\n includeUsage: true,\n };\n // Only send an Authorization header when a key is configured; LM Studio\n // ignores auth, so we do not invent a placeholder bearer token.\n if (config.apiKey !== undefined) settings.apiKey = config.apiKey;\n const lmstudio = mod.createOpenAICompatible(settings);\n const name = config.modelId ?? modelId;\n const rawModel = lmstudio(name);\n assertLanguageModelShape(rawModel, \"LM Studio\", name);\n return rawModel;\n}\n\nfunction resolveCustom(\n config: import(\"../types.ts\").LlmModelConfigCustom,\n modelId: string,\n): unknown {\n const { model } = config;\n const resolved =\n typeof model === \"function\"\n ? (model as (id: string) => unknown)(modelId)\n : model;\n assertLanguageModelShape(resolved, \"Custom\", modelId || \"(custom)\");\n return resolved;\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: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 { type CraftContext, type Principal } from \"@routecraft/routecraft\";\nimport { isBlockLoaderTool } from \"../block/resolve.ts\";\nimport { toAiInputSchema } from \"../llm/structured-output.ts\";\nimport { makeFnHandlerContext } from \"../fn/handler-context.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 }])`).\n * Throwing inside the guard surfaces back to the model as a tool\n * error so the model can self-correct; the wrapper emits\n * `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 // Block-loader synthetic tools emit `agent:block:loaded` /\n // `agent:block:error` events instead of the user-tool family so\n // observability consumers can wire framework bookkeeping separately\n // from the agent's user-tool usage.\n const isLoader = isBlockLoaderTool(r);\n const blockName = isLoader\n ? ((r as { blockName?: string }).blockName ?? r.name)\n : undefined;\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 (!isLoader && ctx && dispatchIdentity) {\n ctx.emit(\"route:agent:tool:invoked\", {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n toolName: r.name,\n // Sensitive payload: only persisted to telemetry when\n // snapshot capture is enabled (see telemetry `_snapshot`).\n _snapshot: { input },\n });\n }\n\n try {\n if (guard) await guard(input, callCtx);\n const output = await handler(input, callCtx);\n if (ctx && dispatchIdentity) {\n if (isLoader) {\n ctx.emit(\"route:agent:block:loaded\", {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n blockName: blockName!,\n // Sensitive payload: gated by snapshot capture.\n _snapshot: { output },\n duration: Date.now() - start,\n });\n } else {\n ctx.emit(\"route:agent:tool:result\", {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n toolName: r.name,\n // Sensitive payload: only persisted to telemetry when\n // snapshot capture is enabled (see telemetry `_snapshot`).\n _snapshot: { output },\n duration: Date.now() - start,\n });\n }\n }\n return output;\n } catch (err) {\n if (ctx && dispatchIdentity) {\n if (isLoader) {\n ctx.emit(\"route:agent:block:error\", {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n blockName: blockName!,\n errorName: errorName(err),\n // Sensitive payload: error messages can echo the\n // rejected input, so the full error is gated by\n // snapshot capture like input/output.\n _snapshot: { error: err },\n duration: Date.now() - start,\n });\n } else {\n ctx.emit(\"route:agent:tool:error\", {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n toolCallId,\n toolName: r.name,\n errorName: errorName(err),\n // Sensitive payload: error messages can echo the\n // rejected input, so the full error is gated by\n // snapshot capture like input/output.\n _snapshot: { error: err },\n duration: Date.now() - start,\n });\n }\n }\n throw err;\n }\n },\n });\n }\n return out;\n}\n\n/**\n * Non-sensitive error classifier for tool/block error events. The error\n * message and stack may echo the rejected tool input, so they stay inside\n * the `_snapshot` envelope; the name alone (e.g. `TypeError`, `CraftError`)\n * is safe to persist unconditionally and is enough for dashboards to\n * distinguish failure classes.\n *\n * @internal\n */\nfunction errorName(err: unknown): string {\n if (err instanceof Error) return err.name || \"Error\";\n return typeof err;\n}\n","import {\n HeadersKeys,\n rcError,\n type CraftContext,\n type Exchange,\n} from \"@routecraft/routecraft\";\nimport { isBlockLoaderCall, summariseBlockLoads } from \"../block/resolve.ts\";\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 /**\n * Full `providerId:modelName` identifier this dispatch resolved to\n * (e.g. `anthropic:claude-opus-4-7`). Emitted on the agent lifecycle\n * events so observability consumers can show the model per run.\n */\n readonly model: string;\n /**\n * Registered agent id when dispatched by name (`agent(\"id\")`),\n * undefined for inline agents (which are identified by their route).\n * Emitted on the agent lifecycle events so the TUI can attribute a\n * run to a named agent rather than only the dispatching route.\n */\n readonly agentName?: 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: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 this.emitStarted(maxTurns);\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 // Inside the try so a prepare failure (tool resolution, schema\n // resolution) still emits agent:error; otherwise the started event\n // would be orphaned and observability would show the run as\n // running forever.\n const prepared = await this.prepare(abortSignal);\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:agent:started` on the context bus at the start of\n * a dispatch. Carries the agent identity, resolved model, tool names,\n * and turn budget so observability consumers (the TUI) can show that\n * an agent executed, with what model and tools, even if the run later\n * fails mid-flight.\n *\n * @internal\n */\n private emitStarted(maxTurns: number): void {\n const id = this.input.dispatchIdentity;\n const ctx = this.input.context;\n if (!id || !ctx) return;\n ctx.emit(\"route:agent:started\", {\n routeId: id.routeId,\n exchangeId: id.exchangeId,\n correlationId: id.correlationId,\n ...(this.input.agentName !== undefined && {\n agentName: this.input.agentName,\n }),\n model: this.input.model,\n toolNames: this.input.tools.map((t) => t.name),\n maxTurns,\n });\n }\n\n /**\n * Emit `route:agent:finished` on the context bus once the\n * dispatch returns a consolidated result. Carries the agent identity,\n * model, finish reason and total token usage so observability\n * consumers can wire dashboards / metrics / billing without\n * subscribing to per-token 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 const agentName =\n this.input.agentName !== undefined\n ? { agentName: this.input.agentName }\n : {};\n const identity = {\n routeId: id.routeId,\n exchangeId: id.exchangeId,\n correlationId: id.correlationId,\n ...agentName,\n model: this.input.model,\n };\n ctx.emit(\"route:agent:finished\", {\n ...identity,\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 ctx.emit(\"route:agent:usage\", {\n ...identity,\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 ...(result.usage?.cacheReadTokens !== undefined && {\n cacheReadTokens: result.usage.cacheReadTokens,\n }),\n ...(result.usage?.cacheWriteTokens !== undefined && {\n cacheWriteTokens: result.usage.cacheWriteTokens,\n }),\n });\n }\n\n /**\n * Emit `route: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:agent:error\", {\n routeId: id.routeId,\n exchangeId: id.exchangeId,\n correlationId: id.correlationId,\n ...(this.input.agentName !== undefined && {\n agentName: this.input.agentName,\n }),\n model: this.input.model,\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. Synthetic block-loader invocations are\n // partitioned out into `blocksLoaded` so user-tool assertions stay\n // clean.\n const userCalls: LlmToolCallSummary[] = [];\n const blockCalls: LlmToolCallSummary[] = [];\n for (const call of accumulatedToolCalls) {\n if (isBlockLoaderCall(call.toolName)) {\n blockCalls.push(call);\n } else {\n userCalls.push(call);\n }\n }\n if (userCalls.length > 0) out.toolCalls = userCalls;\n if (blockCalls.length > 0) out.blocksLoaded = summariseBlockLoads(blockCalls);\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\";\nimport type { AgentToolPolicy } from \"./tools/policy.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\n/**\n * Store key for the tool policies installed via\n * `agentPlugin({ toolPolicy })`.\n *\n * An array rather than a single value, because multiple `agentPlugin`\n * installs compose with AND: each contributes a policy and a tool must\n * satisfy all of them. Kept out of `ADAPTER_AGENT_DEFAULT_OPTIONS` on\n * purpose, since defaults are per-agent overridable and a policy must\n * not be.\n * @internal\n */\nexport const ADAPTER_AGENT_TOOL_POLICIES = Symbol.for(\n \"routecraft.adapter.agent.tool-policies\",\n);\n\ndeclare module \"@routecraft/routecraft\" {\n interface StoreRegistry {\n [ADAPTER_AGENT_REGISTRY]: Map<string, AgentRegisteredOptions>;\n [ADAPTER_AGENT_DEFAULT_OPTIONS]: AgentDefaultOptions;\n [ADAPTER_AGENT_TOOL_POLICIES]: AgentToolPolicy[];\n }\n}\n","import type { Tag } from \"@routecraft/routecraft\";\nimport type { McpToolAnnotations } from \"../../mcp/types.ts\";\n\n/**\n * Where a resolved tool came from. Set by the resolver, never by user\n * config, so a policy rule can trust it as provenance rather than as a\n * self-declared label.\n *\n * The `direct` arm covers both spellings of the same thing: a\n * `Direct(<routeId>)` reference and a `directTool(routeId)` registered\n * under a fn id. Aliasing a capability into the fn registry changes the\n * name the model sees, not what the tool reaches, so classifying the\n * alias as `fn` would make the alias a policy bypass.\n */\nexport type AgentToolSource =\n | { readonly kind: \"fn\"; readonly id: string }\n | { readonly kind: \"direct\"; readonly routeId: string }\n | {\n readonly kind: \"mcp\";\n readonly server: string;\n readonly tool: string;\n /**\n * Raw hints exactly as the remote declared them. An absent key\n * means the server was silent, which is NOT the same as the hint\n * being false: the MCP specification assigns per-hint defaults,\n * and `destructiveHint` defaults to true when absent. Consult\n * this rather than `tags` when the difference matters.\n */\n readonly annotations?: McpToolAnnotations;\n }\n | {\n /**\n * A framework-synthesised block loader. Present so every resolved\n * tool declares its provenance, but never seen by a policy rule:\n * loader tools are merged in after policy evaluation and are\n * deliberately out of scope (they assemble context, they do not\n * grant reach).\n */\n readonly kind: \"block\";\n readonly name: string;\n };\n\n/**\n * The tool kinds a {@link AgentToolPolicy} can govern. Derived from\n * {@link AgentToolSource} rather than restated, so adding a source kind\n * cannot silently leave the policy surface behind. Excludes `block`,\n * which is framework machinery rather than a granted capability.\n */\nexport type AgentToolPolicyKind = Exclude<AgentToolSource[\"kind\"], \"block\">;\n\n/**\n * Presence map over the governable kinds, existing purely so the\n * compiler enforces completeness.\n *\n * `satisfies Record<AgentToolPolicyKind, true>` fails when a key is\n * MISSING, which a `satisfies readonly AgentToolPolicyKind[]` on an\n * array does not: an array of valid kinds satisfies that constraint\n * whether or not it lists them all. Adding a kind to\n * {@link AgentToolSource} therefore breaks the build here, which is the\n * point, because the alternative is a validator that silently stops\n * recognising a kind the type system already governs.\n *\n * @internal\n */\nconst AGENT_TOOL_POLICY_KIND_PRESENCE = {\n fn: true,\n direct: true,\n mcp: true,\n} as const satisfies Record<AgentToolPolicyKind, true>;\n\n/**\n * The governable kinds as a runtime value, for validators that need to\n * enumerate them. Derived from\n * {@link AGENT_TOOL_POLICY_KIND_PRESENCE} so it cannot drift from the\n * type.\n *\n * @internal\n */\nexport const AGENT_TOOL_POLICY_KINDS = Object.keys(\n AGENT_TOOL_POLICY_KIND_PRESENCE,\n) as readonly AgentToolPolicyKind[];\n\n/**\n * Whether `kind` is a provenance a policy can govern.\n *\n * Takes `unknown` because the callers are guarding exactly the case the\n * type system does not cover: a `ResolvedTool` hand-built from\n * JavaScript, or one written against older typings, whose `source.kind`\n * may be absent or a string nobody here defined. Derived from\n * {@link AGENT_TOOL_POLICY_KIND_PRESENCE}, so it cannot fall behind the\n * type.\n *\n * Note `block` is deliberately NOT governable: it is a real\n * resolver-set kind, so callers distinguishing \"unclassifiable\" from\n * \"exempt\" must test for it separately.\n *\n * @internal\n */\nexport function isGovernableToolKind(\n kind: unknown,\n): kind is AgentToolPolicyKind {\n return (\n typeof kind === \"string\" &&\n Object.hasOwn(AGENT_TOOL_POLICY_KIND_PRESENCE, kind)\n );\n}\n\n/**\n * The provenance arms a policy rule can actually be handed. Excludes\n * `block`: loader tools are merged in after policy evaluation, so no\n * predicate ever sees one, and leaving the arm in the union would force\n * every predicate to carry a dead `kind` guard to reach its own fields.\n */\nexport type AgentToolPolicySource = Extract<\n AgentToolSource,\n { kind: AgentToolPolicyKind }\n>;\n\n/**\n * Read-only view of a tool handed to a policy rule.\n *\n * Deliberately not the `ResolvedTool` itself: `handler` stays out of\n * user policy code, so a rule cannot wrap, mutate, or invoke the thing\n * it is deciding about. New metadata can arrive here as optional fields\n * without breaking existing predicates.\n */\nexport interface AgentToolDescriptor<\n K extends AgentToolPolicyKind = AgentToolPolicyKind,\n> {\n /** The LLM-facing tool name, already in its final wire form. */\n readonly name: string;\n /** Description the model would be shown. */\n readonly description: string;\n /** Tags from the underlying registration, empty when it carries none. */\n readonly tags: readonly Tag[];\n /**\n * Resolver-set provenance, narrowed to the kind whose rule is being\n * evaluated. An `mcp` rule therefore reads `tool.source.server`\n * directly, with no `kind` guard to satisfy the type checker.\n */\n readonly source: Extract<AgentToolPolicySource, { kind: K }>;\n}\n\n/**\n * Context in which a rule is being evaluated.\n */\nexport interface AgentToolPolicyContext {\n /**\n * The registered agent's id, or `undefined` for an inline agent.\n *\n * Present for logging and diagnostics. Rules must not branch on it:\n * inline agents have no id, so an identity-keyed rule has no\n * defensible default for them (denying breaks every inline agent,\n * allowing creates a trivial bypass). If per-agent policy is wanted\n * later, the missing ingredient is provenance carried through agent\n * registration, not this field.\n */\n readonly agentId: string | undefined;\n}\n\n/**\n * A single admission rule. `true` admits every tool of the kind,\n * `false` denies every tool of the kind, and a predicate decides per\n * tool.\n */\nexport type AgentToolRule<K extends AgentToolPolicyKind = AgentToolPolicyKind> =\n | boolean\n | ((tool: AgentToolDescriptor<K>, ctx: AgentToolPolicyContext) => boolean);\n\n/**\n * Repository-wide admission rules for the agent tool surface, one entry\n * per tool kind.\n *\n * **Absent `toolPolicy` means no policy at all: every tool is\n * admitted**, so existing contexts are untouched. Once `toolPolicy` is\n * present it is an allowlist and every kind must be decided.\n *\n * Every key is required, deliberately. An optional key would read the\n * way `?` reads everywhere else in TypeScript, \"omit it and get the\n * default\", when the effective default here is total denial. Writing\n * only the line you care about:\n *\n * ```ts\n * agentPlugin({ toolPolicy: { mcp: false } }); // does not compile\n * ```\n *\n * would otherwise strip every fn and every capability from every agent\n * in the repository, with no diff signal and nothing to notice but a\n * warn line per dropped tool. Requiring all three turns that into a\n * compile error naming the kinds you forgot. It also means a future\n * release adding a fourth kind breaks the build rather than silently\n * narrowing what you already deployed.\n *\n * Multiple `agentPlugin` installs compose with AND. A tool is admitted\n * only when every installed policy admits it, so adding a plugin can\n * only ever narrow the surface.\n *\n * @example Deny external MCP client tools outright\n * ```ts\n * agentPlugin({\n * agents: await agents(\"./agents\"),\n * toolPolicy: {\n * fn: true,\n * direct: true,\n * mcp: false, // reachable only by wrapping one in a capability\n * },\n * });\n * ```\n *\n * @example Refine with predicates\n * ```ts\n * agentPlugin({\n * toolPolicy: {\n * fn: true,\n * direct: (tool) => !tool.tags.includes(\"experimental\"),\n * mcp: (tool) => tool.source.server === \"docs\",\n * },\n * });\n * ```\n */\nexport type AgentToolPolicy = {\n /**\n * Rule for the tools of this kind.\n *\n * - `fn`: in-process fns registered via `agentPlugin({ functions })`.\n * - `direct`: capabilities in the capability registry, reached via\n * `Direct(<routeId>)` or a `directTool` alias. Named for the\n * capability registry rather than for routes, because that registry\n * is what the agent surface can actually reach: a route sourced\n * only from `http()` or `mcp()` never registers a capability, so it\n * is not addressable as an agent tool and a rule here would give a\n * false impression of governing it.\n * - `mcp`: tools discovered from external MCP clients.\n */\n [K in AgentToolPolicyKind]: AgentToolRule<K>;\n};\n\n/**\n * Reports a predicate that threw. Supplied by the caller so the failure\n * can be logged with the context's logger; the policy module itself\n * stays free of logging concerns.\n *\n * @internal\n */\nexport type AgentToolRuleErrorReporter = (\n tool: AgentToolDescriptor,\n cause: unknown,\n) => void;\n\n/**\n * The outcome of evaluating a policy against one tool. `reported` says\n * whether the denial has already been surfaced through\n * {@link AgentToolRuleErrorReporter}, so the caller can log the routine\n * denial line without duplicating a failure it has already described in\n * more detail.\n *\n * @internal\n */\nexport interface AgentToolVerdict {\n readonly admitted: boolean;\n readonly reported: boolean;\n}\n\n/**\n * Evaluate one rule against one tool.\n *\n * A predicate that throws denies the tool rather than propagating. The\n * alternative would contradict the documented contract twice over: a\n * policy is meant to fail closed, and a denial is meant never to abort\n * a dispatch. Letting the throw escape would do the opposite of both,\n * turning one bad predicate into a total outage for every agent that\n * lists a tool of that kind. The throw is still surfaced through\n * `onRuleError` at error level, because a throwing predicate is a bug\n * in the policy, not a decision.\n *\n * @internal\n */\nfunction ruleAdmits(\n rule: AgentToolRule | undefined,\n tool: AgentToolDescriptor,\n ctx: AgentToolPolicyContext,\n onRuleError: AgentToolRuleErrorReporter | undefined,\n): AgentToolVerdict {\n // A kind with no entry under a present policy is denied: the policy\n // is an allowlist once it exists. The type requires every key, so\n // this is only reachable from JavaScript or a cast.\n if (rule === undefined) return { admitted: false, reported: false };\n if (typeof rule === \"boolean\") {\n return { admitted: rule, reported: false };\n }\n try {\n return { admitted: rule(tool, ctx) === true, reported: false };\n } catch (cause) {\n // Guarded: a thrown value whose inspection itself throws must not\n // escape the catch that exists to keep one bad predicate from\n // aborting the dispatch.\n let reported = false;\n if (onRuleError !== undefined) {\n try {\n onRuleError(tool, cause);\n reported = true;\n } catch {\n reported = false;\n }\n }\n // `reported` says the failure HAS been described elsewhere, so the\n // caller may skip its own blander line. Claiming it without a\n // reporter would suppress the only diagnostic there was.\n return { admitted: false, reported };\n }\n}\n\n/**\n * Decide whether every installed policy admits `tool`. Composition is\n * AND, so installing another `agentPlugin` can only narrow the surface.\n *\n * Block-sourced tools are never passed here; the caller applies the\n * policy to the user tool list only.\n *\n * @internal\n */\nexport function policiesAdmit(\n policies: readonly AgentToolPolicy[],\n tool: AgentToolDescriptor,\n ctx: AgentToolPolicyContext,\n onRuleError?: AgentToolRuleErrorReporter,\n): AgentToolVerdict {\n if (policies.length === 0) return { admitted: true, reported: false };\n const kind = (tool.source as AgentToolSource | undefined)?.kind;\n // Loader tools are exempt and are also merged in after this runs, so\n // this arm is belt-and-braces rather than the primary guard.\n if (kind === \"block\") return { admitted: true, reported: false };\n // Provenance is resolver-set, so an absent or unrecognised kind means\n // a hand-built `ResolvedTool` from outside the type contract. Deny it\n // rather than dereferencing undefined and taking down the dispatch:\n // an allowlist cannot admit what it cannot classify. `reported` stays\n // false so the caller's denial line names the tool.\n //\n // Callers that report a reason are expected to classify first, so\n // they can distinguish this from a rule deciding against the tool;\n // `applyToolPolicy` does. This stays as the module's own guarantee,\n // so `policiesAdmit` is safe to call with an unchecked descriptor.\n if (!isGovernableToolKind(kind)) {\n return { admitted: false, reported: false };\n }\n for (const policy of policies) {\n // The rule is typed for its own kind, so it declares a narrower\n // descriptor than the wide one this function holds. The narrowing is\n // real: `kind` was read off `tool.source`, so the descriptor being\n // passed IS of that kind. TypeScript cannot see that link through\n // the index access, and function parameters are contravariant, so\n // the two-step cast is the honest way to state it. This is the only\n // cast in the policy path and it sits one line below the check that\n // justifies it.\n const rule = policy[kind] as unknown as AgentToolRule | undefined;\n const verdict = ruleAdmits(rule, tool, ctx, onRuleError);\n if (!verdict.admitted) return verdict;\n }\n return { admitted: true, reported: false };\n}\n","import {\n getExchangeContext,\n getExchangeRoute,\n rcError,\n type CraftContext,\n type Enricher,\n type Exchange,\n type Principal,\n} from \"@routecraft/routecraft\";\nimport { BLOCK_RESERVED_PREFIX, resolveBlocks } from \"../block/resolve.ts\";\nimport type { BlockBody, Blocks } from \"../block/types.ts\";\nimport { resolveModel, resolvePrompt } from \"../llm/shared.ts\";\nimport {\n AgentSession,\n buildUserPrompt,\n dispatchIdentityFrom,\n type AgentDispatchIdentity,\n} from \"./session.ts\";\nimport {\n ADAPTER_AGENT_DEFAULT_OPTIONS,\n ADAPTER_AGENT_REGISTRY,\n ADAPTER_AGENT_TOOL_POLICIES,\n} from \"./store.ts\";\nimport { isGovernableToolKind, policiesAdmit } from \"./tools/policy.ts\";\nimport type {\n AgentToolDescriptor,\n AgentToolPolicyContext,\n AgentToolSource,\n} from \"./tools/policy.ts\";\nimport type { AgentDeltaListener } from \"./events.ts\";\nimport type { ResolvedTool } from \"./tools/selection.ts\";\nimport type {\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 enricher 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}.\n *\n * Fetch-only: an agent run PRODUCES a value, so it fills the `fetch` slot and\n * implements no `send`. The resulting `AgentResult { text, output?,\n * reasoning?, usage? }` becomes the body in `.to()` / bare `.enrich()`, feeds\n * the aggregator in `.enrich(x, agg)`, and is discarded by `.tap()`.\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 AgentEnricherAdapter implements Enricher<unknown, AgentResult> {\n readonly adapterId = \"routecraft.adapter.agent\";\n\n constructor(public readonly binding: AgentBinding) {}\n\n async fetch(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 const model = merged.model;\n\n const { config, modelName } = resolveModel(model, context);\n // Registered agents carry their own id (used to attribute runs in\n // observability, and to name the agent in a tool-policy denial);\n // inline agents are identified by their route, so agentName stays\n // undefined and the consumer falls back to routeId.\n const agentName =\n this.binding.kind === \"by-name\" ? this.binding.name : undefined;\n // Resolved before tools so a tool-policy denial can be emitted as an\n // exchange-scoped event, not just logged.\n const route = getExchangeRoute(exchange);\n const dispatchIdentity = dispatchIdentityFrom(\n exchange,\n route?.definition.id,\n );\n const userTools = resolveAgentTools(\n merged,\n context,\n agentName,\n dispatchIdentity,\n );\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 { systemAppend, loaderTools } = await resolveBlocks(\n merged.blocks,\n exchange,\n context,\n );\n const tools = mergeUserAndLoaderTools(userTools, loaderTools);\n const withBlocks = `${baseSystem}${systemAppend}`;\n // Caller identity is appended last (after blocks) so the author's own\n // prompt and any block 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 withBlocks,\n merged.principal,\n exchange.principal,\n exchange,\n );\n\n const session = new AgentSession({\n options: merged,\n modelConfig: config,\n modelName,\n model,\n ...(agentName !== undefined && { agentName }),\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(ADAPTER_AGENT_REGISTRY);\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(ADAPTER_AGENT_DEFAULT_OPTIONS);\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 if (defaults.blocks !== undefined) {\n out.blocks = mergeBlocks(defaults.blocks, base.blocks);\n }\n return out;\n}\n\n/**\n * Merge default blocks with the agent's own. The per-agent record is\n * applied on top of the defaults by name: a key in both records picks\n * the per-agent body (overrides only that entry); non-colliding\n * defaults still apply; per-agent keys with new names extend the\n * record. A per-agent value of `false` removes the matching default;\n * a `false` for a name absent from defaults is a no-op so adding or\n * removing defaults later cannot break the agent definition.\n *\n * Insertion order is preserved by walking defaults first, then any\n * per-agent keys that didn't override a default. Inject blocks appear\n * in the system prompt in this order, which matters because the model\n * is sensitive to earlier system-prompt content.\n *\n * Merge is by top-level name only. When a name's value is a nested\n * group, a per-agent entry replaces the whole group (not a per-member\n * merge), and `false` removes the whole group. Per-member merge inside\n * a group is intentionally unsupported; see the agentPlugin reference.\n *\n * @internal\n */\nfunction mergeBlocks(\n defaults: { [name: string]: BlockBody | Blocks },\n agent: Blocks | undefined,\n): Blocks {\n // Null-prototype accumulator so a block name like `__proto__` cannot\n // mutate Object.prototype via `out[name] = body`. Block-name validation\n // (validateBlocks / validatePluginDefaults) already rejects the\n // reserved `_block_` prefix and empty strings, but `__proto__` is\n // outside both rules, so this is defence-in-depth.\n const out = Object.create(null) as Blocks;\n if (!agent) {\n for (const [name, body] of Object.entries(defaults)) out[name] = body;\n return out;\n }\n for (const [name, body] of Object.entries(defaults)) {\n if (Object.prototype.hasOwnProperty.call(agent, name)) {\n const override = agent[name];\n // `false` removes the default for this agent; an undefined value\n // shouldn't reach here under the Blocks type, but guard anyway.\n if (override === false || override === undefined) continue;\n out[name] = override;\n } else {\n out[name] = body;\n }\n }\n for (const [name, body] of Object.entries(agent)) {\n if (Object.prototype.hasOwnProperty.call(out, name)) continue;\n if (body === false) continue;\n out[name] = body;\n }\n return out;\n}\n\n/**\n * Merge user tools (from `tools([...])`) with synthetic block-loader\n * tools produced by {@link resolveBlocks}. Rejects (AI1002) any user\n * tool whose resolved name starts with the reserved `_block_` prefix,\n * so a misconfigured registry cannot shadow the framework's surface.\n *\n * @internal\n */\nfunction mergeUserAndLoaderTools(\n userTools: ResolvedTool[],\n loaderTools: ResolvedTool[],\n): ResolvedTool[] {\n for (const tool of userTools) {\n if (tool.name.startsWith(BLOCK_RESERVED_PREFIX)) {\n throw rcError(\"AI1002\", undefined, {\n message: `Agent tool \"${tool.name}\": names starting with \"${BLOCK_RESERVED_PREFIX}\" are reserved for synthetic block tools. Rename the fn or route.`,\n });\n }\n }\n return [...userTools, ...loaderTools];\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 agentId: string | undefined,\n dispatchIdentity: AgentDispatchIdentity | 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 applyToolPolicy(\n options.tools.resolve(context),\n context,\n agentId,\n dispatchIdentity,\n );\n}\n\n/**\n * Filter a resolved tool list through every `agentPlugin({ toolPolicy })`\n * installed on the context.\n *\n * This runs at the single point both agent forms converge on. Inline\n * options and by-name registry lookups (which is what a markdown agent\n * becomes) both arrive here through `resolveOptions`, and a nested\n * agent dispatched from inside a route re-enters the same\n * `AgentDestinationAdapter.send`. Enforcement is therefore total by\n * construction rather than by discipline, and stays that way for any\n * future agent form routed through this destination.\n *\n * A denied tool is dropped and logged at warn, not thrown. A silent\n * drop would be undiagnosable when a model starts claiming it cannot do\n * something; a throw would turn tightening a policy into an outage for\n * every agent that happened to list the tool.\n *\n * @internal\n */\nfunction applyToolPolicy(\n resolved: ResolvedTool[],\n context: CraftContext,\n agentId: string | undefined,\n dispatchIdentity: AgentDispatchIdentity | undefined,\n): ResolvedTool[] {\n const policies = context.getStore(ADAPTER_AGENT_TOOL_POLICIES);\n if (!policies || policies.length === 0) return resolved;\n const policyContext: AgentToolPolicyContext = { agentId };\n const admitted: ResolvedTool[] = [];\n // A denial is a decision, so it goes on the bus as well as into the\n // log. Alerting on \"a tool was silently dropped from an agent\" needs\n // something queryable; a log line is not that.\n //\n // `toolKind` is passed in rather than read off the tool, so it is\n // always a kind the policy surface defines. An unclassifiable tool\n // reports `\"unknown\"`: its raw `source.kind` is whatever a caller\n // outside the type contract put there, so echoing it would hand an\n // audit consumer an unbounded set of kind values that look\n // authoritative while carrying nothing the `reason` does not already\n // say. It also keeps this off the raw `source`, which the\n // unknown-provenance path has deliberately not dereferenced.\n const emitDenied = (\n tool: ResolvedTool,\n reason: \"rule\" | \"rule-error\" | \"unknown-provenance\",\n toolKind: string,\n ): void => {\n if (!dispatchIdentity) return;\n context.emit(\"route:agent:tool:denied\", {\n routeId: dispatchIdentity.routeId,\n exchangeId: dispatchIdentity.exchangeId,\n correlationId: dispatchIdentity.correlationId,\n ...(agentId !== undefined && { agentName: agentId }),\n toolName: tool.name,\n toolKind,\n reason,\n });\n };\n // A predicate that throws is a bug in the policy, not a verdict, so\n // it is reported at error level. The tool is still denied rather than\n // letting the throw abort the dispatch; see `ruleAdmits`.\n const onRuleError = (tool: AgentToolDescriptor, cause: unknown): void => {\n context.logger.error(\n {\n agent: agentId ?? \"<inline>\",\n tool: tool.name,\n kind: tool.source.kind,\n err: cause,\n },\n // Boundary convention: the thrown message is the log message, with\n // a boundary-specific fallback when the predicate threw something\n // that carries none (it may throw any value at all).\n messageOf(cause) ??\n \"Agent tool policy predicate threw; denying the tool. Fix the predicate in agentPlugin({ toolPolicy })\",\n );\n };\n for (const tool of resolved) {\n // Classified before the descriptor is built, because building one\n // reads `tool.source` and a malformed tool would throw there,\n // aborting the dispatch. That is the opposite of failing closed,\n // and it would make the `unknown-provenance` arm inside\n // `policiesAdmit` unreachable for the case it exists to handle.\n const descriptor = toDescriptor(tool);\n if (descriptor === undefined) {\n emitDenied(tool, \"unknown-provenance\", \"unknown\");\n context.logger.warn(\n { agent: agentId ?? \"<inline>\", tool: tool.name, kind: \"unknown\" },\n \"Agent tool carries no recognisable resolver-set provenance, so no policy can classify it; dropping it from the agent's tool list\",\n );\n continue;\n }\n const verdict = policiesAdmit(\n policies,\n descriptor,\n policyContext,\n onRuleError,\n );\n if (verdict.admitted) {\n admitted.push(tool);\n continue;\n }\n emitDenied(\n tool,\n verdict.reported ? \"rule-error\" : \"rule\",\n descriptor.source.kind,\n );\n // A denial already reported through `onRuleError` has been logged at\n // error level with its cause. Repeating it at warn would say less\n // about the same tool and the same outcome, and would bury the line\n // that actually explains what went wrong.\n if (verdict.reported) continue;\n context.logger.warn(\n {\n agent: agentId ?? \"<inline>\",\n tool: tool.name,\n kind: descriptor.source.kind,\n },\n \"Agent tool denied by agentPlugin({ toolPolicy }) and dropped from the agent's tool list\",\n );\n }\n return admitted;\n}\n\n/**\n * Pull a log message out of a thrown value, preferring a\n * `RoutecraftError`'s `meta.message` over the plain `message`, per the\n * boundary convention in `.standards/error-and-logging-policy.md`.\n * Returns undefined when the value carries no usable message, since a\n * predicate may throw anything.\n *\n * @internal\n */\nfunction messageOf(cause: unknown): string | undefined {\n if (typeof cause !== \"object\" || cause === null) return undefined;\n // A predicate may throw anything, including an object whose `meta` or\n // `message` is a getter that itself throws. Reading it must not be\n // able to abort the dispatch the surrounding catch exists to protect.\n try {\n const meta = (cause as { meta?: { message?: unknown } }).meta;\n if (typeof meta?.message === \"string\" && meta.message !== \"\") {\n return meta.message;\n }\n const message = (cause as { message?: unknown }).message;\n return typeof message === \"string\" && message !== \"\" ? message : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Narrow a `ResolvedTool` to the read-only view policy rules receive.\n * Drops `handler` so a rule cannot wrap or invoke the tool it is\n * deciding about, and normalises absent tags to an empty array so\n * predicates can call `.includes` without a guard.\n *\n * Copied and frozen, following the same convention `buildCatalog` uses\n * for the `tools((catalog) => ...)` builder and `snapshotCapability`\n * uses for the capability registry. Without it, `tags` for a fn tool is\n * the array held in the fn registry and `source.annotations` is the\n * object the MCP client refresh wrote, so a predicate assigning a\n * default (`annotations.destructiveHint ??= true` is the plausible\n * accident) would rewrite shared registry state seen by every later\n * policy, every later dispatch, and the MCP server's own `tools/list`.\n * The `readonly` modifiers are compile-time only and do not stop it.\n *\n * @internal\n */\nfunction toDescriptor(tool: ResolvedTool): AgentToolDescriptor | undefined {\n // `source` is resolver-set, so a tool without a recognisable one came\n // from outside the type contract (a hand-built `ResolvedTool`, or one\n // written against 0.5 typings). Report that as unclassifiable rather\n // than dereferencing into a TypeError: an allowlist cannot admit what\n // it cannot classify, and crashing here would take down the dispatch\n // the policy is supposed to be quietly narrowing.\n //\n // An absent `kind` and an unrecognised one are the same defect and\n // get the same answer. Accepting `{ kind: \"bogus\" }` here would still\n // deny the tool, one layer down in `policiesAdmit`, but as an\n // ordinary rule denial: the caller would then report reason `rule`\n // and log that a policy decided against a tool no policy ever saw.\n //\n // `block` is not governable but IS resolver-set, so it is classified\n // rather than rejected; `policiesAdmit` exempts it.\n const kind = (tool.source as AgentToolSource | undefined)?.kind;\n if (kind !== \"block\" && !isGovernableToolKind(kind)) return undefined;\n // The annotations copy is frozen too, not just `source`. One\n // descriptor is built per tool and handed to every composed policy in\n // turn, so a mutable nested object would let the first predicate\n // change what the second one sees, making an AND composition depend\n // on the order its policies happen to be installed in.\n const source =\n tool.source.kind === \"mcp\" && tool.source.annotations\n ? {\n ...tool.source,\n annotations: Object.freeze({ ...tool.source.annotations }),\n }\n : { ...tool.source };\n return Object.freeze({\n name: tool.name,\n description: tool.description,\n tags: Object.freeze(tool.tags ? [...tool.tags] : []),\n source: Object.freeze(source),\n }) as AgentToolDescriptor;\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 type { CraftContext } 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`). Surfaced in error messages so authors can find the\n * offending registration when resolution fails.\n */\n readonly targetId: string;\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 CraftClient,\n HeadersKeys,\n isAuthentic,\n markAuthentic,\n rcError,\n type Capability,\n type CraftContext,\n type KnownTag,\n type Principal,\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 `description` and `input` may be overridden. Guards are policy\n * and live at the consumer (attach them in `tools([{ name, guard }])`\n * at the agent's call site). Tags were previously overridable to\n * influence the removed tag-based selector; without that selector the\n * override has no effect at runtime, so the field is gone.\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\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 * `description` or `input` 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 * }),\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 return {\n [DEFERRED_FN_BRAND]: true,\n kind: \"direct\",\n targetId: routeId,\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 = 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\nfunction readDirectRoute(\n ctx: CraftContext,\n routeId: string,\n fnId: string,\n): Capability {\n const capabilities = ctx.capabilities();\n const route = capabilities.find((c) => c.endpoint === routeId);\n if (!route) {\n const known = capabilities.map((c) => c.endpoint).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 // 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 return new CraftClient(ctx).sendDirect(\n routeId,\n input,\n Object.keys(headers).length > 0 ? headers : undefined,\n );\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 { rcError, type CraftContext, type Tag } from \"@routecraft/routecraft\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { ADAPTER_FN_REGISTRY } from \"../../fn/store.ts\";\nimport type { FnOptions, ToolGuard } 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\";\nimport {\n describeToolNameViolation,\n isSplittableNameHead,\n TOOL_NAME_PATTERN_SOURCE,\n TOOL_NAME_SEPARATOR,\n} from \"../../tool-name.ts\";\nimport type { AgentToolSource } from \"./policy.ts\";\n\n/**\n * Wire-form prefix for a direct capability exposed as an agent tool.\n * `Direct(<routeId>)` is the authoring grammar; `direct__<routeId>` is\n * what the model sees, because a tool name cannot carry parentheses.\n *\n * `__` is the structural separator throughout (see\n * {@link TOOL_NAME_SEPARATOR}), so a route id containing a single\n * underscore stays unambiguous against the prefix boundary.\n *\n * @internal\n */\nexport const DIRECT_TOOL_PREFIX = `direct${TOOL_NAME_SEPARATOR}`;\n\n/**\n * Wire-form prefix for an external MCP client tool. Already used the\n * `__` separator before the rest of the surface was normalised onto it,\n * and matches the `mcp__<server>__<tool>` names Claude Code agent files\n * carry, so those files resolve unchanged.\n *\n * @internal\n */\nexport const MCP_TOOL_PREFIX = `mcp${TOOL_NAME_SEPARATOR}`;\n\n/**\n * Reject a `Direct(<routeId>)` reference whose route id cannot survive\n * as a provider-facing tool name.\n *\n * Route ids are deliberately unconstrained in core: `memory:get` and\n * `orders/cancel` are legitimate and are used as such by\n * `CraftClient.sendDirect` and `BlockClient.forward`. Only the agent\n * tool surface has to satisfy the provider charset, so the constraint\n * is enforced here, at the point of exposure, rather than pushed back\n * onto every route id in the codebase.\n *\n * We reject rather than transliterate on purpose. Any encoding that\n * maps the full route-id space into `[A-Za-z0-9_-]` produces names the\n * model has to read (`direct__memory_x3A_get`), and tool names are part\n * of the prompt: degrading them degrades tool selection. Rejecting\n * keeps every generated name legible and leaves the developer with the\n * better escape hatch, which already exists and is named in the error:\n * register the route under a clean fn id with `directTool(routeId)`.\n *\n * @internal\n */\nfunction assertValidDirectToolName(\n ref: string,\n routeId: string,\n toolName: string,\n): void {\n const violation = describeToolNameViolation(toolName);\n if (violation === undefined) return;\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): \"${ref}\" resolves to the tool name \"${toolName}\", which the model provider will reject: ${violation}.`,\n suggestion:\n `Route ids are unconstrained, but tool names must match ${TOOL_NAME_PATTERN_SOURCE}. ` +\n `Expose this route under a tool-safe name instead: ` +\n `agentPlugin({ functions: { yourToolName: directTool(\"${routeId}\") } }), ` +\n `then reference \"yourToolName\" in tools([...]).`,\n });\n}\n\n/**\n * Re-exported from `fn/types.ts`, where the guard type lives so both the\n * agent tool bridge and the MCP proxy (`mcpPlugin({ proxy })`) share one\n * guard contract. Kept here so existing imports keep working.\n */\nexport type { ToolGuard } from \"../../fn/types.ts\";\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 */\nexport type ToolsItem =\n string | { name: string; guard?: ToolGuard; description?: string };\n\n/**\n * Read-only snapshot of every tool registered in the live context,\n * handed to the function form of `tools()`. Lets a builder filter or\n * compose a list without baking selector languages into the framework\n * (a \"give me all read-only fns\" predicate is the user's `.filter()`\n * call, not a framework-blessed primitive).\n *\n * Walking the snapshot is the explicit, code-visible way to extend an\n * agent's tool surface across registrations: a future fn whose tags\n * match the predicate will silently extend the surface the next time\n * `resolve()` runs. The function form makes that visible at the call\n * site, where a `.filter()` is the obvious signal that the set is\n * dynamic.\n */\nexport interface ToolsCatalog {\n /**\n * Plain fn entries from `agentPlugin({ functions })`. Deferred\n * wrappers (e.g. `directTool(routeId)`) appear here too with their\n * canonical name and the override tags supplied at builder time.\n */\n readonly fns: ReadonlyArray<{\n readonly name: string;\n readonly description?: string;\n readonly tags?: readonly Tag[];\n }>;\n /**\n * Discoverable direct routes (see `CraftContext.capabilities()`).\n * Reference them in a `ToolsItem` as `\"Direct(<id>)\"`.\n */\n readonly routes: ReadonlyArray<{\n readonly id: string;\n readonly description?: string;\n readonly tags?: readonly Tag[];\n }>;\n /**\n * MCP tools populated by `mcpPlugin({ clients })`. Reference them in\n * a `ToolsItem` as `\"MCP(<server>:<tool>)\"` or\n * `\"mcp__<server>__<tool>\"`.\n */\n readonly mcp: ReadonlyArray<{\n readonly server: string;\n readonly tool: string;\n readonly description?: string;\n readonly tags?: readonly Tag[];\n }>;\n}\n\n/**\n * Builder form of `tools()`. Receives a snapshot of the registered\n * tools and returns the list of references to expose. Same return\n * shape as the array form, so the rest of resolution is identical.\n */\nexport type ToolsBuilder = (catalog: ToolsCatalog) => ToolsItem[];\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).\n *\n * One deliberate exception: an MCP client tool whose composed wire\n * name is unusable is DROPPED with a warning rather than thrown, even\n * when named explicitly. The remote owns that name, and resolution\n * runs per dispatch, so throwing would turn a remote renaming a tool\n * into a live route outage instead of a startup error. See\n * {@link resolveMcpRefs}.\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 capabilities, 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 /**\n * Where this tool came from. Set by the resolver, never by user\n * config, so `agentPlugin({ toolPolicy })` can treat it as trusted\n * provenance when deciding admission.\n */\n source: AgentToolSource;\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.\n *\n * Two forms:\n *\n * - **Array**: `tools([...])` -- explicit enumeration of references.\n * Resolution happens lazily at agent dispatch time. Items are bare\n * strings or `{ name, guard?, description? }` objects.\n * - **Builder**: `tools((catalog) => [...])` -- programmatic selection.\n * Receives a snapshot of the live fn / route / MCP registries and\n * returns the same shape the array form accepts. Use this as the\n * escape hatch when explicit enumeration is impractical (e.g. \"give\n * me every read-only fn\"); the predicate lives in your code so the\n * implicit-extension behaviour is visible at the call site.\n *\n * Resolution rules:\n *\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 becomes `direct__<routeId>`).\n * `MCP(server:tool)` / `MCP(server)` and the raw `mcp__server__tool`\n * / `mcp__server` / `mcp__server__*` forms resolve against\n * `MCP_TOOL_REGISTRY`.\n *\n * Two grammars, deliberately distinct. `Direct(<routeId>)` and\n * `MCP(server:tool)` are what a developer writes, here and in markdown\n * agent frontmatter. `direct__<routeId>` and `mcp__<server>__<tool>`\n * are the wire names the model sees, because tool names carry neither\n * parentheses nor colons. Normalisation happens at resolution; nothing\n * outside this module should construct a wire name by hand.\n * - Final list is deduplicated by tool name; later refs to the same\n * name win (so a user's builder can override a tag-derived entry\n * simply by listing it explicitly).\n *\n * @example Array form\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 * ]),\n * });\n * ```\n *\n * @example Builder form\n * ```ts\n * agent({\n * tools: tools((catalog) => [\n * \"fetchOrder\",\n * ...catalog.fns\n * .filter((f) => f.tags?.includes(\"read-only\"))\n * .map((f) => f.name),\n * ]),\n * });\n * ```\n */\nexport function tools(items: ToolsItem[]): ToolSelection;\nexport function tools(builder: ToolsBuilder): ToolSelection;\nexport function tools(arg: ToolsItem[] | ToolsBuilder): ToolSelection {\n if (typeof arg !== \"function\" && !Array.isArray(arg)) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): argument must be an array of ToolsItem or a (catalog) => ToolsItem[] builder.`,\n });\n }\n return {\n [TOOL_SELECTION_BRAND]: true,\n resolve(ctx) {\n const items =\n typeof arg === \"function\" ? runBuilder(arg, buildCatalog(ctx)) : arg;\n const out = new Map<string, ResolvedTool>();\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 out.set(tool.name, tool);\n }\n continue;\n }\n const tool = resolveByName(ctx, item, undefined);\n out.set(tool.name, tool);\n continue;\n }\n if (item === null || typeof item !== \"object\" || !(\"name\" in item)) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): each item must be a string or { name, guard?, description? }.`,\n });\n }\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 out.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 out.set(tool.name, tool);\n }\n return [...out.values()];\n },\n };\n}\n\n/**\n * Build a {@link ToolsCatalog} snapshot from the live context's\n * registries. Each entry and its `tags` array are frozen so the\n * interface's `readonly` modifiers match runtime behaviour: a builder\n * cannot mutate an entry's name / description / tags in place and have\n * it silently affect the rest of resolution. Freeze cost is negligible\n * for a per-dispatch snapshot of a handful of registry entries.\n *\n * @internal\n */\nfunction buildCatalog(ctx: CraftContext): ToolsCatalog {\n const fns: ToolsCatalog[\"fns\"][number][] = [];\n const fnRegistry = ctx.getStore(ADAPTER_FN_REGISTRY) as\n Map<string, FnEntry> | undefined;\n if (fnRegistry) {\n for (const [name, entry] of fnRegistry) {\n if (isDeferredFn(entry)) {\n // Deferred wrappers don't carry their own description/tags in\n // the registry; users who want to filter on those should walk\n // catalog.routes for the underlying route, then reference it\n // as `Direct(<routeId>)` in the returned items list.\n fns.push(Object.freeze({ name }));\n } else {\n const tags =\n entry.tags && entry.tags.length > 0\n ? Object.freeze([...entry.tags])\n : undefined;\n fns.push(\n Object.freeze({\n name,\n description: entry.description,\n ...(tags !== undefined ? { tags } : {}),\n }),\n );\n }\n }\n }\n\n const routes: ToolsCatalog[\"routes\"][number][] = [];\n // `capabilities()` already speaks raw route ids (it decodes the\n // sanitised registry keys), so a builder that does `Direct(${r.id})`\n // resolves cleanly for ids containing `/`, `:`, etc.\n for (const meta of ctx.capabilities()) {\n const tags =\n meta.tags && meta.tags.length > 0\n ? Object.freeze([...meta.tags])\n : undefined;\n routes.push(\n Object.freeze({\n id: meta.endpoint,\n ...(meta.description ? { description: meta.description } : {}),\n ...(tags !== undefined ? { tags } : {}),\n }),\n );\n }\n\n const mcp: ToolsCatalog[\"mcp\"][number][] = [];\n const mcpRegistry = ctx.getStore(MCP_TOOL_REGISTRY);\n if (mcpRegistry) {\n for (const entry of mcpRegistry.getTools()) {\n const tags =\n entry.tags && entry.tags.length > 0\n ? Object.freeze([...entry.tags])\n : undefined;\n mcp.push(\n Object.freeze({\n server: entry.source,\n tool: entry.name,\n ...(entry.description ? { description: entry.description } : {}),\n ...(tags !== undefined ? { tags } : {}),\n }),\n );\n }\n }\n\n return Object.freeze({\n fns: Object.freeze(fns),\n routes: Object.freeze(routes),\n mcp: Object.freeze(mcp),\n });\n}\n\n/**\n * Invoke a user-supplied tools builder safely and surface failures as\n * RC5003 with the original error chained. Validates that the return\n * is an array so a confused builder doesn't silently produce nothing.\n *\n * @internal\n */\nfunction runBuilder(builder: ToolsBuilder, catalog: ToolsCatalog): ToolsItem[] {\n let items: unknown;\n try {\n items = builder(catalog);\n } catch (cause) {\n throw rcError(\"RC5003\", cause, {\n message: `tools(builder): builder threw: ${(cause as Error)?.message ?? String(cause)}`,\n });\n }\n if (!Array.isArray(items)) {\n throw rcError(\"RC5003\", undefined, {\n message: `tools(builder): builder must return an array of ToolsItem (got ${typeof items}).`,\n });\n }\n return items as ToolsItem[];\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> | 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> | 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 is the `direct__<routeId>` wire 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_TOOL_PREFIX}${routeId}`;\n assertValidDirectToolName(name, routeId, toolName);\n const wrapper = directTool(routeId);\n const fn = wrapper.resolve(ctx, toolName);\n return toResolvedTool(toolName, fn, guard, { kind: \"direct\", routeId });\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 // Derived from `entry.kind`, never asserted. `isDeferredFn` is a\n // brand check only, so hardcoding \"direct\" here would silently\n // classify a future deferred kind (a sub-agent tool is the named\n // candidate) as a capability, admitting it under any policy that\n // sets `direct: true`. The exhaustive default turns adding a kind\n // into a compile error, which is the whole point of the allowlist\n // narrowing rather than widening.\n switch (entry.kind) {\n case \"direct\":\n // A `directTool(routeId)` registered under a fn id is still a\n // capability: it reaches the same route, only under a different\n // name. Reporting it as `fn` would let an alias slip past a\n // policy that denies `direct`.\n return toResolvedTool(name, fn, guard, {\n kind: \"direct\",\n routeId: entry.targetId,\n });\n default: {\n const exhaustive: never = entry.kind;\n throw rcError(\"RC5003\", undefined, {\n message: `tools(): fn \"${name}\" has an unsupported deferred kind \"${String(exhaustive)}\", so it carries no tool-policy provenance and cannot be resolved.`,\n });\n }\n }\n }\n return toResolvedTool(name, entry, guard, { kind: \"fn\", id: name });\n}\n\nfunction toResolvedTool(\n name: string,\n fn: FnOptions,\n guard: ToolGuard | undefined,\n source: AgentToolSource,\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 source,\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_TOOL_PREFIX)) 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_TOOL_PREFIX)) {\n const rest = ref.slice(MCP_TOOL_PREFIX.length);\n const sep = rest.indexOf(TOOL_NAME_SEPARATOR);\n const clientName = sep === -1 ? rest : rest.slice(0, sep);\n const toolName =\n sep === -1 ? \"*\" : rest.slice(sep + TOOL_NAME_SEPARATOR.length);\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 * Does NOT throw when a registered tool's composed wire name is\n * unusable: that tool is dropped with a warning, on both the wildcard\n * and the explicit-reference path. The name comes from the remote\n * rather than from this repository, and `resolve` runs per dispatch, so\n * a throw would let a remote rename take down every dispatch of every\n * agent bound to that server. Uniform dropping also keeps the two paths\n * behaving the same, which is easier to reason about than a rule that\n * depends on how the tool happened to be referenced. The warning is\n * emitted once per registry version rather than once per dispatch.\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\n .map((entry) => mcpEntryToResolvedTool(ctx, registry, entry, guard))\n .filter((tool): tool is ResolvedTool => tool !== undefined);\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 const resolved = mcpEntryToResolvedTool(ctx, registry, entry, guard);\n return resolved === undefined ? [] : [resolved];\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 registry: McpToolRegistry,\n entry: McpToolRegistryEntry,\n guard: ToolGuard | undefined,\n): ResolvedTool | undefined {\n // Both name problems below are properties of the registered tool, not\n // of the dispatch being served, and `resolve()` runs per dispatch.\n // Reporting them through the registry's once-per-version gate keeps a\n // permanently broken remote tool from logging on every call of every\n // agent bound to that server, while still re-reporting it if it is\n // still broken after the registry refreshes. Same shape as the MCP\n // server's `warnProxyOnce` for the same registry entries.\n const dropOnce = (\n key: string,\n obj: Record<string, unknown>,\n message: string,\n ): undefined => {\n if (registry.shouldReport(key)) ctx.logger.warn(obj, message);\n return undefined;\n };\n // A client name containing `__` makes the wire name unparseable.\n // `parseMcpRef` splits at the FIRST separator after the prefix, so a\n // server called `a__b` exposing `c` generates `mcp__a__b__c`, which\n // reads back as server `a` with tool `b__c`: a valid-looking name\n // that resolves to the wrong thing, or to nothing.\n //\n // Constraining the server rather than the tool is what makes the\n // grammar unambiguous, and it is the half we own: client names are\n // chosen locally in `mcpPlugin({ clients })`, while tool names come\n // from the remote. With no `__` in the server, the first-separator\n // split is always correct and a remote may use `__` in its tool\n // names freely.\n //\n // A server ending in a single `_` fails the same way: joining `foo_`\n // to a tool with `__` yields `mcp__foo___bar`, whose first separator\n // sits a character early. That case also collides, since `foo_` +\n // `bar` and `foo` + `_bar` compose one name and this map is keyed by\n // it. `mcpPlugin` rejects those shapes at registration; this stays\n // for a registry populated directly, and shares the predicate so the\n // two layers cannot disagree about what they reject.\n //\n // The predicate also rejects an empty head, which cannot arrive here:\n // `parseMcpRef` throws on an empty server segment, and every entry\n // reaching this function came from `getToolsByServer(clientName)` for\n // that already-validated name. It is reachable at the registration\n // site, which is where it earns its place.\n if (!isSplittableNameHead(entry.source)) {\n // Keyed by server alone: every tool on it is dropped for the same\n // reason, so one line names the fix rather than one line per tool.\n return dropOnce(\n `mcp-server-separator:${entry.source}`,\n { server: entry.source },\n `MCP client name is empty, contains \"${TOOL_NAME_SEPARATOR}\", or ends with \"_\", which makes the generated tool name ambiguous to parse and able to collide with another client; dropping its tools from the agent's tool list. Rename the client in mcpPlugin({ clients }).`,\n );\n }\n const name = `${MCP_TOOL_PREFIX}${entry.source}${TOOL_NAME_SEPARATOR}${entry.name}`;\n // The remote names its own tools, so this is the one composed name\n // built from input nobody in this repository authored. An unusable\n // name is dropped with a warning rather than thrown, matching what\n // the MCP proxy already does for the same registry entries\n // (`mcp/proxy.ts`): a throw here would let one malformed remote tool\n // fail every dispatch of every agent bound to that server, and\n // because `resolve()` runs per dispatch, a remote renaming a tool\n // would become a live route outage rather than a startup error.\n const violation = describeToolNameViolation(name);\n if (violation !== undefined) {\n return dropOnce(\n `mcp-tool-name:${name}`,\n { server: entry.source, tool: entry.name, toolName: name },\n `MCP tool name is not usable as a provider tool name (${violation}); dropping it from the agent's tool list. Expose it through a capability under a tool-safe name if the agent needs it.`,\n );\n }\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 // Raw annotations ride along beside the derived tags. `tags` cannot\n // distinguish \"the server declared this safe\" from \"the server said\n // nothing\", because tag derivation only fires on a truthy hint, and\n // the MCP defaults for an absent hint are not uniformly false.\n source: {\n kind: \"mcp\",\n server: entry.source,\n tool: entry.name,\n ...(entry.annotations ? { annotations: entry.annotations } : {}),\n },\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\nfunction listKnownNames(ctx: CraftContext): string[] {\n const fnNames = [\n ...(ctx.getStore(ADAPTER_FN_REGISTRY) ?? new Map<string, FnEntry>()).keys(),\n ];\n const routeNames = ctx.capabilities().map((c) => `Direct(${c.endpoint})`);\n return [...fnNames, ...routeNames].sort();\n}\n","import {\n type Enricher,\n factoryArgs,\n rcError,\n tagAdapter,\n} from \"@routecraft/routecraft\";\nimport {\n BLOCK_LOADER_PREFIX,\n BLOCK_NAME_SEPARATOR,\n BLOCK_RESERVED_PREFIX,\n BLOCK_TOOL_NAME_CHARSET,\n blockCollisionError,\n blockCycleError,\n isBlockGroup,\n} from \"../block/resolve.ts\";\nimport { TOOL_NAME_MAX_LENGTH } from \"../tool-name.ts\";\nimport type { BlockBody, Blocks } from \"../block/types.ts\";\nimport { parseProviderModel } from \"../llm/shared.ts\";\nimport { AgentEnricherAdapter, type AgentByNameOverrides } from \"./enricher.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 if (options.blocks !== undefined) {\n validateBlocks(options.blocks);\n }\n}\n\n/**\n * Validate the shape of every entry on an agent's `blocks` record.\n * Throws AI1003 on individual block misconfiguration and AI1002 on\n * reserved-prefix collisions or empty names. Runs at construction so\n * misconfigured blocks surface immediately, not at first dispatch.\n *\n * Duplicate keys are impossible by construction (object literal); a\n * value of `false` is permitted and means \"remove this block from\n * defaults\" -- the validator only checks the body shape for non-`false`\n * entries. Empty-string keys are rejected because they round-trip as\n * an unloadable block name.\n *\n * Exported (`@internal`) so `agentPlugin({ defaultOptions: { blocks } })`\n * can reuse the same checks. Pass `defaultsLabel` from the defaults\n * path: it switches `false` from \"allowed (per-agent removal sentinel)\"\n * to \"rejected with RC5003\" at every nesting level, because defaults\n * cannot sensibly remove themselves, and names the offending entry\n * with that label.\n *\n * Validation is authoritative at construction: alongside the per-leaf\n * structural checks it enforces the flattened-name rules a synthetic\n * loader tool depends on (reserved `_block_` namespace, provider\n * charset and length, no two blocks collapsing to one name) so those\n * surface at `agent()` rather than at the provider on first dispatch.\n *\n * @internal\n */\nexport function validateBlocks(blocks: unknown, defaultsLabel?: string): void {\n const state: BlockValidationState = {\n seenNames: new Set<string>(),\n seenObjects: new WeakSet<object>(),\n // Only set when present: `exactOptionalPropertyTypes` forbids an\n // explicit `undefined` for the optional `defaultsLabel`.\n ...(defaultsLabel !== undefined ? { defaultsLabel } : {}),\n };\n validateBlocksLevel(blocks, \"\", state);\n}\n\ninterface BlockValidationState {\n /** Flattened leaf names seen so far, for collision detection. */\n readonly seenNames: Set<string>;\n /** Groups on the current recursion path, for cycle detection. */\n readonly seenObjects: WeakSet<object>;\n /** Defaults label; when set, `false` is rejected (see {@link validateBlocks}). */\n readonly defaultsLabel?: string;\n}\n\n/**\n * Recursive worker for {@link validateBlocks}. Validates one level of a\n * {@link Blocks} tree, recursing into nested groups. `prefix` carries\n * the flattened-name path (joined by {@link BLOCK_NAME_SEPARATOR}) so\n * error messages name the offending block the way it resolves at\n * dispatch. A record value is a leaf or a nested group per {@link\n * isBlockGroup}.\n *\n * @internal\n */\nfunction validateBlocksLevel(\n blocks: unknown,\n prefix: string,\n state: BlockValidationState,\n): number {\n if (blocks === null || typeof blocks !== \"object\" || Array.isArray(blocks)) {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent: \"blocks\" must be a Record<string, BlockBody | Blocks | false>.`,\n });\n }\n if (state.seenObjects.has(blocks)) throw blockCycleError(prefix);\n state.seenObjects.add(blocks);\n // Count of leaves at this level and below. A nested group that\n // produces zero leaves (empty `{}` or only `false` members) is an\n // author mistake the strict-at-construction contract should surface,\n // so the caller rejects it; the top-level record is allowed to be\n // empty (an agent with no blocks).\n let leafCount = 0;\n for (const [name, body] of Object.entries(blocks as Blocks)) {\n const qualified = prefix ? `${prefix}${BLOCK_NAME_SEPARATOR}${name}` : name;\n if (name.trim() === \"\") {\n throw rcError(\"AI1002\", undefined, {\n message: `Agent block: block name must be a non-empty string.`,\n });\n }\n // Reject reserved-prefix segments and any combination whose\n // flattened name lands in the reserved namespace (e.g. a group\n // \"_block\" with a leaf \"x\" flattens to \"_block__x\").\n if (\n name.startsWith(BLOCK_RESERVED_PREFIX) ||\n qualified.startsWith(BLOCK_RESERVED_PREFIX)\n ) {\n throw rcError(\"AI1002\", undefined, {\n message: `Agent block \"${qualified}\": names starting with \"${BLOCK_RESERVED_PREFIX}\" are reserved for synthetic block tools. Rename the block or a parent group.`,\n });\n }\n if (body === false) {\n if (state.defaultsLabel !== undefined) {\n throw rcError(\"RC5003\", undefined, {\n message:\n `agentPlugin: \"${state.defaultsLabel}.${qualified}\" cannot be false. ` +\n `\"false\" is the per-agent removal sentinel; defaults cannot remove themselves. ` +\n `Drop the entry or replace it with a BlockBody.`,\n });\n }\n continue;\n }\n if (body === null || typeof body !== \"object\") {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": value must be a BlockBody object (with mode and value), a nested Blocks group, or \"false\" to remove a default.`,\n });\n }\n if (isBlockGroup(body)) {\n // A value with no string `mode` is normally a nested group. But a\n // BlockBody-shaped `value` (string or function) is a strong signal\n // the author meant a leaf and forgot or mistyped `mode`; report\n // that precisely instead of recursing and blaming a phantom\n // `<name>__value` block. A real group's members are objects, so\n // this never misfires on a member that merely happens to be named\n // `value`.\n const maybeValue = (body as Partial<BlockBody>).value;\n if (typeof maybeValue === \"string\" || typeof maybeValue === \"function\") {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": \"mode\" must be \"inject\" or \"progressive\" (got ${JSON.stringify((body as Partial<BlockBody>).mode)}).`,\n });\n }\n const childLeaves = validateBlocksLevel(body, qualified, state);\n if (childLeaves === 0) {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": a nested group must contain at least one block (got an empty group or only \"false\" members).`,\n });\n }\n leafCount += childLeaves;\n continue;\n }\n if (state.seenNames.has(qualified)) throw blockCollisionError(qualified);\n state.seenNames.add(qualified);\n leafCount += 1;\n const b = body as BlockBody;\n if (b.mode !== \"inject\" && b.mode !== \"progressive\") {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": \"mode\" must be \"inject\" or \"progressive\" (got ${JSON.stringify(b.mode)}).`,\n });\n }\n if (\n b.mode === \"progressive\" &&\n (typeof b.description !== \"string\" || b.description.trim() === \"\")\n ) {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": progressive-mode blocks require a non-empty \"description\" so the model can decide whether to load.`,\n });\n }\n // Progressive blocks become the synthetic loader tool\n // `_block__load__<flattenedName>`, which the provider constrains to\n // `^[A-Za-z0-9_-]{1,64}$`. Check the flattened name here so an\n // unsafe or over-long name fails at construction, not at the\n // provider on first dispatch.\n if (b.mode === \"progressive\") {\n if (!BLOCK_TOOL_NAME_CHARSET.test(qualified)) {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": a progressive block becomes the loader tool \"${BLOCK_LOADER_PREFIX}${qualified}\", so its flattened name must match ${BLOCK_TOOL_NAME_CHARSET.source} (letters, digits, \"_\", \"-\"). Rename the block or its parent group.`,\n });\n }\n const toolName = `${BLOCK_LOADER_PREFIX}${qualified}`;\n if (toolName.length > TOOL_NAME_MAX_LENGTH) {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": the loader tool name \"${toolName}\" is ${toolName.length} characters, over the provider limit of ${TOOL_NAME_MAX_LENGTH}. Shorten the block name or its parent group.`,\n });\n }\n }\n if (\n b.lifetime !== undefined &&\n b.lifetime !== \"dispatch\" &&\n b.lifetime !== \"context\"\n ) {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": \"lifetime\" must be \"dispatch\" or \"context\" when present (got ${JSON.stringify(b.lifetime)}).`,\n });\n }\n if (typeof b.value !== \"string\" && typeof b.value !== \"function\") {\n throw rcError(\"AI1003\", undefined, {\n message: `Agent block \"${qualified}\": \"value\" must be a string or a function returning a string.`,\n });\n }\n }\n state.seenObjects.delete(blocks);\n return leafCount;\n}\n\n/**\n * Create an agent enricher.\n *\n * An agent run produces a value, so `agent()` fills the `fetch` slot: use it\n * with `.enrich(agent(...))` to merge or replace the body with the\n * `AgentResult`, with `.to(agent(...))` to replace the body outright, or with\n * `.tap(agent(...))` to run it and discard the result.\n *\n * Two forms:\n *\n * - **Inline**: `agent({ model, system, user? })` -- enricher constructed\n * from inline options. Identity and description come from the enclosing\n * route (`.id()`, `.description()`).\n * - **By name**: `agent(\"name\")` -- enricher 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): Enricher<unknown, AgentResult>;\nexport function agent(name: string): Enricher<unknown, AgentResult>;\nexport function agent(\n name: string,\n perCall: AgentByNameOverrides,\n): Enricher<unknown, AgentResult>;\nexport function agent(\n arg: AgentOptions | string,\n perCall?: AgentByNameOverrides,\n): Enricher<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 AgentEnricherAdapter({\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 AgentEnricherAdapter({ 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 type EventName,\n} from \"@routecraft/routecraft\";\nimport { validateAgentOptions, validateBlocks } from \"./agent.ts\";\nimport {\n ADAPTER_AGENT_DEFAULT_OPTIONS,\n ADAPTER_AGENT_REGISTRY,\n ADAPTER_AGENT_TOOL_POLICIES,\n} from \"./store.ts\";\nimport { AGENT_TOOL_POLICY_KINDS } from \"./tools/policy.ts\";\nimport type {\n AgentToolPolicy,\n AgentToolPolicyKind,\n AgentToolRule,\n} from \"./tools/policy.ts\";\nimport { validateFnOptions } from \"../fn/fn.ts\";\nimport { ADAPTER_FN_REGISTRY } from \"../fn/store.ts\";\nimport { parseProviderModel } from \"../llm/shared.ts\";\nimport type { AgentDefaultOptions, AgentRegisteredOptions } from \"./types.ts\";\nimport { isDeferredFn, type FnEntry } from \"./tools/types.ts\";\nimport { isToolSelection } from \"./tools/selection.ts\";\nimport {\n describeToolNameViolation,\n TOOL_NAME_PATTERN_SOURCE,\n} from \"../tool-name.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 * 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 /**\n * Repository-wide admission rules for the agent tool surface.\n *\n * Deliberately NOT part of `defaultOptions`: defaults are per-agent\n * overridable and a policy must not be. An agent's own `tools([...])`\n * selection cannot widen what this admits.\n *\n * Omit it and nothing changes: every tool is admitted, exactly as\n * before. Supply it and it becomes an allowlist in which every kind\n * must be decided: a partial policy is rejected at construction, not\n * quietly treated as denying the kinds you left out. Denied tools are\n * dropped from the agent's list and logged; they never throw.\n *\n * This is admission control, not a security boundary. It converts a\n * failure of omission (a tool name appearing in markdown frontmatter,\n * with no diff signal and nothing to notice) into a failure of\n * commission (someone must author a capability, name it, and write an\n * authorization line a reviewer can read). It does not stop a\n * developer who deliberately wraps a client tool in a capability.\n *\n * @see {@link AgentToolPolicy} for semantics and examples.\n */\n toolPolicy?: AgentToolPolicy;\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 defaultOptions = validatePluginDefaults(options.defaultOptions);\n const toolPolicy = validateToolPolicy(options.toolPolicy);\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(ADAPTER_AGENT_REGISTRY);\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(ADAPTER_AGENT_REGISTRY, agentMap);\n }\n\n const existingFns = ctx.getStore(ADAPTER_FN_REGISTRY);\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 // A fn id IS the tool name the model sees, with no prefix and no\n // encoding in between, so the provider charset applies to it\n // directly. Checking at registration turns what was an opaque\n // provider-side rejection on the first dispatch into a startup\n // error naming the offending id.\n const idViolation = describeToolNameViolation(id);\n if (idViolation !== undefined) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: fn id \"${id}\" is not usable as a tool name: ${idViolation}.`,\n suggestion: `A fn id reaches the model provider verbatim as the tool name, so it must match ${TOOL_NAME_PATTERN_SOURCE}. Rename the fn.`,\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(ADAPTER_FN_REGISTRY, fnMap);\n }\n\n if (defaultOptions !== undefined) {\n const existing = ctx.getStore(ADAPTER_AGENT_DEFAULT_OPTIONS);\n const merged = mergePluginDefaults(existing, defaultOptions);\n ctx.setStore(ADAPTER_AGENT_DEFAULT_OPTIONS, merged);\n }\n\n if (toolPolicy !== undefined) {\n // Appended, never merged. Policies compose with AND at\n // evaluation time, so two installs that disagree narrow rather\n // than conflict, and neither needs to know about the other.\n const existingPolicies = ctx.getStore(ADAPTER_AGENT_TOOL_POLICIES);\n if (existingPolicies) {\n existingPolicies.push(toolPolicy);\n } else {\n ctx.setStore(ADAPTER_AGENT_TOOL_POLICIES, [toolPolicy]);\n }\n }\n\n emitRegistrations(ctx, agents, functions);\n },\n };\n}\n\n/**\n * Announce the agents and fns this plugin install registered, so that\n * generic observability (the telemetry plugin / TUI) can list them even\n * before any of them runs. Inline agents are not announced here: they\n * only exist at dispatch inside a route and surface via their\n * `route:agent:started` event instead.\n *\n * The events fire on `context:started` rather than inside `apply()` so\n * the telemetry plugin has already subscribed regardless of plugin\n * install order (mirroring how `route:*:registered` fires after plugins\n * are applied). When the context is never started there is nothing\n * running to observe, so emitting nothing is correct.\n *\n * @internal\n */\nfunction emitRegistrations(\n ctx: CraftContext,\n agents: Record<string, AgentRegisteredOptions>,\n functions: Record<string, FnEntry>,\n): void {\n const agentEntries = Object.entries(agents);\n const fnEntries = Object.entries(functions);\n if (agentEntries.length === 0 && fnEntries.length === 0) return;\n\n ctx.once(\"context:started\", () => {\n for (const [id, entry] of agentEntries) {\n ctx.emit(\"agent:registered\" as EventName, {\n agentId: id,\n description: entry.description,\n ...(typeof entry.model === \"string\" && { model: entry.model }),\n source: \"registered\",\n });\n }\n for (const [id, entry] of fnEntries) {\n // Deferred fns (e.g. directTool) carry no eager description/tags;\n // they resolve at dispatch and surface via tool-invocation events.\n const eager = isDeferredFn(entry) ? undefined : entry;\n ctx.emit(\"agent:tool:registered\" as EventName, {\n toolName: id,\n ...(eager && { description: eager.description }),\n ...(eager &&\n Array.isArray(eager.tags) &&\n eager.tags.length > 0 && { tags: eager.tags }),\n source: \"registered\",\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 if (raw.blocks !== undefined) {\n // Run the same validation as AgentOptions.blocks (blank names, the\n // reserved `_block_` namespace, provider-unsafe / over-long loader\n // names, flatten collisions, malformed BlockBody values) at plugin\n // construction rather than at agent dispatch. The `defaultsLabel`\n // argument additionally rejects `false` at every nesting level,\n // because defaults are the base layer and cannot remove themselves;\n // the error names the offending entry by its flattened path.\n validateBlocks(raw.blocks, \"defaultOptions.blocks\");\n }\n return raw;\n}\n\n/**\n * Validate the shape of `agentPlugin({ toolPolicy })` at plugin\n * construction. Every entry must be a boolean or a function; anything\n * else is a config mistake that would otherwise surface as a silent\n * denial on the first dispatch (a non-callable rule cannot admit\n * anything), which is exactly the failure mode a policy must not have.\n *\n * An empty object is accepted and is meaningful: it denies every kind,\n * because a present policy is an allowlist.\n *\n * @internal\n */\nfunction validateToolPolicy(\n raw: AgentToolPolicy | undefined,\n): AgentToolPolicy | 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: \"toolPolicy\" must be an object carrying a rule for each of \"fn\" / \"direct\" / \"mcp\".`,\n });\n }\n const known = AGENT_TOOL_POLICY_KINDS;\n const missing = known.filter(\n (k) => !Object.prototype.hasOwnProperty.call(raw, k),\n );\n if (missing.length > 0) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"toolPolicy\" is missing a rule for ${missing.map((k) => `\"${k}\"`).join(\", \")}.`,\n suggestion:\n `A policy is an allowlist, so an unlisted kind is denied. Decide each kind explicitly ` +\n `(\\`true\\`, \\`false\\`, or a predicate) rather than omitting it, so a partial policy cannot ` +\n `silently strip tools you meant to keep.`,\n });\n }\n for (const key of Object.keys(raw)) {\n if (!known.includes(key as AgentToolPolicyKind)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"toolPolicy.${key}\" is not a known tool kind. Valid keys: ${known.join(\", \")}.`,\n suggestion: `Block loader tools are framework machinery and are deliberately not policy-governed, so there is no \"block\" key.`,\n });\n }\n const rule = raw[key as AgentToolPolicyKind] as AgentToolRule | undefined;\n // An explicit `undefined` is rejected, not skipped. Owning the key\n // with an undefined value satisfies the missing-key check above\n // while `ruleAdmits` treats it as a denial at dispatch, which is\n // precisely the silent strip that requiring every key exists to\n // prevent. There is no reading of `mcp: undefined` where dropping\n // every MCP tool with only a warn line is what the author meant.\n if (typeof rule !== \"boolean\" && typeof rule !== \"function\") {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"toolPolicy.${key}\" must be a boolean or a (tool, ctx) => boolean predicate (got ${typeof rule}).`,\n });\n }\n }\n // Shallow-copied so a caller holding a reference cannot add or\n // remove kinds after the context installed the policy. Predicates\n // stay caller-owned by design; this only closes the key-level\n // mutation path, which would otherwise contradict the promise that\n // a policy is not overridable once set.\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 // Blocks merge additively across multiple `agentPlugin` installs:\n // each install contributes named entries, and a name set in two\n // installs throws so we never silently pick one. This differs from\n // `model` / `tools` (single-valued) and matches how blocks compose\n // per-agent: independent named contributions.\n let mergedBlocks: typeof existing.blocks | undefined;\n if (existing.blocks !== undefined || next.blocks !== undefined) {\n mergedBlocks = { ...(existing.blocks ?? {}) };\n if (next.blocks !== undefined) {\n for (const [name, body] of Object.entries(next.blocks)) {\n if (Object.prototype.hasOwnProperty.call(mergedBlocks, name)) {\n throw rcError(\"RC5003\", undefined, {\n message: `agentPlugin: \"defaultOptions.blocks\" already contains \"${name}\" from a previous install. Each block name may be defined once across all installs.`,\n });\n }\n mergedBlocks[name] = body;\n }\n }\n }\n return {\n ...existing,\n ...(next.model !== undefined ? { model: next.model } : {}),\n ...(next.tools !== undefined ? { tools: next.tools } : {}),\n ...(mergedBlocks !== undefined ? { blocks: mergedBlocks } : {}),\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","import { registerErrorCodes, type RCMeta } from \"@routecraft/routecraft\";\n\n/**\n * Error codes owned by `@routecraft/ai` under the `AI` namespace.\n *\n * The declaration merge makes the codes valid `rcError()` arguments at\n * compile time; the `registerErrorCodes` call below provides the runtime\n * metadata. Loaded as a side-effect import from this package's index so\n * the codes are registered before any adapter can throw them.\n *\n * Numbering: AI1xxx = agent block subsystem. Formerly core RC5025-RC5027,\n * renumbered when the codes moved into this package.\n */\n/**\n * Provenance of an MCP tool-lifecycle event. Modeled as a discriminated\n * union so `proxied: true` guarantees the `serverId` / `remoteTool` of the\n * registered client the call was forwarded to; a local `.from(mcp())` route\n * call omits `proxied` (or sets it false) and carries neither identifier.\n */\ntype McpToolProvenance =\n | { proxied?: false; serverId?: undefined; remoteTool?: undefined }\n | { proxied: true; serverId: string; remoteTool: string };\n\ndeclare module \"@routecraft/routecraft\" {\n interface EventDetailsMap {\n /** MCP HTTP server bound its port. */\n \"plugin:mcp:server:listening\": { host: string; port: number; path: string };\n /** Tool list assembled and exposed to clients. */\n \"plugin:mcp:server:tools:exposed\": { tools: string[]; count: number };\n /**\n * Inbound MCP tool call dispatched to a route, or (when `proxied` is\n * true) forwarded to a registered client identified by `serverId` /\n * `remoteTool`.\n */\n \"plugin:mcp:tool:called\": {\n tool: string;\n args: unknown;\n } & McpToolProvenance;\n /** MCP tool call completed successfully. */\n \"plugin:mcp:tool:completed\": { tool: string } & McpToolProvenance;\n /** MCP tool call failed. */\n \"plugin:mcp:tool:failed\": {\n tool: string;\n error: string;\n } & McpToolProvenance;\n }\n interface ErrorCodeRegistry {\n /** Agent block resolution failed (formerly RC5025) */\n AI1001: RCMeta;\n /** Agent block name collision (formerly RC5026) */\n AI1002: RCMeta;\n /** Agent block misconfigured (formerly RC5027) */\n AI1003: RCMeta;\n }\n}\n\nconst DOCS_BASE = \"https://routecraft.dev/docs/reference/errors\";\n\nregisterErrorCodes(\n \"AI\",\n {\n AI1001: {\n category: \"Adapter\",\n message: \"Agent block resolution failed\",\n suggestion:\n \"A block resolver threw or returned a non-string. Check the resolver function for the named block; inject-mode failures abort the dispatch, progressive-mode failures surface back to the model as a loader-tool error.\",\n docs: `${DOCS_BASE}#ai1001`,\n retryable: false,\n },\n AI1002: {\n category: \"Adapter\",\n message: \"Agent block name collision\",\n suggestion:\n \"A block name duplicates another block, collides with a user tool, or starts with the reserved `_block_` prefix used by synthetic loader tools. Rename the block (or the tool) so every name in the agent's surface is unique.\",\n docs: `${DOCS_BASE}#ai1002`,\n retryable: false,\n },\n AI1003: {\n category: \"Adapter\",\n message: \"Agent block misconfigured\",\n suggestion:\n \"A block is missing required fields or has an invalid shape: every block needs a non-empty `name`, a `mode` of `inject` or `progressive`, and a string-or-function `value`. Progressive blocks additionally require a non-empty `description` so the model can decide whether to load them.\",\n docs: `${DOCS_BASE}#ai1003`,\n retryable: false,\n },\n },\n \"@routecraft/ai\",\n);\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 Enricher,\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 LlmEnricherAdapter<\n S extends StandardSchemaV1 | undefined = undefined,\n>\n implements\n Enricher<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(ADAPTER_LLM_OPTIONS);\n return {\n temperature: DEFAULT_TEMPERATURE,\n maxTokens: DEFAULT_MAX_TOKENS,\n ...store,\n ...this.options,\n } as LlmOptionsMerged;\n }\n\n async fetch(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 { Enricher } from \"@routecraft/routecraft\";\nimport { tagAdapter, factoryArgs } from \"@routecraft/routecraft\";\nimport { LlmEnricherAdapter } from \"./enricher.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): Enricher<unknown, LlmResultWithOutput<S>> {\n return tagAdapter(\n new LlmEnricherAdapter<S>(modelId, options),\n llm,\n factoryArgs(modelId, options),\n );\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 Exchange,\n type Source,\n type Subscription,\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\";\nimport {\n deriveAnnotationsFromTags,\n mergeAnnotations,\n} from \"../../annotation-tags.ts\";\nimport { MCP_TOOL_NAME_PATTERN } from \"../../types.ts\";\n\nfunction assertValidMcpToolName(endpoint: string): void {\n if (!MCP_TOOL_NAME_PATTERN.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(sub: Subscription<McpMessage<undefined>>): Promise<void> {\n const { context, meta } = sub;\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(MCP_PLUGIN_REGISTERED);\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(MCP_LOCAL_TOOL_REGISTRY);\n if (!registry) {\n registry = new Map<string, McpLocalToolEntry>();\n context.setStore(MCP_LOCAL_TOOL_REGISTRY, registry);\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 on headers[\"routecraft.auth.principal\"], the single source\n // of truth for identity.\n const entryHandler = async (exchange: Exchange): Promise<Exchange> => {\n return sub.emit({\n message: exchange.body as McpMessage<undefined>,\n headers: exchange.headers,\n });\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\n // Derive the MCP tool annotation hints from the route's tags so the same\n // fact (does this tool mutate state? is it idempotent? does it reach\n // external systems?) is declared once via `.tag()` rather than duplicated\n // as both a tag and an annotation. Explicit `annotations` passed to\n // `mcp()` override the derived values per-key, so callers retain full\n // control when they need it.\n const annotations = mergeAnnotations(\n deriveAnnotationsFromTags(discovery?.tags),\n this.options.annotations,\n );\n if (annotations !== undefined) entry.annotations = annotations;\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 sub.signal.addEventListener(\n \"abort\",\n () => {\n const current = context.getStore(MCP_LOCAL_TOOL_REGISTRY);\n current?.delete(endpoint);\n },\n { once: true },\n );\n\n if (sub.signal.aborted) {\n return;\n }\n\n registry.set(endpoint, entry);\n\n sub.ready();\n\n await new Promise<void>((resolve) => {\n if (sub.signal.aborted) {\n resolve();\n return;\n }\n sub.signal.addEventListener(\"abort\", () => resolve(), {\n once: true,\n });\n });\n }\n}\n","import type { Exchange, Enricher } 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 * McpEnricherAdapter implements the Enricher (fetch) role 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 McpEnricherAdapter implements Enricher<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 fetch(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 Enricher,\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 { McpEnricherAdapter } from \"./enricher.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 * - **Enricher (for `.enrich()` / `.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 * // Enricher (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): Enricher<unknown, unknown>;\nexport function mcp(\n shorthand: RegisteredMcpShorthand,\n options?: { args?: McpArgsExtractor },\n): Enricher<unknown, unknown>;\nexport function mcp(\n arg?: McpServerOptions | McpClientOptions | RegisteredMcpShorthand,\n options?: { args?: McpArgsExtractor },\n): Source<McpMessage<undefined>> | Enricher<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 McpEnricherAdapter(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 McpEnricherAdapter(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 \"./enricher\";\n","import type {\n OAuthPrincipal,\n OAuthTokenVerifier,\n OAuthValidatorAuthOptions,\n} from \"@routecraft/routecraft\";\nimport type { McpHttpAuthOptions } from \"./types.ts\";\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`, so a token\n * that outlives its expiry cannot slip through a well-typed verifier.\n */\nexport type OAuthVerifier = OAuthValidatorAuthOptions | OAuthTokenVerifier;\n\n/**\n * Options for the `oauth()` factory.\n */\nexport interface OAuthFactoryOptions {\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 request: protocol revision 2026-07-28 is\n * stateless, so there is no session in which a past verification could be\n * cached.\n */\n verify: OAuthVerifier;\n /**\n * Authorization Server issuer(s) advertised to clients as\n * `authorization_servers` in the RFC 9728 protected-resource metadata.\n *\n * Optional when `verify` is a `jwks()` / `jwt()` result, which already\n * carries the issuer it validates against. Required when `verify` is a raw\n * function, since nothing else names the IdP a client should authenticate\n * with.\n */\n issuer?: string | string[];\n /**\n * Scopes required on every request to `/mcp`. A token missing any of them is\n * refused with `403 insufficient_scope`.\n */\n requiredScopes?: string[];\n /**\n * Clock skew allowed when the server re-checks the verified principal's\n * `expiresAt`. Taken from `jwks()` / `jwt()` automatically; pass it here\n * when `verify` is a raw function that tolerates skew of its own, so the\n * gate does not refuse a token the function accepted.\n */\n clockToleranceSec?: number;\n}\n\n/** True when the issuer is a non-empty string, or an array of them. */\nfunction isNonEmptyIssuer(issuer: string | string[]): boolean {\n return typeof issuer === \"string\"\n ? issuer.trim().length > 0\n : issuer.length > 0 && issuer.every((value) => value.trim().length > 0);\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 const base: (token: string) => Promise<OAuthPrincipal> =\n typeof verify === \"function\"\n ? async (token) => verify(token)\n : async (token) => verify.validator(token);\n\n // `OAuthPrincipal` makes `expiresAt` required, so this only fires when the\n // type contract was bypassed (`as any`, a dynamically wired plugin). It is\n // checked here rather than in the shared auth gate because the promise is\n // `oauth()`'s: a plain `validator` may legitimately describe a credential\n // with no expiry, such as an API key.\n return async (token) => {\n const principal = await base(token);\n if (principal.expiresAt === undefined) {\n throw new TypeError(\n \"oauth: `verify` returned a principal with no `expiresAt`. A credential \" +\n \"with no expiry never expires; populate it from the token's `exp` claim \" +\n \"or introspection response.\",\n );\n }\n return principal;\n };\n}\n\n/**\n * Built-in OAuth authentication helper for MCP HTTP servers.\n *\n * Configures the MCP server as an OAuth 2.0 **Resource Server**: it verifies\n * bearer tokens on every request, enforces `requiredScopes`, and advertises\n * the Authorization Server through RFC 9728 protected-resource metadata so\n * clients run the authorization flow directly against the IdP.\n *\n * Routecraft does not proxy `/authorize`, `/token`, `/register` or `/revoke`.\n * Protocol revision 2026-07-28 deprecated Dynamic Client Registration in\n * favour of Client ID Metadata Documents and steers MCP servers towards\n * delegating to a dedicated provider, so those endpoints belong to the IdP.\n * A client discovers the IdP from the metadata document this server publishes\n * and from the `resource_metadata` hint on a `401`.\n *\n * Returns an {@link McpHttpAuthOptions} for `mcpPlugin({ auth: oauth({...}) })`.\n * It is a thin, explicit layer over the same options `jwks()` / `jwt()`\n * produce: reach for it when you want `requiredScopes` enforcement or an\n * explicit issuer, and pass the validator directly otherwise.\n *\n * @example JWKS-backed verification (e.g. Clerk, Auth0, WorkOS)\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 * 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 * requiredScopes: [\"mcp:invoke\"],\n * }),\n * });\n * ```\n *\n * @example Custom verification (opaque tokens, introspection)\n * ```ts\n * oauth({\n * issuer: \"https://idp.example.com\",\n * verify: async (token) => {\n * const introspected = await myIntrospectionCall(token);\n * return {\n * kind: \"custom\",\n * scheme: \"bearer\",\n * subject: introspected.userId,\n * clientId: introspected.clientId,\n * expiresAt: introspected.exp,\n * };\n * },\n * });\n * ```\n */\nexport function oauth(options: OAuthFactoryOptions): McpHttpAuthOptions {\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\n // A raw verifier names no issuer, so without an explicit one the metadata\n // document would advertise no Authorization Server and a client could not\n // discover where to authenticate. Fail at construction rather than serving\n // an undiscoverable resource.\n const issuer =\n options.issuer ??\n (typeof options.verify === \"function\" ? undefined : options.verify.issuer);\n if (issuer === undefined || !isNonEmptyIssuer(issuer)) {\n throw new TypeError(\n \"oauth: a non-empty `issuer` is required. Pass the Authorization Server \" +\n \"issuer explicitly, or use jwks(...) / jwt(...), which carry their own. \" +\n \"Without it the RFC 9728 metadata document advertises no authorization \" +\n \"server and clients cannot discover where to authenticate.\",\n );\n }\n\n const clockToleranceSec =\n options.clockToleranceSec ??\n (typeof options.verify === \"function\"\n ? undefined\n : options.verify.clockToleranceSec);\n\n const resolved: McpHttpAuthOptions = {\n validator: buildVerifier(options.verify),\n issuer,\n };\n if (options.requiredScopes && options.requiredScopes.length > 0) {\n resolved.requiredScopes = options.requiredScopes;\n }\n if (clockToleranceSec !== undefined) {\n resolved.clockToleranceSec = clockToleranceSec;\n }\n return resolved;\n}\n","import { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { join, resolve, basename, extname } from \"node:path\";\nimport { loadOptionalPeer, 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 or block `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()` or `skills()`\n * do 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 const mod = (await loadOptionalPeer(() => import(\"yaml\"), {\n adapterName: \"Markdown loader (agents() / skills())\",\n packageName: \"yaml\",\n })) as { parse: YamlParse };\n cachedParseYaml = mod.parse;\n return cachedParseYaml;\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 if (yamlText) {\n // Load OUTSIDE the parse-error wrap: a missing `yaml` package must\n // surface as RC5017 with an install hint, not as a misleading\n // \"front matter failed to parse\" error pointing at the user's file.\n const parseYaml = await loadYamlParse();\n try {\n parsed = parseYaml(yamlText);\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 } else {\n parsed = {};\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 \"../block/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 \"principal\",\n]);\n\n/**\n * Fields whose values are not YAML-expressible today (function-form block\n * resolvers, Standard Schema objects with a live `validate` function).\n * They get a pointed error instead of the generic \"not yet supported\"\n * one: the override map is their home unless a serializable form (say, a\n * JSON Schema string for `output`) is ever adopted.\n */\nconst OVERRIDE_ONLY_AGENT_KEYS = new Set([\"blocks\", \"output\"]);\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 *\n * `output` is override-only, mirroring `blocks`: a Standard Schema is a\n * live object with a `validate` function, so YAML frontmatter can never\n * express one. Supply the schema here to give a markdown-defined agent\n * structured output (the parsed value lands on `AgentResult.output`).\n */\nexport interface AgentMarkdownOverride extends Partial<\n Pick<\n AgentRegisteredOptions,\n | \"description\"\n | \"model\"\n | \"maxTurns\"\n | \"tools\"\n | \"principal\"\n | \"blocks\"\n | \"output\"\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 (OVERRIDE_ONLY_AGENT_KEYS.has(key)) {\n throw rcError(\"RC5003\", undefined, {\n message: `Markdown file \"${source}\": frontmatter field \"${key}\" is override-only; YAML cannot express its value. Supply it via the override map instead: agents(path, { ${JSON.stringify(filename)}: { ${key}: ... } }).`,\n });\n }\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 // 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 (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.principal !== undefined) out.principal = override.principal;\n if (override.blocks !== undefined) out.blocks = override.blocks;\n if (override.output !== undefined) out.output = override.output;\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 * | `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` / `blocks` /\n * `principal` / `output` / `system` per agent without editing the\n * markdown source. `blocks` and `output` are override-only because\n * YAML cannot express the function-form resolvers a block may carry,\n * nor a Standard Schema (a live object with a `validate` function).\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 // Null-prototype map so a frontmatter `name` like `__proto__` or\n // `toString` cannot collide with Object.prototype (the `in` check\n // below would otherwise pass for keys that were never loaded, and\n // an assignment to `__proto__` would mutate the prototype).\n const out = Object.create(null) as 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 (!Object.prototype.hasOwnProperty.call(out, name)) {\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 { readFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\nimport {\n rcError,\n type CraftContext,\n type Exchange,\n} from \"@routecraft/routecraft\";\nimport {\n readMarkdownDir,\n readMarkdownFile,\n requireString,\n} from \"./markdown.ts\";\nimport type {\n BlockBody,\n BlockClient,\n BlockLifetime,\n BlockMode,\n Blocks,\n} from \"./types.ts\";\n\n/**\n * Options for {@link skills}. Loads markdown skills from disk and\n * returns one {@link BlockBody} per skill, keyed by skill name, so\n * the agent picks them up via its `blocks: { ... }` record.\n */\nexport interface SkillsOptions {\n /**\n * Path to a single `.md` file or a directory containing skill\n * markdown files. Directories support the Claude Code convention:\n * flat `.md` files and nested `<name>/SKILL.md` folders may\n * coexist.\n */\n source: string;\n /**\n * How skills are surfaced to the model. Defaults to `\"progressive\"`\n * so the model sees each skill's name + description in the system\n * prompt and only loads the body via a tool call when relevant\n * (matches Claude Code's default progressive-disclosure behaviour).\n * Pass `\"inject\"` to concatenate every skill's full body into the\n * system prompt on every dispatch.\n */\n mode?: BlockMode;\n /**\n * Per-block lifetime applied to every loaded skill. Defaults to\n * `\"dispatch\"`. Pass `\"context\"` to read each skill file once per\n * `CraftContext` and reuse the parsed content across dispatches.\n */\n lifetime?: BlockLifetime;\n}\n\n/**\n * Load markdown skills from disk and return them as a {@link Blocks}\n * record ready to spread into an agent's `blocks: { ... }` map.\n *\n * Two layouts are supported and may coexist in the same folder:\n *\n * - **Flat**: `<dir>/<name>.md` -- filename (without `.md`) is the\n * skill name and must match the frontmatter `name`.\n * - **Nested**: `<dir>/<name>/SKILL.md` -- the subdirectory name is\n * the skill name and must match the frontmatter `name`. The folder\n * can also bundle supporting assets; only `SKILL.md` is consumed.\n *\n * The `description` frontmatter becomes the block's description (used\n * verbatim when `mode: \"progressive\"` so the model can decide whether\n * to load); the markdown body becomes the block's static `value`.\n *\n * @example\n * ```ts\n * agent({\n * model: \"anthropic:claude-sonnet-4-6\",\n * system: \"You are an analyst.\",\n * blocks: {\n * ...(await skills({ source: \"./skills\" })),\n * },\n * });\n * ```\n */\nexport async function skills(options: SkillsOptions): Promise<Blocks> {\n if (!options || typeof options !== \"object\") {\n throw rcError(\"AI1003\", undefined, {\n message: `skills: options must be an object with at least { source }.`,\n });\n }\n const { source, mode = \"progressive\", lifetime } = options;\n if (typeof source !== \"string\" || source.trim() === \"\") {\n throw rcError(\"AI1003\", undefined, {\n message: `skills: \"source\" must be a non-empty path to a markdown file or directory.`,\n });\n }\n if (mode !== \"inject\" && mode !== \"progressive\") {\n throw rcError(\"AI1003\", undefined, {\n message: `skills: \"mode\" must be \"inject\" or \"progressive\" (got ${JSON.stringify(mode)}).`,\n });\n }\n if (\n lifetime !== undefined &&\n lifetime !== \"dispatch\" &&\n lifetime !== \"context\"\n ) {\n throw rcError(\"AI1003\", undefined, {\n message: `skills: \"lifetime\" must be \"dispatch\" or \"context\" when present (got ${JSON.stringify(lifetime)}).`,\n });\n }\n const docs = source.endsWith(\".md\")\n ? [await readMarkdownFile(source)]\n : await readMarkdownDir(source, { sentinelFilename: \"SKILL.md\" });\n const sources = new Map<string, string>();\n const out: Record<string, BlockBody> = {};\n for (const doc of docs) {\n const name = requireString(doc.frontmatter[\"name\"], \"name\", doc.path);\n if (name !== doc.filename) {\n throw rcError(\"AI1003\", undefined, {\n message: `skills: markdown file \"${doc.path}\": frontmatter \"name\" (\"${name}\") must match the filename (\"${doc.filename}\"). Rename one or the other.`,\n });\n }\n const description = requireString(\n doc.frontmatter[\"description\"],\n \"description\",\n doc.path,\n );\n if (doc.body.trim() === \"\") {\n throw rcError(\"AI1003\", undefined, {\n message: `skills: markdown file \"${doc.path}\": skill body is empty. The body becomes the block's content; an empty body would not change the agent's behaviour.`,\n });\n }\n const prior = sources.get(name);\n if (prior) {\n throw rcError(\"AI1002\", undefined, {\n message: `skills(\"${source}\"): duplicate skill name \"${name}\" loaded from both \"${prior}\" and \"${doc.path}\". Each skill name must be unique within a source; rename or remove one.`,\n });\n }\n sources.set(name, doc.path);\n const body: BlockBody = { description, mode, value: doc.body };\n if (lifetime !== undefined) body.lifetime = lifetime;\n out[name] = body;\n }\n return out;\n}\n\n/**\n * Return a function-form resolver that reads a UTF-8 text file at\n * dispatch (or context-init) time. Useful when a block's content\n * lives on disk and may be edited without restarting the process.\n *\n * Resolves the path against `process.cwd()` so relative paths\n * (`\"./prompts/identity.md\"`) work the same way the markdown loaders\n * do.\n *\n * @example\n * ```ts\n * agent({\n * model: \"anthropic:claude-sonnet-4-6\",\n * system: \"You are Zoe.\",\n * blocks: {\n * identity: {\n * mode: \"inject\",\n * lifetime: \"context\",\n * value: fromFile(\"./prompts/identity.md\"),\n * },\n * },\n * });\n * ```\n */\nexport function fromFile(\n path: string,\n): (\n exchange: Exchange<unknown>,\n context: CraftContext,\n events: readonly unknown[],\n client: BlockClient,\n) => Promise<string> {\n if (typeof path !== \"string\" || path.trim() === \"\") {\n throw rcError(\"AI1003\", undefined, {\n message: `fromFile: \"path\" must be a non-empty string.`,\n });\n }\n return async () => {\n const abs = resolvePath(process.cwd(), path);\n try {\n // Async read so the resolver does not block the event loop on\n // every dispatch (default lifetime is `\"dispatch\"`, so this can\n // fire often under concurrent agent traffic).\n return await readFile(abs, \"utf-8\");\n } catch (cause) {\n throw rcError(\"AI1001\", cause, {\n message: `fromFile(\"${path}\"): could not read file: ${(cause as Error)?.message ?? String(cause)}`,\n });\n }\n };\n}\n","import {\n getExchangeContext,\n type CraftContext,\n type Enricher,\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(ADAPTER_EMBEDDING_PROVIDERS);\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 EmbeddingEnricherAdapter<T = unknown>\n implements Enricher<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(ADAPTER_EMBEDDING_OPTIONS);\n return { ...store, ...this.options } as EmbeddingOptions;\n }\n\n async fetch(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 { Enricher } from \"@routecraft/routecraft\";\nimport { tagAdapter, factoryArgs } from \"@routecraft/routecraft\";\nimport { EmbeddingEnricherAdapter } from \"./enricher.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): Enricher<T, EmbeddingResult> {\n return tagAdapter(\n new EmbeddingEnricherAdapter<T>(modelId, options),\n embedding,\n factoryArgs(modelId, options),\n );\n}\n"]}
|