@mcp-ts/sdk 1.1.0 → 1.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 +65 -50
- package/dist/adapters/agui-adapter.js +0 -1
- package/dist/adapters/agui-adapter.js.map +1 -1
- package/dist/adapters/agui-adapter.mjs +0 -1
- package/dist/adapters/agui-adapter.mjs.map +1 -1
- package/dist/adapters/agui-middleware.d.mts +2 -16
- package/dist/adapters/agui-middleware.d.ts +2 -16
- package/dist/adapters/agui-middleware.js +9 -40
- package/dist/adapters/agui-middleware.js.map +1 -1
- package/dist/adapters/agui-middleware.mjs +10 -40
- package/dist/adapters/agui-middleware.mjs.map +1 -1
- package/dist/client/react.d.mts +72 -5
- package/dist/client/react.d.ts +72 -5
- package/dist/client/react.js +102 -6
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +102 -7
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.js +1 -1
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +1 -1
- package/dist/client/vue.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18 -1
- package/dist/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +38 -2
- package/dist/shared/index.d.ts +38 -2
- package/dist/shared/index.js +19 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +18 -1
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/adapters/agui-adapter.ts +2 -4
- package/src/adapters/agui-middleware.ts +38 -99
- package/src/client/react/index.ts +16 -11
- package/src/client/react/{use-mcp-app.ts → use-app-host.ts} +2 -2
- package/src/client/react/use-mcp-apps.tsx +213 -0
- package/src/client/react/{useMcp.ts → use-mcp.ts} +2 -2
- package/src/client/vue/index.ts +1 -1
- package/src/shared/index.ts +6 -1
- package/src/shared/tool-utils.ts +61 -0
- /package/src/client/vue/{useMcp.ts → use-mcp.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<
|
|
3
|
-
<img src="docs/static/img/logo.svg" alt="mcp-ts Logo" width="80" height="80" />
|
|
4
|
-
</a>
|
|
5
|
-
<h1 align="center">@mcp-ts</h1>
|
|
6
|
-
<p>TypeScript SDK providing MCP capabilities to agents across JavaScript/cross-runtime environments.</p>
|
|
2
|
+
<img src="docs/static/img/mcp-ts-banner.svg" alt="MCP-TS Banner" width="100%" style="max-width: 1200px;" />
|
|
7
3
|
</div>
|
|
8
4
|
|
|
9
5
|
<div align="center">
|
|
10
|
-
<a href="https://github.
|
|
11
|
-
<em>
|
|
6
|
+
<a href="https://zonlabs.github.io/mcp-ts/#ag-ui-demo">
|
|
7
|
+
<em>Watch AG-UI + LangChain demo</em>
|
|
12
8
|
</a>
|
|
13
9
|
</div>
|
|
14
10
|
<br />
|
|
@@ -24,7 +20,10 @@
|
|
|
24
20
|
|
|
25
21
|
<p align="center">
|
|
26
22
|
<a href="https://www.npmjs.com/package/@mcp-ts/sdk">
|
|
27
|
-
<img src="https://
|
|
23
|
+
<img src="https://img.shields.io/npm/v/@mcp-ts/sdk.svg" alt="npm version" />
|
|
24
|
+
</a>
|
|
25
|
+
<a href="https://zonlabs.github.io/mcp-ts/">
|
|
26
|
+
<img src="https://img.shields.io/badge/docs-website-brightgreen.svg" alt="Documentation" />
|
|
28
27
|
</a>
|
|
29
28
|
<a href="https://opensource.org/licenses/MIT">
|
|
30
29
|
<img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" />
|
|
@@ -44,8 +43,23 @@
|
|
|
44
43
|
- **Agent Adapters** - Built-in adapters for AI SDK, LangChain, Mastra, and AG-UI
|
|
45
44
|
- **MCP Apps Extension (SEP-1865)** - Interactive UI-driven tool interfaces
|
|
46
45
|
|
|
46
|
+
## Examples
|
|
47
|
+
|
|
48
|
+
Check out working examples demonstrating the MCP Apps extension and agent integrations in the [examples/agents](examples/agents) directory.
|
|
49
|
+
|
|
50
|
+
> Examples MCP Apps referred from [modelcontextprotocol/ext-apps](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples)
|
|
51
|
+
|
|
47
52
|
<div align="center">
|
|
48
|
-
<
|
|
53
|
+
<table cellspacing="5" cellpadding="0">
|
|
54
|
+
<tr>
|
|
55
|
+
<td width="50%">
|
|
56
|
+
<img src="docs/static/img/mcp-apps-img-1.png" alt="MCP Apps 1" width="100%" />
|
|
57
|
+
</td>
|
|
58
|
+
<td width="50%">
|
|
59
|
+
<img src="docs/static/img/mcp-apps-img-2.png" alt="MCP Apps 2" width="100%" />
|
|
60
|
+
</td>
|
|
61
|
+
</tr>
|
|
62
|
+
</table>
|
|
49
63
|
<p><em>Interactive UIs for MCP tools</em></p>
|
|
50
64
|
</div>
|
|
51
65
|
|
|
@@ -108,15 +122,11 @@ import { openai } from '@ai-sdk/openai';
|
|
|
108
122
|
|
|
109
123
|
export async function POST(req: Request) {
|
|
110
124
|
const { messages, identity } = await req.json();
|
|
111
|
-
|
|
112
125
|
const client = new MultiSessionClient(identity);
|
|
113
126
|
|
|
114
127
|
try {
|
|
115
128
|
await client.connect();
|
|
116
|
-
|
|
117
129
|
const tools = await AIAdapter.getTools(client);
|
|
118
|
-
|
|
119
|
-
|
|
120
130
|
const result = streamText({
|
|
121
131
|
model: openai('gpt-4'),
|
|
122
132
|
messages,
|
|
@@ -125,7 +135,6 @@ export async function POST(req: Request) {
|
|
|
125
135
|
await mcp.disconnect();
|
|
126
136
|
}
|
|
127
137
|
});
|
|
128
|
-
|
|
129
138
|
return result.toDataStreamResponse();
|
|
130
139
|
} catch (error) {
|
|
131
140
|
await mcp.disconnect();
|
|
@@ -134,41 +143,47 @@ export async function POST(req: Request) {
|
|
|
134
143
|
}
|
|
135
144
|
```
|
|
136
145
|
|
|
137
|
-
### Client-Side (React)
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
'use client';
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
146
|
+
### Client-Side (React)
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
'use client';
|
|
150
|
+
|
|
151
|
+
import { useMcp } from '@mcp-ts/sdk/client/react';
|
|
152
|
+
|
|
153
|
+
function App() {
|
|
154
|
+
const { connections, connect, status } = useMcp({
|
|
155
|
+
url: '/api/mcp',
|
|
156
|
+
identity: 'user-123',
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<>
|
|
161
|
+
<p>Status: {status}</p>
|
|
162
|
+
|
|
163
|
+
<button
|
|
164
|
+
onClick={() =>
|
|
165
|
+
connect({
|
|
166
|
+
serverId: 'my-server',
|
|
167
|
+
serverName: 'My MCP Server',
|
|
168
|
+
serverUrl: 'https://mcp.example.com',
|
|
169
|
+
callbackUrl: `${window.location.origin}/callback`,
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
>
|
|
173
|
+
Connect
|
|
174
|
+
</button>
|
|
175
|
+
|
|
176
|
+
{connections.map((conn) => (
|
|
177
|
+
<div key={conn.sessionId}>
|
|
178
|
+
<h3>{conn.serverName}</h3>
|
|
179
|
+
<p>State: {conn.state}</p>
|
|
180
|
+
<p>Tools: {conn.tools.length}</p>
|
|
181
|
+
</div>
|
|
182
|
+
))}
|
|
183
|
+
</>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
```
|
|
172
187
|
|
|
173
188
|
### <img src="docs/static/img/agent-framework/agui.webp" width="20" height="20" align="center" /> AG-UI Middleware
|
|
174
189
|
|
|
@@ -299,7 +314,7 @@ For more details, refer to the documentation and follow the **installation guide
|
|
|
299
314
|
|
|
300
315
|
## Contributing
|
|
301
316
|
|
|
302
|
-
Contributions are welcome! Please read [
|
|
317
|
+
Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on how to contribute.
|
|
303
318
|
|
|
304
319
|
## License
|
|
305
320
|
|
|
@@ -104,7 +104,6 @@ var AguiAdapter = class {
|
|
|
104
104
|
parameters: cleanSchema(tool.inputSchema),
|
|
105
105
|
_meta: { ...mcpTool._meta, sessionId: client.getSessionId?.() },
|
|
106
106
|
handler: async (args) => {
|
|
107
|
-
console.log(`[AguiAdapter] Executing MCP tool: ${mcpToolName}`, args);
|
|
108
107
|
const callResult = await client.callTool(mcpToolName, args ?? {});
|
|
109
108
|
return callResult;
|
|
110
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/agui-adapter.ts"],"names":[],"mappings":"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","file":"agui-adapter.js","sourcesContent":["/**\r\n * MCP Adapter for AG-UI Integration\r\n *\r\n * This adapter transforms MCP tools into formats compatible with AG-UI agents.\r\n * It provides tools with handlers for server-side execution and tool definitions\r\n * in JSON Schema format for passing to remote agents.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { MultiSessionClient } from '@mcp-ts/sdk/server';\r\n * import { AguiAdapter } from '@mcp-ts/sdk/adapters/agui-adapter';\r\n * import { createMcpMiddleware } from '@mcp-ts/sdk/adapters/agui-middleware';\r\n * import { HttpAgent } from '@ag-ui/client';\r\n *\r\n * // Create MCP client\r\n * const mcpClient = new MultiSessionClient('user_123');\r\n * await mcpClient.connect();\r\n *\r\n * // Create adapter and get tools\r\n * const adapter = new AguiAdapter(mcpClient);\r\n * const tools = await adapter.getTools();\r\n *\r\n * // Use with AG-UI middleware\r\n * const agent = new HttpAgent({ url: 'http://localhost:8000/agent' });\r\n * agent.use(createMcpMiddleware({ tools }));\r\n * ```\r\n */\r\n\r\nimport { MCPClient } from '../server/mcp/oauth-client.js';\r\nimport { MultiSessionClient } from '../server/mcp/multi-session-client.js';\r\n\r\n/**\r\n * Extended JSON Schema properties that Pydantic's strict validation rejects.\r\n * These are valid JSON Schema extensions but not part of the core spec.\r\n */\r\nconst PYDANTIC_FORBIDDEN_PROPS = [\r\n // JSON Schema meta-properties\r\n '$schema', '$id', '$comment', '$defs', 'definitions',\r\n // Extended properties used by some MCP servers (e.g., Apify)\r\n 'prefill', 'examples', 'enumTitles', 'enumDescriptions',\r\n // Other common extensions\r\n 'deprecated', 'readOnly', 'writeOnly', 'contentMediaType', 'contentEncoding',\r\n];\r\n\r\n/**\r\n * Cleans a JSON Schema by removing meta-properties that cause issues with\r\n * strict Pydantic validation (e.g., Google ADK, LangGraph).\r\n *\r\n * @param schema - The JSON Schema to clean\r\n * @returns Cleaned schema without forbidden properties\r\n */\r\nexport function cleanSchema(schema: Record<string, any> | undefined): Record<string, any> {\r\n if (!schema) {\r\n return { type: 'object', properties: {} };\r\n }\r\n\r\n const cleaned = { ...schema };\r\n\r\n // Remove all forbidden properties\r\n for (const prop of PYDANTIC_FORBIDDEN_PROPS) {\r\n delete cleaned[prop];\r\n }\r\n\r\n // Recursively clean nested properties\r\n if (cleaned.properties && typeof cleaned.properties === 'object') {\r\n const cleanedProps: Record<string, any> = {};\r\n for (const [key, value] of Object.entries(cleaned.properties)) {\r\n if (typeof value === 'object' && value !== null) {\r\n cleanedProps[key] = cleanSchema(value as Record<string, any>);\r\n } else {\r\n cleanedProps[key] = value;\r\n }\r\n }\r\n cleaned.properties = cleanedProps;\r\n }\r\n\r\n // Clean items if it's an array schema\r\n if (cleaned.items && typeof cleaned.items === 'object') {\r\n cleaned.items = cleanSchema(cleaned.items);\r\n }\r\n\r\n // Clean additionalProperties if it's an object schema\r\n if (cleaned.additionalProperties && typeof cleaned.additionalProperties === 'object') {\r\n cleaned.additionalProperties = cleanSchema(cleaned.additionalProperties);\r\n }\r\n\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Configuration options for AguiAdapter\r\n */\r\nexport interface AguiAdapterOptions {\r\n /**\r\n * Prefix for tool names to avoid collision with other tools.\r\n * @default serverId or 'mcp'\r\n */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * AG-UI Tool with handler for server-side execution.\r\n */\r\nexport interface AguiTool {\r\n name: string;\r\n description: string;\r\n parameters?: Record<string, any>;\r\n _meta?: Record<string, any>; // Add _meta to AguiTool\r\n handler?: (args: any) => any | Promise<any>;\r\n}\r\n\r\n/**\r\n * Tool definition format for passing to remote agents (without handler).\r\n */\r\nexport interface AguiToolDefinition {\r\n name: string;\r\n description: string;\r\n parameters: Record<string, any>;\r\n _meta?: Record<string, any>; // Add _meta to AguiToolDefinition\r\n}\r\n\r\n/**\r\n * Adapter that transforms MCP tools into AG-UI compatible formats.\r\n */\r\nexport class AguiAdapter {\r\n constructor(\r\n private client: MCPClient | MultiSessionClient,\r\n private options: AguiAdapterOptions = {}\r\n ) { }\r\n\r\n /**\r\n * Get tools with handlers for MCP tool execution.\r\n */\r\n async getTools(): Promise<AguiTool[]> {\r\n if (this.isMultiSession()) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiTool[] = [];\r\n for (const client of clients) {\r\n allTools.push(...await this.transformTools(client));\r\n }\r\n return allTools;\r\n }\r\n return this.transformTools(this.client as MCPClient);\r\n }\r\n\r\n /**\r\n * Get tool definitions in JSON Schema format for passing to remote agents.\r\n */\r\n async getToolDefinitions(): Promise<AguiToolDefinition[]> {\r\n if (this.isMultiSession()) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiToolDefinition[] = [];\r\n for (const client of clients) {\r\n allTools.push(...await this.transformToolDefinitions(client));\r\n }\r\n return allTools;\r\n }\r\n return this.transformToolDefinitions(this.client as MCPClient);\r\n }\r\n\r\n /**\r\n * Get tools as a function (for dynamic loading).\r\n */\r\n getToolsFunction(): () => Promise<AguiTool[]> {\r\n return () => this.getTools();\r\n }\r\n\r\n private isMultiSession(): boolean {\r\n return typeof (this.client as any).getClients === 'function';\r\n }\r\n\r\n private async transformTools(client: MCPClient): Promise<AguiTool[]> {\r\n if (!client.isConnected()) return [];\r\n\r\n const result = await client.listTools();\r\n const serverId = (typeof (client as any).getServerId === 'function'\r\n ? (client as any).getServerId()\r\n : undefined) as string | undefined;\r\n const normalizedPrefix = (this.options.prefix ?? serverId ?? 'mcp').replace(/-/g, '');\r\n const prefix = `tool_${normalizedPrefix}`;\r\n\r\n return result.tools.map(tool => {\r\n // Type assertion to access _meta if it exists on the tool object (it comes from MCP SDK)\r\n const mcpTool = tool as any;\r\n const mcpToolName = tool.name;\r\n return {\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n _meta: { ...mcpTool._meta, sessionId: (client as any).getSessionId?.() },\r\n handler: async (args: any) => {\r\n console.log(`[AguiAdapter] Executing MCP tool: ${mcpToolName}`, args);\r\n\r\n // IMPORTANT: call the actual MCP tool. (Previously this mistakenly returned the listTools() result.)\r\n const callResult = await (client as any).callTool(mcpToolName, args ?? {});\r\n\r\n // Return the raw result object so middleware can inspect `_meta` (e.g. for UI triggers).\r\n return callResult;\r\n }\r\n }\r\n });\r\n }\r\n\r\n private async transformToolDefinitions(client: MCPClient): Promise<AguiToolDefinition[]> {\r\n if (!client.isConnected()) return [];\r\n\r\n const result = await client.listTools();\r\n const serverId = (typeof (client as any).getServerId === 'function'\r\n ? (client as any).getServerId()\r\n : undefined) as string | undefined;\r\n const normalizedPrefix = (this.options.prefix ?? serverId ?? 'mcp').replace(/-/g, '');\r\n const prefix = `tool_${normalizedPrefix}`;\r\n\r\n return result.tools.map(tool => {\r\n const mcpTool = tool as any;\r\n return {\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n _meta: { ...mcpTool._meta, sessionId: (client as any).getSessionId?.() },\r\n };\r\n });\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/agui-adapter.ts"],"names":[],"mappings":"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","file":"agui-adapter.js","sourcesContent":["/**\r\n * MCP Adapter for AG-UI Integration\r\n *\r\n * This adapter transforms MCP tools into formats compatible with AG-UI agents.\r\n * It provides tools with handlers for server-side execution and tool definitions\r\n * in JSON Schema format for passing to remote agents.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { MultiSessionClient } from '@mcp-ts/sdk/server';\r\n * import { AguiAdapter } from '@mcp-ts/sdk/adapters/agui-adapter';\r\n * import { createMcpMiddleware } from '@mcp-ts/sdk/adapters/agui-middleware';\r\n * import { HttpAgent } from '@ag-ui/client';\r\n *\r\n * // Create MCP client\r\n * const mcpClient = new MultiSessionClient('user_123');\r\n * await mcpClient.connect();\r\n *\r\n * // Create adapter and get tools\r\n * const adapter = new AguiAdapter(mcpClient);\r\n * const tools = await adapter.getTools();\r\n *\r\n * // Use with AG-UI middleware\r\n * const agent = new HttpAgent({ url: 'http://localhost:8000/agent' });\r\n * agent.use(createMcpMiddleware({ tools }));\r\n * ```\r\n */\r\n\r\nimport { MCPClient } from '../server/mcp/oauth-client.js';\r\nimport { MultiSessionClient } from '../server/mcp/multi-session-client.js';\r\n\r\n/**\r\n * Extended JSON Schema properties that Pydantic's strict validation rejects.\r\n * These are valid JSON Schema extensions but not part of the core spec.\r\n */\r\nconst PYDANTIC_FORBIDDEN_PROPS = [\r\n // JSON Schema meta-properties\r\n '$schema', '$id', '$comment', '$defs', 'definitions',\r\n // Extended properties used by some MCP servers (e.g., Apify)\r\n 'prefill', 'examples', 'enumTitles', 'enumDescriptions',\r\n // Other common extensions\r\n 'deprecated', 'readOnly', 'writeOnly', 'contentMediaType', 'contentEncoding',\r\n];\r\n\r\n/**\r\n * Cleans a JSON Schema by removing meta-properties that cause issues with\r\n * strict Pydantic validation (e.g., Google ADK, LangGraph).\r\n *\r\n * @param schema - The JSON Schema to clean\r\n * @returns Cleaned schema without forbidden properties\r\n */\r\nexport function cleanSchema(schema: Record<string, any> | undefined): Record<string, any> {\r\n if (!schema) {\r\n return { type: 'object', properties: {} };\r\n }\r\n\r\n const cleaned = { ...schema };\r\n\r\n // Remove all forbidden properties\r\n for (const prop of PYDANTIC_FORBIDDEN_PROPS) {\r\n delete cleaned[prop];\r\n }\r\n\r\n // Recursively clean nested properties\r\n if (cleaned.properties && typeof cleaned.properties === 'object') {\r\n const cleanedProps: Record<string, any> = {};\r\n for (const [key, value] of Object.entries(cleaned.properties)) {\r\n if (typeof value === 'object' && value !== null) {\r\n cleanedProps[key] = cleanSchema(value as Record<string, any>);\r\n } else {\r\n cleanedProps[key] = value;\r\n }\r\n }\r\n cleaned.properties = cleanedProps;\r\n }\r\n\r\n // Clean items if it's an array schema\r\n if (cleaned.items && typeof cleaned.items === 'object') {\r\n cleaned.items = cleanSchema(cleaned.items);\r\n }\r\n\r\n // Clean additionalProperties if it's an object schema\r\n if (cleaned.additionalProperties && typeof cleaned.additionalProperties === 'object') {\r\n cleaned.additionalProperties = cleanSchema(cleaned.additionalProperties);\r\n }\r\n\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Configuration options for AguiAdapter\r\n */\r\nexport interface AguiAdapterOptions {\r\n /**\r\n * Prefix for tool names to avoid collision with other tools.\r\n * @default serverId or 'mcp'\r\n */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * AG-UI Tool with handler for server-side execution.\r\n */\r\nexport interface AguiTool {\r\n name: string;\r\n description: string;\r\n parameters?: Record<string, any>;\r\n _meta?: Record<string, any>; // Add _meta to AguiTool\r\n handler?: (args: any) => any | Promise<any>;\r\n}\r\n\r\n/**\r\n * Tool definition format for passing to remote agents (without handler).\r\n */\r\nexport interface AguiToolDefinition {\r\n name: string;\r\n description: string;\r\n parameters: Record<string, any>;\r\n _meta?: Record<string, any>; // Add _meta to AguiToolDefinition\r\n}\r\n\r\n/**\r\n * Adapter that transforms MCP tools into AG-UI compatible formats.\r\n */\r\nexport class AguiAdapter {\r\n constructor(\r\n private client: MCPClient | MultiSessionClient,\r\n private options: AguiAdapterOptions = {}\r\n ) { }\r\n\r\n /**\r\n * Get tools with handlers for MCP tool execution.\r\n */\r\n async getTools(): Promise<AguiTool[]> {\r\n if (this.isMultiSession()) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiTool[] = [];\r\n for (const client of clients) {\r\n allTools.push(...await this.transformTools(client));\r\n }\r\n return allTools;\r\n }\r\n return this.transformTools(this.client as MCPClient);\r\n }\r\n\r\n /**\r\n * Get tool definitions in JSON Schema format for passing to remote agents.\r\n */\r\n async getToolDefinitions(): Promise<AguiToolDefinition[]> {\r\n if (this.isMultiSession()) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiToolDefinition[] = [];\r\n for (const client of clients) {\r\n allTools.push(...await this.transformToolDefinitions(client));\r\n }\r\n return allTools;\r\n }\r\n return this.transformToolDefinitions(this.client as MCPClient);\r\n }\r\n\r\n /**\r\n * Get tools as a function (for dynamic loading).\r\n */\r\n getToolsFunction(): () => Promise<AguiTool[]> {\r\n return () => this.getTools();\r\n }\r\n\r\n private isMultiSession(): boolean {\r\n return typeof (this.client as any).getClients === 'function';\r\n }\r\n\r\n private async transformTools(client: MCPClient): Promise<AguiTool[]> {\r\n if (!client.isConnected()) return [];\r\n\r\n const result = await client.listTools();\r\n const serverId = (typeof (client as any).getServerId === 'function'\r\n ? (client as any).getServerId()\r\n : undefined) as string | undefined;\r\n const normalizedPrefix = (this.options.prefix ?? serverId ?? 'mcp').replace(/-/g, '');\r\n const prefix = `tool_${normalizedPrefix}`;\r\n\r\n return result.tools.map(tool => {\r\n // Type assertion to access _meta if it exists on the tool object (it comes from MCP SDK)\r\n const mcpTool = tool as any;\r\n const mcpToolName = tool.name;\r\n return {\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n _meta: { ...mcpTool._meta, sessionId: (client as any).getSessionId?.() },\r\n handler: async (args: any) => {\r\n // Call the actual MCP tool\r\n const callResult = await (client as any).callTool(mcpToolName, args ?? {});\r\n\r\n // Return the raw result object so middleware can inspect `_meta` (e.g. for UI triggers)\r\n return callResult;\r\n }\r\n }\r\n });\r\n }\r\n\r\n private async transformToolDefinitions(client: MCPClient): Promise<AguiToolDefinition[]> {\r\n if (!client.isConnected()) return [];\r\n\r\n const result = await client.listTools();\r\n const serverId = (typeof (client as any).getServerId === 'function'\r\n ? (client as any).getServerId()\r\n : undefined) as string | undefined;\r\n const normalizedPrefix = (this.options.prefix ?? serverId ?? 'mcp').replace(/-/g, '');\r\n const prefix = `tool_${normalizedPrefix}`;\r\n\r\n return result.tools.map(tool => {\r\n const mcpTool = tool as any;\r\n return {\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n _meta: { ...mcpTool._meta, sessionId: (client as any).getSessionId?.() },\r\n };\r\n });\r\n }\r\n}\r\n"]}
|
|
@@ -102,7 +102,6 @@ var AguiAdapter = class {
|
|
|
102
102
|
parameters: cleanSchema(tool.inputSchema),
|
|
103
103
|
_meta: { ...mcpTool._meta, sessionId: client.getSessionId?.() },
|
|
104
104
|
handler: async (args) => {
|
|
105
|
-
console.log(`[AguiAdapter] Executing MCP tool: ${mcpToolName}`, args);
|
|
106
105
|
const callResult = await client.callTool(mcpToolName, args ?? {});
|
|
107
106
|
return callResult;
|
|
108
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/agui-adapter.ts"],"names":[],"mappings":";AAmCA,IAAM,wBAAA,GAA2B;AAAA;AAAA,EAE7B,SAAA;AAAA,EAAW,KAAA;AAAA,EAAO,UAAA;AAAA,EAAY,OAAA;AAAA,EAAS,aAAA;AAAA;AAAA,EAEvC,SAAA;AAAA,EAAW,UAAA;AAAA,EAAY,YAAA;AAAA,EAAc,kBAAA;AAAA;AAAA,EAErC,YAAA;AAAA,EAAc,UAAA;AAAA,EAAY,WAAA;AAAA,EAAa,kBAAA;AAAA,EAAoB;AAC/D,CAAA;AASO,SAAS,YAAY,MAAA,EAA8D;AACtF,EAAA,IAAI,CAAC,MAAA,EAAQ;AACT,IAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,UAAA,EAAY,EAAC,EAAE;AAAA,EAC5C;AAEA,EAAA,MAAM,OAAA,GAAU,EAAE,GAAG,MAAA,EAAO;AAG5B,EAAA,KAAA,MAAW,QAAQ,wBAAA,EAA0B;AACzC,IAAA,OAAO,QAAQ,IAAI,CAAA;AAAA,EACvB;AAGA,EAAA,IAAI,OAAA,CAAQ,UAAA,IAAc,OAAO,OAAA,CAAQ,eAAe,QAAA,EAAU;AAC9D,IAAA,MAAM,eAAoC,EAAC;AAC3C,IAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC3D,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,EAAM;AAC7C,QAAA,YAAA,CAAa,GAAG,CAAA,GAAI,WAAA,CAAY,KAA4B,CAAA;AAAA,MAChE,CAAA,MAAO;AACH,QAAA,YAAA,CAAa,GAAG,CAAA,GAAI,KAAA;AAAA,MACxB;AAAA,IACJ;AACA,IAAA,OAAA,CAAQ,UAAA,GAAa,YAAA;AAAA,EACzB;AAGA,EAAA,IAAI,OAAA,CAAQ,KAAA,IAAS,OAAO,OAAA,CAAQ,UAAU,QAAA,EAAU;AACpD,IAAA,OAAA,CAAQ,KAAA,GAAQ,WAAA,CAAY,OAAA,CAAQ,KAAK,CAAA;AAAA,EAC7C;AAGA,EAAA,IAAI,OAAA,CAAQ,oBAAA,IAAwB,OAAO,OAAA,CAAQ,yBAAyB,QAAA,EAAU;AAClF,IAAA,OAAA,CAAQ,oBAAA,GAAuB,WAAA,CAAY,OAAA,CAAQ,oBAAoB,CAAA;AAAA,EAC3E;AAEA,EAAA,OAAO,OAAA;AACX;AAqCO,IAAM,cAAN,MAAkB;AAAA,EACrB,WAAA,CACY,MAAA,EACA,OAAA,GAA8B,EAAC,EACzC;AAFU,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKJ,MAAM,QAAA,GAAgC;AAClC,IAAA,IAAI,IAAA,CAAK,gBAAe,EAAG;AACvB,MAAA,MAAM,OAAA,GAAW,IAAA,CAAK,MAAA,CAA8B,UAAA,EAAW;AAC/D,MAAA,MAAM,WAAuB,EAAC;AAC9B,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC1B,QAAA,QAAA,CAAS,KAAK,GAAG,MAAM,IAAA,CAAK,cAAA,CAAe,MAAM,CAAC,CAAA;AAAA,MACtD;AACA,MAAA,OAAO,QAAA;AAAA,IACX;AACA,IAAA,OAAO,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,MAAmB,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAA,GAAoD;AACtD,IAAA,IAAI,IAAA,CAAK,gBAAe,EAAG;AACvB,MAAA,MAAM,OAAA,GAAW,IAAA,CAAK,MAAA,CAA8B,UAAA,EAAW;AAC/D,MAAA,MAAM,WAAiC,EAAC;AACxC,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC1B,QAAA,QAAA,CAAS,KAAK,GAAG,MAAM,IAAA,CAAK,wBAAA,CAAyB,MAAM,CAAC,CAAA;AAAA,MAChE;AACA,MAAA,OAAO,QAAA;AAAA,IACX;AACA,IAAA,OAAO,IAAA,CAAK,wBAAA,CAAyB,IAAA,CAAK,MAAmB,CAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAA,GAA8C;AAC1C,IAAA,OAAO,MAAM,KAAK,QAAA,EAAS;AAAA,EAC/B;AAAA,EAEQ,cAAA,GAA0B;AAC9B,IAAA,OAAO,OAAQ,IAAA,CAAK,MAAA,CAAe,UAAA,KAAe,UAAA;AAAA,EACtD;AAAA,EAEA,MAAc,eAAe,MAAA,EAAwC;AACjE,IAAA,IAAI,CAAC,MAAA,CAAO,WAAA,EAAY,SAAU,EAAC;AAEnC,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,SAAA,EAAU;AACtC,IAAA,MAAM,WAAY,OAAQ,MAAA,CAAe,gBAAgB,UAAA,GAClD,MAAA,CAAe,aAAY,GAC5B,MAAA;AACN,IAAA,MAAM,gBAAA,GAAA,CAAoB,KAAK,OAAA,CAAQ,MAAA,IAAU,YAAY,KAAA,EAAO,OAAA,CAAQ,MAAM,EAAE,CAAA;AACpF,IAAA,MAAM,MAAA,GAAS,QAAQ,gBAAgB,CAAA,CAAA;AAEvC,IAAA,OAAO,MAAA,CAAO,KAAA,CAAM,GAAA,CAAI,CAAA,IAAA,KAAQ;AAE5B,MAAA,MAAM,OAAA,GAAU,IAAA;AAChB,MAAA,MAAM,cAAc,IAAA,CAAK,IAAA;AACzB,MAAA,OAAO;AAAA,QACH,IAAA,EAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,KAAK,IAAI,CAAA,CAAA;AAAA,QAC5B,WAAA,EAAa,IAAA,CAAK,WAAA,IAAe,CAAA,QAAA,EAAW,KAAK,IAAI,CAAA,CAAA;AAAA,QACrD,UAAA,EAAY,WAAA,CAAY,IAAA,CAAK,WAAW,CAAA;AAAA,QACxC,KAAA,EAAO,EAAE,GAAG,OAAA,CAAQ,OAAO,SAAA,EAAY,MAAA,CAAe,gBAAe,EAAE;AAAA,QACvE,OAAA,EAAS,OAAO,IAAA,KAAc;AAC1B,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kCAAA,EAAqC,WAAW,CAAA,CAAA,EAAI,IAAI,CAAA;AAGpE,UAAA,MAAM,aAAa,MAAO,MAAA,CAAe,SAAS,WAAA,EAAa,IAAA,IAAQ,EAAE,CAAA;AAGzE,UAAA,OAAO,UAAA;AAAA,QACX;AAAA,OACJ;AAAA,IACJ,CAAC,CAAA;AAAA,EACL;AAAA,EAEA,MAAc,yBAAyB,MAAA,EAAkD;AACrF,IAAA,IAAI,CAAC,MAAA,CAAO,WAAA,EAAY,SAAU,EAAC;AAEnC,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,SAAA,EAAU;AACtC,IAAA,MAAM,WAAY,OAAQ,MAAA,CAAe,gBAAgB,UAAA,GAClD,MAAA,CAAe,aAAY,GAC5B,MAAA;AACN,IAAA,MAAM,gBAAA,GAAA,CAAoB,KAAK,OAAA,CAAQ,MAAA,IAAU,YAAY,KAAA,EAAO,OAAA,CAAQ,MAAM,EAAE,CAAA;AACpF,IAAA,MAAM,MAAA,GAAS,QAAQ,gBAAgB,CAAA,CAAA;AAEvC,IAAA,OAAO,MAAA,CAAO,KAAA,CAAM,GAAA,CAAI,CAAA,IAAA,KAAQ;AAC5B,MAAA,MAAM,OAAA,GAAU,IAAA;AAChB,MAAA,OAAO;AAAA,QACH,IAAA,EAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,KAAK,IAAI,CAAA,CAAA;AAAA,QAC5B,WAAA,EAAa,IAAA,CAAK,WAAA,IAAe,CAAA,QAAA,EAAW,KAAK,IAAI,CAAA,CAAA;AAAA,QACrD,UAAA,EAAY,WAAA,CAAY,IAAA,CAAK,WAAW,CAAA;AAAA,QACxC,KAAA,EAAO,EAAE,GAAG,OAAA,CAAQ,OAAO,SAAA,EAAY,MAAA,CAAe,gBAAe;AAAE,OAC3E;AAAA,IACJ,CAAC,CAAA;AAAA,EACL;AACJ","file":"agui-adapter.mjs","sourcesContent":["/**\r\n * MCP Adapter for AG-UI Integration\r\n *\r\n * This adapter transforms MCP tools into formats compatible with AG-UI agents.\r\n * It provides tools with handlers for server-side execution and tool definitions\r\n * in JSON Schema format for passing to remote agents.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { MultiSessionClient } from '@mcp-ts/sdk/server';\r\n * import { AguiAdapter } from '@mcp-ts/sdk/adapters/agui-adapter';\r\n * import { createMcpMiddleware } from '@mcp-ts/sdk/adapters/agui-middleware';\r\n * import { HttpAgent } from '@ag-ui/client';\r\n *\r\n * // Create MCP client\r\n * const mcpClient = new MultiSessionClient('user_123');\r\n * await mcpClient.connect();\r\n *\r\n * // Create adapter and get tools\r\n * const adapter = new AguiAdapter(mcpClient);\r\n * const tools = await adapter.getTools();\r\n *\r\n * // Use with AG-UI middleware\r\n * const agent = new HttpAgent({ url: 'http://localhost:8000/agent' });\r\n * agent.use(createMcpMiddleware({ tools }));\r\n * ```\r\n */\r\n\r\nimport { MCPClient } from '../server/mcp/oauth-client.js';\r\nimport { MultiSessionClient } from '../server/mcp/multi-session-client.js';\r\n\r\n/**\r\n * Extended JSON Schema properties that Pydantic's strict validation rejects.\r\n * These are valid JSON Schema extensions but not part of the core spec.\r\n */\r\nconst PYDANTIC_FORBIDDEN_PROPS = [\r\n // JSON Schema meta-properties\r\n '$schema', '$id', '$comment', '$defs', 'definitions',\r\n // Extended properties used by some MCP servers (e.g., Apify)\r\n 'prefill', 'examples', 'enumTitles', 'enumDescriptions',\r\n // Other common extensions\r\n 'deprecated', 'readOnly', 'writeOnly', 'contentMediaType', 'contentEncoding',\r\n];\r\n\r\n/**\r\n * Cleans a JSON Schema by removing meta-properties that cause issues with\r\n * strict Pydantic validation (e.g., Google ADK, LangGraph).\r\n *\r\n * @param schema - The JSON Schema to clean\r\n * @returns Cleaned schema without forbidden properties\r\n */\r\nexport function cleanSchema(schema: Record<string, any> | undefined): Record<string, any> {\r\n if (!schema) {\r\n return { type: 'object', properties: {} };\r\n }\r\n\r\n const cleaned = { ...schema };\r\n\r\n // Remove all forbidden properties\r\n for (const prop of PYDANTIC_FORBIDDEN_PROPS) {\r\n delete cleaned[prop];\r\n }\r\n\r\n // Recursively clean nested properties\r\n if (cleaned.properties && typeof cleaned.properties === 'object') {\r\n const cleanedProps: Record<string, any> = {};\r\n for (const [key, value] of Object.entries(cleaned.properties)) {\r\n if (typeof value === 'object' && value !== null) {\r\n cleanedProps[key] = cleanSchema(value as Record<string, any>);\r\n } else {\r\n cleanedProps[key] = value;\r\n }\r\n }\r\n cleaned.properties = cleanedProps;\r\n }\r\n\r\n // Clean items if it's an array schema\r\n if (cleaned.items && typeof cleaned.items === 'object') {\r\n cleaned.items = cleanSchema(cleaned.items);\r\n }\r\n\r\n // Clean additionalProperties if it's an object schema\r\n if (cleaned.additionalProperties && typeof cleaned.additionalProperties === 'object') {\r\n cleaned.additionalProperties = cleanSchema(cleaned.additionalProperties);\r\n }\r\n\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Configuration options for AguiAdapter\r\n */\r\nexport interface AguiAdapterOptions {\r\n /**\r\n * Prefix for tool names to avoid collision with other tools.\r\n * @default serverId or 'mcp'\r\n */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * AG-UI Tool with handler for server-side execution.\r\n */\r\nexport interface AguiTool {\r\n name: string;\r\n description: string;\r\n parameters?: Record<string, any>;\r\n _meta?: Record<string, any>; // Add _meta to AguiTool\r\n handler?: (args: any) => any | Promise<any>;\r\n}\r\n\r\n/**\r\n * Tool definition format for passing to remote agents (without handler).\r\n */\r\nexport interface AguiToolDefinition {\r\n name: string;\r\n description: string;\r\n parameters: Record<string, any>;\r\n _meta?: Record<string, any>; // Add _meta to AguiToolDefinition\r\n}\r\n\r\n/**\r\n * Adapter that transforms MCP tools into AG-UI compatible formats.\r\n */\r\nexport class AguiAdapter {\r\n constructor(\r\n private client: MCPClient | MultiSessionClient,\r\n private options: AguiAdapterOptions = {}\r\n ) { }\r\n\r\n /**\r\n * Get tools with handlers for MCP tool execution.\r\n */\r\n async getTools(): Promise<AguiTool[]> {\r\n if (this.isMultiSession()) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiTool[] = [];\r\n for (const client of clients) {\r\n allTools.push(...await this.transformTools(client));\r\n }\r\n return allTools;\r\n }\r\n return this.transformTools(this.client as MCPClient);\r\n }\r\n\r\n /**\r\n * Get tool definitions in JSON Schema format for passing to remote agents.\r\n */\r\n async getToolDefinitions(): Promise<AguiToolDefinition[]> {\r\n if (this.isMultiSession()) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiToolDefinition[] = [];\r\n for (const client of clients) {\r\n allTools.push(...await this.transformToolDefinitions(client));\r\n }\r\n return allTools;\r\n }\r\n return this.transformToolDefinitions(this.client as MCPClient);\r\n }\r\n\r\n /**\r\n * Get tools as a function (for dynamic loading).\r\n */\r\n getToolsFunction(): () => Promise<AguiTool[]> {\r\n return () => this.getTools();\r\n }\r\n\r\n private isMultiSession(): boolean {\r\n return typeof (this.client as any).getClients === 'function';\r\n }\r\n\r\n private async transformTools(client: MCPClient): Promise<AguiTool[]> {\r\n if (!client.isConnected()) return [];\r\n\r\n const result = await client.listTools();\r\n const serverId = (typeof (client as any).getServerId === 'function'\r\n ? (client as any).getServerId()\r\n : undefined) as string | undefined;\r\n const normalizedPrefix = (this.options.prefix ?? serverId ?? 'mcp').replace(/-/g, '');\r\n const prefix = `tool_${normalizedPrefix}`;\r\n\r\n return result.tools.map(tool => {\r\n // Type assertion to access _meta if it exists on the tool object (it comes from MCP SDK)\r\n const mcpTool = tool as any;\r\n const mcpToolName = tool.name;\r\n return {\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n _meta: { ...mcpTool._meta, sessionId: (client as any).getSessionId?.() },\r\n handler: async (args: any) => {\r\n console.log(`[AguiAdapter] Executing MCP tool: ${mcpToolName}`, args);\r\n\r\n // IMPORTANT: call the actual MCP tool. (Previously this mistakenly returned the listTools() result.)\r\n const callResult = await (client as any).callTool(mcpToolName, args ?? {});\r\n\r\n // Return the raw result object so middleware can inspect `_meta` (e.g. for UI triggers).\r\n return callResult;\r\n }\r\n }\r\n });\r\n }\r\n\r\n private async transformToolDefinitions(client: MCPClient): Promise<AguiToolDefinition[]> {\r\n if (!client.isConnected()) return [];\r\n\r\n const result = await client.listTools();\r\n const serverId = (typeof (client as any).getServerId === 'function'\r\n ? (client as any).getServerId()\r\n : undefined) as string | undefined;\r\n const normalizedPrefix = (this.options.prefix ?? serverId ?? 'mcp').replace(/-/g, '');\r\n const prefix = `tool_${normalizedPrefix}`;\r\n\r\n return result.tools.map(tool => {\r\n const mcpTool = tool as any;\r\n return {\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n _meta: { ...mcpTool._meta, sessionId: (client as any).getSessionId?.() },\r\n };\r\n });\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/agui-adapter.ts"],"names":[],"mappings":"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","file":"agui-adapter.mjs","sourcesContent":["/**\r\n * MCP Adapter for AG-UI Integration\r\n *\r\n * This adapter transforms MCP tools into formats compatible with AG-UI agents.\r\n * It provides tools with handlers for server-side execution and tool definitions\r\n * in JSON Schema format for passing to remote agents.\r\n *\r\n * @example\r\n * ```typescript\r\n * import { MultiSessionClient } from '@mcp-ts/sdk/server';\r\n * import { AguiAdapter } from '@mcp-ts/sdk/adapters/agui-adapter';\r\n * import { createMcpMiddleware } from '@mcp-ts/sdk/adapters/agui-middleware';\r\n * import { HttpAgent } from '@ag-ui/client';\r\n *\r\n * // Create MCP client\r\n * const mcpClient = new MultiSessionClient('user_123');\r\n * await mcpClient.connect();\r\n *\r\n * // Create adapter and get tools\r\n * const adapter = new AguiAdapter(mcpClient);\r\n * const tools = await adapter.getTools();\r\n *\r\n * // Use with AG-UI middleware\r\n * const agent = new HttpAgent({ url: 'http://localhost:8000/agent' });\r\n * agent.use(createMcpMiddleware({ tools }));\r\n * ```\r\n */\r\n\r\nimport { MCPClient } from '../server/mcp/oauth-client.js';\r\nimport { MultiSessionClient } from '../server/mcp/multi-session-client.js';\r\n\r\n/**\r\n * Extended JSON Schema properties that Pydantic's strict validation rejects.\r\n * These are valid JSON Schema extensions but not part of the core spec.\r\n */\r\nconst PYDANTIC_FORBIDDEN_PROPS = [\r\n // JSON Schema meta-properties\r\n '$schema', '$id', '$comment', '$defs', 'definitions',\r\n // Extended properties used by some MCP servers (e.g., Apify)\r\n 'prefill', 'examples', 'enumTitles', 'enumDescriptions',\r\n // Other common extensions\r\n 'deprecated', 'readOnly', 'writeOnly', 'contentMediaType', 'contentEncoding',\r\n];\r\n\r\n/**\r\n * Cleans a JSON Schema by removing meta-properties that cause issues with\r\n * strict Pydantic validation (e.g., Google ADK, LangGraph).\r\n *\r\n * @param schema - The JSON Schema to clean\r\n * @returns Cleaned schema without forbidden properties\r\n */\r\nexport function cleanSchema(schema: Record<string, any> | undefined): Record<string, any> {\r\n if (!schema) {\r\n return { type: 'object', properties: {} };\r\n }\r\n\r\n const cleaned = { ...schema };\r\n\r\n // Remove all forbidden properties\r\n for (const prop of PYDANTIC_FORBIDDEN_PROPS) {\r\n delete cleaned[prop];\r\n }\r\n\r\n // Recursively clean nested properties\r\n if (cleaned.properties && typeof cleaned.properties === 'object') {\r\n const cleanedProps: Record<string, any> = {};\r\n for (const [key, value] of Object.entries(cleaned.properties)) {\r\n if (typeof value === 'object' && value !== null) {\r\n cleanedProps[key] = cleanSchema(value as Record<string, any>);\r\n } else {\r\n cleanedProps[key] = value;\r\n }\r\n }\r\n cleaned.properties = cleanedProps;\r\n }\r\n\r\n // Clean items if it's an array schema\r\n if (cleaned.items && typeof cleaned.items === 'object') {\r\n cleaned.items = cleanSchema(cleaned.items);\r\n }\r\n\r\n // Clean additionalProperties if it's an object schema\r\n if (cleaned.additionalProperties && typeof cleaned.additionalProperties === 'object') {\r\n cleaned.additionalProperties = cleanSchema(cleaned.additionalProperties);\r\n }\r\n\r\n return cleaned;\r\n}\r\n\r\n/**\r\n * Configuration options for AguiAdapter\r\n */\r\nexport interface AguiAdapterOptions {\r\n /**\r\n * Prefix for tool names to avoid collision with other tools.\r\n * @default serverId or 'mcp'\r\n */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * AG-UI Tool with handler for server-side execution.\r\n */\r\nexport interface AguiTool {\r\n name: string;\r\n description: string;\r\n parameters?: Record<string, any>;\r\n _meta?: Record<string, any>; // Add _meta to AguiTool\r\n handler?: (args: any) => any | Promise<any>;\r\n}\r\n\r\n/**\r\n * Tool definition format for passing to remote agents (without handler).\r\n */\r\nexport interface AguiToolDefinition {\r\n name: string;\r\n description: string;\r\n parameters: Record<string, any>;\r\n _meta?: Record<string, any>; // Add _meta to AguiToolDefinition\r\n}\r\n\r\n/**\r\n * Adapter that transforms MCP tools into AG-UI compatible formats.\r\n */\r\nexport class AguiAdapter {\r\n constructor(\r\n private client: MCPClient | MultiSessionClient,\r\n private options: AguiAdapterOptions = {}\r\n ) { }\r\n\r\n /**\r\n * Get tools with handlers for MCP tool execution.\r\n */\r\n async getTools(): Promise<AguiTool[]> {\r\n if (this.isMultiSession()) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiTool[] = [];\r\n for (const client of clients) {\r\n allTools.push(...await this.transformTools(client));\r\n }\r\n return allTools;\r\n }\r\n return this.transformTools(this.client as MCPClient);\r\n }\r\n\r\n /**\r\n * Get tool definitions in JSON Schema format for passing to remote agents.\r\n */\r\n async getToolDefinitions(): Promise<AguiToolDefinition[]> {\r\n if (this.isMultiSession()) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiToolDefinition[] = [];\r\n for (const client of clients) {\r\n allTools.push(...await this.transformToolDefinitions(client));\r\n }\r\n return allTools;\r\n }\r\n return this.transformToolDefinitions(this.client as MCPClient);\r\n }\r\n\r\n /**\r\n * Get tools as a function (for dynamic loading).\r\n */\r\n getToolsFunction(): () => Promise<AguiTool[]> {\r\n return () => this.getTools();\r\n }\r\n\r\n private isMultiSession(): boolean {\r\n return typeof (this.client as any).getClients === 'function';\r\n }\r\n\r\n private async transformTools(client: MCPClient): Promise<AguiTool[]> {\r\n if (!client.isConnected()) return [];\r\n\r\n const result = await client.listTools();\r\n const serverId = (typeof (client as any).getServerId === 'function'\r\n ? (client as any).getServerId()\r\n : undefined) as string | undefined;\r\n const normalizedPrefix = (this.options.prefix ?? serverId ?? 'mcp').replace(/-/g, '');\r\n const prefix = `tool_${normalizedPrefix}`;\r\n\r\n return result.tools.map(tool => {\r\n // Type assertion to access _meta if it exists on the tool object (it comes from MCP SDK)\r\n const mcpTool = tool as any;\r\n const mcpToolName = tool.name;\r\n return {\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n _meta: { ...mcpTool._meta, sessionId: (client as any).getSessionId?.() },\r\n handler: async (args: any) => {\r\n // Call the actual MCP tool\r\n const callResult = await (client as any).callTool(mcpToolName, args ?? {});\r\n\r\n // Return the raw result object so middleware can inspect `_meta` (e.g. for UI triggers)\r\n return callResult;\r\n }\r\n }\r\n });\r\n }\r\n\r\n private async transformToolDefinitions(client: MCPClient): Promise<AguiToolDefinition[]> {\r\n if (!client.isConnected()) return [];\r\n\r\n const result = await client.listTools();\r\n const serverId = (typeof (client as any).getServerId === 'function'\r\n ? (client as any).getServerId()\r\n : undefined) as string | undefined;\r\n const normalizedPrefix = (this.options.prefix ?? serverId ?? 'mcp').replace(/-/g, '');\r\n const prefix = `tool_${normalizedPrefix}`;\r\n\r\n return result.tools.map(tool => {\r\n const mcpTool = tool as any;\r\n return {\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n _meta: { ...mcpTool._meta, sessionId: (client as any).getSessionId?.() },\r\n };\r\n });\r\n }\r\n}\r\n"]}
|
|
@@ -18,21 +18,6 @@ import '@modelcontextprotocol/sdk/client/auth.js';
|
|
|
18
18
|
* @requires rxjs - Uses RxJS Observables for event streaming
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
/** New event type for MCP UI triggers */
|
|
22
|
-
declare const MCP_APP_UI_EVENT = "mcp-apps-ui";
|
|
23
|
-
/**
|
|
24
|
-
* MCP Apps UI trigger event.
|
|
25
|
-
*
|
|
26
|
-
* IMPORTANT: This must be emitted as an AG-UI CustomEvent so subscribers
|
|
27
|
-
* (e.g. CopilotKit `onCustomEvent`) can receive it.
|
|
28
|
-
*/
|
|
29
|
-
interface McpAppUiEventPayload {
|
|
30
|
-
toolCallId: string;
|
|
31
|
-
resourceUri: string;
|
|
32
|
-
sessionId?: string;
|
|
33
|
-
toolName: string;
|
|
34
|
-
result?: any;
|
|
35
|
-
}
|
|
36
21
|
/**
|
|
37
22
|
* Configuration for McpMiddleware
|
|
38
23
|
*/
|
|
@@ -56,6 +41,7 @@ declare class McpMiddleware extends Middleware {
|
|
|
56
41
|
private handleToolCallEvent;
|
|
57
42
|
/** Execute pending MCP tools and return results */
|
|
58
43
|
private executeTools;
|
|
44
|
+
/** Emit tool results (without RUN_FINISHED - that's emitted when truly done) */
|
|
59
45
|
private emitToolResults;
|
|
60
46
|
run(input: RunAgentInput, next: AbstractAgent): Observable<BaseEvent>;
|
|
61
47
|
}
|
|
@@ -66,4 +52,4 @@ declare function createMcpMiddleware(options: {
|
|
|
66
52
|
tools: AguiTool[];
|
|
67
53
|
}): (input: RunAgentInput, next: AbstractAgent) => Observable<BaseEvent>;
|
|
68
54
|
|
|
69
|
-
export {
|
|
55
|
+
export { McpMiddleware, type McpMiddlewareConfig, McpMiddleware as McpToolExecutorMiddleware, createMcpMiddleware, createMcpMiddleware as createMcpToolMiddleware };
|
|
@@ -18,21 +18,6 @@ import '@modelcontextprotocol/sdk/client/auth.js';
|
|
|
18
18
|
* @requires rxjs - Uses RxJS Observables for event streaming
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
/** New event type for MCP UI triggers */
|
|
22
|
-
declare const MCP_APP_UI_EVENT = "mcp-apps-ui";
|
|
23
|
-
/**
|
|
24
|
-
* MCP Apps UI trigger event.
|
|
25
|
-
*
|
|
26
|
-
* IMPORTANT: This must be emitted as an AG-UI CustomEvent so subscribers
|
|
27
|
-
* (e.g. CopilotKit `onCustomEvent`) can receive it.
|
|
28
|
-
*/
|
|
29
|
-
interface McpAppUiEventPayload {
|
|
30
|
-
toolCallId: string;
|
|
31
|
-
resourceUri: string;
|
|
32
|
-
sessionId?: string;
|
|
33
|
-
toolName: string;
|
|
34
|
-
result?: any;
|
|
35
|
-
}
|
|
36
21
|
/**
|
|
37
22
|
* Configuration for McpMiddleware
|
|
38
23
|
*/
|
|
@@ -56,6 +41,7 @@ declare class McpMiddleware extends Middleware {
|
|
|
56
41
|
private handleToolCallEvent;
|
|
57
42
|
/** Execute pending MCP tools and return results */
|
|
58
43
|
private executeTools;
|
|
44
|
+
/** Emit tool results (without RUN_FINISHED - that's emitted when truly done) */
|
|
59
45
|
private emitToolResults;
|
|
60
46
|
run(input: RunAgentInput, next: AbstractAgent): Observable<BaseEvent>;
|
|
61
47
|
}
|
|
@@ -66,4 +52,4 @@ declare function createMcpMiddleware(options: {
|
|
|
66
52
|
tools: AguiTool[];
|
|
67
53
|
}): (input: RunAgentInput, next: AbstractAgent) => Observable<BaseEvent>;
|
|
68
54
|
|
|
69
|
-
export {
|
|
55
|
+
export { McpMiddleware, type McpMiddlewareConfig, McpMiddleware as McpToolExecutorMiddleware, createMcpMiddleware, createMcpMiddleware as createMcpToolMiddleware };
|
|
@@ -56,7 +56,6 @@ function cleanSchema(schema) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// src/adapters/agui-middleware.ts
|
|
59
|
-
var MCP_APP_UI_EVENT = "mcp-apps-ui";
|
|
60
59
|
var McpMiddleware = class extends client.Middleware {
|
|
61
60
|
constructor(config) {
|
|
62
61
|
super();
|
|
@@ -66,9 +65,7 @@ var McpMiddleware = class extends client.Middleware {
|
|
|
66
65
|
this.toolSchemas = this.tools.map((t) => ({
|
|
67
66
|
name: t.name,
|
|
68
67
|
description: t.description,
|
|
69
|
-
parameters: cleanSchema(t.parameters)
|
|
70
|
-
_meta: t._meta
|
|
71
|
-
// Include _meta in the tool definition passed to the agent
|
|
68
|
+
parameters: cleanSchema(t.parameters)
|
|
72
69
|
}));
|
|
73
70
|
}
|
|
74
71
|
isMcpTool(toolName) {
|
|
@@ -95,24 +92,17 @@ var McpMiddleware = class extends client.Middleware {
|
|
|
95
92
|
async executeTool(toolName, args) {
|
|
96
93
|
const tool = this.tools.find((t) => t.name === toolName);
|
|
97
94
|
if (!tool?.handler) {
|
|
98
|
-
return
|
|
95
|
+
return `Error: Tool ${tool ? "has no handler" : "not found"}: ${toolName}`;
|
|
99
96
|
}
|
|
100
97
|
try {
|
|
101
98
|
console.log(`[McpMiddleware] Executing tool: ${toolName}`, args);
|
|
102
99
|
const result = await tool.handler(args);
|
|
103
|
-
|
|
104
|
-
if (typeof result === "string") {
|
|
105
|
-
resultStr = result;
|
|
106
|
-
} else if (result && typeof result === "object") {
|
|
107
|
-
resultStr = JSON.stringify(result);
|
|
108
|
-
} else {
|
|
109
|
-
resultStr = String(result);
|
|
110
|
-
}
|
|
100
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
111
101
|
console.log(`[McpMiddleware] Tool result:`, resultStr.slice(0, 200));
|
|
112
|
-
return
|
|
102
|
+
return resultStr;
|
|
113
103
|
} catch (error) {
|
|
114
104
|
console.error(`[McpMiddleware] Error executing tool:`, error);
|
|
115
|
-
return
|
|
105
|
+
return `Error: ${error.message || String(error)}`;
|
|
116
106
|
}
|
|
117
107
|
}
|
|
118
108
|
generateId(prefix) {
|
|
@@ -189,12 +179,11 @@ var McpMiddleware = class extends client.Middleware {
|
|
|
189
179
|
if (!toolName) return;
|
|
190
180
|
const args = this.parseArgs(toolCallArgsBuffer.get(toolCallId) || "{}");
|
|
191
181
|
console.log(`[McpMiddleware] Executing pending tool: ${toolName}`);
|
|
192
|
-
const
|
|
182
|
+
const result = await this.executeTool(toolName, args);
|
|
193
183
|
results.push({
|
|
194
184
|
toolCallId,
|
|
195
185
|
toolName,
|
|
196
|
-
result
|
|
197
|
-
rawResult,
|
|
186
|
+
result,
|
|
198
187
|
messageId: this.generateId("mcp_result")
|
|
199
188
|
});
|
|
200
189
|
pendingMcpCalls.delete(toolCallId);
|
|
@@ -202,28 +191,9 @@ var McpMiddleware = class extends client.Middleware {
|
|
|
202
191
|
await Promise.all(promises);
|
|
203
192
|
return results;
|
|
204
193
|
}
|
|
194
|
+
/** Emit tool results (without RUN_FINISHED - that's emitted when truly done) */
|
|
205
195
|
emitToolResults(observer, results) {
|
|
206
|
-
for (const { toolCallId, toolName, result,
|
|
207
|
-
const toolDef = this.tools.find((t) => t.name === toolName);
|
|
208
|
-
const sessionId = toolDef?._meta?.sessionId;
|
|
209
|
-
const resourceUri = rawResult?._meta?.ui?.resourceUri ?? rawResult?._meta?.["ui/resourceUri"] ?? toolDef?._meta?.ui?.resourceUri ?? toolDef?._meta?.["ui/resourceUri"];
|
|
210
|
-
if (resourceUri) {
|
|
211
|
-
const payload = {
|
|
212
|
-
toolCallId,
|
|
213
|
-
resourceUri,
|
|
214
|
-
sessionId,
|
|
215
|
-
toolName,
|
|
216
|
-
result: rawResult ?? result
|
|
217
|
-
};
|
|
218
|
-
observer.next({
|
|
219
|
-
type: client.EventType.CUSTOM,
|
|
220
|
-
name: MCP_APP_UI_EVENT,
|
|
221
|
-
value: payload,
|
|
222
|
-
timestamp: Date.now(),
|
|
223
|
-
role: "tool"
|
|
224
|
-
});
|
|
225
|
-
console.log(`[McpMiddleware] Emitting CustomEvent(${MCP_APP_UI_EVENT}) for: ${toolName} (session: ${sessionId})`);
|
|
226
|
-
}
|
|
196
|
+
for (const { toolCallId, toolName, result, messageId } of results) {
|
|
227
197
|
observer.next({
|
|
228
198
|
type: client.EventType.TOOL_CALL_RESULT,
|
|
229
199
|
toolCallId,
|
|
@@ -384,7 +354,6 @@ Object.defineProperty(exports, "Middleware", {
|
|
|
384
354
|
enumerable: true,
|
|
385
355
|
get: function () { return client.Middleware; }
|
|
386
356
|
});
|
|
387
|
-
exports.MCP_APP_UI_EVENT = MCP_APP_UI_EVENT;
|
|
388
357
|
exports.McpMiddleware = McpMiddleware;
|
|
389
358
|
exports.McpToolExecutorMiddleware = McpMiddleware;
|
|
390
359
|
exports.createMcpMiddleware = createMcpMiddleware;
|