@mcp-fe/mcp-worker 0.1.5 → 0.1.7
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/docs/structured-output.md +484 -0
- package/index.js +33 -5
- package/mcp-service-worker.js +67 -11
- package/mcp-shared-worker.js +67 -11
- package/package.json +1 -1
- package/src/index.d.ts +1 -1
- package/src/index.d.ts.map +1 -1
- package/src/lib/mcp-controller.d.ts +12 -1
- package/src/lib/mcp-controller.d.ts.map +1 -1
- package/src/lib/tool-registry.d.ts +23 -1
- package/src/lib/tool-registry.d.ts.map +1 -1
- package/src/lib/worker-client.d.ts +22 -2
- package/src/lib/worker-client.d.ts.map +1 -1
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
# Structured Output Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The MCP Worker library supports **structured output** through the `outputSchema` parameter. According to MCP specification, tools with `outputSchema` return **both text and structured versions** of the data, allowing AI models to work with parsed objects directly.
|
|
6
|
+
|
|
7
|
+
## Key Benefits
|
|
8
|
+
|
|
9
|
+
- ✅ **Better AI Understanding**: AI models receive parsed JSON objects in `structuredContent`
|
|
10
|
+
- ✅ **Type Safety**: Define clear schemas for tool outputs using Zod or JSON Schema
|
|
11
|
+
- ✅ **Backward Compatible**: Legacy tools without `outputSchema` continue to work
|
|
12
|
+
- ✅ **Flexible**: Supports simple and complex nested data structures
|
|
13
|
+
- ✅ **MCP Compliant**: Follows official MCP specification format
|
|
14
|
+
|
|
15
|
+
## How It Works (MCP Specification)
|
|
16
|
+
|
|
17
|
+
### Without outputSchema (Legacy Behavior)
|
|
18
|
+
|
|
19
|
+
When `outputSchema` is not defined, the tool returns only text content:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
useMCPTool({
|
|
23
|
+
name: 'get_user',
|
|
24
|
+
inputSchema: { /* ... */ },
|
|
25
|
+
// NO outputSchema
|
|
26
|
+
handler: async () => {
|
|
27
|
+
const data = { name: 'John', email: 'john@example.com' };
|
|
28
|
+
return {
|
|
29
|
+
content: [{ type: 'text', text: JSON.stringify(data) }]
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Result sent to AI:**
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"content": [
|
|
39
|
+
{
|
|
40
|
+
"type": "text",
|
|
41
|
+
"text": "{\"name\":\"John\",\"email\":\"john@example.com\"}"
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### With outputSchema (Structured Output)
|
|
48
|
+
|
|
49
|
+
When `outputSchema` is defined, the handler returns JSON text, and MCPController **automatically adds** `structuredContent`:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
useMCPTool({
|
|
53
|
+
name: 'get_user',
|
|
54
|
+
inputSchema: { /* ... */ },
|
|
55
|
+
outputSchema: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
name: { type: 'string' },
|
|
59
|
+
email: { type: 'string' }
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
handler: async () => {
|
|
63
|
+
const data = { name: 'John', email: 'john@example.com' };
|
|
64
|
+
// Return as JSON text - MCPController will parse it
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: 'text', text: JSON.stringify(data) }]
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Result sent to AI (automatic):**
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"content": [
|
|
76
|
+
{
|
|
77
|
+
"type": "text",
|
|
78
|
+
"text": "{\"name\":\"John\",\"email\":\"john@example.com\"}"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"structuredContent": {
|
|
82
|
+
"name": "John",
|
|
83
|
+
"email": "john@example.com"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Key point:** You return text, MCPController adds `structuredContent` automatically!
|
|
89
|
+
|
|
90
|
+
## Usage Examples
|
|
91
|
+
|
|
92
|
+
### Simple Structured Output with Zod
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { useMCPTool } from '@mcp-fe/react-tools';
|
|
96
|
+
import { z } from 'zod';
|
|
97
|
+
|
|
98
|
+
function MyComponent() {
|
|
99
|
+
// Define Zod schema
|
|
100
|
+
const productOutputSchema = z.object({
|
|
101
|
+
id: z.string(),
|
|
102
|
+
name: z.string(),
|
|
103
|
+
price: z.number(),
|
|
104
|
+
inStock: z.boolean(),
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
useMCPTool({
|
|
108
|
+
name: 'get_product',
|
|
109
|
+
description: 'Get product information',
|
|
110
|
+
inputSchema: z.object({
|
|
111
|
+
productId: z.string(),
|
|
112
|
+
}).toJSONSchema(),
|
|
113
|
+
outputSchema: productOutputSchema.toJSONSchema(),
|
|
114
|
+
handler: async (args) => {
|
|
115
|
+
const { productId } = args as { productId: string };
|
|
116
|
+
|
|
117
|
+
// Fetch product data
|
|
118
|
+
const product = await fetchProduct(productId);
|
|
119
|
+
|
|
120
|
+
// Return as JSON text
|
|
121
|
+
return {
|
|
122
|
+
content: [{
|
|
123
|
+
type: 'text',
|
|
124
|
+
text: JSON.stringify(product)
|
|
125
|
+
}]
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**AI receives:**
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"content": [{ "type": "text", "text": "{\"id\":\"123\",\"name\":\"Laptop\"...}" }],
|
|
136
|
+
"structuredContent": {
|
|
137
|
+
"id": "123",
|
|
138
|
+
"name": "Laptop Pro",
|
|
139
|
+
"price": 1299.99,
|
|
140
|
+
"inStock": true
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Complex Nested Output
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import { z } from 'zod';
|
|
149
|
+
|
|
150
|
+
const analyticsOutputSchema = z.object({
|
|
151
|
+
period: z.string(),
|
|
152
|
+
summary: z.object({
|
|
153
|
+
totalVisits: z.number(),
|
|
154
|
+
uniqueVisitors: z.number(),
|
|
155
|
+
}),
|
|
156
|
+
topPages: z.array(z.object({
|
|
157
|
+
path: z.string(),
|
|
158
|
+
views: z.number(),
|
|
159
|
+
})),
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
useMCPTool({
|
|
163
|
+
name: 'get_analytics',
|
|
164
|
+
description: 'Get website analytics',
|
|
165
|
+
inputSchema: z.object({
|
|
166
|
+
period: z.enum(['day', 'week', 'month']),
|
|
167
|
+
}).toJSONSchema(),
|
|
168
|
+
outputSchema: analyticsOutputSchema.toJSONSchema(),
|
|
169
|
+
handler: async (args) => {
|
|
170
|
+
const analytics = await getAnalytics(args);
|
|
171
|
+
|
|
172
|
+
// Return as JSON text
|
|
173
|
+
return {
|
|
174
|
+
content: [{
|
|
175
|
+
type: 'text',
|
|
176
|
+
text: JSON.stringify(analytics)
|
|
177
|
+
}]
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Array Output
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
const usersOutputSchema = z.array(z.object({
|
|
187
|
+
id: z.string(),
|
|
188
|
+
name: z.string(),
|
|
189
|
+
email: z.string(),
|
|
190
|
+
}));
|
|
191
|
+
|
|
192
|
+
useMCPTool({
|
|
193
|
+
name: 'search_users',
|
|
194
|
+
description: 'Search for users',
|
|
195
|
+
inputSchema: z.object({
|
|
196
|
+
query: z.string(),
|
|
197
|
+
}).toJSONSchema(),
|
|
198
|
+
outputSchema: usersOutputSchema.toJSONSchema(),
|
|
199
|
+
handler: async (args) => {
|
|
200
|
+
const users = await searchUsers(args);
|
|
201
|
+
|
|
202
|
+
// Return array as JSON text
|
|
203
|
+
return {
|
|
204
|
+
content: [{
|
|
205
|
+
type: 'text',
|
|
206
|
+
text: JSON.stringify(users)
|
|
207
|
+
}]
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Using with WorkerClient
|
|
214
|
+
|
|
215
|
+
The same functionality works with direct `WorkerClient` usage:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import { workerClient } from '@mcp-fe/mcp-worker';
|
|
219
|
+
|
|
220
|
+
await workerClient.registerTool(
|
|
221
|
+
'get_user',
|
|
222
|
+
'Get user information',
|
|
223
|
+
{
|
|
224
|
+
type: 'object',
|
|
225
|
+
properties: {
|
|
226
|
+
userId: { type: 'string' }
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
async (args) => {
|
|
230
|
+
const user = await fetchUser(args.userId);
|
|
231
|
+
|
|
232
|
+
// Return as JSON text
|
|
233
|
+
return {
|
|
234
|
+
content: [{
|
|
235
|
+
type: 'text',
|
|
236
|
+
text: JSON.stringify(user)
|
|
237
|
+
}]
|
|
238
|
+
};
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
// Define outputSchema in options
|
|
242
|
+
outputSchema: {
|
|
243
|
+
type: 'object',
|
|
244
|
+
properties: {
|
|
245
|
+
id: { type: 'string' },
|
|
246
|
+
name: { type: 'string' },
|
|
247
|
+
email: { type: 'string' }
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Best Practices
|
|
255
|
+
|
|
256
|
+
### 1. Use Zod for Type-Safe Schemas
|
|
257
|
+
|
|
258
|
+
Zod provides better type inference and easier schema definition:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { z } from 'zod';
|
|
262
|
+
|
|
263
|
+
const outputSchema = z.object({
|
|
264
|
+
id: z.string(),
|
|
265
|
+
name: z.string(),
|
|
266
|
+
email: z.string(),
|
|
267
|
+
createdAt: z.string(),
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Use in tool
|
|
271
|
+
outputSchema: outputSchema.toJSONSchema()
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### 2. Mark Optional Fields
|
|
275
|
+
|
|
276
|
+
Use `.optional()` for fields that may not be present:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
const schema = z.object({
|
|
280
|
+
firstName: z.string().optional(),
|
|
281
|
+
lastName: z.string().optional(),
|
|
282
|
+
email: z.string(), // Required
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 3. Always Return JSON Text
|
|
287
|
+
|
|
288
|
+
When using `outputSchema`, always return `type: 'text'` with JSON string:
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// ✅ Correct
|
|
292
|
+
return {
|
|
293
|
+
content: [{
|
|
294
|
+
type: 'text',
|
|
295
|
+
text: JSON.stringify(yourData)
|
|
296
|
+
}]
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// ❌ Incorrect - not JSON
|
|
300
|
+
return {
|
|
301
|
+
content: [{
|
|
302
|
+
type: 'text',
|
|
303
|
+
text: 'Some plain text'
|
|
304
|
+
}]
|
|
305
|
+
};
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### 4. Handle Errors Gracefully
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
handler: async (args) => {
|
|
312
|
+
try {
|
|
313
|
+
const data = await fetchData(args);
|
|
314
|
+
return {
|
|
315
|
+
content: [{
|
|
316
|
+
type: 'text',
|
|
317
|
+
text: JSON.stringify(data)
|
|
318
|
+
}]
|
|
319
|
+
};
|
|
320
|
+
} catch (error) {
|
|
321
|
+
// Errors are automatically handled by the framework
|
|
322
|
+
throw new Error(`Failed to fetch data: ${error.message}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Migration Guide
|
|
328
|
+
|
|
329
|
+
### Migrating Existing Tools
|
|
330
|
+
|
|
331
|
+
If you have existing tools without `outputSchema`, you can add it while keeping the same handler:
|
|
332
|
+
|
|
333
|
+
**Before (Legacy - no outputSchema):**
|
|
334
|
+
```typescript
|
|
335
|
+
useMCPTool({
|
|
336
|
+
name: 'get_data',
|
|
337
|
+
handler: async () => {
|
|
338
|
+
const data = { value: 42 };
|
|
339
|
+
return {
|
|
340
|
+
content: [{
|
|
341
|
+
type: 'text',
|
|
342
|
+
text: JSON.stringify(data)
|
|
343
|
+
}]
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
// AI receives only text
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**After (Structured - with outputSchema):**
|
|
351
|
+
```typescript
|
|
352
|
+
useMCPTool({
|
|
353
|
+
name: 'get_data',
|
|
354
|
+
outputSchema: z.object({
|
|
355
|
+
value: z.number()
|
|
356
|
+
}).toJSONSchema(),
|
|
357
|
+
handler: async () => {
|
|
358
|
+
const data = { value: 42 };
|
|
359
|
+
return {
|
|
360
|
+
content: [{
|
|
361
|
+
type: 'text',
|
|
362
|
+
text: JSON.stringify(data) // Same as before!
|
|
363
|
+
}]
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
// AI receives text + structuredContent automatically
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
**Key point:** You don't need to change your handler! Just add `outputSchema` and MCPController does the rest.
|
|
371
|
+
|
|
372
|
+
## Implementation Details
|
|
373
|
+
|
|
374
|
+
### Internal Flow
|
|
375
|
+
|
|
376
|
+
1. **Tool Registration**: When a tool is registered with `outputSchema`, the flag is stored in `pendingToolCalls`
|
|
377
|
+
2. **Tool Execution**: Handler runs and returns JSON text in `content`
|
|
378
|
+
3. **Result Processing** (MCPController):
|
|
379
|
+
- If `hasOutputSchema` is true → Parse JSON from `content[0].text` and add as `structuredContent`
|
|
380
|
+
- If `hasOutputSchema` is false → Return only `content` (legacy)
|
|
381
|
+
4. **AI Consumption**: AI model receives:
|
|
382
|
+
- With `outputSchema`: `{ content: [...], structuredContent: {...} }`
|
|
383
|
+
- Without `outputSchema`: `{ content: [...] }`
|
|
384
|
+
|
|
385
|
+
### Automatic Processing
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// Your handler returns:
|
|
389
|
+
{
|
|
390
|
+
content: [{ type: 'text', text: '{"name":"John","age":30}' }]
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// MCPController automatically adds (when outputSchema is present):
|
|
394
|
+
{
|
|
395
|
+
content: [{ type: 'text', text: '{"name":"John","age":30}' }],
|
|
396
|
+
structuredContent: { name: 'John', age: 30 }
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Type Definitions
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
interface ToolCallResult {
|
|
404
|
+
success: boolean;
|
|
405
|
+
result?: {
|
|
406
|
+
content: Array<{ type: string; text: string }>;
|
|
407
|
+
};
|
|
408
|
+
error?: string;
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Examples
|
|
413
|
+
|
|
414
|
+
See complete examples in:
|
|
415
|
+
- [`examples/structured-output.ts`](../examples/structured-output.ts) - WorkerClient examples
|
|
416
|
+
- [`react-tools/docs/examples.md`](../../react-tools/docs/examples.md#structured-output) - React hook examples
|
|
417
|
+
|
|
418
|
+
## Troubleshooting
|
|
419
|
+
|
|
420
|
+
### AI doesn't receive structuredContent
|
|
421
|
+
|
|
422
|
+
**Problem**: Tool has `outputSchema` but AI only receives text.
|
|
423
|
+
|
|
424
|
+
**Solution**: Verify your handler returns valid JSON:
|
|
425
|
+
```typescript
|
|
426
|
+
// ✅ Valid JSON string
|
|
427
|
+
return {
|
|
428
|
+
content: [{
|
|
429
|
+
type: 'text',
|
|
430
|
+
text: JSON.stringify(yourData) // Valid JSON
|
|
431
|
+
}]
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// ❌ Invalid - not JSON
|
|
435
|
+
return {
|
|
436
|
+
content: [{
|
|
437
|
+
type: 'text',
|
|
438
|
+
text: 'Some plain text' // Can't parse
|
|
439
|
+
}]
|
|
440
|
+
};
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### JSON parse error in MCPController
|
|
444
|
+
|
|
445
|
+
**Problem**: MCPController logs "Failed to parse structured content"
|
|
446
|
+
|
|
447
|
+
**Solution**: Ensure your data is JSON-serializable:
|
|
448
|
+
```typescript
|
|
449
|
+
// ✅ Serializable
|
|
450
|
+
const data = {
|
|
451
|
+
name: 'John',
|
|
452
|
+
date: new Date().toISOString(), // String, not Date object
|
|
453
|
+
value: 42
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
// ❌ Not serializable
|
|
457
|
+
const data = {
|
|
458
|
+
name: 'John',
|
|
459
|
+
date: new Date(), // Date object fails JSON.stringify
|
|
460
|
+
func: () => {} // Functions fail
|
|
461
|
+
};
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### TypeScript errors with handler return type
|
|
465
|
+
|
|
466
|
+
**Problem**: TypeScript complains about return type.
|
|
467
|
+
|
|
468
|
+
**Solution**: Handler type expects `{ content: Array<{ type: string; text: string }> }`:
|
|
469
|
+
```typescript
|
|
470
|
+
handler: async (): Promise<{ content: Array<{ type: string; text: string }> }> => {
|
|
471
|
+
return {
|
|
472
|
+
content: [{
|
|
473
|
+
type: 'text',
|
|
474
|
+
text: JSON.stringify(data)
|
|
475
|
+
}]
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## See Also
|
|
481
|
+
|
|
482
|
+
- [Tool Registry Documentation](./api.md#tool-registry)
|
|
483
|
+
- [MCP Specification](https://spec.modelcontextprotocol.io/)
|
|
484
|
+
- [JSON Schema Reference](https://json-schema.org/)
|
package/index.js
CHANGED
|
@@ -268,13 +268,22 @@ var WorkerClient = class _WorkerClient {
|
|
|
268
268
|
const pending = [...this.pendingRegistrations];
|
|
269
269
|
this.pendingRegistrations = [];
|
|
270
270
|
pending.forEach(
|
|
271
|
-
async ({
|
|
271
|
+
async ({
|
|
272
|
+
name,
|
|
273
|
+
description,
|
|
274
|
+
inputSchema,
|
|
275
|
+
handler,
|
|
276
|
+
options,
|
|
277
|
+
resolve,
|
|
278
|
+
reject
|
|
279
|
+
}) => {
|
|
272
280
|
try {
|
|
273
281
|
await this.registerToolInternal(
|
|
274
282
|
name,
|
|
275
283
|
description,
|
|
276
284
|
inputSchema,
|
|
277
|
-
handler
|
|
285
|
+
handler,
|
|
286
|
+
options
|
|
278
287
|
);
|
|
279
288
|
resolve();
|
|
280
289
|
} catch (error) {
|
|
@@ -788,7 +797,7 @@ var WorkerClient = class _WorkerClient {
|
|
|
788
797
|
* );
|
|
789
798
|
* ```
|
|
790
799
|
*/
|
|
791
|
-
async registerTool(name, description, inputSchema, handler) {
|
|
800
|
+
async registerTool(name, description, inputSchema, handler, options) {
|
|
792
801
|
if (!this.isInitialized) {
|
|
793
802
|
logger.log(
|
|
794
803
|
`[WorkerClient] Queueing tool registration '${name}' (worker not initialized yet)`
|
|
@@ -799,12 +808,19 @@ var WorkerClient = class _WorkerClient {
|
|
|
799
808
|
description,
|
|
800
809
|
inputSchema,
|
|
801
810
|
handler,
|
|
811
|
+
options,
|
|
802
812
|
resolve,
|
|
803
813
|
reject
|
|
804
814
|
});
|
|
805
815
|
});
|
|
806
816
|
}
|
|
807
|
-
return this.registerToolInternal(
|
|
817
|
+
return this.registerToolInternal(
|
|
818
|
+
name,
|
|
819
|
+
description,
|
|
820
|
+
inputSchema,
|
|
821
|
+
handler,
|
|
822
|
+
options
|
|
823
|
+
);
|
|
808
824
|
}
|
|
809
825
|
/**
|
|
810
826
|
* Enhance tool input schema with optional tabId parameter for multi-tab support
|
|
@@ -825,7 +841,7 @@ var WorkerClient = class _WorkerClient {
|
|
|
825
841
|
* Internal method to register tool (assumes worker is initialized)
|
|
826
842
|
* @private
|
|
827
843
|
*/
|
|
828
|
-
async registerToolInternal(name, description, inputSchema, handler) {
|
|
844
|
+
async registerToolInternal(name, description, inputSchema, handler, options) {
|
|
829
845
|
const existing = this.toolRegistry.get(name);
|
|
830
846
|
if (existing) {
|
|
831
847
|
existing.refCount++;
|
|
@@ -842,6 +858,12 @@ var WorkerClient = class _WorkerClient {
|
|
|
842
858
|
name,
|
|
843
859
|
description,
|
|
844
860
|
inputSchema: enhancedSchema,
|
|
861
|
+
outputSchema: options?.outputSchema,
|
|
862
|
+
annotations: options?.annotations,
|
|
863
|
+
execution: options?.execution,
|
|
864
|
+
_meta: options?._meta,
|
|
865
|
+
icons: options?.icons,
|
|
866
|
+
title: options?.title,
|
|
845
867
|
handlerType: "proxy",
|
|
846
868
|
// Tell worker this is a proxy handler
|
|
847
869
|
tabId: this.tabId
|
|
@@ -851,6 +873,12 @@ var WorkerClient = class _WorkerClient {
|
|
|
851
873
|
refCount: 1,
|
|
852
874
|
description,
|
|
853
875
|
inputSchema: enhancedSchema,
|
|
876
|
+
outputSchema: options?.outputSchema,
|
|
877
|
+
annotations: options?.annotations,
|
|
878
|
+
execution: options?.execution,
|
|
879
|
+
_meta: options?._meta,
|
|
880
|
+
icons: options?.icons,
|
|
881
|
+
title: options?.title,
|
|
854
882
|
isRegistered: true
|
|
855
883
|
});
|
|
856
884
|
logger.log(
|
package/mcp-service-worker.js
CHANGED
|
@@ -28185,6 +28185,14 @@ var TabManager = class {
|
|
|
28185
28185
|
// libs/mcp-worker/src/lib/mcp-controller.ts
|
|
28186
28186
|
var MAX_RECONNECT_DELAY = 3e4;
|
|
28187
28187
|
var INITIAL_RECONNECT_DELAY = 1e3;
|
|
28188
|
+
function isToolCallResult(obj) {
|
|
28189
|
+
if (typeof obj !== "object" || obj === null)
|
|
28190
|
+
return false;
|
|
28191
|
+
const result = obj;
|
|
28192
|
+
return typeof result["success"] === "boolean" && (result["error"] === void 0 || typeof result["error"] === "string") && (result["result"] === void 0 || typeof result["result"] === "object" && result["result"] !== null && Array.isArray(
|
|
28193
|
+
result["result"]["content"]
|
|
28194
|
+
));
|
|
28195
|
+
}
|
|
28188
28196
|
var MCPController = class _MCPController {
|
|
28189
28197
|
constructor(backendUrl2, broadcastFn, requireAuth = true) {
|
|
28190
28198
|
this.backendUrl = backendUrl2;
|
|
@@ -28426,12 +28434,16 @@ var MCPController = class _MCPController {
|
|
|
28426
28434
|
const name = toolData["name"];
|
|
28427
28435
|
const description = toolData["description"];
|
|
28428
28436
|
const inputSchema = toolData["inputSchema"];
|
|
28437
|
+
const outputSchema = toolData["outputSchema"];
|
|
28438
|
+
const annotations = toolData["annotations"];
|
|
28439
|
+
const execution = toolData["execution"];
|
|
28440
|
+
const _meta = toolData["_meta"];
|
|
28441
|
+
const icons = toolData["icons"];
|
|
28442
|
+
const title = toolData["title"];
|
|
28429
28443
|
const handlerType = toolData["handlerType"];
|
|
28430
28444
|
const tabId = toolData["tabId"];
|
|
28431
|
-
if (!name || !
|
|
28432
|
-
throw new Error(
|
|
28433
|
-
"Missing required tool fields: name, description, inputSchema"
|
|
28434
|
-
);
|
|
28445
|
+
if (!name || !inputSchema) {
|
|
28446
|
+
throw new Error("Missing required tool fields: name, inputSchema");
|
|
28435
28447
|
}
|
|
28436
28448
|
if (handlerType !== "proxy") {
|
|
28437
28449
|
throw new Error(
|
|
@@ -28477,8 +28489,9 @@ var MCPController = class _MCPController {
|
|
|
28477
28489
|
reject(
|
|
28478
28490
|
new Error(`Tool call timeout: ${name} (tab: ${targetTabId})`)
|
|
28479
28491
|
);
|
|
28480
|
-
}, 3e4)
|
|
28492
|
+
}, 3e4),
|
|
28481
28493
|
// 30 second timeout
|
|
28494
|
+
hasOutputSchema: !!outputSchema
|
|
28482
28495
|
};
|
|
28483
28496
|
this.pendingToolCalls.set(callId, pendingCall);
|
|
28484
28497
|
this.broadcastFn({
|
|
@@ -28486,7 +28499,8 @@ var MCPController = class _MCPController {
|
|
|
28486
28499
|
toolName: name,
|
|
28487
28500
|
args,
|
|
28488
28501
|
callId,
|
|
28489
|
-
targetTabId
|
|
28502
|
+
targetTabId,
|
|
28503
|
+
hasOutputSchema: !!outputSchema
|
|
28490
28504
|
});
|
|
28491
28505
|
});
|
|
28492
28506
|
};
|
|
@@ -28494,7 +28508,13 @@ var MCPController = class _MCPController {
|
|
|
28494
28508
|
{
|
|
28495
28509
|
name,
|
|
28496
28510
|
description,
|
|
28497
|
-
inputSchema
|
|
28511
|
+
inputSchema,
|
|
28512
|
+
outputSchema,
|
|
28513
|
+
annotations,
|
|
28514
|
+
execution,
|
|
28515
|
+
_meta,
|
|
28516
|
+
icons,
|
|
28517
|
+
title
|
|
28498
28518
|
},
|
|
28499
28519
|
handler
|
|
28500
28520
|
);
|
|
@@ -28513,11 +28533,40 @@ var MCPController = class _MCPController {
|
|
|
28513
28533
|
}
|
|
28514
28534
|
clearTimeout(pendingCall.timeout);
|
|
28515
28535
|
this.pendingToolCalls.delete(callId);
|
|
28516
|
-
|
|
28517
|
-
|
|
28518
|
-
|
|
28536
|
+
if (result.success && result.result !== void 0) {
|
|
28537
|
+
const contentResult = result.result;
|
|
28538
|
+
if (contentResult?.content && Array.isArray(contentResult.content)) {
|
|
28539
|
+
if (pendingCall.hasOutputSchema) {
|
|
28540
|
+
try {
|
|
28541
|
+
const textContent = contentResult.content.find(
|
|
28542
|
+
(c) => c.type === "text"
|
|
28543
|
+
);
|
|
28544
|
+
if (textContent && textContent.text) {
|
|
28545
|
+
const parsed = JSON.parse(textContent.text);
|
|
28546
|
+
pendingCall.resolve({
|
|
28547
|
+
content: contentResult.content,
|
|
28548
|
+
structuredContent: parsed
|
|
28549
|
+
});
|
|
28550
|
+
return;
|
|
28551
|
+
}
|
|
28552
|
+
} catch (error48) {
|
|
28553
|
+
logger.warn(
|
|
28554
|
+
"[MCPController] Failed to parse structured content:",
|
|
28555
|
+
error48
|
|
28556
|
+
);
|
|
28557
|
+
}
|
|
28558
|
+
}
|
|
28559
|
+
pendingCall.resolve(contentResult);
|
|
28560
|
+
} else {
|
|
28561
|
+
logger.warn(
|
|
28562
|
+
"[MCPController] Result missing content array, serializing"
|
|
28563
|
+
);
|
|
28564
|
+
pendingCall.resolve({
|
|
28565
|
+
content: [{ type: "text", text: JSON.stringify(result.result) }]
|
|
28566
|
+
});
|
|
28567
|
+
}
|
|
28519
28568
|
} else {
|
|
28520
|
-
pendingCall.reject(new Error(
|
|
28569
|
+
pendingCall.reject(new Error(result.error || "Tool call failed"));
|
|
28521
28570
|
}
|
|
28522
28571
|
}
|
|
28523
28572
|
async handleUnregisterTool(toolName, tabId) {
|
|
@@ -28845,6 +28894,13 @@ self.addEventListener("message", async (event) => {
|
|
|
28845
28894
|
logger.warn("[ServiceWorker] TOOL_CALL_RESULT missing callId");
|
|
28846
28895
|
return;
|
|
28847
28896
|
}
|
|
28897
|
+
if (!isToolCallResult(msg)) {
|
|
28898
|
+
logger.error(
|
|
28899
|
+
"[ServiceWorker] Invalid TOOL_CALL_RESULT structure:",
|
|
28900
|
+
msg
|
|
28901
|
+
);
|
|
28902
|
+
return;
|
|
28903
|
+
}
|
|
28848
28904
|
getController().handleToolCallResult(callId, msg);
|
|
28849
28905
|
} catch (error48) {
|
|
28850
28906
|
logger.error("[ServiceWorker] Failed to handle TOOL_CALL_RESULT:", error48);
|
package/mcp-shared-worker.js
CHANGED
|
@@ -28185,6 +28185,14 @@ var TabManager = class {
|
|
|
28185
28185
|
// libs/mcp-worker/src/lib/mcp-controller.ts
|
|
28186
28186
|
var MAX_RECONNECT_DELAY = 3e4;
|
|
28187
28187
|
var INITIAL_RECONNECT_DELAY = 1e3;
|
|
28188
|
+
function isToolCallResult(obj) {
|
|
28189
|
+
if (typeof obj !== "object" || obj === null)
|
|
28190
|
+
return false;
|
|
28191
|
+
const result = obj;
|
|
28192
|
+
return typeof result["success"] === "boolean" && (result["error"] === void 0 || typeof result["error"] === "string") && (result["result"] === void 0 || typeof result["result"] === "object" && result["result"] !== null && Array.isArray(
|
|
28193
|
+
result["result"]["content"]
|
|
28194
|
+
));
|
|
28195
|
+
}
|
|
28188
28196
|
var MCPController = class _MCPController {
|
|
28189
28197
|
constructor(backendUrl2, broadcastFn, requireAuth = true) {
|
|
28190
28198
|
this.backendUrl = backendUrl2;
|
|
@@ -28426,12 +28434,16 @@ var MCPController = class _MCPController {
|
|
|
28426
28434
|
const name = toolData["name"];
|
|
28427
28435
|
const description = toolData["description"];
|
|
28428
28436
|
const inputSchema = toolData["inputSchema"];
|
|
28437
|
+
const outputSchema = toolData["outputSchema"];
|
|
28438
|
+
const annotations = toolData["annotations"];
|
|
28439
|
+
const execution = toolData["execution"];
|
|
28440
|
+
const _meta = toolData["_meta"];
|
|
28441
|
+
const icons = toolData["icons"];
|
|
28442
|
+
const title = toolData["title"];
|
|
28429
28443
|
const handlerType = toolData["handlerType"];
|
|
28430
28444
|
const tabId = toolData["tabId"];
|
|
28431
|
-
if (!name || !
|
|
28432
|
-
throw new Error(
|
|
28433
|
-
"Missing required tool fields: name, description, inputSchema"
|
|
28434
|
-
);
|
|
28445
|
+
if (!name || !inputSchema) {
|
|
28446
|
+
throw new Error("Missing required tool fields: name, inputSchema");
|
|
28435
28447
|
}
|
|
28436
28448
|
if (handlerType !== "proxy") {
|
|
28437
28449
|
throw new Error(
|
|
@@ -28477,8 +28489,9 @@ var MCPController = class _MCPController {
|
|
|
28477
28489
|
reject(
|
|
28478
28490
|
new Error(`Tool call timeout: ${name} (tab: ${targetTabId})`)
|
|
28479
28491
|
);
|
|
28480
|
-
}, 3e4)
|
|
28492
|
+
}, 3e4),
|
|
28481
28493
|
// 30 second timeout
|
|
28494
|
+
hasOutputSchema: !!outputSchema
|
|
28482
28495
|
};
|
|
28483
28496
|
this.pendingToolCalls.set(callId, pendingCall);
|
|
28484
28497
|
this.broadcastFn({
|
|
@@ -28486,7 +28499,8 @@ var MCPController = class _MCPController {
|
|
|
28486
28499
|
toolName: name,
|
|
28487
28500
|
args,
|
|
28488
28501
|
callId,
|
|
28489
|
-
targetTabId
|
|
28502
|
+
targetTabId,
|
|
28503
|
+
hasOutputSchema: !!outputSchema
|
|
28490
28504
|
});
|
|
28491
28505
|
});
|
|
28492
28506
|
};
|
|
@@ -28494,7 +28508,13 @@ var MCPController = class _MCPController {
|
|
|
28494
28508
|
{
|
|
28495
28509
|
name,
|
|
28496
28510
|
description,
|
|
28497
|
-
inputSchema
|
|
28511
|
+
inputSchema,
|
|
28512
|
+
outputSchema,
|
|
28513
|
+
annotations,
|
|
28514
|
+
execution,
|
|
28515
|
+
_meta,
|
|
28516
|
+
icons,
|
|
28517
|
+
title
|
|
28498
28518
|
},
|
|
28499
28519
|
handler
|
|
28500
28520
|
);
|
|
@@ -28513,11 +28533,40 @@ var MCPController = class _MCPController {
|
|
|
28513
28533
|
}
|
|
28514
28534
|
clearTimeout(pendingCall.timeout);
|
|
28515
28535
|
this.pendingToolCalls.delete(callId);
|
|
28516
|
-
|
|
28517
|
-
|
|
28518
|
-
|
|
28536
|
+
if (result.success && result.result !== void 0) {
|
|
28537
|
+
const contentResult = result.result;
|
|
28538
|
+
if (contentResult?.content && Array.isArray(contentResult.content)) {
|
|
28539
|
+
if (pendingCall.hasOutputSchema) {
|
|
28540
|
+
try {
|
|
28541
|
+
const textContent = contentResult.content.find(
|
|
28542
|
+
(c) => c.type === "text"
|
|
28543
|
+
);
|
|
28544
|
+
if (textContent && textContent.text) {
|
|
28545
|
+
const parsed = JSON.parse(textContent.text);
|
|
28546
|
+
pendingCall.resolve({
|
|
28547
|
+
content: contentResult.content,
|
|
28548
|
+
structuredContent: parsed
|
|
28549
|
+
});
|
|
28550
|
+
return;
|
|
28551
|
+
}
|
|
28552
|
+
} catch (error48) {
|
|
28553
|
+
logger.warn(
|
|
28554
|
+
"[MCPController] Failed to parse structured content:",
|
|
28555
|
+
error48
|
|
28556
|
+
);
|
|
28557
|
+
}
|
|
28558
|
+
}
|
|
28559
|
+
pendingCall.resolve(contentResult);
|
|
28560
|
+
} else {
|
|
28561
|
+
logger.warn(
|
|
28562
|
+
"[MCPController] Result missing content array, serializing"
|
|
28563
|
+
);
|
|
28564
|
+
pendingCall.resolve({
|
|
28565
|
+
content: [{ type: "text", text: JSON.stringify(result.result) }]
|
|
28566
|
+
});
|
|
28567
|
+
}
|
|
28519
28568
|
} else {
|
|
28520
|
-
pendingCall.reject(new Error(
|
|
28569
|
+
pendingCall.reject(new Error(result.error || "Tool call failed"));
|
|
28521
28570
|
}
|
|
28522
28571
|
}
|
|
28523
28572
|
async handleUnregisterTool(toolName, tabId) {
|
|
@@ -28853,6 +28902,13 @@ self.onconnect = (event) => {
|
|
|
28853
28902
|
logger.warn("[SharedWorker] TOOL_CALL_RESULT missing callId");
|
|
28854
28903
|
return;
|
|
28855
28904
|
}
|
|
28905
|
+
if (!isToolCallResult(messageData)) {
|
|
28906
|
+
logger.error(
|
|
28907
|
+
"[SharedWorker] Invalid TOOL_CALL_RESULT structure:",
|
|
28908
|
+
messageData
|
|
28909
|
+
);
|
|
28910
|
+
return;
|
|
28911
|
+
}
|
|
28856
28912
|
getController().handleToolCallResult(callId, messageData);
|
|
28857
28913
|
} catch (error48) {
|
|
28858
28914
|
logger.error(
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { WorkerClient } from './lib/worker-client';
|
|
17
17
|
export { WorkerClient, type WorkerClientInitOptions, } from './lib/worker-client';
|
|
18
18
|
export { queryEvents, type UserEvent } from './lib/database';
|
|
19
|
-
export { type ToolHandler, type ToolDefinition } from './lib/tool-registry';
|
|
19
|
+
export { type ToolHandler, type ToolDefinition, type Icon, type ToolAnnotations, type ToolExecution, } from './lib/tool-registry';
|
|
20
20
|
export { TabManager, type TabInfo } from './lib/tab-manager';
|
|
21
21
|
export { logger } from './lib/logger';
|
|
22
22
|
export declare const workerClient: WorkerClient;
|
package/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../libs/mcp-worker/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EACL,YAAY,EACZ,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../libs/mcp-worker/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EACL,YAAY,EACZ,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,IAAI,EACT,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -8,6 +8,17 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { queryEvents, UserEvent } from './database';
|
|
10
10
|
export type BroadcastFn = (message: unknown) => void;
|
|
11
|
+
export interface ToolCallResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
result?: {
|
|
14
|
+
content: Array<{
|
|
15
|
+
type: string;
|
|
16
|
+
text: string;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function isToolCallResult(obj: unknown): obj is ToolCallResult;
|
|
11
22
|
export declare class MCPController {
|
|
12
23
|
private backendUrl;
|
|
13
24
|
private broadcastFn;
|
|
@@ -50,7 +61,7 @@ export declare class MCPController {
|
|
|
50
61
|
* @private
|
|
51
62
|
*/
|
|
52
63
|
private handleRegisterToolInternal;
|
|
53
|
-
handleToolCallResult(callId: string, result:
|
|
64
|
+
handleToolCallResult(callId: string, result: ToolCallResult): void;
|
|
54
65
|
handleUnregisterTool(toolName: string, tabId?: string): Promise<boolean>;
|
|
55
66
|
getConnectionStatus(): boolean;
|
|
56
67
|
dispose(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-controller.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/lib/mcp-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAc,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAWhE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-controller.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/lib/mcp-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAc,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAWhE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAGrD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAChD,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,cAAc,CAapE;AAED,qBAAa,aAAa;IAmCtB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,WAAW;IAnCrB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,sBAAsB,CAAS;IAGvC,OAAO,CAAC,wBAAwB,CAIxB;IAER,OAAO,CAAC,gBAAgB,CAAS;IAGjC,OAAO,CAAC,UAAU,CAAoB;IAGtC,OAAO,CAAC,gBAAgB,CAUpB;gBAGM,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EAChC,WAAW,UAAO;IAOpB;;;OAGG;IACI,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAmB7D;;;OAGG;IACI,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAW9D,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,aAAa;IAOR,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmIvC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAgClC,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IAIvE;;;OAGG;IACH,OAAO,CAAC,+BAA+B;IAoB1B,kBAAkB,CAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,OAAO,CAAC,IAAI,CAAC;IAoBhB;;;OAGG;YACW,0BAA0B;IAmJjC,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI;IAyD5D,oBAAoB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC;IA0CZ,mBAAmB,IAAI,OAAO;IAI9B,OAAO,IAAI,IAAI;IAYtB;;;OAGG;WACW,MAAM,CAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EACxB,WAAW,UAAO,GACjB,aAAa;CAGjB"}
|
|
@@ -2,10 +2,32 @@
|
|
|
2
2
|
* Dynamic tool registry for MCP server
|
|
3
3
|
* Manages tool definitions and their handlers
|
|
4
4
|
*/
|
|
5
|
+
export interface Icon {
|
|
6
|
+
src: string;
|
|
7
|
+
mimeType?: string;
|
|
8
|
+
sizes?: string[];
|
|
9
|
+
theme?: 'light' | 'dark';
|
|
10
|
+
}
|
|
11
|
+
export interface ToolAnnotations {
|
|
12
|
+
title?: string;
|
|
13
|
+
readOnlyHint?: boolean;
|
|
14
|
+
destructiveHint?: boolean;
|
|
15
|
+
idempotentHint?: boolean;
|
|
16
|
+
openWorldHint?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface ToolExecution {
|
|
19
|
+
taskSupport?: 'optional' | 'required' | 'forbidden';
|
|
20
|
+
}
|
|
5
21
|
export interface ToolDefinition {
|
|
6
22
|
name: string;
|
|
7
|
-
description
|
|
23
|
+
description?: string;
|
|
8
24
|
inputSchema: Record<string, unknown>;
|
|
25
|
+
outputSchema?: Record<string, unknown>;
|
|
26
|
+
annotations?: ToolAnnotations;
|
|
27
|
+
execution?: ToolExecution;
|
|
28
|
+
_meta?: Record<string, unknown>;
|
|
29
|
+
icons?: Icon[];
|
|
30
|
+
title?: string;
|
|
9
31
|
}
|
|
10
32
|
export interface ToolHandler {
|
|
11
33
|
(args: unknown): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/lib/tool-registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/lib/tool-registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAGD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;CACrD;AAGD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;QACvB,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAChD,CAAC,CAAC;CACJ;AAGD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,QAAQ,CAAkC;IAElD,QAAQ,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IAKhE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAMjC,QAAQ,IAAI,cAAc,EAAE;IAI5B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAIjD,KAAK,IAAI,IAAI;CAId;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -175,12 +175,32 @@ export declare class WorkerClient {
|
|
|
175
175
|
* );
|
|
176
176
|
* ```
|
|
177
177
|
*/
|
|
178
|
-
registerTool(name: string, description: string, inputSchema: Record<string, unknown>, handler: (args: unknown) => Promise<{
|
|
178
|
+
registerTool(name: string, description: string | undefined, inputSchema: Record<string, unknown>, handler: (args: unknown) => Promise<{
|
|
179
179
|
content: Array<{
|
|
180
180
|
type: string;
|
|
181
181
|
text: string;
|
|
182
182
|
}>;
|
|
183
|
-
}
|
|
183
|
+
}>, options?: {
|
|
184
|
+
outputSchema?: Record<string, unknown>;
|
|
185
|
+
annotations?: {
|
|
186
|
+
title?: string;
|
|
187
|
+
readOnlyHint?: boolean;
|
|
188
|
+
destructiveHint?: boolean;
|
|
189
|
+
idempotentHint?: boolean;
|
|
190
|
+
openWorldHint?: boolean;
|
|
191
|
+
};
|
|
192
|
+
execution?: {
|
|
193
|
+
taskSupport?: 'optional' | 'required' | 'forbidden';
|
|
194
|
+
};
|
|
195
|
+
_meta?: Record<string, unknown>;
|
|
196
|
+
icons?: Array<{
|
|
197
|
+
src: string;
|
|
198
|
+
mimeType?: string;
|
|
199
|
+
sizes?: string[];
|
|
200
|
+
theme?: 'light' | 'dark';
|
|
201
|
+
}>;
|
|
202
|
+
title?: string;
|
|
203
|
+
}): Promise<void>;
|
|
184
204
|
/**
|
|
185
205
|
* Enhance tool input schema with optional tabId parameter for multi-tab support
|
|
186
206
|
* @private
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-client.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/lib/worker-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAOH,MAAM,MAAM,uBAAuB,GAAG;IACpC,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,qBAAa,YAAY;IAEvB,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,gBAAgB,CAA4B;IAEpD,OAAO,CAAC,YAAY,CAAwC;IAE5D,OAAO,CAAC,yBAAyB,CAA0C;IAC3E,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,gBAAgB,CAAuB;IAE/C,OAAO,CAAC,yBAAyB,CACrB;IAGZ,OAAO,CAAC,WAAW,CAA8B;IAGjD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAyB;IAG9C,OAAO,CAAC,oBAAoB,
|
|
1
|
+
{"version":3,"file":"worker-client.d.ts","sourceRoot":"","sources":["../../../../../libs/mcp-worker/src/lib/worker-client.ts"],"names":[],"mappings":"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"}
|