@mcp-ts/sdk 1.4.0 → 1.5.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 +20 -27
- package/dist/adapters/agui-adapter.d.mts +16 -0
- package/dist/adapters/agui-adapter.d.ts +16 -0
- package/dist/adapters/agui-adapter.js +185 -0
- package/dist/adapters/agui-adapter.js.map +1 -1
- package/dist/adapters/agui-adapter.mjs +185 -0
- package/dist/adapters/agui-adapter.mjs.map +1 -1
- package/dist/adapters/agui-middleware.d.mts +2 -0
- package/dist/adapters/agui-middleware.d.ts +2 -0
- package/dist/adapters/agui-middleware.js.map +1 -1
- package/dist/adapters/agui-middleware.mjs.map +1 -1
- package/dist/adapters/ai-adapter.d.mts +21 -0
- package/dist/adapters/ai-adapter.d.ts +21 -0
- package/dist/adapters/ai-adapter.js +175 -0
- package/dist/adapters/ai-adapter.js.map +1 -1
- package/dist/adapters/ai-adapter.mjs +175 -0
- package/dist/adapters/ai-adapter.mjs.map +1 -1
- package/dist/adapters/langchain-adapter.d.mts +16 -0
- package/dist/adapters/langchain-adapter.d.ts +16 -0
- package/dist/adapters/langchain-adapter.js +179 -0
- package/dist/adapters/langchain-adapter.js.map +1 -1
- package/dist/adapters/langchain-adapter.mjs +179 -0
- package/dist/adapters/langchain-adapter.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 +14 -7
- package/dist/client/react.d.ts +14 -7
- package/dist/client/react.js +48 -23
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +47 -24
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +4 -4
- package/dist/client/vue.d.ts +4 -4
- package/dist/{index-CQr9q0bF.d.mts → index-DcYfpY3H.d.mts} +1 -1
- package/dist/{index-nE_7Io0I.d.ts → index-GfC_eNEv.d.ts} +1 -1
- package/dist/index.d.mts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +883 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +868 -2
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +3 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +3 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +86 -4
- package/dist/shared/index.d.ts +86 -4
- package/dist/shared/index.js +874 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +865 -1
- package/dist/shared/index.mjs.map +1 -1
- package/dist/tool-router-Bo8qZbsD.d.ts +325 -0
- package/dist/tool-router-XnWVxPzv.d.mts +325 -0
- package/dist/{types-CW6lghof.d.mts → types-CfCoIsWI.d.mts} +27 -1
- package/dist/{types-CW6lghof.d.ts → types-CfCoIsWI.d.ts} +27 -1
- package/package.json +3 -2
- package/src/adapters/agui-adapter.ts +79 -0
- package/src/adapters/ai-adapter.ts +75 -0
- package/src/adapters/langchain-adapter.ts +74 -0
- package/src/client/react/index.ts +2 -0
- package/src/client/react/use-mcp-apps.tsx +50 -32
- package/src/server/index.ts +2 -0
- package/src/server/mcp/oauth-client.ts +3 -1
- package/src/shared/index.ts +36 -0
- package/src/shared/meta-tools.ts +387 -0
- package/src/shared/schema-compressor.ts +124 -0
- package/src/shared/tool-index.ts +499 -0
- package/src/shared/tool-router.ts +469 -0
- package/src/shared/types.ts +30 -0
|
@@ -2,6 +2,8 @@ import { MCPClient } from '../server/mcp/oauth-client';
|
|
|
2
2
|
import { MultiSessionClient } from '../server/mcp/multi-session-client';
|
|
3
3
|
import type { DynamicStructuredTool, StructuredTool } from '@langchain/core/tools';
|
|
4
4
|
import type { z } from 'zod';
|
|
5
|
+
import { ToolRouter } from '../shared/tool-router.js';
|
|
6
|
+
import { executeMetaTool, isMetaTool } from '../shared/meta-tools.js';
|
|
5
7
|
|
|
6
8
|
export interface LangChainAdapterOptions {
|
|
7
9
|
/**
|
|
@@ -16,6 +18,12 @@ export interface LangChainAdapterOptions {
|
|
|
16
18
|
* @default false
|
|
17
19
|
*/
|
|
18
20
|
simplifyErrors?: boolean;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Optional ToolRouter for intelligent tool selection.
|
|
24
|
+
* See AIAdapterOptions.toolRouter for details.
|
|
25
|
+
*/
|
|
26
|
+
toolRouter?: ToolRouter;
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
/**
|
|
@@ -99,6 +107,11 @@ export class LangChainAdapter {
|
|
|
99
107
|
* Fetches tools from the MCP server and converts them to LangChain StructuredTools.
|
|
100
108
|
*/
|
|
101
109
|
async getTools(): Promise<StructuredTool[]> {
|
|
110
|
+
// If a ToolRouter is provided, use its filtered output
|
|
111
|
+
if (this.options.toolRouter) {
|
|
112
|
+
return this.getToolsViaRouter(this.options.toolRouter);
|
|
113
|
+
}
|
|
114
|
+
|
|
102
115
|
// Use duck typing instead of instanceof to handle module bundling issues
|
|
103
116
|
const isMultiSession = typeof (this.client as any).getClients === 'function';
|
|
104
117
|
const clients = isMultiSession
|
|
@@ -118,6 +131,67 @@ export class LangChainAdapter {
|
|
|
118
131
|
return results.flat();
|
|
119
132
|
}
|
|
120
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Build StructuredTools from a ToolRouter's filtered output.
|
|
136
|
+
*
|
|
137
|
+
* In `search` strategy, only meta-tools are registered with the framework.
|
|
138
|
+
* Real tool execution is proxied through `mcp_execute_tool` which uses
|
|
139
|
+
* `router.callTool()` to route to the correct MCP client.
|
|
140
|
+
*/
|
|
141
|
+
private async getToolsViaRouter(router: ToolRouter): Promise<StructuredTool[]> {
|
|
142
|
+
await this.ensureDependencies();
|
|
143
|
+
|
|
144
|
+
const filteredTools = await router.getFilteredTools();
|
|
145
|
+
|
|
146
|
+
return filteredTools.map((tool) => {
|
|
147
|
+
const routedTool = tool as typeof tool & { sessionId?: string; serverName?: string };
|
|
148
|
+
const namespace = routedTool.serverName ?? routedTool.sessionId;
|
|
149
|
+
const schema = this.jsonSchemaToZod(tool.inputSchema);
|
|
150
|
+
|
|
151
|
+
return new this.DynamicStructuredTool!({
|
|
152
|
+
name: isMetaTool(tool.name)
|
|
153
|
+
? tool.name
|
|
154
|
+
: this.getRouterToolKey(tool.name, routedTool.sessionId, routedTool.serverName),
|
|
155
|
+
description: tool.description || `Tool ${tool.name}`,
|
|
156
|
+
schema: schema,
|
|
157
|
+
func: async (args: any) => {
|
|
158
|
+
try {
|
|
159
|
+
// Handle meta-tool calls via the router
|
|
160
|
+
if (isMetaTool(tool.name)) {
|
|
161
|
+
const result = await executeMetaTool(
|
|
162
|
+
tool.name,
|
|
163
|
+
args,
|
|
164
|
+
router,
|
|
165
|
+
(name, toolArgs, namespace) => router.callTool(name, toolArgs, namespace)
|
|
166
|
+
);
|
|
167
|
+
if (result) {
|
|
168
|
+
return result.content.map((c: any) => c.text ?? '').join('\n');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// For non-meta tools in 'all' or 'groups' strategy,
|
|
173
|
+
// route directly to the correct MCP client
|
|
174
|
+
return await router.callTool(tool.name, args, namespace);
|
|
175
|
+
} catch (error: any) {
|
|
176
|
+
if (this.options.simplifyErrors) {
|
|
177
|
+
return `Error: ${error.message}`;
|
|
178
|
+
}
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private getRouterToolKey(toolName: string, sessionId?: string, serverName?: string): string {
|
|
187
|
+
const namespace = sessionId ?? serverName ?? 'mcp';
|
|
188
|
+
const normalized = namespace
|
|
189
|
+
.toLowerCase()
|
|
190
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
191
|
+
.replace(/^_+|_+$/g, '') || 'mcp';
|
|
192
|
+
return `tool_${normalized}_${toolName}`;
|
|
193
|
+
}
|
|
194
|
+
|
|
121
195
|
/**
|
|
122
196
|
* Convenience static method to fetch tools in a single line.
|
|
123
197
|
*/
|
|
@@ -15,7 +15,9 @@ import React, {
|
|
|
15
15
|
useImperativeHandle,
|
|
16
16
|
type MutableRefObject,
|
|
17
17
|
} from 'react';
|
|
18
|
-
import {
|
|
18
|
+
import type { UseAppHostOptions } from './use-app-host.js';
|
|
19
|
+
import { useAppHost } from './use-app-host.js';
|
|
20
|
+
import { resolveMetaToolProxy } from '../../shared/meta-tools.js';
|
|
19
21
|
import type { SSEClient } from '../core/sse-client.js';
|
|
20
22
|
import { APP_HOST_DEFAULTS } from '../core/constants.js';
|
|
21
23
|
import type { SandboxConfig } from '../core/app-host.js';
|
|
@@ -56,9 +58,10 @@ export interface McpAppRendererHandle {
|
|
|
56
58
|
/** Props for {@link useMcpApps}'s `McpAppRenderer` (client is supplied via the hook). */
|
|
57
59
|
export interface McpAppRendererProps extends Pick<UseAppHostOptions, 'sandbox' | 'hostContext' | 'onCallTool' | 'onReadResource' | 'onFallbackRequest' | 'onMessage' | 'onOpenLink' | 'onLoggingMessage' | 'onSizeChanged' | 'onError'> {
|
|
58
60
|
name: string;
|
|
61
|
+
client?: McpClient | null;
|
|
59
62
|
toolResourceUri?: string;
|
|
60
63
|
html?: string;
|
|
61
|
-
input?: Record<string, unknown
|
|
64
|
+
input?: Record<string, unknown> | null;
|
|
62
65
|
result?: unknown;
|
|
63
66
|
status?: 'executing' | 'inProgress' | 'complete' | 'idle';
|
|
64
67
|
toolInputPartial?: any;
|
|
@@ -102,8 +105,10 @@ const McpAppViewInner = forwardRef<McpAppRendererHandle, McpAppViewProps>(functi
|
|
|
102
105
|
},
|
|
103
106
|
ref,
|
|
104
107
|
) {
|
|
108
|
+
|
|
105
109
|
const mcpClient = clientRef.current;
|
|
106
|
-
const
|
|
110
|
+
const { toolName: resolvedToolName, args: resolvedInput } = resolveMetaToolProxy(name, input);
|
|
111
|
+
const metadata = getMcpAppMetadata(mcpClient, resolvedToolName, resolvedInput);
|
|
107
112
|
const sseClient = mcpClient?.sseClient ?? null;
|
|
108
113
|
const resourceUri = toolResourceUri || metadata?.resourceUri;
|
|
109
114
|
const appSessionId = metadata?.sessionId;
|
|
@@ -194,7 +199,7 @@ const McpAppViewInner = forwardRef<McpAppRendererHandle, McpAppViewProps>(functi
|
|
|
194
199
|
|
|
195
200
|
const sentInputRef = useRef(false);
|
|
196
201
|
const sentResultRef = useRef(false);
|
|
197
|
-
const lastInputRef = useRef(
|
|
202
|
+
const lastInputRef = useRef(resolvedInput);
|
|
198
203
|
const lastResultRef = useRef(result);
|
|
199
204
|
const lastStatusRef = useRef(status);
|
|
200
205
|
|
|
@@ -236,15 +241,16 @@ const McpAppViewInner = forwardRef<McpAppRendererHandle, McpAppViewProps>(functi
|
|
|
236
241
|
.catch((err) => setError(err instanceof Error ? err : new Error(String(err))));
|
|
237
242
|
}, [host, resourceUri, html, appSessionId]);
|
|
238
243
|
|
|
244
|
+
// Send tool inputs
|
|
239
245
|
useEffect(() => {
|
|
240
|
-
if (!host || !isLaunched || !resourceUri || !appSessionId || !
|
|
246
|
+
if (!host || !isLaunched || !resourceUri || !appSessionId || !resolvedInput) return;
|
|
241
247
|
|
|
242
|
-
if (!sentInputRef.current || JSON.stringify(
|
|
248
|
+
if (!sentInputRef.current || JSON.stringify(resolvedInput) !== JSON.stringify(lastInputRef.current)) {
|
|
243
249
|
sentInputRef.current = true;
|
|
244
|
-
lastInputRef.current =
|
|
245
|
-
host.sendToolInput(
|
|
250
|
+
lastInputRef.current = resolvedInput;
|
|
251
|
+
host.sendToolInput(resolvedInput);
|
|
246
252
|
}
|
|
247
|
-
}, [host, isLaunched,
|
|
253
|
+
}, [host, isLaunched, resolvedInput, resourceUri, appSessionId, resolvedToolName]);
|
|
248
254
|
|
|
249
255
|
useEffect(() => {
|
|
250
256
|
if (!host || !isLaunched || !resourceUri || !appSessionId || result === undefined) return;
|
|
@@ -259,7 +265,7 @@ const McpAppViewInner = forwardRef<McpAppRendererHandle, McpAppViewProps>(functi
|
|
|
259
265
|
: result;
|
|
260
266
|
host.sendToolResult(formattedResult);
|
|
261
267
|
}
|
|
262
|
-
}, [host, isLaunched, result, status, resourceUri, appSessionId,
|
|
268
|
+
}, [host, isLaunched, result, status, resourceUri, appSessionId, resolvedToolName]);
|
|
263
269
|
|
|
264
270
|
useEffect(() => {
|
|
265
271
|
if (status === 'executing' && lastStatusRef.current !== 'executing') {
|
|
@@ -354,34 +360,44 @@ const McpAppViewInner = forwardRef<McpAppRendererHandle, McpAppViewProps>(functi
|
|
|
354
360
|
const McpAppView = memo(McpAppViewInner);
|
|
355
361
|
McpAppView.displayName = 'McpAppView';
|
|
356
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Renders an interactive MCP application inside a sandboxed iframe.
|
|
365
|
+
*/
|
|
366
|
+
export const McpAppRenderer = memo(
|
|
367
|
+
forwardRef<McpAppRendererHandle, McpAppRendererProps>(function McpAppRenderer(
|
|
368
|
+
{ client, ...props },
|
|
369
|
+
ref
|
|
370
|
+
) {
|
|
371
|
+
const clientRef = useRef(client || null);
|
|
372
|
+
clientRef.current = client || null;
|
|
373
|
+
|
|
374
|
+
return <McpAppView ref={ref} clientRef={clientRef} {...props} />;
|
|
375
|
+
})
|
|
376
|
+
);
|
|
377
|
+
|
|
357
378
|
/**
|
|
358
379
|
* Helpers scoped to one `mcpClient`. Pass the client here once; `McpAppRenderer` only needs per-tool props (`name`, `input`, `result`, `status`).
|
|
359
380
|
*
|
|
360
381
|
* @param mcpClient - From `useMcp()` or context (for example `useMcpContext()`).
|
|
382
|
+
* @deprecated Use the standalone `<McpAppRenderer>` component and `getMcpAppMetadata` utility directly.
|
|
361
383
|
*/
|
|
362
384
|
export function useMcpApps(mcpClient: McpClient | null) {
|
|
363
|
-
// Stable `McpAppRenderer` type: parent re-renders and `connections` updates must not remount the iframe.
|
|
364
|
-
const clientRef = useRef(mcpClient);
|
|
365
|
-
clientRef.current = mcpClient;
|
|
366
|
-
|
|
367
385
|
const getAppMetadata = useCallback(
|
|
368
|
-
(toolName: string) => getMcpAppMetadata(
|
|
369
|
-
[]
|
|
386
|
+
(toolName: string) => getMcpAppMetadata(mcpClient, toolName),
|
|
387
|
+
[mcpClient]
|
|
370
388
|
);
|
|
371
389
|
|
|
372
|
-
const
|
|
373
|
-
const
|
|
374
|
-
props,
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return { getAppMetadata, McpAppRenderer };
|
|
390
|
+
const BoundMcpAppRenderer = useMemo(() => {
|
|
391
|
+
const Renderer = forwardRef<McpAppRendererHandle, Omit<McpAppRendererProps, 'client'>>(
|
|
392
|
+
function BoundMcpAppRenderer(props, ref) {
|
|
393
|
+
return <McpAppRenderer ref={ref} client={mcpClient} {...props} />;
|
|
394
|
+
}
|
|
395
|
+
);
|
|
396
|
+
Renderer.displayName = 'BoundMcpAppRenderer';
|
|
397
|
+
return memo(Renderer);
|
|
398
|
+
}, [mcpClient]);
|
|
399
|
+
|
|
400
|
+
return { getAppMetadata, McpAppRenderer: BoundMcpAppRenderer };
|
|
385
401
|
}
|
|
386
402
|
|
|
387
403
|
function extractToolName(fullName: string): string {
|
|
@@ -389,13 +405,15 @@ function extractToolName(fullName: string): string {
|
|
|
389
405
|
return match?.[1] || fullName;
|
|
390
406
|
}
|
|
391
407
|
|
|
392
|
-
function getMcpAppMetadata(
|
|
408
|
+
export function getMcpAppMetadata(
|
|
393
409
|
mcpClient: McpClient | null,
|
|
394
|
-
toolName: string
|
|
410
|
+
toolName: string,
|
|
411
|
+
input?: Record<string, unknown> | null
|
|
395
412
|
): McpAppMetadata | undefined {
|
|
396
413
|
if (!mcpClient) return undefined;
|
|
397
414
|
|
|
398
|
-
const
|
|
415
|
+
const { toolName: proxyToolName } = resolveMetaToolProxy(toolName, input);
|
|
416
|
+
const extractedName = extractToolName(proxyToolName);
|
|
399
417
|
|
|
400
418
|
for (const conn of mcpClient.connections) {
|
|
401
419
|
for (const tool of conn.tools) {
|
package/src/server/index.ts
CHANGED
|
@@ -1108,7 +1108,9 @@ export class MCPClient {
|
|
|
1108
1108
|
* @returns Server name or undefined
|
|
1109
1109
|
*/
|
|
1110
1110
|
getServerName(): string | undefined {
|
|
1111
|
-
|
|
1111
|
+
const info = (this.client as any)?.getServerVersion();
|
|
1112
|
+
console.log('server info ->', info);
|
|
1113
|
+
return info?.title ?? info?.name ?? this.serverName;
|
|
1112
1114
|
}
|
|
1113
1115
|
|
|
1114
1116
|
/**
|
package/src/shared/index.ts
CHANGED
|
@@ -22,6 +22,8 @@ export * from './errors';
|
|
|
22
22
|
|
|
23
23
|
// Types
|
|
24
24
|
export type {
|
|
25
|
+
ToolClient,
|
|
26
|
+
ToolClientProvider,
|
|
25
27
|
ToolInfo,
|
|
26
28
|
McpRpcRequest,
|
|
27
29
|
McpRpcResponse,
|
|
@@ -73,3 +75,37 @@ export {
|
|
|
73
75
|
type ToolUiConfig,
|
|
74
76
|
} from './tool-utils.js';
|
|
75
77
|
|
|
78
|
+
// Tool Router — Context window optimization
|
|
79
|
+
export {
|
|
80
|
+
ToolRouter,
|
|
81
|
+
type ToolRouterOptions,
|
|
82
|
+
type ToolRouterStrategy,
|
|
83
|
+
type ToolRouterClientInput,
|
|
84
|
+
type ToolGroupInfo,
|
|
85
|
+
} from './tool-router.js';
|
|
86
|
+
|
|
87
|
+
export {
|
|
88
|
+
ToolIndex,
|
|
89
|
+
type ToolSummary,
|
|
90
|
+
type IndexedTool,
|
|
91
|
+
type ToolIndexOptions,
|
|
92
|
+
type EmbedFn,
|
|
93
|
+
} from './tool-index.js';
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
SchemaCompressor,
|
|
97
|
+
type CompactTool,
|
|
98
|
+
type CompressionStats,
|
|
99
|
+
} from './schema-compressor.js';
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
createSearchToolDefinition,
|
|
103
|
+
createRegexSearchToolDefinition,
|
|
104
|
+
createGetSchemaToolDefinition,
|
|
105
|
+
createExecuteToolDefinition,
|
|
106
|
+
executeMetaTool,
|
|
107
|
+
isMetaTool,
|
|
108
|
+
resolveMetaToolProxy,
|
|
109
|
+
type CallToolFn,
|
|
110
|
+
} from './meta-tools.js';
|
|
111
|
+
|