@mcp-ts/sdk 1.0.0 → 1.0.1
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 +3 -3
- package/dist/adapters/agui-adapter.d.mts +19 -42
- package/dist/adapters/agui-adapter.d.ts +19 -42
- package/dist/adapters/agui-adapter.js +69 -69
- package/dist/adapters/agui-adapter.js.map +1 -1
- package/dist/adapters/agui-adapter.mjs +69 -70
- package/dist/adapters/agui-adapter.mjs.map +1 -1
- package/dist/adapters/agui-middleware.d.mts +24 -136
- package/dist/adapters/agui-middleware.d.ts +24 -136
- package/dist/adapters/agui-middleware.js +275 -350
- package/dist/adapters/agui-middleware.js.map +1 -1
- package/dist/adapters/agui-middleware.mjs +275 -350
- package/dist/adapters/agui-middleware.mjs.map +1 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/react.d.mts +2 -2
- package/dist/client/react.d.ts +2 -2
- package/dist/client/vue.d.mts +2 -2
- package/dist/client/vue.d.ts +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +3 -3
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +2 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs.map +1 -1
- package/dist/{types-SbDlA2VX.d.mts → types-CLccx9wW.d.mts} +1 -1
- package/dist/{types-SbDlA2VX.d.ts → types-CLccx9wW.d.ts} +1 -1
- package/package.json +2 -2
- package/src/adapters/agui-adapter.ts +98 -109
- package/src/adapters/agui-middleware.ts +424 -512
- package/src/server/handlers/sse-handler.ts +4 -1
- package/src/server/storage/types.ts +1 -1
- package/src/shared/types.ts +1 -1
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>
|
|
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/
|
|
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>
|
|
@@ -185,7 +185,7 @@ const mcpTools = await adapter.getTools();
|
|
|
185
185
|
|
|
186
186
|
// Create agent with middleware
|
|
187
187
|
const agent = new HttpAgent({ url: "http://localhost:8000/agent" });
|
|
188
|
-
agent.use(createMcpMiddleware(
|
|
188
|
+
agent.use(createMcpMiddleware({
|
|
189
189
|
toolPrefix: 'server-',
|
|
190
190
|
tools: mcpTools,
|
|
191
191
|
}));
|
|
@@ -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/
|
|
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,20 @@ 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(
|
|
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).
|
|
38
|
+
*
|
|
39
|
+
* Removes: $schema, $id, $comment, $defs, definitions
|
|
40
|
+
*
|
|
41
|
+
* @param schema - The JSON Schema to clean
|
|
42
|
+
* @returns Cleaned schema without meta-properties
|
|
43
|
+
*/
|
|
44
|
+
declare function cleanSchema(schema: Record<string, any> | undefined): Record<string, any>;
|
|
35
45
|
/**
|
|
36
46
|
* Configuration options for AguiAdapter
|
|
37
47
|
*/
|
|
@@ -44,41 +54,23 @@ interface AguiAdapterOptions {
|
|
|
44
54
|
}
|
|
45
55
|
/**
|
|
46
56
|
* 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
57
|
*/
|
|
54
58
|
interface AguiTool {
|
|
55
|
-
/** Unique tool name (e.g., "server-abc_get_weather") */
|
|
56
59
|
name: string;
|
|
57
|
-
/** Human-readable description for the LLM */
|
|
58
60
|
description: string;
|
|
59
|
-
/** JSON Schema format parameters */
|
|
60
61
|
parameters?: Record<string, any>;
|
|
61
|
-
/** Handler function that executes the MCP tool */
|
|
62
62
|
handler?: (args: any) => any | Promise<any>;
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
65
|
* Tool definition format for passing to remote agents (without handler).
|
|
66
|
-
* Compatible with OpenAI's function calling API.
|
|
67
66
|
*/
|
|
68
67
|
interface AguiToolDefinition {
|
|
69
|
-
/** Tool name (e.g., "server-abc_get_weather") */
|
|
70
68
|
name: string;
|
|
71
|
-
/** Human-readable description */
|
|
72
69
|
description: string;
|
|
73
|
-
/** JSON Schema format parameters */
|
|
74
70
|
parameters: 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 };
|
|
@@ -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/
|
|
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,20 @@ 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(
|
|
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).
|
|
38
|
+
*
|
|
39
|
+
* Removes: $schema, $id, $comment, $defs, definitions
|
|
40
|
+
*
|
|
41
|
+
* @param schema - The JSON Schema to clean
|
|
42
|
+
* @returns Cleaned schema without meta-properties
|
|
43
|
+
*/
|
|
44
|
+
declare function cleanSchema(schema: Record<string, any> | undefined): Record<string, any>;
|
|
35
45
|
/**
|
|
36
46
|
* Configuration options for AguiAdapter
|
|
37
47
|
*/
|
|
@@ -44,41 +54,23 @@ interface AguiAdapterOptions {
|
|
|
44
54
|
}
|
|
45
55
|
/**
|
|
46
56
|
* 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
57
|
*/
|
|
54
58
|
interface AguiTool {
|
|
55
|
-
/** Unique tool name (e.g., "server-abc_get_weather") */
|
|
56
59
|
name: string;
|
|
57
|
-
/** Human-readable description for the LLM */
|
|
58
60
|
description: string;
|
|
59
|
-
/** JSON Schema format parameters */
|
|
60
61
|
parameters?: Record<string, any>;
|
|
61
|
-
/** Handler function that executes the MCP tool */
|
|
62
62
|
handler?: (args: any) => any | Promise<any>;
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
65
|
* Tool definition format for passing to remote agents (without handler).
|
|
66
|
-
* Compatible with OpenAI's function calling API.
|
|
67
66
|
*/
|
|
68
67
|
interface AguiToolDefinition {
|
|
69
|
-
/** Tool name (e.g., "server-abc_get_weather") */
|
|
70
68
|
name: string;
|
|
71
|
-
/** Human-readable description */
|
|
72
69
|
description: string;
|
|
73
|
-
/** JSON Schema format parameters */
|
|
74
70
|
parameters: 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,35 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// src/adapters/agui-adapter.ts
|
|
4
|
+
function cleanSchema(schema) {
|
|
5
|
+
if (!schema) {
|
|
6
|
+
return { type: "object", properties: {} };
|
|
7
|
+
}
|
|
8
|
+
const cleaned = { ...schema };
|
|
9
|
+
delete cleaned.$schema;
|
|
10
|
+
delete cleaned.$id;
|
|
11
|
+
delete cleaned.$comment;
|
|
12
|
+
delete cleaned.$defs;
|
|
13
|
+
delete cleaned.definitions;
|
|
14
|
+
if (cleaned.properties && typeof cleaned.properties === "object") {
|
|
15
|
+
const cleanedProps = {};
|
|
16
|
+
for (const [key, value] of Object.entries(cleaned.properties)) {
|
|
17
|
+
if (typeof value === "object" && value !== null) {
|
|
18
|
+
cleanedProps[key] = cleanSchema(value);
|
|
19
|
+
} else {
|
|
20
|
+
cleanedProps[key] = value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
cleaned.properties = cleanedProps;
|
|
24
|
+
}
|
|
25
|
+
if (cleaned.items && typeof cleaned.items === "object") {
|
|
26
|
+
cleaned.items = cleanSchema(cleaned.items);
|
|
27
|
+
}
|
|
28
|
+
if (cleaned.additionalProperties && typeof cleaned.additionalProperties === "object") {
|
|
29
|
+
cleaned.additionalProperties = cleanSchema(cleaned.additionalProperties);
|
|
30
|
+
}
|
|
31
|
+
return cleaned;
|
|
32
|
+
}
|
|
4
33
|
var AguiAdapter = class {
|
|
5
34
|
constructor(client, options = {}) {
|
|
6
35
|
this.client = client;
|
|
@@ -8,102 +37,73 @@ var AguiAdapter = class {
|
|
|
8
37
|
}
|
|
9
38
|
/**
|
|
10
39
|
* 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
40
|
*/
|
|
19
41
|
async getTools() {
|
|
20
|
-
|
|
21
|
-
if (isMultiSession) {
|
|
42
|
+
if (this.isMultiSession()) {
|
|
22
43
|
const clients = this.client.getClients();
|
|
23
44
|
const allTools = [];
|
|
24
45
|
for (const client of clients) {
|
|
25
|
-
|
|
26
|
-
allTools.push(...tools);
|
|
46
|
+
allTools.push(...await this.transformTools(client));
|
|
27
47
|
}
|
|
28
48
|
return allTools;
|
|
29
49
|
}
|
|
30
50
|
return this.transformTools(this.client);
|
|
31
51
|
}
|
|
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
52
|
/**
|
|
67
53
|
* 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
54
|
*/
|
|
76
55
|
async getToolDefinitions() {
|
|
77
|
-
|
|
78
|
-
if (isMultiSession) {
|
|
56
|
+
if (this.isMultiSession()) {
|
|
79
57
|
const clients = this.client.getClients();
|
|
80
58
|
const allTools = [];
|
|
81
59
|
for (const client of clients) {
|
|
82
|
-
|
|
83
|
-
allTools.push(...tools);
|
|
60
|
+
allTools.push(...await this.transformToolDefinitions(client));
|
|
84
61
|
}
|
|
85
62
|
return allTools;
|
|
86
63
|
}
|
|
87
64
|
return this.transformToolDefinitions(this.client);
|
|
88
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Get tools as a function (for dynamic loading).
|
|
68
|
+
*/
|
|
69
|
+
getToolsFunction() {
|
|
70
|
+
return () => this.getTools();
|
|
71
|
+
}
|
|
72
|
+
isMultiSession() {
|
|
73
|
+
return typeof this.client.getClients === "function";
|
|
74
|
+
}
|
|
75
|
+
async transformTools(client) {
|
|
76
|
+
if (!client.isConnected()) return [];
|
|
77
|
+
const result = await client.listTools();
|
|
78
|
+
const prefix = this.options.prefix ?? `tool_${client.getServerId() ?? "mcp"}`;
|
|
79
|
+
return result.tools.map((tool) => ({
|
|
80
|
+
name: `${prefix}_${tool.name}`,
|
|
81
|
+
description: tool.description || `Execute ${tool.name}`,
|
|
82
|
+
parameters: cleanSchema(tool.inputSchema),
|
|
83
|
+
handler: async (args) => {
|
|
84
|
+
console.log(`[AguiAdapter] Executing MCP tool: ${tool.name}`, args);
|
|
85
|
+
const result2 = await client.callTool(tool.name, args);
|
|
86
|
+
if (result2.content && Array.isArray(result2.content)) {
|
|
87
|
+
const textContent = result2.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
88
|
+
return textContent || result2;
|
|
89
|
+
}
|
|
90
|
+
return result2;
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
89
94
|
async transformToolDefinitions(client) {
|
|
90
|
-
if (!client.isConnected())
|
|
91
|
-
return [];
|
|
92
|
-
}
|
|
95
|
+
if (!client.isConnected()) return [];
|
|
93
96
|
const result = await client.listTools();
|
|
94
|
-
const prefix = this.options.prefix ?? client.getServerId() ?? "mcp"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
parameters: tool.inputSchema || { type: "object", properties: {} }
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
return tools;
|
|
97
|
+
const prefix = this.options.prefix ?? `tool_${client.getServerId() ?? "mcp"}`;
|
|
98
|
+
return result.tools.map((tool) => ({
|
|
99
|
+
name: `${prefix}_${tool.name}`,
|
|
100
|
+
description: tool.description || `Execute ${tool.name}`,
|
|
101
|
+
parameters: cleanSchema(tool.inputSchema)
|
|
102
|
+
}));
|
|
104
103
|
}
|
|
105
104
|
};
|
|
106
105
|
|
|
107
106
|
exports.AguiAdapter = AguiAdapter;
|
|
107
|
+
exports.cleanSchema = cleanSchema;
|
|
108
108
|
//# sourceMappingURL=agui-adapter.js.map
|
|
109
109
|
//# 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":["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/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 * Cleans a JSON Schema by removing meta-properties that cause issues with\r\n * strict Pydantic validation (e.g., Google ADK).\r\n *\r\n * Removes: $schema, $id, $comment, $defs, definitions\r\n *\r\n * @param schema - The JSON Schema to clean\r\n * @returns Cleaned schema without meta-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 JSON Schema meta-properties that cause Pydantic validation errors\r\n delete cleaned.$schema;\r\n delete cleaned.$id;\r\n delete cleaned.$comment;\r\n delete cleaned.$defs;\r\n delete cleaned.definitions;\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 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}\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 prefix = this.options.prefix ?? `tool_${client.getServerId() ?? 'mcp'}`;\r\n\r\n return result.tools.map(tool => ({\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\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 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 return result;\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 prefix = this.options.prefix ?? `tool_${client.getServerId() ?? 'mcp'}`;\r\n\r\n return result.tools.map(tool => ({\r\n name: `${prefix}_${tool.name}`,\r\n description: tool.description || `Execute ${tool.name}`,\r\n parameters: cleanSchema(tool.inputSchema),\r\n }));\r\n }\r\n}\r\n"]}
|
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
// src/adapters/agui-adapter.ts
|
|
2
|
+
function cleanSchema(schema) {
|
|
3
|
+
if (!schema) {
|
|
4
|
+
return { type: "object", properties: {} };
|
|
5
|
+
}
|
|
6
|
+
const cleaned = { ...schema };
|
|
7
|
+
delete cleaned.$schema;
|
|
8
|
+
delete cleaned.$id;
|
|
9
|
+
delete cleaned.$comment;
|
|
10
|
+
delete cleaned.$defs;
|
|
11
|
+
delete cleaned.definitions;
|
|
12
|
+
if (cleaned.properties && typeof cleaned.properties === "object") {
|
|
13
|
+
const cleanedProps = {};
|
|
14
|
+
for (const [key, value] of Object.entries(cleaned.properties)) {
|
|
15
|
+
if (typeof value === "object" && value !== null) {
|
|
16
|
+
cleanedProps[key] = cleanSchema(value);
|
|
17
|
+
} else {
|
|
18
|
+
cleanedProps[key] = value;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
cleaned.properties = cleanedProps;
|
|
22
|
+
}
|
|
23
|
+
if (cleaned.items && typeof cleaned.items === "object") {
|
|
24
|
+
cleaned.items = cleanSchema(cleaned.items);
|
|
25
|
+
}
|
|
26
|
+
if (cleaned.additionalProperties && typeof cleaned.additionalProperties === "object") {
|
|
27
|
+
cleaned.additionalProperties = cleanSchema(cleaned.additionalProperties);
|
|
28
|
+
}
|
|
29
|
+
return cleaned;
|
|
30
|
+
}
|
|
2
31
|
var AguiAdapter = class {
|
|
3
32
|
constructor(client, options = {}) {
|
|
4
33
|
this.client = client;
|
|
@@ -6,102 +35,72 @@ var AguiAdapter = class {
|
|
|
6
35
|
}
|
|
7
36
|
/**
|
|
8
37
|
* Get tools with handlers for MCP tool execution.
|
|
9
|
-
*
|
|
10
|
-
* Each tool includes a handler function that:
|
|
11
|
-
* 1. Calls the MCP tool via the client
|
|
12
|
-
* 2. Extracts text content from the result
|
|
13
|
-
* 3. Returns the result as a string or JSON
|
|
14
|
-
*
|
|
15
|
-
* @returns Array of AguiTool objects
|
|
16
38
|
*/
|
|
17
39
|
async getTools() {
|
|
18
|
-
|
|
19
|
-
if (isMultiSession) {
|
|
40
|
+
if (this.isMultiSession()) {
|
|
20
41
|
const clients = this.client.getClients();
|
|
21
42
|
const allTools = [];
|
|
22
43
|
for (const client of clients) {
|
|
23
|
-
|
|
24
|
-
allTools.push(...tools);
|
|
44
|
+
allTools.push(...await this.transformTools(client));
|
|
25
45
|
}
|
|
26
46
|
return allTools;
|
|
27
47
|
}
|
|
28
48
|
return this.transformTools(this.client);
|
|
29
49
|
}
|
|
30
|
-
async transformTools(client) {
|
|
31
|
-
if (!client.isConnected()) {
|
|
32
|
-
return [];
|
|
33
|
-
}
|
|
34
|
-
const result = await client.listTools();
|
|
35
|
-
const prefix = this.options.prefix ?? client.getServerId() ?? "mcp";
|
|
36
|
-
const tools = [];
|
|
37
|
-
for (const tool of result.tools) {
|
|
38
|
-
const toolName = `${prefix}_${tool.name}`;
|
|
39
|
-
tools.push({
|
|
40
|
-
name: toolName,
|
|
41
|
-
description: tool.description || `Execute ${tool.name}`,
|
|
42
|
-
parameters: tool.inputSchema || { type: "object", properties: {} },
|
|
43
|
-
handler: async (args) => {
|
|
44
|
-
console.log(`[AguiAdapter] Executing MCP tool: ${tool.name}`, args);
|
|
45
|
-
const result2 = await client.callTool(tool.name, args);
|
|
46
|
-
if (result2.content && Array.isArray(result2.content)) {
|
|
47
|
-
const textContent = result2.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
48
|
-
return textContent || result2;
|
|
49
|
-
}
|
|
50
|
-
return result2;
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
return tools;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Get tools as a function (for dynamic loading).
|
|
58
|
-
*
|
|
59
|
-
* @returns Function that returns a Promise of tools
|
|
60
|
-
*/
|
|
61
|
-
getToolsFunction() {
|
|
62
|
-
return async () => this.getTools();
|
|
63
|
-
}
|
|
64
50
|
/**
|
|
65
51
|
* Get tool definitions in JSON Schema format for passing to remote agents.
|
|
66
|
-
*
|
|
67
|
-
* This format is compatible with:
|
|
68
|
-
* - OpenAI's function calling API
|
|
69
|
-
* - AG-UI input.tools format
|
|
70
|
-
* - Most LLM tool/function calling implementations
|
|
71
|
-
*
|
|
72
|
-
* @returns Array of AguiToolDefinition objects
|
|
73
52
|
*/
|
|
74
53
|
async getToolDefinitions() {
|
|
75
|
-
|
|
76
|
-
if (isMultiSession) {
|
|
54
|
+
if (this.isMultiSession()) {
|
|
77
55
|
const clients = this.client.getClients();
|
|
78
56
|
const allTools = [];
|
|
79
57
|
for (const client of clients) {
|
|
80
|
-
|
|
81
|
-
allTools.push(...tools);
|
|
58
|
+
allTools.push(...await this.transformToolDefinitions(client));
|
|
82
59
|
}
|
|
83
60
|
return allTools;
|
|
84
61
|
}
|
|
85
62
|
return this.transformToolDefinitions(this.client);
|
|
86
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Get tools as a function (for dynamic loading).
|
|
66
|
+
*/
|
|
67
|
+
getToolsFunction() {
|
|
68
|
+
return () => this.getTools();
|
|
69
|
+
}
|
|
70
|
+
isMultiSession() {
|
|
71
|
+
return typeof this.client.getClients === "function";
|
|
72
|
+
}
|
|
73
|
+
async transformTools(client) {
|
|
74
|
+
if (!client.isConnected()) return [];
|
|
75
|
+
const result = await client.listTools();
|
|
76
|
+
const prefix = this.options.prefix ?? `tool_${client.getServerId() ?? "mcp"}`;
|
|
77
|
+
return result.tools.map((tool) => ({
|
|
78
|
+
name: `${prefix}_${tool.name}`,
|
|
79
|
+
description: tool.description || `Execute ${tool.name}`,
|
|
80
|
+
parameters: cleanSchema(tool.inputSchema),
|
|
81
|
+
handler: async (args) => {
|
|
82
|
+
console.log(`[AguiAdapter] Executing MCP tool: ${tool.name}`, args);
|
|
83
|
+
const result2 = await client.callTool(tool.name, args);
|
|
84
|
+
if (result2.content && Array.isArray(result2.content)) {
|
|
85
|
+
const textContent = result2.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
86
|
+
return textContent || result2;
|
|
87
|
+
}
|
|
88
|
+
return result2;
|
|
89
|
+
}
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
87
92
|
async transformToolDefinitions(client) {
|
|
88
|
-
if (!client.isConnected())
|
|
89
|
-
return [];
|
|
90
|
-
}
|
|
93
|
+
if (!client.isConnected()) return [];
|
|
91
94
|
const result = await client.listTools();
|
|
92
|
-
const prefix = this.options.prefix ?? client.getServerId() ?? "mcp"
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
parameters: tool.inputSchema || { type: "object", properties: {} }
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
return tools;
|
|
95
|
+
const prefix = this.options.prefix ?? `tool_${client.getServerId() ?? "mcp"}`;
|
|
96
|
+
return result.tools.map((tool) => ({
|
|
97
|
+
name: `${prefix}_${tool.name}`,
|
|
98
|
+
description: tool.description || `Execute ${tool.name}`,
|
|
99
|
+
parameters: cleanSchema(tool.inputSchema)
|
|
100
|
+
}));
|
|
102
101
|
}
|
|
103
102
|
};
|
|
104
103
|
|
|
105
|
-
export { AguiAdapter };
|
|
104
|
+
export { AguiAdapter, cleanSchema };
|
|
106
105
|
//# sourceMappingURL=agui-adapter.mjs.map
|
|
107
106
|
//# sourceMappingURL=agui-adapter.mjs.map
|