@mcp-ts/sdk 1.0.0 → 1.1.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.
Files changed (77) hide show
  1. package/README.md +25 -13
  2. package/dist/adapters/agui-adapter.d.mts +21 -44
  3. package/dist/adapters/agui-adapter.d.ts +21 -44
  4. package/dist/adapters/agui-adapter.js +93 -67
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +93 -68
  7. package/dist/adapters/agui-adapter.mjs.map +1 -1
  8. package/dist/adapters/agui-middleware.d.mts +32 -134
  9. package/dist/adapters/agui-middleware.d.ts +32 -134
  10. package/dist/adapters/agui-middleware.js +314 -350
  11. package/dist/adapters/agui-middleware.js.map +1 -1
  12. package/dist/adapters/agui-middleware.mjs +314 -351
  13. package/dist/adapters/agui-middleware.mjs.map +1 -1
  14. package/dist/adapters/ai-adapter.d.mts +2 -2
  15. package/dist/adapters/ai-adapter.d.ts +2 -2
  16. package/dist/adapters/langchain-adapter.d.mts +2 -2
  17. package/dist/adapters/langchain-adapter.d.ts +2 -2
  18. package/dist/adapters/mastra-adapter.d.mts +2 -2
  19. package/dist/adapters/mastra-adapter.d.ts +2 -2
  20. package/dist/client/index.d.mts +184 -57
  21. package/dist/client/index.d.ts +184 -57
  22. package/dist/client/index.js +535 -130
  23. package/dist/client/index.js.map +1 -1
  24. package/dist/client/index.mjs +535 -131
  25. package/dist/client/index.mjs.map +1 -1
  26. package/dist/client/react.d.mts +40 -6
  27. package/dist/client/react.d.ts +40 -6
  28. package/dist/client/react.js +587 -142
  29. package/dist/client/react.js.map +1 -1
  30. package/dist/client/react.mjs +586 -143
  31. package/dist/client/react.mjs.map +1 -1
  32. package/dist/client/vue.d.mts +5 -5
  33. package/dist/client/vue.d.ts +5 -5
  34. package/dist/client/vue.js +545 -140
  35. package/dist/client/vue.js.map +1 -1
  36. package/dist/client/vue.mjs +545 -141
  37. package/dist/client/vue.mjs.map +1 -1
  38. package/dist/{events-BP6WyRNh.d.mts → events-BgeztGYZ.d.mts} +12 -1
  39. package/dist/{events-BP6WyRNh.d.ts → events-BgeztGYZ.d.ts} +12 -1
  40. package/dist/index.d.mts +4 -4
  41. package/dist/index.d.ts +4 -4
  42. package/dist/index.js +779 -248
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +775 -245
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/{multi-session-client-DMF3ED2O.d.mts → multi-session-client-CxogNckF.d.mts} +1 -1
  47. package/dist/{multi-session-client-BOFgPypS.d.ts → multi-session-client-cox_WXUj.d.ts} +1 -1
  48. package/dist/server/index.d.mts +44 -40
  49. package/dist/server/index.d.ts +44 -40
  50. package/dist/server/index.js +242 -116
  51. package/dist/server/index.js.map +1 -1
  52. package/dist/server/index.mjs +238 -112
  53. package/dist/server/index.mjs.map +1 -1
  54. package/dist/shared/index.d.mts +2 -2
  55. package/dist/shared/index.d.ts +2 -2
  56. package/dist/shared/index.js.map +1 -1
  57. package/dist/shared/index.mjs.map +1 -1
  58. package/dist/{types-SbDlA2VX.d.mts → types-CLccx9wW.d.mts} +1 -1
  59. package/dist/{types-SbDlA2VX.d.ts → types-CLccx9wW.d.ts} +1 -1
  60. package/package.json +8 -1
  61. package/src/adapters/agui-adapter.ts +121 -107
  62. package/src/adapters/agui-middleware.ts +474 -512
  63. package/src/client/core/app-host.ts +417 -0
  64. package/src/client/core/sse-client.ts +365 -212
  65. package/src/client/core/types.ts +31 -0
  66. package/src/client/index.ts +1 -0
  67. package/src/client/react/index.ts +1 -0
  68. package/src/client/react/use-mcp-app.ts +73 -0
  69. package/src/client/react/useMcp.ts +18 -0
  70. package/src/server/handlers/nextjs-handler.ts +8 -7
  71. package/src/server/handlers/sse-handler.ts +131 -164
  72. package/src/server/mcp/oauth-client.ts +32 -2
  73. package/src/server/storage/index.ts +17 -1
  74. package/src/server/storage/sqlite-backend.ts +185 -0
  75. package/src/server/storage/types.ts +1 -1
  76. package/src/shared/events.ts +12 -0
  77. package/src/shared/types.ts +4 -2
