@routecraft/ai 0.3.0-canary.8 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @routecraft/ai
2
2
 
3
- AI and MCP integrations for RouteCraft.
3
+ AI adapters and MCP integration for RouteCraft. Call LLMs, run agents, generate embeddings, and expose your capabilities to Claude, Cursor, and other MCP clients.
4
4
 
5
5
  ## Installation
6
6
 
@@ -16,30 +16,91 @@ pnpm add @routecraft/ai
16
16
 
17
17
  ## Quick Start
18
18
 
19
+ Define a capability and expose it as an MCP tool:
20
+
19
21
  ```typescript
22
+ // capabilities/fetch-webpage.ts
20
23
  import { mcp } from '@routecraft/ai';
21
- import { craft, simple, direct } from '@routecraft/routecraft';
24
+ import { craft, context, http } from '@routecraft/routecraft';
25
+ import { z } from 'zod';
22
26
 
23
- // In-process: use direct(); MCP server route needs description
24
- craft()
25
- .from(simple({ query: 'hello' }))
26
- .to(direct('my-tool'));
27
+ const ctx = context()
28
+ .routes([
29
+ craft()
30
+ .id('fetch-webpage')
31
+ .from(
32
+ mcp('fetch-webpage', {
33
+ description: 'Fetch and return the content of a webpage',
34
+ schema: z.object({ url: z.string().url() }),
35
+ })
36
+ )
37
+ .enrich(http({ url: (ex) => ex.body.url })),
38
+ ])
39
+ .build();
27
40
 
28
- craft()
29
- .from(mcp('my-tool', { description: 'My tool' }))
30
- .process((body) => body);
41
+ await ctx.start();
31
42
  ```
32
43
 
33
- ## Features
44
+ Run it as an MCP server:
45
+
46
+ ```bash
47
+ npx @routecraft/cli run capabilities/fetch-webpage.ts
48
+ ```
49
+
50
+ ## Two Modes
51
+
52
+ ### Server Mode: expose capabilities outward via MCP
53
+
54
+ Use `mcp()` as a `.from()` source. This registers the capability as an MCP tool that Claude Desktop, Cursor, or any MCP client can invoke.
55
+
56
+ ```typescript
57
+ import { mcp, llm, llmPlugin } from '@routecraft/ai';
58
+ import { craft, context, http } from '@routecraft/routecraft';
59
+ import { z } from 'zod';
60
+
61
+ const ctx = context()
62
+ .plugins([
63
+ llmPlugin({
64
+ providers: { anthropic: { apiKey: process.env.ANTHROPIC_API_KEY! } },
65
+ }),
66
+ ])
67
+ .routes([
68
+ craft()
69
+ .id('summarize-webpage')
70
+ .from(
71
+ mcp('summarize-webpage', {
72
+ description: 'Fetch and summarize the content of a webpage',
73
+ schema: z.object({ url: z.string().url() }),
74
+ })
75
+ )
76
+ .enrich(http({ url: (ex) => ex.body.url }))
77
+ .to(llm('anthropic:claude-sonnet-4-6', {
78
+ systemPrompt: 'Summarize the following webpage content concisely.',
79
+ userPrompt: (ex) => String(ex.body),
80
+ })),
81
+ ])
82
+ .build();
83
+ ```
84
+
85
+ ### Client Mode: route data to agents in code
34
86
 
35
- - **mcp()**: MCP server (`.from(mcp(endpoint, { description }))`) and client (`.to(mcp({ url, tool }))` or `.to(mcp('server:tool', { args }))`). For in-process use `direct()`.
36
- - **Discovery**: Tools register in the context store for querying endpoints, descriptions, and schemas
37
- - **Schema validation**: Use Zod (or other Standard Schema libs) for body and header validation on tools
38
- - **Coming soon**: LLM adapters (OpenAI, Gemini), MCP source/destination, agent routing
87
+ Use `mcp()` as a `.to()` destination to call another MCP server, or use `direct()` to call a capability in the same process by ID.
39
88
 
40
- ## Connecting from Cursor / Claude Desktop (MCP)
89
+ ```typescript
90
+ import { direct, timer } from '@routecraft/routecraft';
91
+
92
+ // Call a capability in the same process on a schedule
93
+ craft()
94
+ .id('orchestrator')
95
+ .from(timer({ intervalMs: 60_000 }))
96
+ .to(direct('fetch-webpage'));
97
+ ```
41
98
 
42
- **Recommended:** use **npx** so the MCP client runs the CLI without needing a global install or full paths. The server requires **Node.js 18.19+ or 20+** (Pino 10 needs `diagnostics_channel.tracingChannel`). If the client uses an older Node, start Cursor/Claude from a shell where a newer Node is first in `PATH` (e.g. `nvm use 22`), or set **command** to the full path of a Node 20+ binary and **args** with the path to the CLI entry (see fallback below).
99
+ ## Connecting Claude Desktop and Cursor
100
+
101
+ The CLI runs your capability file as an MCP server. Use `npx` so clients do not need a global install.
102
+
103
+ **Node.js 18.19+ or 20+** is required.
43
104
 
44
105
  In **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS) or **Cursor** (MCP settings):
45
106
 
@@ -51,62 +112,38 @@ In **Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_conf
51
112
  "args": [
52
113
  "@routecraft/cli",
53
114
  "run",
54
- "--log-file",
55
- "/path/to/craft.log",
56
- "--log-level",
57
- "debug",
58
- "/path/to/your/index.mjs"
115
+ "--log-file", "/path/to/craft.log",
116
+ "--log-level", "debug",
117
+ "/path/to/your/capabilities/index.ts"
59
118
  ]
60
119
  }
61
120
  }
62
121
  }
63
122
  ```
64
123
 
65
- Use `@routecraft/cli@canary` for the latest canary build. Logging to a file keeps stdout JSON-RPC-only; omit `--log-file` / `--log-level` or use `--log-level silent` to disable logs.
124
+ Use `@routecraft/cli@canary` for the latest canary build. Writing logs to a file keeps stdout JSON-RPC-only, which is required for MCP transport. Use `--log-level silent` to disable logs entirely.
66
125
 
67
- **Fallback (minimal PATH):** if `npx` is not available to the MCP client, set **command** to the full path of a Node 20+ binary and **args** so the first element is the CLI’s JavaScript entry. From a project with `@routecraft/cli` installed: `node -e "console.log(require.resolve('@routecraft/cli/dist/index.js'))"`.
126
+ **If `npx` is not available to the MCP client:** set `command` to the full path of a Node 20+ binary and set the first `args` element to the CLI entry point. From a project with `@routecraft/cli` installed, find it with:
68
127
 
69
- ## Documentation
128
+ ```bash
129
+ node -e "console.log(require.resolve('@routecraft/cli/dist/index.js'))"
130
+ ```
70
131
 
71
- For comprehensive documentation, examples, and guides, visit [routecraft.dev](https://routecraft.dev).
132
+ ## Features
72
133
 
73
- ## Example
134
+ - **`mcp(name, options)`**: Register a capability as an MCP tool (server mode) or call an external MCP server (client mode)
135
+ - **`llm(modelId, options?)`**: Call any LLM provider from a capability pipeline. Supports Anthropic, OpenAI, Gemini, Ollama, and OpenRouter. Register providers via `llmPlugin`.
136
+ - **`embedding(modelId, options?)`**: Generate embeddings from a capability pipeline.
137
+ - **Schema validation**: Use Zod (or any Standard Schema library) for strict input validation on MCP tools
138
+ - **Tool discovery**: Registered tools are available via the context store for querying endpoints, descriptions, and schemas
74
139
 
75
- ```typescript
76
- import { mcp } from '@routecraft/ai';
77
- import {
78
- craft,
79
- context,
80
- DirectAdapter,
81
- http,
82
- } from '@routecraft/routecraft';
83
- import { z } from 'zod';
84
-
85
- const ctx = context()
86
- .routes([
87
- craft()
88
- .from(
89
- mcp('fetch-webpage', {
90
- description: 'Fetch and return the content of a webpage',
91
- schema: z.object({
92
- url: z.string().url(),
93
- }),
94
- keywords: ['fetch', 'web', 'http'],
95
- })
96
- )
97
- .enrich(http({ url: (ex) => ex.body.url })),
98
- ])
99
- .build();
100
- await ctx.start();
140
+ ## Documentation
101
141
 
