@mcp-ts/sdk 1.0.1 → 1.2.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 +42 -19
- package/dist/adapters/agui-adapter.d.mts +6 -6
- package/dist/adapters/agui-adapter.d.ts +6 -6
- package/dist/adapters/agui-adapter.js +50 -25
- package/dist/adapters/agui-adapter.js.map +1 -1
- package/dist/adapters/agui-adapter.mjs +50 -25
- package/dist/adapters/agui-adapter.mjs.map +1 -1
- package/dist/adapters/agui-middleware.d.mts +23 -8
- package/dist/adapters/agui-middleware.d.ts +23 -8
- package/dist/adapters/agui-middleware.js +71 -43
- package/dist/adapters/agui-middleware.js.map +1 -1
- package/dist/adapters/agui-middleware.mjs +71 -44
- package/dist/adapters/agui-middleware.mjs.map +1 -1
- package/dist/adapters/ai-adapter.d.mts +2 -2
- package/dist/adapters/ai-adapter.d.ts +2 -2
- package/dist/adapters/langchain-adapter.d.mts +2 -2
- package/dist/adapters/langchain-adapter.d.ts +2 -2
- package/dist/adapters/mastra-adapter.d.mts +2 -2
- package/dist/adapters/mastra-adapter.d.ts +2 -2
- package/dist/client/index.d.mts +182 -55
- package/dist/client/index.d.ts +182 -55
- package/dist/client/index.js +535 -130
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +535 -131
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/react.d.mts +386 -4
- package/dist/client/react.d.ts +386 -4
- package/dist/client/react.js +890 -143
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +883 -145
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +3 -3
- package/dist/client/vue.d.ts +3 -3
- package/dist/client/vue.js +546 -141
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +546 -142
- package/dist/client/vue.mjs.map +1 -1
- package/dist/{events-BP6WyRNh.d.mts → events-BgeztGYZ.d.mts} +12 -1
- package/dist/{events-BP6WyRNh.d.ts → events-BgeztGYZ.d.ts} +12 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +797 -248
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +791 -245
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-DMF3ED2O.d.mts → multi-session-client-CxogNckF.d.mts} +1 -1
- package/dist/{multi-session-client-BOFgPypS.d.ts → multi-session-client-cox_WXUj.d.ts} +1 -1
- package/dist/server/index.d.mts +41 -37
- package/dist/server/index.d.ts +41 -37
- package/dist/server/index.js +241 -116
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +237 -112
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +39 -3
- package/dist/shared/index.d.ts +39 -3
- package/dist/shared/index.js +19 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +18 -1
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +9 -2
- package/src/adapters/agui-adapter.ts +58 -35
- package/src/adapters/agui-middleware.ts +83 -45
- package/src/client/core/app-host.ts +417 -0
- package/src/client/core/sse-client.ts +365 -212
- package/src/client/core/types.ts +31 -0
- package/src/client/index.ts +1 -0
- package/src/client/react/agui-subscriber.ts +275 -0
- package/src/client/react/index.ts +23 -3
- package/src/client/react/use-agui-subscriber.ts +270 -0
- package/src/client/react/use-app-host.ts +73 -0
- package/src/client/react/use-mcp-app-iframe.ts +164 -0
- package/src/client/react/{useMcp.ts → use-mcp.ts} +18 -0
- package/src/client/vue/index.ts +1 -1
- package/src/server/handlers/nextjs-handler.ts +8 -7
- package/src/server/handlers/sse-handler.ts +129 -165
- package/src/server/mcp/oauth-client.ts +32 -2
- package/src/server/storage/index.ts +17 -1
- package/src/server/storage/sqlite-backend.ts +185 -0
- package/src/shared/events.ts +12 -0
- package/src/shared/index.ts +6 -1
- package/src/shared/tool-utils.ts +61 -0
- package/src/shared/types.ts +3 -1
- /package/src/client/vue/{useMcp.ts → use-mcp.ts} +0 -0
|
@@ -20,11 +20,32 @@ import {
|
|
|
20
20
|
} from '@ag-ui/client';
|
|
21
21
|
import { type AguiTool, cleanSchema } from './agui-adapter.js';
|
|
22
22
|
|
|
23
|
+
/** New event type for MCP UI triggers */
|
|
24
|
+
export const MCP_APP_UI_EVENT = 'mcp-apps-ui';
|
|
25
|
+
/**
|
|
26
|
+
* MCP Apps UI trigger event.
|
|
27
|
+
*
|
|
28
|
+
* IMPORTANT: This must be emitted as an AG-UI CustomEvent so subscribers
|
|
29
|
+
* (e.g. CopilotKit `onCustomEvent`) can receive it.
|
|
30
|
+
*/
|
|
31
|
+
export interface McpAppUiEventPayload {
|
|
32
|
+
toolCallId: string;
|
|
33
|
+
resourceUri: string;
|
|
34
|
+
sessionId?: string;
|
|
35
|
+
toolName: string;
|
|
36
|
+
result?: any;
|
|
37
|
+
}
|
|
38
|
+
|
|
23
39
|
/** Tool execution result for continuation */
|
|
24
40
|
interface ToolResult {
|
|
25
41
|
toolCallId: string;
|
|
26
42
|
toolName: string;
|
|
27
43
|
result: string;
|
|
44
|
+
/**
|
|
45
|
+
* Raw result object (if available).
|
|
46
|
+
* Used to preserve metadata (e.g. `_meta`) that is lost in the stringified `result`.
|
|
47
|
+
*/
|
|
48
|
+
rawResult?: any;
|
|
28
49
|
messageId: string;
|
|
29
50
|
}
|
|
30
51
|
|
|
@@ -43,8 +64,6 @@ interface RunState {
|
|
|
43
64
|
export interface McpMiddlewareConfig {
|
|
44
65
|
/** Pre-loaded tools with handlers (required) */
|
|
45
66
|
tools: AguiTool[];
|
|
46
|
-
/** Max result length in chars (default: 50000) */
|
|
47
|
-
maxResultLength?: number;
|
|
48
67
|
}
|
|
49
68
|
|
|
50
69
|
/**
|
|
@@ -53,20 +72,29 @@ export interface McpMiddlewareConfig {
|
|
|
53
72
|
export class McpMiddleware extends Middleware {
|
|
54
73
|
private tools: AguiTool[];
|
|
55
74
|
private toolSchemas: Tool[];
|
|
56
|
-
private maxResultLength: number;
|
|
57
75
|
|
|
58
76
|
constructor(config: McpMiddlewareConfig) {
|
|
59
77
|
super();
|
|
60
78
|
this.tools = config.tools;
|
|
61
|
-
this.maxResultLength = config.maxResultLength ?? 50000;
|
|
62
79
|
this.toolSchemas = this.tools.map((t: AguiTool) => ({
|
|
63
80
|
name: t.name,
|
|
64
81
|
description: t.description,
|
|
65
82
|
parameters: cleanSchema(t.parameters),
|
|
83
|
+
_meta: t._meta, // Include _meta in the tool definition passed to the agent
|
|
66
84
|
}));
|
|
67
85
|
}
|
|
68
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Extract base tool name from prefixed format for event emission
|
|
89
|
+
* e.g., "tool_abc123_get-time" -> "get-time"
|
|
90
|
+
*/
|
|
91
|
+
private getBaseToolName(toolName: string): string {
|
|
92
|
+
const match = toolName.match(/^tool_[^_]+_(.+)$/);
|
|
93
|
+
return match ? match[1] : toolName;
|
|
94
|
+
}
|
|
95
|
+
|
|
69
96
|
private isMcpTool(toolName: string): boolean {
|
|
97
|
+
// Direct comparison - tool names should match as-is
|
|
70
98
|
return this.tools.some(t => t.name === toolName);
|
|
71
99
|
}
|
|
72
100
|
|
|
@@ -91,29 +119,31 @@ export class McpMiddleware extends Middleware {
|
|
|
91
119
|
}
|
|
92
120
|
}
|
|
93
121
|
|
|
94
|
-
private async executeTool(toolName: string, args: Record<string, any>): Promise<string> {
|
|
122
|
+
private async executeTool(toolName: string, args: Record<string, any>): Promise<{ resultStr: string, rawResult?: any }> {
|
|
95
123
|
const tool = this.tools.find(t => t.name === toolName);
|
|
96
124
|
if (!tool?.handler) {
|
|
97
|
-
return `Error: Tool ${tool ? 'has no handler' : 'not found'}: ${toolName}
|
|
125
|
+
return { resultStr: `Error: Tool ${tool ? 'has no handler' : 'not found'}: ${toolName}` };
|
|
98
126
|
}
|
|
99
127
|
|
|
100
128
|
try {
|
|
101
|
-
|
|
129
|
+
// Result can be a string (legacy) or an object (MCP Result with content array)
|
|
102
130
|
const result = await tool.handler(args);
|
|
103
|
-
let resultStr = typeof result === 'string' ? result : JSON.stringify(result);
|
|
104
131
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
132
|
+
let resultStr: string;
|
|
133
|
+
|
|
134
|
+
if (typeof result === 'string') {
|
|
135
|
+
resultStr = result;
|
|
136
|
+
} else if (result && typeof result === 'object') {
|
|
137
|
+
// Determine if we should preserve the object structure (e.g. for MCP Tool Results)
|
|
138
|
+
resultStr = JSON.stringify(result);
|
|
139
|
+
} else {
|
|
140
|
+
resultStr = String(result);
|
|
110
141
|
}
|
|
111
142
|
|
|
112
|
-
|
|
113
|
-
return resultStr;
|
|
143
|
+
return { resultStr, rawResult: result };
|
|
114
144
|
} catch (error: any) {
|
|
115
145
|
console.error(`[McpMiddleware] Error executing tool:`, error);
|
|
116
|
-
return `Error: ${error.message || String(error)}
|
|
146
|
+
return { resultStr: `Error: ${error.message || String(error)}` };
|
|
117
147
|
}
|
|
118
148
|
}
|
|
119
149
|
|
|
@@ -146,7 +176,6 @@ export class McpMiddleware extends Middleware {
|
|
|
146
176
|
if (this.isMcpTool(e.toolCallName)) {
|
|
147
177
|
pendingMcpCalls.add(e.toolCallId);
|
|
148
178
|
}
|
|
149
|
-
console.log(`[McpMiddleware] TOOL_CALL_START: ${e.toolCallName} (id: ${e.toolCallId}, isMCP: ${this.isMcpTool(e.toolCallName)})`);
|
|
150
179
|
}
|
|
151
180
|
}
|
|
152
181
|
|
|
@@ -159,8 +188,7 @@ export class McpMiddleware extends Middleware {
|
|
|
159
188
|
}
|
|
160
189
|
|
|
161
190
|
if (event.type === EventType.TOOL_CALL_END) {
|
|
162
|
-
|
|
163
|
-
console.log(`[McpMiddleware] TOOL_CALL_END: ${toolCallNames.get(e.toolCallId) ?? 'unknown'} (id: ${e.toolCallId})`);
|
|
191
|
+
// Track tool call end event
|
|
164
192
|
}
|
|
165
193
|
|
|
166
194
|
// Workaround: Extract parallel tool calls from MESSAGES_SNAPSHOT
|
|
@@ -186,7 +214,6 @@ export class McpMiddleware extends Middleware {
|
|
|
186
214
|
toolCallArgsBuffer.set(tc.id, tc.function.arguments || '{}');
|
|
187
215
|
if (this.isMcpTool(tc.function.name)) {
|
|
188
216
|
pendingMcpCalls.add(tc.id);
|
|
189
|
-
console.log(`[McpMiddleware] MESSAGES_SNAPSHOT: Discovered ${tc.function.name} (id: ${tc.id})`);
|
|
190
217
|
}
|
|
191
218
|
}
|
|
192
219
|
}
|
|
@@ -207,13 +234,12 @@ export class McpMiddleware extends Middleware {
|
|
|
207
234
|
if (!toolName) return;
|
|
208
235
|
|
|
209
236
|
const args = this.parseArgs(toolCallArgsBuffer.get(toolCallId) || '{}');
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const result = await this.executeTool(toolName, args);
|
|
237
|
+
const { resultStr, rawResult } = await this.executeTool(toolName, args);
|
|
213
238
|
results.push({
|
|
214
239
|
toolCallId,
|
|
215
240
|
toolName,
|
|
216
|
-
result,
|
|
241
|
+
result: resultStr,
|
|
242
|
+
rawResult,
|
|
217
243
|
messageId: this.generateId('mcp_result'),
|
|
218
244
|
});
|
|
219
245
|
pendingMcpCalls.delete(toolCallId);
|
|
@@ -223,9 +249,39 @@ export class McpMiddleware extends Middleware {
|
|
|
223
249
|
return results;
|
|
224
250
|
}
|
|
225
251
|
|
|
226
|
-
/** Emit tool results (without RUN_FINISHED - that's emitted when truly done) */
|
|
227
252
|
private emitToolResults(observer: Subscriber<BaseEvent>, results: ToolResult[]): void {
|
|
228
|
-
for (const { toolCallId, toolName, result, messageId } of results) {
|
|
253
|
+
for (const { toolCallId, toolName, result, rawResult, messageId } of results) {
|
|
254
|
+
// UI metadata may appear either on the tool CALL result (rawResult._meta)
|
|
255
|
+
// or only on the tool DEFINITION (listTools result). We support both.
|
|
256
|
+
const toolDef = this.tools.find(t => t.name === toolName);
|
|
257
|
+
const sessionId = toolDef?._meta?.sessionId;
|
|
258
|
+
const resourceUri =
|
|
259
|
+
rawResult?._meta?.ui?.resourceUri ??
|
|
260
|
+
rawResult?._meta?.['ui/resourceUri'] ??
|
|
261
|
+
toolDef?._meta?.ui?.resourceUri ??
|
|
262
|
+
toolDef?._meta?.['ui/resourceUri'];
|
|
263
|
+
|
|
264
|
+
if (resourceUri) {
|
|
265
|
+
// Extract base name for event emission to match metadata
|
|
266
|
+
const baseToolName = this.getBaseToolName(toolName);
|
|
267
|
+
|
|
268
|
+
const payload: McpAppUiEventPayload = {
|
|
269
|
+
toolCallId,
|
|
270
|
+
resourceUri,
|
|
271
|
+
sessionId,
|
|
272
|
+
toolName: baseToolName, // Use base name to match metadata
|
|
273
|
+
result: rawResult ?? result,
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
observer.next({
|
|
277
|
+
type: EventType.CUSTOM,
|
|
278
|
+
name: MCP_APP_UI_EVENT,
|
|
279
|
+
value: payload,
|
|
280
|
+
timestamp: Date.now(),
|
|
281
|
+
role: 'tool',
|
|
282
|
+
} as any);
|
|
283
|
+
}
|
|
284
|
+
|
|
229
285
|
observer.next({
|
|
230
286
|
type: EventType.TOOL_CALL_RESULT,
|
|
231
287
|
toolCallId,
|
|
@@ -234,7 +290,6 @@ export class McpMiddleware extends Middleware {
|
|
|
234
290
|
role: 'tool',
|
|
235
291
|
timestamp: Date.now(),
|
|
236
292
|
} as any);
|
|
237
|
-
console.log(`[McpMiddleware] Emitting TOOL_CALL_RESULT for: ${toolName}`);
|
|
238
293
|
}
|
|
239
294
|
}
|
|
240
295
|
|
|
@@ -251,14 +306,9 @@ export class McpMiddleware extends Middleware {
|
|
|
251
306
|
this.ensureIds(input);
|
|
252
307
|
const anyInput = input as any;
|
|
253
308
|
|
|
254
|
-
console.log(`[McpMiddleware] === NEW RUN ===`);
|
|
255
|
-
console.log(`[McpMiddleware] threadId: ${anyInput.threadId}, runId: ${anyInput.runId}`);
|
|
256
|
-
console.log(`[McpMiddleware] messages: ${input.messages?.length ?? 0}, tools: ${this.tools?.length ?? 0}`);
|
|
257
|
-
|
|
258
309
|
// Inject MCP tools
|
|
259
310
|
if (this.toolSchemas?.length) {
|
|
260
311
|
input.tools = [...(input.tools || []), ...this.toolSchemas];
|
|
261
|
-
console.log(`[McpMiddleware] Injected ${this.toolSchemas.length} tools:`, this.toolSchemas.map((t: Tool) => t.name));
|
|
262
312
|
}
|
|
263
313
|
|
|
264
314
|
const handleRunFinished = async () => {
|
|
@@ -275,8 +325,6 @@ export class McpMiddleware extends Middleware {
|
|
|
275
325
|
return;
|
|
276
326
|
}
|
|
277
327
|
|
|
278
|
-
console.log(`[McpMiddleware] RUN_FINISHED with ${state.pendingMcpCalls.size} pending calls`);
|
|
279
|
-
|
|
280
328
|
// Reconstruct the Assistant Message that triggered these tools
|
|
281
329
|
const toolCalls = [];
|
|
282
330
|
for (const toolCallId of state.pendingMcpCalls) {
|
|
@@ -300,16 +348,12 @@ export class McpMiddleware extends Middleware {
|
|
|
300
348
|
tool_calls: toolCalls.length > 0 ? toolCalls : undefined
|
|
301
349
|
};
|
|
302
350
|
input.messages.push(assistantMsg as any);
|
|
303
|
-
console.log(`[McpMiddleware] Added assistant message to history before tools: ${state.textContent?.slice(0, 50)}... [${toolCalls.length} tools]`);
|
|
304
351
|
}
|
|
305
352
|
|
|
306
353
|
// Execute tools and emit results (no RUN_FINISHED yet - continuation follows)
|
|
307
354
|
const results = await this.executeTools(state);
|
|
308
355
|
this.emitToolResults(observer, results);
|
|
309
356
|
|
|
310
|
-
// Prepare continuation
|
|
311
|
-
console.log(`[McpMiddleware] Triggering continuation with ${results.length} results`);
|
|
312
|
-
|
|
313
357
|
// Add tool result messages to history
|
|
314
358
|
for (const { toolCallId, result, messageId } of results) {
|
|
315
359
|
input.messages.push({
|
|
@@ -326,7 +370,6 @@ export class McpMiddleware extends Middleware {
|
|
|
326
370
|
state.textContent = ''; // Clear text content for next turn
|
|
327
371
|
|
|
328
372
|
anyInput.runId = this.generateId('mcp_run');
|
|
329
|
-
console.log(`[McpMiddleware] === CONTINUATION RUN === messages: ${input.messages.length}`);
|
|
330
373
|
|
|
331
374
|
// Subscribe to continuation
|
|
332
375
|
next.run(input).subscribe({
|
|
@@ -336,7 +379,6 @@ export class McpMiddleware extends Middleware {
|
|
|
336
379
|
this.handleToolCallEvent(event, state);
|
|
337
380
|
|
|
338
381
|
if (event.type === EventType.RUN_ERROR) {
|
|
339
|
-
console.log(`[McpMiddleware] RUN_ERROR received in continuation`);
|
|
340
382
|
state.error = true;
|
|
341
383
|
observer.next(event);
|
|
342
384
|
observer.complete();
|
|
@@ -344,7 +386,6 @@ export class McpMiddleware extends Middleware {
|
|
|
344
386
|
}
|
|
345
387
|
|
|
346
388
|
if (event.type === EventType.RUN_STARTED) {
|
|
347
|
-
console.log(`[McpMiddleware] Filtering RUN_STARTED from continuation`);
|
|
348
389
|
return;
|
|
349
390
|
}
|
|
350
391
|
|
|
@@ -376,7 +417,6 @@ export class McpMiddleware extends Middleware {
|
|
|
376
417
|
this.handleToolCallEvent(event, state);
|
|
377
418
|
|
|
378
419
|
if (event.type === EventType.RUN_ERROR) {
|
|
379
|
-
console.log(`[McpMiddleware] RUN_ERROR received`);
|
|
380
420
|
state.error = true;
|
|
381
421
|
observer.next(event);
|
|
382
422
|
observer.complete();
|
|
@@ -406,9 +446,7 @@ export class McpMiddleware extends Middleware {
|
|
|
406
446
|
/**
|
|
407
447
|
* Factory function to create MCP middleware.
|
|
408
448
|
*/
|
|
409
|
-
export function createMcpMiddleware(
|
|
410
|
-
options: { tools: AguiTool[]; maxResultLength?: number }
|
|
411
|
-
) {
|
|
449
|
+
export function createMcpMiddleware(options: { tools: AguiTool[] }) {
|
|
412
450
|
const middleware = new McpMiddleware(options);
|
|
413
451
|
return (input: RunAgentInput, next: AbstractAgent): Observable<BaseEvent> => {
|
|
414
452
|
return middleware.run(input, next);
|