package/README.md CHANGED
@@ -3,11 +3,11 @@
3
3
  <img src="docs/static/img/logo.svg" alt="mcp-ts Logo" width="80" height="80" />
4
4
  </a>
5
5
  <h1 align="center">@mcp-ts</h1>
6
- <p>A Lightweight MCP (Model Context Protocol) client library with integrated persistence.</p>
6
+ <p>TypeScript SDK providing MCP capabilities to agents across JavaScript/cross-runtime environments.</p>
7
7
  </div>
8
8
 
9
9
  <div align="center">
10
- <a href="https://github.com/zonlabs/mcp-ts/raw/main/docs/static/vid/mcp-ts.mp4">
10
+ <a href="https://github.com/zonlabs/mcp-ts/raw/main/docs/static/vid/langchain-agui.mp4">
11
11
  <em>Click to watch demo video</em>
12
12
  </a>
13
13
  </div>
@@ -18,7 +18,7 @@
18
18
 
19
19
  | *Supported Frameworks* | *Agent Frameworks and Protocol* | *Storage Backends* |
20
20
  | :---: | :---: | :---: |
21
- | <img src="docs/static/img/framework/next.svg" width="35" height="35" /> <img src="docs/static/img/framework/node.svg" width="35" height="35" /> <img src="docs/static/img/framework/react.svg" width="35" height="35" /> <img src="docs/static/img/framework/vue.svg" width="35" height="35" /> <img src="docs/static/img/framework/express.svg" width="35" height="35" /> | <img src="docs/static/img/framework/vercel.svg" width="35" height="35" /> <img src="docs/static/img/agent-framework/langchain.svg" width="35" height="35" /> <img src="docs/static/img/agent-framework/mastra.svg" width="35" height="35" /> <img src="docs/static/img/agent-framework/agui.webp" width="35" height="35" /> | <img src="docs/static/img/storage-backend/redis.svg" width="35" height="35" /> <img src="docs/static/img/storage-backend/filesystem.svg" width="35" height="35" /> <img src="docs/static/img/storage-backend/memory.svg" width="35" height="35" /> |
21
+ | <img src="docs/static/img/framework/next.svg" width="35" height="35" /> <img src="docs/static/img/framework/node.svg" width="35" height="35" /> <img src="docs/static/img/framework/react.svg" width="35" height="35" /> <img src="docs/static/img/framework/vue.svg" width="35" height="35" /> <img src="docs/static/img/framework/express.svg" width="35" height="35" /> | <img src="docs/static/img/framework/vercel.svg" width="35" height="35" /> <img src="docs/static/img/agent-framework/langchain.svg" width="35" height="35" /> <img src="docs/static/img/agent-framework/mastra.svg" width="35" height="35" /> <img src="docs/static/img/agent-framework/agui.webp" width="35" height="35" /> | <img src="docs/static/img/storage-backend/redis.svg" width="35" height="35" /> <img src="docs/static/img/storage-backend/sqlite.svg" width="35" height="35" /> <img src="docs/static/img/storage-backend/filesystem.svg" width="35" height="35" /> <img src="docs/static/img/storage-backend/memory.svg" width="35" height="35" /> |
22
22
 
23
23
  </div>
24
24
 
@@ -35,18 +35,22 @@
35
35
 
36
36
  ## Features
37
37
 
38
- - **Real-Time SSE** - Server-Sent Events for live connection and observability updates
39
- - **Flexible Storage** - Redis, File System, or In-Memory backends
40
- - **Serverless-Ready** - Works in serverless environments (Vercel, AWS Lambda, etc.)
38
+ - **SSE** - Server-Sent Events for connection state and observability updates
39
+ - **Flexible Storage** - Redis, SQLite, File System, or In-Memory backends
40
+ - **Serverless** - Works in serverless environments (Vercel, AWS Lambda, etc.)
41
41
  - **React Hook** - `useMcp` hook for easy React integration
42
42
  - **Vue Composable** - `useMcp` composable for Vue applications
43
- - **Full MCP Protocol** - Support for tools, prompts, and resources
44
- - **TypeScript** - Complete type safety with exported types
43
+ - **MCP Protocol** - Support for tools, prompts, and resources
45
44
  - **Agent Adapters** - Built-in adapters for AI SDK, LangChain, Mastra, and AG-UI
45
+ - **MCP Apps Extension (SEP-1865)** - Interactive UI-driven tool interfaces
46
+
47
+ <div align="center">
48
+ <img src="docs/static/img/mcp-apps.png" alt="MCP Apps" width="100%" />
49
+ <p><em>Interactive UIs for MCP tools</em></p>
50
+ </div>
46
51
 