102
- // Query registered tools after context has started
103
- const registry = ctx.getStore(DirectAdapter.ADAPTER_DIRECT_REGISTRY);
104
- const tools = Array.from(registry?.values() ?? []);
105
- ```
142
+ For full guides and examples, visit [routecraft.dev](https://routecraft.dev).
106
143
 
107
144
  ## Contributing
108
145
 
109
- Contributions are welcome! Please see our [Contributing Guide](https://github.com/routecraftjs/routecraft/blob/main/CONTRIBUTING.md).
146
+ Contributions are welcome. See the [Contributing Guide](https://github.com/routecraftjs/routecraft/blob/main/CONTRIBUTING.md).
110
147
 
111
148
  ## License
112
149
 
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var routecraft=require('@routecraft/routecraft'),ai=require('ai'),http=require('http');var V={McpAdapter:Symbol.for("routecraft.ai.McpAdapter")};function se(t,e){return typeof t=="object"&&t!==null&&t[e]===true}function ae(t){return se(t,V.McpAdapter)}function L(t,e){throw new Error(`The ${e} LLM provider requires the "${t}" package. Install it with: pnpm add ${t}`)}function O(t,e){if(!(t instanceof Error))return false;let n=t.message??"";return (n.includes("ERR_MODULE_NOT_FOUND")||n.includes("Cannot find module")||n.includes("Cannot find package"))&&n.includes(e)}var pe={ollama:{baseURL:"http://localhost:11434/api"}};function C(t){return {...t.inputTokens!==void 0&&{inputTokens:t.inputTokens},...t.outputTokens!==void 0&&{outputTokens:t.outputTokens},...t.totalTokens!==void 0&&{totalTokens:t.totalTokens}}}function T(t){try{if("output"in t&&t.output!==void 0)return t.output}catch{}}function K(t,e,n){if(t===null||typeof t!="object")throw new Error(`[${e}] Invalid model: expected an object, got ${typeof t}. Model id: ${n}`);let r=t;if(typeof r.doGenerate!="function")throw new Error(`[${e}] Invalid model: missing or invalid doGenerate method. Model id: ${n}. Ensure the provider returns an AI SDK-compatible language model.`);if(typeof r.doStream!="function")throw new Error(`[${e}] Invalid model: missing or invalid doStream method. Model id: ${n}. Ensure the provider returns an AI SDK-compatible language model.`)}async function F(t){let{config:e,modelId:n,options:r,systemPrompt:o,userPrompt:i,output:s}=t;switch(e.provider){case "openai":return de(e,n,r,o,i,s);case "anthropic":return le(e,n,r,o,i,s);case "gemini":return ce(e,n,r,o,i,s);case "openrouter":return ue(e,n,r,o,i,s);case "ollama":return me(e,n,r,o,i,s);default:{let d=e;throw new Error(`LLM provider not implemented: ${d.provider}`)}}}async function de(t,e,n,r,o,i){let s;try{s=(await import('@ai-sdk/openai')).createOpenAI;}catch(y){throw O(y,"@ai-sdk/openai")&&L("@ai-sdk/openai","OpenAI"),y}let{generateText:d}=await import('ai'),c={apiKey:t.apiKey};t.baseURL!==void 0&&(c.baseURL=t.baseURL);let l={model:s(c)(e),prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(l.system=r),n.topP!==void 0&&(l.topP=n.topP),n.frequencyPenalty!==void 0&&(l.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(l.presencePenalty=n.presencePenalty);let p=i!==void 0?{...l,output:i}:l,g=await d(p),u={text:g.text??"",raw:g};g.usage&&(u.usage=C(g.usage));let m=T(g);return m!==void 0&&(u.output=m),u}async function le(t,e,n,r,o,i){let s;try{s=(await import('@ai-sdk/anthropic')).createAnthropic;}catch(m){throw O(m,"@ai-sdk/anthropic")&&L("@ai-sdk/anthropic","Anthropic"),m}let{generateText:d}=await import('ai'),a={model:s({apiKey:t.apiKey})(e),prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(a.system=r),n.topP!==void 0&&(a.topP=n.topP),n.frequencyPenalty!==void 0&&(a.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(a.presencePenalty=n.presencePenalty);let l=i!==void 0?{...a,output:i}:a,p=await d(l),g={text:p.text??"",raw:p};p.usage&&(g.usage=C(p.usage));let u=T(p);return u!==void 0&&(g.output=u),g}async function ce(t,e,n,r,o,i){let s;try{s=(await import('@ai-sdk/google')).createGoogleGenerativeAI;}catch(m){throw O(m,"@ai-sdk/google")&&L("@ai-sdk/google","Gemini"),m}let{generateText:d}=await import('ai'),a={model:s({apiKey:t.apiKey})(e),prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(a.system=r),n.topP!==void 0&&(a.topP=n.topP),n.frequencyPenalty!==void 0&&(a.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(a.presencePenalty=n.presencePenalty);let l=i!==void 0?{...a,output:i}:a,p=await d(l),g={text:p.text??"",raw:p};p.usage&&(g.usage=C(p.usage));let u=T(p);return u!==void 0&&(g.output=u),g}async function ue(t,e,n,r,o,i){let s;try{s=(await import('@openrouter/ai-sdk-provider')).createOpenRouter;}catch(P){throw O(P,"@openrouter/ai-sdk-provider")&&L("@openrouter/ai-sdk-provider","OpenRouter"),P}let{generateText:d}=await import('ai'),c=s({apiKey:t.apiKey}),f=t.modelId??e,a=c.chat(f);K(a,"OpenRouter",f);let p={model:a,prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(p.system=r),n.topP!==void 0&&(p.topP=n.topP),n.frequencyPenalty!==void 0&&(p.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(p.presencePenalty=n.presencePenalty);let g=i!==void 0?{...p,output:i}:p,u=await d(g),m={text:u.text??"",raw:u};u.usage&&(m.usage=C(u.usage));let y=T(u);return y!==void 0&&(m.output=y),m}async function me(t,e,n,r,o,i){let s;try{s=(await import('ollama-ai-provider-v2')).createOllama;}catch(P){throw O(P,"ollama-ai-provider-v2")&&L("ollama-ai-provider-v2","Ollama"),P}let{generateText:d}=await import('ai'),c=s({baseURL:t.baseURL??pe.ollama.baseURL}),f=t.modelId??e,a=c(f);K(a,"Ollama",f);let p={model:a,prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(p.system=r),n.topP!==void 0&&(p.topP=n.topP),n.frequencyPenalty!==void 0&&(p.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(p.presencePenalty=n.presencePenalty);let g=i!==void 0?{...p,output:i}:p,u=await d(g),m={text:u.text??"",raw:u};u.usage&&(m.usage=C(u.usage));let y=T(u);return y!==void 0&&(m.output=y),m}function B(t){let e=t["~standard"];if(!e?.validate)throw new Error("LLM outputSchema must be a StandardSchemaV1 with ~standard.validate");let n=e.jsonSchema?.output?.({target:"draft-2020-12"})??e.jsonSchema?.input?.({target:"draft-2020-12"});if(!n||typeof n!="object")throw new Error("LLM outputSchema must expose ~standard.jsonSchema.output or .input for provider structured output");function r(i){let s;try{s=e.validate(i);}catch(c){return {success:false,error:c instanceof Error?c:new Error(String(c))}}return s instanceof Promise?{success:false,error:new Error("Async output schema is not supported for LLM structured output")}:s.issues!=null&&(Array.isArray(s.issues)?s.issues.length>0:typeof s.issues=="object"&&s.issues!==null?Object.keys(s.issues).length>0:!!s.issues)?{success:false,error:new Error(typeof s.issues=="string"?s.issues:JSON.stringify(s.issues))}:{success:true,value:s.value}}let o=ai.jsonSchema(n,{validate:r});return ai.Output.object({schema:o})}var w=Symbol.for("routecraft.adapter.llm.providers"),E=Symbol.for("routecraft.adapter.llm.options");async function he(t,e){let n;try{n=JSON.parse(t);}catch{return}let r=e["~standard"];if(!r?.validate)return;let o=r.validate(n);if(o instanceof Promise&&(o=await o),!(o&&typeof o=="object"&&"issues"in o&&o.issues))return o&&typeof o=="object"&&"value"in o?o.value:void 0}var Pe=0,we=1024;function W(t,e){return t===void 0||t===""?"":typeof t=="function"?t(e):t}function ve(t){let e=t.body;return typeof e=="string"?e:e==null?"":typeof e=="object"?JSON.stringify(e):String(e)}function Ee(t){let e=t.indexOf(":");if(e<1||e===t.length-1)throw new Error(`LLM adapter: model id must be "providerId:modelName" (e.g. ollama:lfm2.5-thinking). Got: "${t}"`);return {providerId:t.slice(0,e),modelName:t.slice(e+1)}}function Me(t,e){if(!e)throw new Error(`LLM adapter: model id "${t}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store "${w.description}" can be read.`);let n=e.getStore(w);if(!n)throw new Error('LLM provider not found: no providers registered. Add llmPlugin({ providers: { ollama: { provider: "ollama" }, ... } }) to your config.');let{providerId:r,modelName:o}=Ee(t),i=n.get(r);if(!i)throw new Error(`LLM provider "${r}" not found. Register it with llmPlugin({ providers: { "${r}": { provider, apiKey?, baseURL? } } }).`);return {config:i,modelName:o}}var M=class{constructor(e,n={}){this.modelId=e;this.options=n;}adapterId="routecraft.adapter.llm";options;mergedOptions(e){let n=e.getStore(E);return {temperature:Pe,maxTokens:we,...n,...this.options}}async send(e){let n=routecraft.getExchangeContext(e),{config:r,modelName:o}=Me(this.modelId,n),i=this.mergedOptions(n),s=W(i.systemPrompt,e),d=W(i.userPrompt,e)||ve(e),c={temperature:i.temperature,maxTokens:i.maxTokens};i.topP!==void 0&&(c.topP=i.topP),i.frequencyPenalty!==void 0&&(c.frequencyPenalty=i.frequencyPenalty),i.presencePenalty!==void 0&&(c.presencePenalty=i.presencePenalty);let f=i.outputSchema!==void 0?B(i.outputSchema):void 0,a=await F({config:r,modelId:o,options:c,systemPrompt:s,userPrompt:d,output:f});if(a.output===void 0&&a.text&&i.outputSchema!==void 0){let l=await he(a.text,i.outputSchema);l!==void 0&&(a.output=l);}return a}};function J(t,e){return new M(t,e)}var z=["openai","anthropic","openrouter","ollama","gemini"];function xe(t){return z.includes(t)}function I(t){if(!t||typeof t!="object")throw new TypeError("llmPlugin: options must be an object");if(!t.providers||typeof t.providers!="object")throw new TypeError("llmPlugin: options.providers must be an object (record of provider id \u2192 options)");for(let[e,n]of Object.entries(t.providers))if(n!==void 0){if(!n||typeof n!="object")throw new TypeError(`llmPlugin: providers["${e}"] must be an object`);if(!xe(e))throw new TypeError(`llmPlugin: providers["${e}"] is not a supported provider. Supported: ${z.join(", ")}`);switch(e){case "openai":case "anthropic":case "openrouter":case "gemini":if(typeof n.apiKey!="string"||!n.apiKey.trim())throw new TypeError(`llmPlugin: providers["${e}"].apiKey is required`);break;case "ollama":if(n.baseURL!==void 0&&typeof n.baseURL!="string")throw new TypeError(`llmPlugin: providers["${e}"].baseURL must be a string when provided`);if(n.modelId!==void 0&&(typeof n.modelId!="string"||!n.modelId.trim()))throw new TypeError(`llmPlugin: providers["${e}"].modelId must be a non-empty string when provided`);break}}if(t.defaultOptions!==void 0&&(typeof t.defaultOptions!="object"||t.defaultOptions===null))throw new TypeError("llmPlugin: defaultOptions must be an object when provided")}var be=["openai","anthropic","openrouter","ollama","gemini"];function Re(t,e){return {provider:t,...e}}function X(t={providers:{}}){return I(t),{apply(e){let n=new Map;for(let r of be){let o=t.providers[r];o!==void 0&&n.set(r,Re(r,o));}e.setStore(w,n),t.defaultOptions&&Object.keys(t.defaultOptions).length>0&&e.setStore(E,t.defaultOptions);}}}var x=Symbol.for("routecraft.mcp.plugin.registered"),h=Symbol.for("routecraft.mcp.client.servers");var v=Symbol.for("routecraft.mcp.adapter");var _=class{adapterId="routecraft.adapter.mcp";endpoint;options;constructor(e,n){if(this[v]=true,typeof e!="string")throw routecraft.rcError("RC5003",void 0,{message:"Dynamic endpoints cannot be used as source",suggestion:"Use a static string endpoint for source: .from(mcp('endpoint', options))."});if("url"in n||"serverId"in n)throw routecraft.rcError("RC5003",void 0,{message:"mcp() with url or serverId must be used as destination: .to(mcp({ url, tool }))",suggestion:"Use .to(mcp({ url: '...', tool: '...' })) to call a remote MCP server."});if("args"in n&&n.args!==void 0&&!("description"in n))throw routecraft.rcError("RC5003",void 0,{message:"mcp(endpoint, { args }) is for client usage with a 'server:tool' target, not for defining a source",suggestion:"Use .to(mcp('server:tool', { args })) to call a remote tool, or .from(mcp('endpoint', { description: '...' })) to define a source."});if(!("description"in n)||typeof n.description!="string")throw routecraft.rcError("RC5003",void 0,{message:"mcp(endpoint, options) as source requires options.description",suggestion:"Use .from(mcp('endpoint', { description: '...' })) to define a source."});this.endpoint=e,this.options=n;}async subscribe(e,n,r,o){if(e.getStore(x)!==true)throw new Error("MCP plugin required: routes using .from(mcp(...)) require the MCP plugin. Add mcpPlugin() to your config: plugins: [mcpPlugin()].");return routecraft.direct(this.endpoint,this.options).subscribe(e,n,r,o)}};function Oe(t){let e=t.trim().toLowerCase();if(!e.startsWith("http://")&&!e.startsWith("https://"))throw new Error(`MCP client: url must be HTTP or HTTPS. Stdio is not supported in routes; register stdio clients via mcpPlugin({ clients: { name: { command, args } } }). Got: "${t.slice(0,50)}${t.length>50?"...":""}"`)}function Ce(t,e){if(t.url)return Oe(t.url),t.url;if(t.serverId&&!e)throw new Error(`MCP client: serverId "${t.serverId}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store "${String(h)}" can be read.`);if(t.serverId&&e){let r=e.getStore(h)?.get(t.serverId);if(!r)throw new Error(`MCP client: serverId "${t.serverId}" not found in context store. Register it with context store key "${String(h)}".`);return typeof r=="string"?r:r.url}throw new Error("MCP client: either url or serverId must be provided in McpClientOptions.")}var N=t=>typeof t.body=="object"&&t.body!==null?t.body:{input:t.body},k=class{constructor(e){this.options=e;if(this[v]=true,!e.url&&!e.serverId)throw new Error("MCP client: either url or serverId must be provided in McpClientOptions.");if(e.url&&e.serverId)throw new Error("MCP client: cannot provide both url and serverId. Use either url for direct HTTP or serverId for registered servers.")}adapterId="routecraft.adapter.mcp";async send(e){let n=routecraft.getExchangeContext(e),r=Ce(this.options,n),o=this.options.tool??(typeof e.body=="object"&&e.body!==null&&"tool"in e.body&&typeof e.body.tool=="string"?e.body.tool:void 0);if(!o)throw new Error("MCP client: tool name required. Set options.tool or exchange.body.tool.");let s=(this.options.args??N)(e);return await this.callRemoteTool(r,o,s)}async callRemoteTool(e,n,r){let o,i;try{o=await import('@modelcontextprotocol/sdk/client/index.js'),i=await import('@modelcontextprotocol/sdk/client/streamableHttp.js');}catch{throw new Error('MCP client requires "@modelcontextprotocol/sdk". Install it with: pnpm add @modelcontextprotocol/sdk')}let s=o.Client,d=i.StreamableHTTPClientTransport,c=new URL(e),f=new d(c),a={name:"routecraft-mcp-client",version:"1.0.0"},l=new s(a,{capabilities:{}});try{await l.connect.call(l,f);let u=await l.callTool.call(l,{name:n,arguments:r}),m=u?.content;if(Array.isArray(m)&&m.length>0){let y=m[0];if(y&&typeof y=="object"&&"text"in y)return y.text;if(y&&typeof y=="object"&&"data"in y)return y.data}return u}finally{let p=l,g=p.close??p.disconnect;if(typeof g=="function")try{await Promise.resolve(g.call(l));}catch{}let u=f,m=u.close??u.destroy;if(typeof m=="function")try{await Promise.resolve(m.call(f));}catch{}}}};function Y(t,e){if(typeof t=="object"&&t!==null&&("url"in t||"serverId"in t))return new k(t);let n=e===void 0||typeof e=="object"&&e!==null&&!("description"in e);if(typeof t=="string"&&t.includes(":")&&n){let o=t.indexOf(":"),i=t.slice(0,o),s=t.slice(o+1),d={serverId:i,tool:s};return e!==void 0&&typeof e=="object"&&"args"in e&&e.args!==void 0&&(d.args=e.args),new k(d)}let r=t;if(e!==void 0)return new _(r,e);throw routecraft.rcError("RC5003",void 0,{message:"mcp() with only an endpoint is not supported. Use direct('endpoint') for in-process. For MCP server use .from(mcp('endpoint', { description: '...' })); for client use .to(mcp({ url, tool })) or .to(mcp('server:tool', { args })).",suggestion:"Use .from(mcp('endpoint', { description: '...' })) or .to(mcp({ url, tool })) or direct('endpoint')."})}var H='MCP server requires "@modelcontextprotocol/sdk". Install it with: pnpm add @modelcontextprotocol/sdk',b=class{context;options;server=null;transport=null;httpServer=null;running=false;toolsListLogged=false;constructor(e,n={}){this.context=e,this.options={name:"routecraft",version:"1.0.0",transport:"stdio",port:3001,host:"localhost",...n};}async start(){if(this.running){this.context.logger.warn({},"MCP server already running");return}try{let e=this.options.transport;e==="http"?await this.startHttp():await this.startStdio(),this.running=!0,this.context.logger.info({name:this.options.name,version:this.options.version,transport:e},"MCP server started"),this.logExposedToolsOnce();}catch(e){let n=routecraft.isRouteCraftError(e)?e.meta.message:e instanceof Error?e.message:"Failed to start MCP server";throw this.context.logger.error({err:e},n),e}}async startStdio(){let e,n;try{e=(await import('@modelcontextprotocol/sdk/server/index.js')).Server,n=(await import('@modelcontextprotocol/sdk/server/stdio.js')).StdioServerTransport;}catch{throw new Error(H)}this.server=new e({name:this.options.name,version:this.options.version},{capabilities:{tools:{}}}),await this.setupRequestHandlers(),this.transport=new n,await this.server.connect(this.transport);}async startHttp(){let e;try{e=(await import('@modelcontextprotocol/sdk/server/index.js')).Server;}catch{throw new Error(H)}let r=(await import('@modelcontextprotocol/sdk/server/streamableHttp.js').catch(()=>null))?.StreamableHTTPServerTransport;if(!r)throw new Error("StreamableHTTPServerTransport not found in MCP SDK - ensure @modelcontextprotocol/sdk v1.26.0+ is installed");this.server=new e({name:this.options.name,version:this.options.version},{capabilities:{tools:{}}}),await this.setupRequestHandlers();let o=this.options.port,i=this.options.host;this.transport=new r({sessionIdGenerator:()=>crypto.randomUUID(),enableJsonResponse:true}),await this.server.connect(this.transport);let d=this.transport.handleRequest;if(typeof d!="function")throw new Error("StreamableHTTPServerTransport.handleRequest not found - SDK may have changed");this.httpServer=http.createServer(async(f,a)=>{let l=f.url?.split("?")[0]??"";if(l!=="/mcp"&&l!=="/mcp/"){a.writeHead(404,{"Content-Type":"application/json"}),a.end(JSON.stringify({error:"Not Found",path:l}));return}try{await d.call(this.transport,f,a);}catch(p){let g=routecraft.isRouteCraftError(p)?p.meta.message:p instanceof Error?p.message:"MCP HTTP request error";this.context.logger.error({err:p},g),a.headersSent||(a.writeHead(500,{"Content-Type":"application/json"}),a.end(JSON.stringify({error:"Internal Server Error"})));}}),await new Promise((f,a)=>{this.httpServer.listen(o,i,()=>f()),this.httpServer.on("error",l=>{let p=routecraft.isRouteCraftError(l)?l.meta.message:l instanceof Error?l.message:"MCP HTTP server listen failed";this.context.logger.error({err:l},p),a(l);});});let c=this.getHttpPort()??o;this.context.logger.info({host:i,port:c,path:"/mcp"},"MCP HTTP server listening");}getHttpPort(){let e=this.httpServer?.address();if(e&&typeof e=="object"&&"port"in e)return e.port}async setupRequestHandlers(){let e;try{e=await import('@modelcontextprotocol/sdk/types.js');}catch{throw new Error(H)}let n=e,r=n.ListToolsRequestSchema,o=n.CallToolRequestSchema;if(!r||!o)throw new Error("MCP SDK types missing ListToolsRequestSchema or CallToolRequestSchema - ensure @modelcontextprotocol/sdk is installed");let i=this.server;i.setRequestHandler(r,async()=>{let s=this.getAvailableTools();return this.logExposedToolsOnce(),{tools:s}}),i.setRequestHandler(o,async s=>{let c=s.params;return await this.handleToolCall(c.name||"",c.arguments||{})});}async stop(){if(this.running)try{if(this.httpServer&&(await new Promise(e=>{this.httpServer.close(()=>e());}),this.httpServer=null),this.transport){let e=this.transport;typeof e.close=="function"&&await e.close();}this.running=!1,this.context.logger.info({},"MCP server stopped");}catch(e){let n=routecraft.isRouteCraftError(e)?e.meta.message:e instanceof Error?e.message:"Error stopping MCP server";this.context.logger.error({err:e},n);}}logExposedToolsOnce(){if(this.toolsListLogged)return;let e=this.getAvailableTools();if(e.length===0)return;let n=e.map(r=>r.name??"?");this.context.logger.info({tools:n,count:n.length},"Exposing MCP tools"),this.toolsListLogged=true;}getAvailableTools(){let e=this.context.getStore(routecraft.ADAPTER_DIRECT_REGISTRY);if(!e)return [];let n=Array.from(e.values()).filter(o=>o.description!==void 0),r=this.options.tools;if(r)if(Array.isArray(r)){let o=new Set(r);n=n.filter(i=>o.has(i.endpoint));}else typeof r=="function"&&(n=n.filter(r));return n.map(o=>this.metadataToMcpTool(o))}metadataToMcpTool(e){return {name:e.endpoint,description:e.description||"",inputSchema:this.schemaToJsonSchema(e.schema)}}schemaToJsonSchema(e){if(!e||typeof e!="object")return {type:"object"};let n=e["~standard"];if(n?.jsonSchema?.input)try{let r=n.jsonSchema.input({target:"draft-2020-12"});return typeof r=="object"&&r!==null?r:{type:"object"}}catch(r){return this.context.logger.debug(r,"Standard JSON Schema conversion failed"),{type:"object"}}return "~standard"in e?{type:"object",additionalProperties:true}:{type:"object"}}async handleToolCall(e,n){try{let r=this.context.getStore(routecraft.ADAPTER_DIRECT_STORE);if(!r){let a=new Error("No direct channels available");return this.context.emit("error",{error:a}),{content:[{type:"text",text:"Error: No direct channels available"}]}}let o=r.get(e);if(!o){let a=new Error(`Tool not found: ${e}`);return this.context.emit("error",{error:a}),{content:[{type:"text",text:`Error: Tool not found: ${e}`}]}}let i=typeof n=="string"?(()=>{try{return JSON.parse(n)||{}}catch{return {input:n}}})():n&&typeof n=="object"?n:{};this.context.logger.debug({bodyType:typeof i,body:i},"MCP tool call exchange body");let s=new routecraft.DefaultExchange(this.context,{body:i,headers:{"routecraft.mcp.tool":e,"routecraft.mcp.session":`mcp-${Date.now()}`}}),c=await o.send(e,s);return {content:[{type:"text",text:typeof c.body=="string"?c.body:JSON.stringify(c.body)}]}}catch(r){let o=routecraft.isRouteCraftError(r)?r.meta.message:r instanceof Error?r.message:String(r);return this.context.logger.error({tool:e,err:r},o),this.context.emit("error",{error:r}),{content:[{type:"text",text:`Error: ${o}`}]}}}};function Q(t){if(t.transport==="http"){if(t.port!==void 0){if(typeof t.port!="number")throw new TypeError("mcpPlugin: when transport is 'http', port must be a number");if(t.port<0||t.port>65535)throw new RangeError("mcpPlugin: port must be between 0 and 65535 when transport is 'http'")}if(t.host!==void 0&&typeof t.host!="string")throw new TypeError("mcpPlugin: when provided, host must be a string")}}async function Z(t,e){let n=e["~standard"];if(!n?.validate)throw new Error("mcpPlugin: schema must be a StandardSchemaV1 with ~standard.validate");let r=n.validate(t);if(r instanceof Promise&&(r=await r),r.issues)throw new Error(`mcpPlugin options validation failed: ${JSON.stringify(r.issues)}`);if(r.value===void 0)throw new Error("mcpPlugin options validation failed: no value returned");return r.value}function ee(t={}){Q(t);let e=null;return {async apply(n){if(n.setStore(x,true),t.clients&&Object.keys(t.clients).length>0){let r=new Map(Object.entries(t.clients));n.setStore(h,r);}e=new b(n,t),await e.start();},async teardown(n){if(e){try{await e.stop();}catch(r){n.logger.error(r,"Error stopping MCP server plugin");}e=null;}}}}var U=class{constructor(e){this._options=e;}async run(e){return this._options,e.logger&&e.logger.debug({adapter:"agent"},"Agent pass-through \u2014 implementation pending"),{output:e.body,steps:0}}};function _e(t){let e=t.indexOf(":");if(e<1||e===t.length-1)throw new Error(`Agent adapter: modelId must be "providerId:modelName" (e.g. ollama:llama3). Got: "${t}"`)}var R=class{adapterId="routecraft.adapter.agent";runner;constructor(e){_e(e.modelId),this.runner=new U(e);}async send(e){return this.runner.run(e)}};function te(t){return new R(t)}var q=new Map;async function j(){let t=[...q.entries()];q.clear(),t.length!==0&&await Promise.all(t.map(async([,e])=>{try{typeof e.dispose=="function"&&await e.dispose();}catch{}}));}function Ne(t){return t.includes("/")?t:`Xenova/${t}`}var Ue='The Hugging Face embedding provider requires "@huggingface/transformers". Install it with: pnpm add @huggingface/transformers';function qe(t,e){if(!(t instanceof Error))return false;let n=t.message??"";return (n.includes("ERR_MODULE_NOT_FOUND")||n.includes("Cannot find module")||n.includes("Cannot find package"))&&n.includes(e)}async function je(t){let e=Ne(t),n=q.get(e);if(n)return n.run;let r;try{r=(await import('@huggingface/transformers')).pipeline;}catch(d){throw qe(d,"@huggingface/transformers")?new Error(Ue):d}let o=await r("feature-extraction",e,{dtype:"fp32"}),i=(d,c)=>o(d,{pooling:c?.pooling??"mean",normalize:c?.normalize??true}),s={run:i,dispose:typeof o.dispose=="function"?()=>Promise.resolve(o.dispose()):void 0};return q.set(e,s),i}function ne(t){if(t===null)return "null";if(typeof t!="object")return String(t);if(Array.isArray(t))return `array(${t.length})`;try{let e=JSON.stringify(t);return e.length>100?e.slice(0,100)+"...":e}catch{return "object"}}function Ge(t){if(Array.isArray(t))return t;if(t instanceof Float32Array)return Array.from(t);if(t&&typeof t=="object"&&"data"in t){let e=t.data;if(Array.isArray(e))return e;if(e instanceof Float32Array)return Array.from(e);throw new Error(`Embedding output .data must be an Array or Float32Array; got ${typeof e}: ${ne(e)}`)}throw new Error(`Embedding output must be an Array, Float32Array, or object with .data; got ${typeof t}: ${ne(t)}`)}async function re(t){let{config:e,modelName:n,text:r}=t;if(e.provider==="mock"){let i=[];for(let s=0;s<8;s++)i.push((r.length+s)%100/100);return i}if(e.provider==="huggingface"){let i=await(await je(n))(r,{pooling:"mean",normalize:true}),s=i&&typeof i=="object"&&"data"in i?i.data:i;return Ge(s)}throw e.provider==="ollama"||e.provider==="openai"?new Error(`Embedding provider "${e.provider}" is not yet implemented. Use huggingface for now.`):new Error(`Unknown embedding provider: ${e.provider}`)}var G=Symbol.for("routecraft.adapter.embedding.providers"),$=Symbol.for("routecraft.adapter.embedding.options");function He(t){let e=t.indexOf(":");if(e<1||e===t.length-1)throw new Error(`Embedding adapter: model id must be "providerId:modelName" (e.g. huggingface:all-MiniLM-L6-v2). Got: "${t}"`);return {providerId:t.slice(0,e),modelName:t.slice(e+1)}}function Ve(t,e){if(!e)throw new Error(`Embedding adapter: model id "${t}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so embedding providers can be read.`);let n=e.getStore(G);if(!n)throw new Error("Embedding provider not found: no providers registered. Add embeddingPlugin({ providers: { huggingface: {} } }) to your config.");let{providerId:r,modelName:o}=He(t),i=n.get(r);if(!i)throw new Error(`Embedding provider "${r}" not found. Register it with embeddingPlugin({ providers: { "${r}": {} } }).`);return {config:i,modelName:o}}function Ke(t){return e=>{let n=t(e);return Array.isArray(n)?n.filter(Boolean).join(" | "):n}}var S=class{constructor(e,n={}){this.modelId=e;this.options=n;}adapterId="routecraft.adapter.embedding";options;mergedOptions(e){return {...e.getStore($),...this.options}}async send(e){let n=routecraft.getExchangeContext(e),{config:r,modelName:o}=Ve(this.modelId,n),i=this.mergedOptions(n);if(!i.using)throw new Error("Embedding adapter: options.using(exchange) is required to build the string to embed.");let d=Ke(i.using)(e);return {embedding:await re({config:r,modelName:o,text:d})}}};function oe(t,e){return new S(t,e)}function Fe(t,e){return {...e,provider:t}}function ie(t={providers:{}}){return {apply(e){let n=new Map;for(let[r,o]of Object.entries(t.providers))o!==void 0&&n.set(r,Fe(r,o));e.setStore(G,n),t.defaultOptions&&Object.keys(t.defaultOptions).length>0&&e.setStore($,t.defaultOptions);},async teardown(){await j();}}}
2
- exports.ADAPTER_LLM_OPTIONS=E;exports.ADAPTER_LLM_PROVIDERS=w;exports.ADAPTER_MCP_CLIENT_SERVERS=h;exports.AgentDestinationAdapter=R;exports.BRAND=V;exports.BRAND_MCP_ADAPTER=v;exports.EmbeddingDestinationAdapter=S;exports.LlmDestinationAdapter=M;exports.MCP_PLUGIN_REGISTERED=x;exports.McpServer=b;exports.agent=te;exports.defaultArgs=N;exports.disposeEmbeddingPipelineCache=j;exports.embedding=oe;exports.embeddingPlugin=ie;exports.isMcpAdapter=ae;exports.llm=J;exports.llmPlugin=X;exports.mcp=Y;exports.mcpPlugin=ee;exports.validateLlmPluginOptions=I;exports.validateWithSchema=Z;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var routecraft=require('@routecraft/routecraft'),ai=require('ai'),http=require('http');var V={McpAdapter:Symbol.for("routecraft.ai.McpAdapter")};function ae(t,e){return typeof t=="object"&&t!==null&&t[e]===true}function pe(t){return ae(t,V.McpAdapter)}function L(t,e){throw new Error(`The ${e} LLM provider requires the "${t}" package. Install it with: pnpm add ${t}`)}function O(t,e){if(!(t instanceof Error))return false;let n=t.message??"";return (n.includes("ERR_MODULE_NOT_FOUND")||n.includes("Cannot find module")||n.includes("Cannot find package"))&&n.includes(e)}var de={ollama:{baseURL:"http://localhost:11434/api"}};function C(t){return {...t.inputTokens!==void 0&&{inputTokens:t.inputTokens},...t.outputTokens!==void 0&&{outputTokens:t.outputTokens},...t.totalTokens!==void 0&&{totalTokens:t.totalTokens}}}function k(t){try{if("output"in t&&t.output!==void 0)return t.output}catch{}}function K(t,e,n){if(t===null||typeof t!="object")throw new Error(`[${e}] Invalid model: expected an object, got ${typeof t}. Model id: ${n}`);let r=t;if(typeof r.doGenerate!="function")throw new Error(`[${e}] Invalid model: missing or invalid doGenerate method. Model id: ${n}. Ensure the provider returns an AI SDK-compatible language model.`);if(typeof r.doStream!="function")throw new Error(`[${e}] Invalid model: missing or invalid doStream method. Model id: ${n}. Ensure the provider returns an AI SDK-compatible language model.`)}async function F(t){let{config:e,modelId:n,options:r,systemPrompt:o,userPrompt:i,output:s}=t;switch(e.provider){case "openai":return le(e,n,r,o,i,s);case "anthropic":return ce(e,n,r,o,i,s);case "gemini":return ue(e,n,r,o,i,s);case "openrouter":return me(e,n,r,o,i,s);case "ollama":return ge(e,n,r,o,i,s);default:{let d=e;throw new Error(`LLM provider not implemented: ${d.provider}`)}}}async function le(t,e,n,r,o,i){let s;try{s=(await import('@ai-sdk/openai')).createOpenAI;}catch(y){throw O(y,"@ai-sdk/openai")&&L("@ai-sdk/openai","OpenAI"),y}let{generateText:d}=await import('ai'),c={apiKey:t.apiKey};t.baseURL!==void 0&&(c.baseURL=t.baseURL);let l={model:s(c)(e),prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(l.system=r),n.topP!==void 0&&(l.topP=n.topP),n.frequencyPenalty!==void 0&&(l.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(l.presencePenalty=n.presencePenalty);let p=i!==void 0?{...l,output:i}:l,g=await d(p),u={text:g.text??"",raw:g};g.usage&&(u.usage=C(g.usage));let m=k(g);return m!==void 0&&(u.output=m),u}async function ce(t,e,n,r,o,i){let s;try{s=(await import('@ai-sdk/anthropic')).createAnthropic;}catch(m){throw O(m,"@ai-sdk/anthropic")&&L("@ai-sdk/anthropic","Anthropic"),m}let{generateText:d}=await import('ai'),a={model:s({apiKey:t.apiKey})(e),prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(a.system=r),n.topP!==void 0&&(a.topP=n.topP),n.frequencyPenalty!==void 0&&(a.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(a.presencePenalty=n.presencePenalty);let l=i!==void 0?{...a,output:i}:a,p=await d(l),g={text:p.text??"",raw:p};p.usage&&(g.usage=C(p.usage));let u=k(p);return u!==void 0&&(g.output=u),g}async function ue(t,e,n,r,o,i){let s;try{s=(await import('@ai-sdk/google')).createGoogleGenerativeAI;}catch(m){throw O(m,"@ai-sdk/google")&&L("@ai-sdk/google","Gemini"),m}let{generateText:d}=await import('ai'),a={model:s({apiKey:t.apiKey})(e),prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(a.system=r),n.topP!==void 0&&(a.topP=n.topP),n.frequencyPenalty!==void 0&&(a.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(a.presencePenalty=n.presencePenalty);let l=i!==void 0?{...a,output:i}:a,p=await d(l),g={text:p.text??"",raw:p};p.usage&&(g.usage=C(p.usage));let u=k(p);return u!==void 0&&(g.output=u),g}async function me(t,e,n,r,o,i){let s;try{s=(await import('@openrouter/ai-sdk-provider')).createOpenRouter;}catch(P){throw O(P,"@openrouter/ai-sdk-provider")&&L("@openrouter/ai-sdk-provider","OpenRouter"),P}let{generateText:d}=await import('ai'),c=s({apiKey:t.apiKey}),f=t.modelId??e,a=c.chat(f);K(a,"OpenRouter",f);let p={model:a,prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(p.system=r),n.topP!==void 0&&(p.topP=n.topP),n.frequencyPenalty!==void 0&&(p.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(p.presencePenalty=n.presencePenalty);let g=i!==void 0?{...p,output:i}:p,u=await d(g),m={text:u.text??"",raw:u};u.usage&&(m.usage=C(u.usage));let y=k(u);return y!==void 0&&(m.output=y),m}async function ge(t,e,n,r,o,i){let s;try{s=(await import('ollama-ai-provider-v2')).createOllama;}catch(P){throw O(P,"ollama-ai-provider-v2")&&L("ollama-ai-provider-v2","Ollama"),P}let{generateText:d}=await import('ai'),c=s({baseURL:t.baseURL??de.ollama.baseURL}),f=t.modelId??e,a=c(f);K(a,"Ollama",f);let p={model:a,prompt:o,...n.maxTokens!==void 0&&{maxOutputTokens:n.maxTokens},temperature:n.temperature};r&&(p.system=r),n.topP!==void 0&&(p.topP=n.topP),n.frequencyPenalty!==void 0&&(p.frequencyPenalty=n.frequencyPenalty),n.presencePenalty!==void 0&&(p.presencePenalty=n.presencePenalty);let g=i!==void 0?{...p,output:i}:p,u=await d(g),m={text:u.text??"",raw:u};u.usage&&(m.usage=C(u.usage));let y=k(u);return y!==void 0&&(m.output=y),m}function B(t){let e=t["~standard"];if(!e?.validate)throw new Error("LLM outputSchema must be a StandardSchemaV1 with ~standard.validate");let n=e.jsonSchema?.output?.({target:"draft-2020-12"})??e.jsonSchema?.input?.({target:"draft-2020-12"});if(!n||typeof n!="object")throw new Error("LLM outputSchema must expose ~standard.jsonSchema.output or .input for provider structured output");function r(i){let s;try{s=e.validate(i);}catch(c){return {success:false,error:c instanceof Error?c:new Error(String(c))}}return s instanceof Promise?{success:false,error:new Error("Async output schema is not supported for LLM structured output")}:s.issues!=null&&(Array.isArray(s.issues)?s.issues.length>0:typeof s.issues=="object"&&s.issues!==null?Object.keys(s.issues).length>0:!!s.issues)?{success:false,error:new Error(typeof s.issues=="string"?s.issues:JSON.stringify(s.issues))}:{success:true,value:s.value}}let o=ai.jsonSchema(n,{validate:r});return ai.Output.object({schema:o})}var w=Symbol.for("routecraft.adapter.llm.providers"),M=Symbol.for("routecraft.adapter.llm.options");async function Pe(t,e){let n;try{n=JSON.parse(t);}catch{return}let r=e["~standard"];if(!r?.validate)return;let o=r.validate(n);if(o instanceof Promise&&(o=await o),!(o&&typeof o=="object"&&"issues"in o&&o.issues))return o&&typeof o=="object"&&"value"in o?o.value:void 0}var we=0,ve=1024;function W(t,e){return t===void 0||t===""?"":typeof t=="function"?t(e):t}function Me(t){let e=t.body;return typeof e=="string"?e:e==null?"":typeof e=="object"?JSON.stringify(e):String(e)}function J(t){let e=t.indexOf(":");if(e<1||e===t.length-1)throw new Error(`LLM adapter: model id must be "providerId:modelName" (e.g. ollama:lfm2.5-thinking). Got: "${t}"`);return {providerId:t.slice(0,e),modelName:t.slice(e+1)}}function Ee(t,e){if(!e)throw new Error(`LLM adapter: model id "${t}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store "${w.description}" can be read.`);let n=e.getStore(w);if(!n)throw new Error('LLM provider not found: no providers registered. Add llmPlugin({ providers: { ollama: { provider: "ollama" }, ... } }) to your config.');let{providerId:r,modelName:o}=J(t),i=n.get(r);if(!i)throw new Error(`LLM provider "${r}" not found. Register it with llmPlugin({ providers: { "${r}": { provider, apiKey?, baseURL? } } }).`);return {config:i,modelName:o}}var E=class{constructor(e,n={}){this.modelId=e;this.options=n;}adapterId="routecraft.adapter.llm";options;mergedOptions(e){let n=e.getStore(M);return {temperature:we,maxTokens:ve,...n,...this.options}}async send(e){let n=routecraft.getExchangeContext(e),{config:r,modelName:o}=Ee(this.modelId,n),i=this.mergedOptions(n),s=W(i.systemPrompt,e),d=W(i.userPrompt,e)||Me(e),c={temperature:i.temperature,maxTokens:i.maxTokens};i.topP!==void 0&&(c.topP=i.topP),i.frequencyPenalty!==void 0&&(c.frequencyPenalty=i.frequencyPenalty),i.presencePenalty!==void 0&&(c.presencePenalty=i.presencePenalty);let f=i.outputSchema!==void 0?B(i.outputSchema):void 0,a=await F({config:r,modelId:o,options:c,systemPrompt:s,userPrompt:d,output:f});if(a.output===void 0&&a.text&&i.outputSchema!==void 0){let l=await Pe(a.text,i.outputSchema);l!==void 0&&(a.output=l);}return a}getMetadata(e){let n=e,{providerId:r}=J(this.modelId),o={model:this.modelId,provider:r};return n.usage&&(n.usage.inputTokens!==void 0&&(o.inputTokens=n.usage.inputTokens),n.usage.outputTokens!==void 0&&(o.outputTokens=n.usage.outputTokens)),o}};function z(t,e){return new E(t,e)}var X=["openai","anthropic","openrouter","ollama","gemini"];function be(t){return X.includes(t)}function I(t){if(!t||typeof t!="object")throw new TypeError("llmPlugin: options must be an object");if(!t.providers||typeof t.providers!="object")throw new TypeError("llmPlugin: options.providers must be an object (record of provider id \u2192 options)");for(let[e,n]of Object.entries(t.providers))if(n!==void 0){if(!n||typeof n!="object")throw new TypeError(`llmPlugin: providers["${e}"] must be an object`);if(!be(e))throw new TypeError(`llmPlugin: providers["${e}"] is not a supported provider. Supported: ${X.join(", ")}`);switch(e){case "openai":case "anthropic":case "openrouter":case "gemini":if(typeof n.apiKey!="string"||!n.apiKey.trim())throw new TypeError(`llmPlugin: providers["${e}"].apiKey is required`);break;case "ollama":if(n.baseURL!==void 0&&typeof n.baseURL!="string")throw new TypeError(`llmPlugin: providers["${e}"].baseURL must be a string when provided`);if(n.modelId!==void 0&&(typeof n.modelId!="string"||!n.modelId.trim()))throw new TypeError(`llmPlugin: providers["${e}"].modelId must be a non-empty string when provided`);break}}if(t.defaultOptions!==void 0&&(typeof t.defaultOptions!="object"||t.defaultOptions===null))throw new TypeError("llmPlugin: defaultOptions must be an object when provided")}var xe=["openai","anthropic","openrouter","ollama","gemini"];function Re(t,e){return {provider:t,...e}}function Y(t={providers:{}}){return I(t),{apply(e){let n=new Map;for(let r of xe){let o=t.providers[r];o!==void 0&&n.set(r,Re(r,o));}e.setStore(w,n),t.defaultOptions&&Object.keys(t.defaultOptions).length>0&&e.setStore(M,t.defaultOptions);}}}var b=Symbol.for("routecraft.mcp.plugin.registered"),h=Symbol.for("routecraft.mcp.client.servers");var v=Symbol.for("routecraft.mcp.adapter");var _=class{adapterId="routecraft.adapter.mcp";endpoint;options;constructor(e,n){if(this[v]=true,typeof e!="string")throw routecraft.rcError("RC5003",void 0,{message:"Dynamic endpoints cannot be used as source",suggestion:"Use a static string endpoint for source: .from(mcp('endpoint', options))."});if("url"in n||"serverId"in n)throw routecraft.rcError("RC5003",void 0,{message:"mcp() with url or serverId must be used as destination: .to(mcp({ url, tool }))",suggestion:"Use .to(mcp({ url: '...', tool: '...' })) to call a remote MCP server."});if("args"in n&&n.args!==void 0&&!("description"in n))throw routecraft.rcError("RC5003",void 0,{message:"mcp(endpoint, { args }) is for client usage with a 'server:tool' target, not for defining a source",suggestion:"Use .to(mcp('server:tool', { args })) to call a remote tool, or .from(mcp('endpoint', { description: '...' })) to define a source."});if(!("description"in n)||typeof n.description!="string")throw routecraft.rcError("RC5003",void 0,{message:"mcp(endpoint, options) as source requires options.description",suggestion:"Use .from(mcp('endpoint', { description: '...' })) to define a source."});this.endpoint=e,this.options=n;}async subscribe(e,n,r,o){if(e.getStore(b)!==true)throw new Error("MCP plugin required: routes using .from(mcp(...)) require the MCP plugin. Add mcpPlugin() to your config: plugins: [mcpPlugin()].");return routecraft.direct(this.endpoint,this.options).subscribe(e,n,r,o)}};function Oe(t){let e=t.trim().toLowerCase();if(!e.startsWith("http://")&&!e.startsWith("https://"))throw new Error(`MCP client: url must be HTTP or HTTPS. Stdio is not supported in routes; register stdio clients via mcpPlugin({ clients: { name: { command, args } } }). Got: "${t.slice(0,50)}${t.length>50?"...":""}"`)}function Ce(t,e){if(t.url)return Oe(t.url),t.url;if(t.serverId&&!e)throw new Error(`MCP client: serverId "${t.serverId}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so store "${String(h)}" can be read.`);if(t.serverId&&e){let r=e.getStore(h)?.get(t.serverId);if(!r)throw new Error(`MCP client: serverId "${t.serverId}" not found in context store. Register it with context store key "${String(h)}".`);return typeof r=="string"?r:r.url}throw new Error("MCP client: either url or serverId must be provided in McpClientOptions.")}var N=t=>typeof t.body=="object"&&t.body!==null?t.body:{input:t.body},T=class{constructor(e){this.options=e;if(this[v]=true,!e.url&&!e.serverId)throw new Error("MCP client: either url or serverId must be provided in McpClientOptions.");if(e.url&&e.serverId)throw new Error("MCP client: cannot provide both url and serverId. Use either url for direct HTTP or serverId for registered servers.")}adapterId="routecraft.adapter.mcp";async send(e){let n=routecraft.getExchangeContext(e),r=Ce(this.options,n),o=this.options.tool??(typeof e.body=="object"&&e.body!==null&&"tool"in e.body&&typeof e.body.tool=="string"?e.body.tool:void 0);if(!o)throw new Error("MCP client: tool name required. Set options.tool or exchange.body.tool.");let s=(this.options.args??N)(e),d=await this.callRemoteTool(r,o,s);return d&&typeof d=="object"&&(d.metadata={toolName:o,url:r,transport:"http",...this.options.serverId?{serverId:this.options.serverId}:{}}),d}getMetadata(e){return e&&typeof e=="object"&&"metadata"in e?e.metadata:{toolName:"unknown",transport:"http"}}async callRemoteTool(e,n,r){let o,i;try{o=await import('@modelcontextprotocol/sdk/client/index.js'),i=await import('@modelcontextprotocol/sdk/client/streamableHttp.js');}catch{throw new Error('MCP client requires "@modelcontextprotocol/sdk". Install it with: pnpm add @modelcontextprotocol/sdk')}let s=o.Client,d=i.StreamableHTTPClientTransport,c=new URL(e),f=new d(c),a={name:"routecraft-mcp-client",version:"1.0.0"},l=new s(a,{capabilities:{}});try{await l.connect.call(l,f);let u=await l.callTool.call(l,{name:n,arguments:r}),m=u?.content;if(Array.isArray(m)&&m.length>0){let y=m[0];if(y&&typeof y=="object"&&"text"in y)return y.text;if(y&&typeof y=="object"&&"data"in y)return y.data}return u}finally{let p=l,g=p.close??p.disconnect;if(typeof g=="function")try{await Promise.resolve(g.call(l));}catch{}let u=f,m=u.close??u.destroy;if(typeof m=="function")try{await Promise.resolve(m.call(f));}catch{}}}};function Q(t,e){if(typeof t=="object"&&t!==null&&("url"in t||"serverId"in t))return new T(t);let n=e===void 0||typeof e=="object"&&e!==null&&!("description"in e);if(typeof t=="string"&&t.includes(":")&&n){let o=t.indexOf(":"),i=t.slice(0,o),s=t.slice(o+1),d={serverId:i,tool:s};return e!==void 0&&typeof e=="object"&&"args"in e&&e.args!==void 0&&(d.args=e.args),new T(d)}let r=t;if(e!==void 0)return new _(r,e);throw routecraft.rcError("RC5003",void 0,{message:"mcp() with only an endpoint is not supported. Use direct('endpoint') for in-process. For MCP server use .from(mcp('endpoint', { description: '...' })); for client use .to(mcp({ url, tool })) or .to(mcp('server:tool', { args })).",suggestion:"Use .from(mcp('endpoint', { description: '...' })) or .to(mcp({ url, tool })) or direct('endpoint')."})}var H='MCP server requires "@modelcontextprotocol/sdk". Install it with: pnpm add @modelcontextprotocol/sdk',x=class{context;options;server=null;transport=null;httpServer=null;running=false;toolsListLogged=false;constructor(e,n={}){this.context=e,this.options={name:"routecraft",version:"1.0.0",transport:"stdio",port:3001,host:"localhost",...n};}async start(){if(this.running){this.context.logger.warn({},"MCP server already running");return}try{let e=this.options.transport;e==="http"?await this.startHttp():await this.startStdio(),this.running=!0,this.context.logger.info({name:this.options.name,version:this.options.version,transport:e},"MCP server started"),this.logExposedToolsOnce();}catch(e){let n=routecraft.isRouteCraftError(e)?e.meta.message:e instanceof Error?e.message:"Failed to start MCP server";throw this.context.logger.error({err:e},n),e}}async startStdio(){let e,n;try{e=(await import('@modelcontextprotocol/sdk/server/index.js')).Server,n=(await import('@modelcontextprotocol/sdk/server/stdio.js')).StdioServerTransport;}catch{throw new Error(H)}this.server=new e({name:this.options.name,version:this.options.version},{capabilities:{tools:{}}}),await this.setupRequestHandlers(),this.transport=new n,await this.server.connect(this.transport);}async startHttp(){let e;try{e=(await import('@modelcontextprotocol/sdk/server/index.js')).Server;}catch{throw new Error(H)}let r=(await import('@modelcontextprotocol/sdk/server/streamableHttp.js').catch(()=>null))?.StreamableHTTPServerTransport;if(!r)throw new Error("StreamableHTTPServerTransport not found in MCP SDK - ensure @modelcontextprotocol/sdk v1.26.0+ is installed");this.server=new e({name:this.options.name,version:this.options.version},{capabilities:{tools:{}}}),await this.setupRequestHandlers();let o=this.options.port,i=this.options.host;this.transport=new r({sessionIdGenerator:()=>crypto.randomUUID(),enableJsonResponse:true}),await this.server.connect(this.transport);let d=this.transport.handleRequest;if(typeof d!="function")throw new Error("StreamableHTTPServerTransport.handleRequest not found - SDK may have changed");this.httpServer=http.createServer(async(f,a)=>{let l=f.url?.split("?")[0]??"";if(l!=="/mcp"&&l!=="/mcp/"){a.writeHead(404,{"Content-Type":"application/json"}),a.end(JSON.stringify({error:"Not Found",path:l}));return}try{await d.call(this.transport,f,a);}catch(p){let g=routecraft.isRouteCraftError(p)?p.meta.message:p instanceof Error?p.message:"MCP HTTP request error";this.context.logger.error({err:p},g),a.headersSent||(a.writeHead(500,{"Content-Type":"application/json"}),a.end(JSON.stringify({error:"Internal Server Error"})));}}),await new Promise((f,a)=>{this.httpServer.listen(o,i,()=>f()),this.httpServer.on("error",l=>{let p=routecraft.isRouteCraftError(l)?l.meta.message:l instanceof Error?l.message:"MCP HTTP server listen failed";this.context.logger.error({err:l},p),a(l);});});let c=this.getHttpPort()??o;this.context.logger.info({host:i,port:c,path:"/mcp"},"MCP HTTP server listening");}getHttpPort(){let e=this.httpServer?.address();if(e&&typeof e=="object"&&"port"in e)return e.port}async setupRequestHandlers(){let e;try{e=await import('@modelcontextprotocol/sdk/types.js');}catch{throw new Error(H)}let n=e,r=n.ListToolsRequestSchema,o=n.CallToolRequestSchema;if(!r||!o)throw new Error("MCP SDK types missing ListToolsRequestSchema or CallToolRequestSchema - ensure @modelcontextprotocol/sdk is installed");let i=this.server;i.setRequestHandler(r,async()=>{let s=this.getAvailableTools();return this.logExposedToolsOnce(),{tools:s}}),i.setRequestHandler(o,async s=>{let c=s.params;return await this.handleToolCall(c.name||"",c.arguments||{})});}async stop(){if(this.running)try{if(this.httpServer&&(await new Promise(e=>{this.httpServer.close(()=>e());}),this.httpServer=null),this.transport){let e=this.transport;typeof e.close=="function"&&await e.close();}this.running=!1,this.context.logger.info({},"MCP server stopped");}catch(e){let n=routecraft.isRouteCraftError(e)?e.meta.message:e instanceof Error?e.message:"Error stopping MCP server";this.context.logger.error({err:e},n);}}logExposedToolsOnce(){if(this.toolsListLogged)return;let e=this.getAvailableTools();if(e.length===0)return;let n=e.map(r=>r.name??"?");this.context.logger.info({tools:n,count:n.length},"Exposing MCP tools"),this.toolsListLogged=true;}getAvailableTools(){let e=this.context.getStore(routecraft.ADAPTER_DIRECT_REGISTRY);if(!e)return [];let n=Array.from(e.values()).filter(o=>o.description!==void 0),r=this.options.tools;if(r)if(Array.isArray(r)){let o=new Set(r);n=n.filter(i=>o.has(i.endpoint));}else typeof r=="function"&&(n=n.filter(r));return n.map(o=>this.metadataToMcpTool(o))}metadataToMcpTool(e){return {name:e.endpoint,description:e.description||"",inputSchema:this.schemaToJsonSchema(e.schema)}}schemaToJsonSchema(e){if(!e||typeof e!="object")return {type:"object"};let n=e["~standard"];if(n?.jsonSchema?.input)try{let r=n.jsonSchema.input({target:"draft-2020-12"});return typeof r=="object"&&r!==null?r:{type:"object"}}catch(r){return this.context.logger.debug(r,"Standard JSON Schema conversion failed"),{type:"object"}}return "~standard"in e?{type:"object",additionalProperties:true}:{type:"object"}}async handleToolCall(e,n){try{let r=this.context.getStore(routecraft.ADAPTER_DIRECT_STORE);if(!r){let a=new Error("No direct channels available");return this.context.emit("error",{error:a}),{content:[{type:"text",text:"Error: No direct channels available"}]}}let o=r.get(e);if(!o){let a=new Error(`Tool not found: ${e}`);return this.context.emit("error",{error:a}),{content:[{type:"text",text:`Error: Tool not found: ${e}`}]}}let i=typeof n=="string"?(()=>{try{return JSON.parse(n)||{}}catch{return {input:n}}})():n&&typeof n=="object"?n:{};this.context.logger.debug({bodyType:typeof i,body:i},"MCP tool call exchange body");let s=new routecraft.DefaultExchange(this.context,{body:i,headers:{"routecraft.mcp.tool":e,"routecraft.mcp.session":`mcp-${Date.now()}`}}),c=await o.send(e,s);return {content:[{type:"text",text:typeof c.body=="string"?c.body:JSON.stringify(c.body)}]}}catch(r){let o=routecraft.isRouteCraftError(r)?r.meta.message:r instanceof Error?r.message:String(r);return this.context.logger.error({tool:e,err:r},o),this.context.emit("error",{error:r}),{content:[{type:"text",text:`Error: ${o}`}]}}}};function Z(t){if(t.transport==="http"){if(t.port!==void 0){if(typeof t.port!="number")throw new TypeError("mcpPlugin: when transport is 'http', port must be a number");if(t.port<0||t.port>65535)throw new RangeError("mcpPlugin: port must be between 0 and 65535 when transport is 'http'")}if(t.host!==void 0&&typeof t.host!="string")throw new TypeError("mcpPlugin: when provided, host must be a string")}}async function ee(t,e){let n=e["~standard"];if(!n?.validate)throw new Error("mcpPlugin: schema must be a StandardSchemaV1 with ~standard.validate");let r=n.validate(t);if(r instanceof Promise&&(r=await r),r.issues)throw new Error(`mcpPlugin options validation failed: ${JSON.stringify(r.issues)}`);if(r.value===void 0)throw new Error("mcpPlugin options validation failed: no value returned");return r.value}function te(t={}){Z(t);let e=null;return {async apply(n){if(n.setStore(b,true),t.clients&&Object.keys(t.clients).length>0){let r=new Map(Object.entries(t.clients));n.setStore(h,r);}e=new x(n,t),await e.start();},async teardown(n){if(e){try{await e.stop();}catch(r){n.logger.error(r,"Error stopping MCP server plugin");}e=null;}}}}var U=class{constructor(e){this._options=e;}async run(e){return this._options,e.logger&&e.logger.debug({adapter:"agent"},"Agent pass-through \u2014 implementation pending"),{output:e.body,steps:0}}};function _e(t){let e=t.indexOf(":");if(e<1||e===t.length-1)throw new Error(`Agent adapter: modelId must be "providerId:modelName" (e.g. ollama:llama3). Got: "${t}"`)}var R=class{adapterId="routecraft.adapter.agent";runner;constructor(e){_e(e.modelId),this.runner=new U(e);}async send(e){return this.runner.run(e)}};function ne(t){return new R(t)}var j=new Map;async function q(){let t=[...j.entries()];j.clear(),t.length!==0&&await Promise.all(t.map(async([,e])=>{try{typeof e.dispose=="function"&&await e.dispose();}catch{}}));}function Ne(t){return t.includes("/")?t:`Xenova/${t}`}var Ue='The Hugging Face embedding provider requires "@huggingface/transformers". Install it with: pnpm add @huggingface/transformers';function je(t,e){if(!(t instanceof Error))return false;let n=t.message??"";return (n.includes("ERR_MODULE_NOT_FOUND")||n.includes("Cannot find module")||n.includes("Cannot find package"))&&n.includes(e)}async function qe(t){let e=Ne(t),n=j.get(e);if(n)return n.run;let r;try{r=(await import('@huggingface/transformers')).pipeline;}catch(d){throw je(d,"@huggingface/transformers")?new Error(Ue):d}let o=await r("feature-extraction",e,{dtype:"fp32"}),i=(d,c)=>o(d,{pooling:c?.pooling??"mean",normalize:c?.normalize??true}),s={run:i,dispose:typeof o.dispose=="function"?()=>Promise.resolve(o.dispose()):void 0};return j.set(e,s),i}function re(t){if(t===null)return "null";if(typeof t!="object")return String(t);if(Array.isArray(t))return `array(${t.length})`;try{let e=JSON.stringify(t);return e.length>100?e.slice(0,100)+"...":e}catch{return "object"}}function Ge(t){if(Array.isArray(t))return t;if(t instanceof Float32Array)return Array.from(t);if(t&&typeof t=="object"&&"data"in t){let e=t.data;if(Array.isArray(e))return e;if(e instanceof Float32Array)return Array.from(e);throw new Error(`Embedding output .data must be an Array or Float32Array; got ${typeof e}: ${re(e)}`)}throw new Error(`Embedding output must be an Array, Float32Array, or object with .data; got ${typeof t}: ${re(t)}`)}async function oe(t){let{config:e,modelName:n,text:r}=t;if(e.provider==="mock"){let i=[];for(let s=0;s<8;s++)i.push((r.length+s)%100/100);return i}if(e.provider==="huggingface"){let i=await(await qe(n))(r,{pooling:"mean",normalize:true}),s=i&&typeof i=="object"&&"data"in i?i.data:i;return Ge(s)}throw e.provider==="ollama"||e.provider==="openai"?new Error(`Embedding provider "${e.provider}" is not yet implemented. Use huggingface for now.`):new Error(`Unknown embedding provider: ${e.provider}`)}var G=Symbol.for("routecraft.adapter.embedding.providers"),$=Symbol.for("routecraft.adapter.embedding.options");function He(t){let e=t.indexOf(":");if(e<1||e===t.length-1)throw new Error(`Embedding adapter: model id must be "providerId:modelName" (e.g. huggingface:all-MiniLM-L6-v2). Got: "${t}"`);return {providerId:t.slice(0,e),modelName:t.slice(e+1)}}function Ve(t,e){if(!e)throw new Error(`Embedding adapter: model id "${t}" requires a context to resolve. Ensure the exchange has context (e.g. from a route) so embedding providers can be read.`);let n=e.getStore(G);if(!n)throw new Error("Embedding provider not found: no providers registered. Add embeddingPlugin({ providers: { huggingface: {} } }) to your config.");let{providerId:r,modelName:o}=He(t),i=n.get(r);if(!i)throw new Error(`Embedding provider "${r}" not found. Register it with embeddingPlugin({ providers: { "${r}": {} } }).`);return {config:i,modelName:o}}function Ke(t){return e=>{let n=t(e);return Array.isArray(n)?n.filter(Boolean).join(" | "):n}}var S=class{constructor(e,n={}){this.modelId=e;this.options=n;}adapterId="routecraft.adapter.embedding";options;mergedOptions(e){return {...e.getStore($),...this.options}}async send(e){let n=routecraft.getExchangeContext(e),{config:r,modelName:o}=Ve(this.modelId,n),i=this.mergedOptions(n);if(!i.using)throw new Error("Embedding adapter: options.using(exchange) is required to build the string to embed.");let d=Ke(i.using)(e);return {embedding:await oe({config:r,modelName:o,text:d})}}};function ie(t,e){return new S(t,e)}function Fe(t,e){return {...e,provider:t}}function se(t={providers:{}}){return {apply(e){let n=new Map;for(let[r,o]of Object.entries(t.providers))o!==void 0&&n.set(r,Fe(r,o));e.setStore(G,n),t.defaultOptions&&Object.keys(t.defaultOptions).length>0&&e.setStore($,t.defaultOptions);},async teardown(){await q();}}}
2
+ exports.ADAPTER_LLM_OPTIONS=M;exports.ADAPTER_LLM_PROVIDERS=w;exports.ADAPTER_MCP_CLIENT_SERVERS=h;exports.AgentDestinationAdapter=R;exports.BRAND=V;exports.BRAND_MCP_ADAPTER=v;exports.EmbeddingDestinationAdapter=S;exports.LlmDestinationAdapter=E;exports.MCP_PLUGIN_REGISTERED=b;exports.McpServer=x;exports.agent=ne;exports.defaultArgs=N;exports.disposeEmbeddingPipelineCache=q;exports.embedding=ie;exports.embeddingPlugin=se;exports.isMcpAdapter=pe;exports.llm=z;exports.llmPlugin=Y;exports.mcp=Q;exports.mcpPlugin=te;exports.validateLlmPluginOptions=I;exports.validateWithSchema=ee;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map