47
52
  ## Inspiration
48
53
 
49
- > [!NOTE]
50
54
  > I got the idea for `@mcp-ts` while working on 🌐 **[MCP Assistant](https://mcp-assistant.in)**.
51
55
  While building custom storage for persistence, managing the flow became harder than it should have been.
52
56
  So I built this client to handle the heavy lifting of client applications and make agent interactions easier.
@@ -69,6 +73,7 @@ npm install @mcp-ts/sdk
69
73
  The package supports multiple storage backends out of the box:
70
74
  - **Memory** (default, no setup required)
71
75
  - **File** (local persistence)
76
+ - **SQLite** (fast local persistence, requires `npm install better-sqlite3`)
72
77
  - **Redis** (production-ready, requires `npm install ioredis`)
73
78
 
74
79
  ## Quick Start
@@ -185,7 +190,7 @@ const mcpTools = await adapter.getTools();
185
190
 
186
191
  // Create agent with middleware
187
192
  const agent = new HttpAgent({ url: "http://localhost:8000/agent" });
188
- agent.use(createMcpMiddleware(client, {
193
+ agent.use(createMcpMiddleware({
189
194
  toolPrefix: 'server-',
190
195
  tools: mcpTools,
191
196
  }));
@@ -210,7 +215,7 @@ Full documentation is available at: **[Docs](https://zonlabs.github.io/mcp-ts/)*
210
215
 
211
216
  The library supports multiple storage backends. You can explicitly select one using `MCP_TS_STORAGE_TYPE` or rely on automatic detection.
212
217
 
213
- **Supported Types:** `redis`, `file`, `memory`.
218
+ **Supported Types:** `redis`, `sqlite`, `file`, `memory`.
214
219
 
215
220
  ### Configuration Examples
216
221
 
@@ -220,13 +225,20 @@ The library supports multiple storage backends. You can explicitly select one us
220
225
  REDIS_URL=redis://localhost:6379
221
226
  ```
222
227
 
223
- 2. **<img src="docs/static/img/storage-backend/filesystem.svg" width="20" height="20" align="center" /> File System** (Great for local dev)
228
+ 2. **<img src="docs/static/img/storage-backend/sqlite.svg" width="20" height="20" align="center" /> SQLite** (Fast & Persistent)
229
+ ```bash
230
+ MCP_TS_STORAGE_TYPE=sqlite
231
+ # Optional path
232
+ MCP_TS_STORAGE_SQLITE_PATH=./sessions.db
233
+ ```
234
+
235
+ 3. **<img src="docs/static/img/storage-backend/filesystem.svg" width="20" height="20" align="center" /> File System** (Great for local dev)
224
236
  ```bash
225
237
  MCP_TS_STORAGE_TYPE=file
226
238
  MCP_TS_STORAGE_FILE=./sessions.json
227
239
  ```
228
240
 
229
- 3. **<img src="docs/static/img/storage-backend/memory.svg" width="20" height="20" align="center" /> In-Memory** (Default for testing)
241
+ 4. **<img src="docs/static/img/storage-backend/memory.svg" width="20" height="20" align="center" /> In-Memory** (Default for testing)
230
242
  ```bash
231
243
  MCP_TS_STORAGE_TYPE=memory
232
244
  ```
@@ -1,5 +1,5 @@
1
- import { M as MCPClient, a as MultiSessionClient } from '../multi-session-client-DMF3ED2O.mjs';
2
- import '../events-BP6WyRNh.mjs';
1
+ import { M as MCPClient, a as MultiSessionClient } from '../multi-session-client-CxogNckF.mjs';
2
+ import '../events-BgeztGYZ.mjs';
3
3
  import '@modelcontextprotocol/sdk/types.js';
4
4
  import '@modelcontextprotocol/sdk/shared/auth.js';
5
5
  import '@modelcontextprotocol/sdk/client/auth.js';
@@ -14,7 +14,7 @@ import '@modelcontextprotocol/sdk/client/auth.js';
14
14
  * @example
15
15
  * ```typescript
16
16
  * import { MultiSessionClient } from '@mcp-ts/sdk/server';
17
- * import { AguiAdapter } from '@mcp-ts/sdk/adapters/mcp-adapter';
17
+ * import { AguiAdapter } from '@mcp-ts/sdk/adapters/agui-adapter';
18
18
  * import { createMcpMiddleware } from '@mcp-ts/sdk/adapters/agui-middleware';
19
19
  * import { HttpAgent } from '@ag-ui/client';
20
20
  *
@@ -28,10 +28,18 @@ import '@modelcontextprotocol/sdk/client/auth.js';
28
28
  *
29
29
  * // Use with AG-UI middleware
30
30
  * const agent = new HttpAgent({ url: 'http://localhost:8000/agent' });
31
- * agent.use(createMcpMiddleware(mcpClient, { tools }));
31
+ * agent.use(createMcpMiddleware({ tools }));
32
32
  * ```
33
33
  */
34
34
 
35
+ /**
36
+ * Cleans a JSON Schema by removing meta-properties that cause issues with
37
+ * strict Pydantic validation (e.g., Google ADK, LangGraph).
38
+ *
39
+ * @param schema - The JSON Schema to clean
40
+ * @returns Cleaned schema without forbidden properties
41
+ */
42
+ declare function cleanSchema(schema: Record<string, any> | undefined): Record<string, any>;
35
43
  /**
36
44
  * Configuration options for AguiAdapter
37
45
  */
@@ -44,41 +52,25 @@ interface AguiAdapterOptions {
44
52
  }
45
53
  /**
46
54
  * AG-UI Tool with handler for server-side execution.
47
- *
48
- * Tools contain:
49
- * - `name`: Unique identifier (prefixed with server ID)
50
- * - `description`: Human-readable description for the LLM
51
- * - `parameters`: JSON Schema defining the input format
52
- * - `handler`: Function that executes the tool via MCP client
53
55
  */
54
56
  interface AguiTool {
55
- /** Unique tool name (e.g., "server-abc_get_weather") */
56
57
  name: string;
57
- /** Human-readable description for the LLM */
58
58
  description: string;
59
- /** JSON Schema format parameters */
60
59
  parameters?: Record<string, any>;
61
- /** Handler function that executes the MCP tool */
60
+ _meta?: Record<string, any>;
62
61
  handler?: (args: any) => any | Promise<any>;
63
62
  }
64
63
  /**
65
64
  * Tool definition format for passing to remote agents (without handler).
66
- * Compatible with OpenAI's function calling API.
67
65
  */
68
66
  interface AguiToolDefinition {
69
- /** Tool name (e.g., "server-abc_get_weather") */
70
67
  name: string;
71
- /** Human-readable description */
72
68
  description: string;
73
- /** JSON Schema format parameters */
74
69
  parameters: Record<string, any>;
70
+ _meta?: Record<string, any>;
75
71
  }
76
72
  /**
77
73
  * Adapter that transforms MCP tools into AG-UI compatible formats.
78
- *
79
- * This adapter provides two main outputs:
80
- * - `getTools()`: Returns tools with handlers for server-side execution
81
- * - `getToolDefinitions()`: Returns tool definitions in JSON Schema format for remote agents
82
74
  */
83
75
  declare class AguiAdapter {
84
76
  private client;
@@ -86,34 +78,19 @@ declare class AguiAdapter {
86
78
  constructor(client: MCPClient | MultiSessionClient, options?: AguiAdapterOptions);
87
79
  /**
88
80
  * Get tools with handlers for MCP tool execution.
89
- *
90
- * Each tool includes a handler function that:
91
- * 1. Calls the MCP tool via the client
92
- * 2. Extracts text content from the result
93
- * 3. Returns the result as a string or JSON
94
- *
95
- * @returns Array of AguiTool objects
96
81
  */
97
82
  getTools(): Promise<AguiTool[]>;
98
- private transformTools;
99
- /**
100
- * Get tools as a function (for dynamic loading).
101
- *
102
- * @returns Function that returns a Promise of tools
103
- */
104
- getToolsFunction(): () => Promise<AguiTool[]>;
105
83
  /**
106
84
  * Get tool definitions in JSON Schema format for passing to remote agents.
107
- *
108
- * This format is compatible with:
109
- * - OpenAI's function calling API
110
- * - AG-UI input.tools format
111
- * - Most LLM tool/function calling implementations
112
- *
113
- * @returns Array of AguiToolDefinition objects
114
85
  */
115
86
  getToolDefinitions(): Promise<AguiToolDefinition[]>;
87
+ /**
88
+ * Get tools as a function (for dynamic loading).
89
+ */
90
+ getToolsFunction(): () => Promise<AguiTool[]>;
91
+ private isMultiSession;
92
+ private transformTools;
116
93
  private transformToolDefinitions;
117
94
  }
118
95
 
119
- export { AguiAdapter, type AguiAdapterOptions, type AguiTool, type AguiToolDefinition };
96
+ export { AguiAdapter, type AguiAdapterOptions, type AguiTool, type AguiToolDefinition, cleanSchema };
@@ -1,5 +1,5 @@
1
- import { M as MCPClient, a as MultiSessionClient } from '../multi-session-client-BOFgPypS.js';
2
- import '../events-BP6WyRNh.js';
1
+ import { M as MCPClient, a as MultiSessionClient } from '../multi-session-client-cox_WXUj.js';
2
+ import '../events-BgeztGYZ.js';
3
3
  import '@modelcontextprotocol/sdk/types.js';
4
4
  import '@modelcontextprotocol/sdk/shared/auth.js';
5
5
  import '@modelcontextprotocol/sdk/client/auth.js';
@@ -14,7 +14,7 @@ import '@modelcontextprotocol/sdk/client/auth.js';
14
14
  * @example
15
15
  * ```typescript
16
16
  * import { MultiSessionClient } from '@mcp-ts/sdk/server';
17
- * import { AguiAdapter } from '@mcp-ts/sdk/adapters/mcp-adapter';
17
+ * import { AguiAdapter } from '@mcp-ts/sdk/adapters/agui-adapter';
18
18
  * import { createMcpMiddleware } from '@mcp-ts/sdk/adapters/agui-middleware';
19
19
  * import { HttpAgent } from '@ag-ui/client';
20
20
  *
@@ -28,10 +28,18 @@ import '@modelcontextprotocol/sdk/client/auth.js';
28
28
  *
29
29
  * // Use with AG-UI middleware
30
30
  * const agent = new HttpAgent({ url: 'http://localhost:8000/agent' });
31
- * agent.use(createMcpMiddleware(mcpClient, { tools }));
31
+ * agent.use(createMcpMiddleware({ tools }));
32
32
  * ```
33
33
  */
34
34
 
35
+ /**
36
+ * Cleans a JSON Schema by removing meta-properties that cause issues with
37
+ * strict Pydantic validation (e.g., Google ADK, LangGraph).
38
+ *
39
+ * @param schema - The JSON Schema to clean
40
+ * @returns Cleaned schema without forbidden properties
41
+ */
42
+ declare function cleanSchema(schema: Record<string, any> | undefined): Record<string, any>;
35
43
  /**
36
44
  * Configuration options for AguiAdapter
37
45
  */
@@ -44,41 +52,25 @@ interface AguiAdapterOptions {
44
52
  }
45
53
  /**
46
54
  * AG-UI Tool with handler for server-side execution.
47
- *
48
- * Tools contain:
49
- * - `name`: Unique identifier (prefixed with server ID)
50
- * - `description`: Human-readable description for the LLM
51
- * - `parameters`: JSON Schema defining the input format
52
- * - `handler`: Function that executes the tool via MCP client
53
55
  */
54
56
  interface AguiTool {
55
- /** Unique tool name (e.g., "server-abc_get_weather") */
56
57
  name: string;
57
- /** Human-readable description for the LLM */
58
58
  description: string;
59
- /** JSON Schema format parameters */
60
59
  parameters?: Record<string, any>;
61
- /** Handler function that executes the MCP tool */
60
+ _meta?: Record<string, any>;
62
61
  handler?: (args: any) => any | Promise<any>;
63
62
  }
64
63
  /**
65
64
  * Tool definition format for passing to remote agents (without handler).
66
- * Compatible with OpenAI's function calling API.
67
65
  */
68
66
  interface AguiToolDefinition {
69
- /** Tool name (e.g., "server-abc_get_weather") */
70
67
  name: string;
71
- /** Human-readable description */
72
68
  description: string;
73
- /** JSON Schema format parameters */
74
69
  parameters: Record<string, any>;
70
+ _meta?: Record<string, any>;
75
71
  }
76
72
  /**
77
73
  * Adapter that transforms MCP tools into AG-UI compatible formats.
78
- *
79
- * This adapter provides two main outputs:
80
- * - `getTools()`: Returns tools with handlers for server-side execution
81
- * - `getToolDefinitions()`: Returns tool definitions in JSON Schema format for remote agents
82
74
  */
83
75
  declare class AguiAdapter {
84
76
  private client;
@@ -86,34 +78,19 @@ declare class AguiAdapter {
86
78
  constructor(client: MCPClient | MultiSessionClient, options?: AguiAdapterOptions);
87
79
  /**
88
80
  * Get tools with handlers for MCP tool execution.
89
- *
90
- * Each tool includes a handler function that:
91
- * 1. Calls the MCP tool via the client
92
- * 2. Extracts text content from the result
93
- * 3. Returns the result as a string or JSON
94
- *
95
- * @returns Array of AguiTool objects
96
81
  */
97
82
  getTools(): Promise<AguiTool[]>;
98
- private transformTools;
99
- /**
100
- * Get tools as a function (for dynamic loading).
101
- *
102
- * @returns Function that returns a Promise of tools
103
- */
104
- getToolsFunction(): () => Promise<AguiTool[]>;
105
83
  /**
106
84
  * Get tool definitions in JSON Schema format for passing to remote agents.
107
- *
108
- * This format is compatible with:
109
- * - OpenAI's function calling API
110
- * - AG-UI input.tools format
111
- * - Most LLM tool/function calling implementations
112
- *
113
- * @returns Array of AguiToolDefinition objects
114
85
  */
115
86
  getToolDefinitions(): Promise<AguiToolDefinition[]>;
87
+ /**
88
+ * Get tools as a function (for dynamic loading).
89
+ */
90
+ getToolsFunction(): () => Promise<AguiTool[]>;
91
+ private isMultiSession;
92
+ private transformTools;
116
93
  private transformToolDefinitions;
117
94
  }
118
95
 
119
- export { AguiAdapter, type AguiAdapterOptions, type AguiTool, type AguiToolDefinition };
96
+ export { AguiAdapter, type AguiAdapterOptions, type AguiTool, type AguiToolDefinition, cleanSchema };
@@ -1,6 +1,52 @@
1
1
  'use strict';
2
2
 
3
3
  // src/adapters/agui-adapter.ts
4
+ var PYDANTIC_FORBIDDEN_PROPS = [
5
+ // JSON Schema meta-properties
6
+ "$schema",
7
+ "$id",
8
+ "$comment",
9
+ "$defs",
10
+ "definitions",
11
+ // Extended properties used by some MCP servers (e.g., Apify)
12
+ "prefill",
13
+ "examples",
14
+ "enumTitles",
15
+ "enumDescriptions",
16
+ // Other common extensions
17
+ "deprecated",
18
+ "readOnly",
19
+ "writeOnly",
20
+ "contentMediaType",
21
+ "contentEncoding"
22
+ ];
23
+ function cleanSchema(schema) {
24
+ if (!schema) {
25
+ return { type: "object", properties: {} };
26
+ }
27
+ const cleaned = { ...schema };
28
+ for (const prop of PYDANTIC_FORBIDDEN_PROPS) {
29
+ delete cleaned[prop];
30
+ }
31
+ if (cleaned.properties && typeof cleaned.properties === "object") {
32
+ const cleanedProps = {};
33
+ for (const [key, value] of Object.entries(cleaned.properties)) {
34
+ if (typeof value === "object" && value !== null) {
35
+ cleanedProps[key] = cleanSchema(value);
36
+ } else {
37
+ cleanedProps[key] = value;
38
+ }
39
+ }
40
+ cleaned.properties = cleanedProps;
41
+ }
42
+ if (cleaned.items && typeof cleaned.items === "object") {
43
+ cleaned.items = cleanSchema(cleaned.items);
44
+ }
45
+ if (cleaned.additionalProperties && typeof cleaned.additionalProperties === "object") {
46
+ cleaned.additionalProperties = cleanSchema(cleaned.additionalProperties);
47
+ }
48
+ return cleaned;
49
+ }
4
50
  var AguiAdapter = class {
5
51
  constructor(client, options = {}) {
6
52
  this.client = client;
@@ -8,102 +54,82 @@ var AguiAdapter = class {
8
54
  }
9
55
  /**
10
56
  * Get tools with handlers for MCP tool execution.
11
- *
12
- * Each tool includes a handler function that:
13
- * 1. Calls the MCP tool via the client
14
- * 2. Extracts text content from the result
15
- * 3. Returns the result as a string or JSON
16
- *
17
- * @returns Array of AguiTool objects
18
57
  */
19
58
  async getTools() {
20
- const isMultiSession = typeof this.client.getClients === "function";
21
- if (isMultiSession) {
59
+ if (this.isMultiSession()) {
22
60
  const clients = this.client.getClients();
23
61
  const allTools = [];
24
62
  for (const client of clients) {
25
- const tools = await this.transformTools(client);
26
- allTools.push(...tools);
63
+ allTools.push(...await this.transformTools(client));
27
64
  }
28
65
  return allTools;
29
66
  }
30
67
  return this.transformTools(this.client);
31
68
  }
32
- async transformTools(client) {
33
- if (!client.isConnected()) {
34
- return [];
35
- }
36
- const result = await client.listTools();
37
- const prefix = this.options.prefix ?? client.getServerId() ?? "mcp";
38
- const tools = [];
39
- for (const tool of result.tools) {
40
- const toolName = `${prefix}_${tool.name}`;
41
- tools.push({
42
- name: toolName,
43
- description: tool.description || `Execute ${tool.name}`,
44
- parameters: tool.inputSchema || { type: "object", properties: {} },
45
- handler: async (args) => {
46
- console.log(`[AguiAdapter] Executing MCP tool: ${tool.name}`, args);
47
- const result2 = await client.callTool(tool.name, args);
48
- if (result2.content && Array.isArray(result2.content)) {
49
- const textContent = result2.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
50
- return textContent || result2;
51
- }
52
- return result2;
53
- }
54
- });
55
- }
56
- return tools;
57
- }
58
- /**
59
- * Get tools as a function (for dynamic loading).
60
- *
61
- * @returns Function that returns a Promise of tools
62
- */
63
- getToolsFunction() {
64
- return async () => this.getTools();
65
- }
66
69
  /**
67
70
  * Get tool definitions in JSON Schema format for passing to remote agents.
68
- *
69
- * This format is compatible with:
70
- * - OpenAI's function calling API
71
- * - AG-UI input.tools format
72
- * - Most LLM tool/function calling implementations
73
- *
74
- * @returns Array of AguiToolDefinition objects
75
71
  */
76
72
  async getToolDefinitions() {
77
- const isMultiSession = typeof this.client.getClients === "function";
78
- if (isMultiSession) {
73
+ if (this.isMultiSession()) {
79
74
  const clients = this.client.getClients();
80
75
  const allTools = [];
81
76
  for (const client of clients) {
82
- const tools = await this.transformToolDefinitions(client);
83
- allTools.push(...tools);
77
+ allTools.push(...await this.transformToolDefinitions(client));
84
78
  }
85
79
  return allTools;
86
80
  }
87
81
  return this.transformToolDefinitions(this.client);
88
82
  }
83
+ /**
84
+ * Get tools as a function (for dynamic loading).
85
+ */
86
+ getToolsFunction() {
87
+ return () => this.getTools();
88
+ }
89
+ isMultiSession() {
90
+ return typeof this.client.getClients === "function";
91
+ }
92
+ async transformTools(client) {
93
+ if (!client.isConnected()) return [];
94
+ const result = await client.listTools();
95
+ const serverId = typeof client.getServerId === "function" ? client.getServerId() : void 0;
96
+ const normalizedPrefix = (this.options.prefix ?? serverId ?? "mcp").replace(/-/g, "");
97
+ const prefix = `tool_${normalizedPrefix}`;
98
+ return result.tools.map((tool) => {
99
+ const mcpTool = tool;
100
+ const mcpToolName = tool.name;
101
+ return {
102
+ name: `${prefix}_${tool.name}`,
103
+ description: tool.description || `Execute ${tool.name}`,
104
+ parameters: cleanSchema(tool.inputSchema),
105
+ _meta: { ...mcpTool._meta, sessionId: client.getSessionId?.() },
106
+ handler: async (args) => {
107
+ console.log(`[AguiAdapter] Executing MCP tool: ${mcpToolName}`, args);
108
+ const callResult = await client.callTool(mcpToolName, args ?? {});
109
+ return callResult;
110
+ }
111
+ };
112
+ });
113
+ }
89
114
  async transformToolDefinitions(client) {
90
- if (!client.isConnected()) {
91
- return [];
92
- }
115
+ if (!client.isConnected()) return [];
93
116
  const result = await client.listTools();
94
- const prefix = this.options.prefix ?? client.getServerId() ?? "mcp";
95
- const tools = [];
96
- for (const tool of result.tools) {
97
- tools.push({
117
+ const serverId = typeof client.getServerId === "function" ? client.getServerId() : void 0;
118
+ const normalizedPrefix = (this.options.prefix ?? serverId ?? "mcp").replace(/-/g, "");
119
+ const prefix = `tool_${normalizedPrefix}`;
120
+ return result.tools.map((tool) => {
121
+ const mcpTool = tool;
122
+ return {
98
123
  name: `${prefix}_${tool.name}`,
99
124
  description: tool.description || `Execute ${tool.name}`,
100
- parameters: tool.inputSchema || { type: "object", properties: {} }
101
- });
102
- }
103
- return tools;
125
+ parameters: cleanSchema(tool.inputSchema),
126
+ _meta: { ...mcpTool._meta, sessionId: client.getSessionId?.() }
127
+ };
128
+ });
104
129
  }
105
130
  };
106
131
 
107
132
  exports.AguiAdapter = AguiAdapter;
133
+ exports.cleanSchema = cleanSchema;
108
134
  //# sourceMappingURL=agui-adapter.js.map
109
135
  //# sourceMappingURL=agui-adapter.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/agui-adapter.ts"],"names":["result"],"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/mcp-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(mcpClient, { 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 * 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\n * Tools contain:\r\n * - `name`: Unique identifier (prefixed with server ID)\r\n * - `description`: Human-readable description for the LLM\r\n * - `parameters`: JSON Schema defining the input format\r\n * - `handler`: Function that executes the tool via MCP client\r\n */\r\nexport interface AguiTool {\r\n /** Unique tool name (e.g., \"server-abc_get_weather\") */\r\n name: string;\r\n /** Human-readable description for the LLM */\r\n description: string;\r\n /** JSON Schema format parameters */\r\n parameters?: Record<string, any>;\r\n /** Handler function that executes the MCP tool */\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 * Compatible with OpenAI's function calling API.\r\n */\r\nexport interface AguiToolDefinition {\r\n /** Tool name (e.g., \"server-abc_get_weather\") */\r\n name: string;\r\n /** Human-readable description */\r\n description: string;\r\n /** JSON Schema format parameters */\r\n parameters: Record<string, any>;\r\n}\r\n\r\n/**\r\n * Adapter that transforms MCP tools into AG-UI compatible formats.\r\n *\r\n * This adapter provides two main outputs:\r\n * - `getTools()`: Returns tools with handlers for server-side execution\r\n * - `getToolDefinitions()`: Returns tool definitions in JSON Schema format for remote agents\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 * Each tool includes a handler function that:\r\n * 1. Calls the MCP tool via the client\r\n * 2. Extracts text content from the result\r\n * 3. Returns the result as a string or JSON\r\n *\r\n * @returns Array of AguiTool objects\r\n */\r\n async getTools(): Promise<AguiTool[]> {\r\n const isMultiSession = typeof (this.client as any).getClients === 'function';\r\n\r\n if (isMultiSession) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiTool[] = [];\r\n\r\n for (const client of clients) {\r\n const tools = await this.transformTools(client);\r\n allTools.push(...tools);\r\n }\r\n\r\n return allTools;\r\n }\r\n\r\n return this.transformTools(this.client as MCPClient);\r\n }\r\n\r\n private async transformTools(client: MCPClient): Promise<AguiTool[]> {\r\n if (!client.isConnected()) {\r\n return [];\r\n }\r\n\r\n const result = await client.listTools();\r\n const prefix = this.options.prefix ?? client.getServerId() ?? 'mcp';\r\n const tools: AguiTool[] = [];\r\n\r\n for (const tool of result.tools) {\r\n const toolName = `${prefix}_${tool.name}`;\r\n\r\n tools.push({\r\n name: toolName,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: tool.inputSchema || { type: 'object', properties: {} },\r\n handler: async (args: any) => {\r\n console.log(`[AguiAdapter] Executing MCP tool: ${tool.name}`, args);\r\n const result = await client.callTool(tool.name, args);\r\n\r\n // Extract text content from result\r\n if (result.content && Array.isArray(result.content)) {\r\n const textContent = result.content\r\n .filter((c: any) => c.type === 'text')\r\n .map((c: any) => c.text)\r\n .join('\\n');\r\n return textContent || result;\r\n }\r\n\r\n return result;\r\n }\r\n });\r\n }\r\n\r\n return tools;\r\n }\r\n\r\n /**\r\n * Get tools as a function (for dynamic loading).\r\n *\r\n * @returns Function that returns a Promise of tools\r\n */\r\n getToolsFunction(): () => Promise<AguiTool[]> {\r\n return async () => this.getTools();\r\n }\r\n\r\n /**\r\n * Get tool definitions in JSON Schema format for passing to remote agents.\r\n *\r\n * This format is compatible with:\r\n * - OpenAI's function calling API\r\n * - AG-UI input.tools format\r\n * - Most LLM tool/function calling implementations\r\n *\r\n * @returns Array of AguiToolDefinition objects\r\n */\r\n async getToolDefinitions(): Promise<AguiToolDefinition[]> {\r\n const isMultiSession = typeof (this.client as any).getClients === 'function';\r\n\r\n if (isMultiSession) {\r\n const clients = (this.client as MultiSessionClient).getClients();\r\n const allTools: AguiToolDefinition[] = [];\r\n\r\n for (const client of clients) {\r\n const tools = await this.transformToolDefinitions(client);\r\n allTools.push(...tools);\r\n }\r\n\r\n return allTools;\r\n }\r\n\r\n return this.transformToolDefinitions(this.client as MCPClient);\r\n }\r\n\r\n private async transformToolDefinitions(client: MCPClient): Promise<AguiToolDefinition[]> {\r\n if (!client.isConnected()) {\r\n return [];\r\n }\r\n\r\n const result = await client.listTools();\r\n const prefix = this.options.prefix ?? client.getServerId() ?? 'mcp';\r\n const tools: AguiToolDefinition[] = [];\r\n\r\n for (const tool of result.tools) {\r\n tools.push({\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: tool.inputSchema || { type: 'object', properties: {} },\r\n });\r\n }\r\n\r\n return tools;\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 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"]}