mcp-use 0.1.8 → 0.1.10
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/dist/examples/structured_output.d.ts +9 -0
- package/dist/examples/structured_output.d.ts.map +1 -0
- package/dist/examples/structured_output.js +95 -0
- package/dist/src/agents/mcp_agent.d.ts +15 -1
- package/dist/src/agents/mcp_agent.d.ts.map +1 -1
- package/dist/src/agents/mcp_agent.js +190 -13
- package/package.json +3 -2
@@ -0,0 +1,9 @@
|
|
1
|
+
/**
|
2
|
+
* Structured Output Example - City Research with Playwright
|
3
|
+
*
|
4
|
+
* This example demonstrates intelligent structured output by researching Padova, Italy.
|
5
|
+
* The agent becomes schema-aware and will intelligently retry to gather missing
|
6
|
+
* information until all required fields can be populated.
|
7
|
+
*/
|
8
|
+
export {};
|
9
|
+
//# sourceMappingURL=structured_output.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"structured_output.d.ts","sourceRoot":"","sources":["../../examples/structured_output.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/**
|
2
|
+
* Structured Output Example - City Research with Playwright
|
3
|
+
*
|
4
|
+
* This example demonstrates intelligent structured output by researching Padova, Italy.
|
5
|
+
* The agent becomes schema-aware and will intelligently retry to gather missing
|
6
|
+
* information until all required fields can be populated.
|
7
|
+
*/
|
8
|
+
import { ChatOpenAI } from '@langchain/openai';
|
9
|
+
import { config } from 'dotenv';
|
10
|
+
import { z } from 'zod';
|
11
|
+
import { MCPAgent, MCPClient } from '../index.js';
|
12
|
+
// Load environment variables from .env file
|
13
|
+
config();
|
14
|
+
// Define the structured output schema using Zod
|
15
|
+
const CityInfoSchema = z.object({
|
16
|
+
name: z.string().describe('Official name of the city'),
|
17
|
+
country: z.string().describe('Country where the city is located'),
|
18
|
+
region: z.string().describe('Region or state within the country'),
|
19
|
+
population: z.number().describe('Current population count'),
|
20
|
+
area_km2: z.number().describe('Area in square kilometers'),
|
21
|
+
foundation_date: z.string().describe('When the city was founded (approximate year or period)'),
|
22
|
+
mayor: z.string().describe('Current mayor or city leader'),
|
23
|
+
famous_landmarks: z.array(z.string()).describe('List of famous landmarks, monuments, or attractions'),
|
24
|
+
universities: z.array(z.string()).describe('List of major universities or educational institutions'),
|
25
|
+
economy_sectors: z.array(z.string()).describe('Main economic sectors or industries'),
|
26
|
+
sister_cities: z.array(z.string()).describe('Twin cities or sister cities partnerships'),
|
27
|
+
historical_significance: z.string().describe('Brief description of historical importance'),
|
28
|
+
climate_type: z.string().nullable().describe('Type of climate (e.g., Mediterranean, Continental)'),
|
29
|
+
elevation_meters: z.number().nullable().describe('Elevation above sea level in meters'),
|
30
|
+
});
|
31
|
+
async function main() {
|
32
|
+
const mcpConfig = {
|
33
|
+
mcpServers: {
|
34
|
+
playwright: {
|
35
|
+
command: 'npx',
|
36
|
+
args: ['@playwright/mcp@latest'],
|
37
|
+
env: {
|
38
|
+
DISPLAY: ':1',
|
39
|
+
},
|
40
|
+
},
|
41
|
+
},
|
42
|
+
};
|
43
|
+
const client = new MCPClient(mcpConfig);
|
44
|
+
const llm = new ChatOpenAI({ model: 'gpt-4o' });
|
45
|
+
const agent = new MCPAgent({ llm, client, maxSteps: 50, memoryEnabled: true });
|
46
|
+
try {
|
47
|
+
// Use structured output with intelligent retry
|
48
|
+
// The agent will:
|
49
|
+
// 1. Know exactly what information it needs to collect
|
50
|
+
// 2. Attempt structured output at finish points
|
51
|
+
// 3. Continue execution if required information is missing
|
52
|
+
// 4. Only finish when all required fields can be populated
|
53
|
+
const result = await agent.run(`
|
54
|
+
Research comprehensive information about the city of Padova (also known as Padua) in Italy.
|
55
|
+
|
56
|
+
Visit multiple reliable sources like Wikipedia, official city websites, tourism sites,
|
57
|
+
and university websites to gather detailed information including demographics, history,
|
58
|
+
governance, education, economy, landmarks, and international relationships.
|
59
|
+
`, 50, // maxSteps
|
60
|
+
true, // manageConnector
|
61
|
+
[], // externalHistory
|
62
|
+
CityInfoSchema);
|
63
|
+
// Now you have strongly-typed, validated data!
|
64
|
+
console.log(`Name: ${result.name}`);
|
65
|
+
console.log(`Country: ${result.country}`);
|
66
|
+
console.log(`Region: ${result.region}`);
|
67
|
+
console.log(`Population: ${result.population.toLocaleString()}`);
|
68
|
+
console.log(`Area: ${result.area_km2} km²`);
|
69
|
+
console.log(`Foundation: ${result.foundation_date}`);
|
70
|
+
console.log(`Mayor: ${result.mayor}`);
|
71
|
+
console.log(`Universities: ${result.universities.join(', ')}`);
|
72
|
+
console.log(`Economy: ${result.economy_sectors.join(', ')}`);
|
73
|
+
console.log(`Landmarks: ${result.famous_landmarks.join(', ')}`);
|
74
|
+
console.log(`Sister Cities: ${result.sister_cities.length > 0 ? result.sister_cities.join(', ') : 'None'}`);
|
75
|
+
console.log(`Historical Significance: ${result.historical_significance}`);
|
76
|
+
if (result.climate_type) {
|
77
|
+
console.log(`Climate: ${result.climate_type}`);
|
78
|
+
}
|
79
|
+
if (result.elevation_meters !== null) {
|
80
|
+
console.log(`Elevation: ${result.elevation_meters} meters`);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
catch (error) {
|
84
|
+
console.error('Error:', error);
|
85
|
+
}
|
86
|
+
finally {
|
87
|
+
await agent.close();
|
88
|
+
}
|
89
|
+
}
|
90
|
+
// Handle unhandled promise rejections
|
91
|
+
process.on('unhandledRejection', (reason, promise) => {
|
92
|
+
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
93
|
+
process.exit(1);
|
94
|
+
});
|
95
|
+
main().catch(console.error);
|
@@ -3,6 +3,7 @@ import type { BaseMessage } from '@langchain/core/messages';
|
|
3
3
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
4
4
|
import type { StreamEvent } from '@langchain/core/tracers/log_stream';
|
5
5
|
import type { AgentStep } from 'langchain/agents';
|
6
|
+
import type { z } from 'zod';
|
6
7
|
import type { MCPClient } from '../client.js';
|
7
8
|
import type { BaseConnector } from '../connectors/base.js';
|
8
9
|
import { SystemMessage } from '@langchain/core/messages';
|
@@ -65,15 +66,28 @@ export declare class MCPAgent {
|
|
65
66
|
* Runs the agent and returns a promise for the final result.
|
66
67
|
*/
|
67
68
|
run(query: string, maxSteps?: number, manageConnector?: boolean, externalHistory?: BaseMessage[]): Promise<string>;
|
69
|
+
/**
|
70
|
+
* Runs the agent with structured output and returns a promise for the typed result.
|
71
|
+
*/
|
72
|
+
run<T>(query: string, maxSteps?: number, manageConnector?: boolean, externalHistory?: BaseMessage[], outputSchema?: z.ZodSchema<T>): Promise<T>;
|
68
73
|
/**
|
69
74
|
* Runs the agent and yields intermediate steps as an async generator.
|
75
|
+
* If outputSchema is provided, returns structured output of type T.
|
70
76
|
*/
|
71
|
-
stream(query: string, maxSteps?: number, manageConnector?: boolean, externalHistory?: BaseMessage[]): AsyncGenerator<AgentStep, string, void>;
|
77
|
+
stream<T = string>(query: string, maxSteps?: number, manageConnector?: boolean, externalHistory?: BaseMessage[], outputSchema?: z.ZodSchema<T>): AsyncGenerator<AgentStep, string | T, void>;
|
72
78
|
close(): Promise<void>;
|
73
79
|
/**
|
74
80
|
* Yields LangChain StreamEvent objects from the underlying streamEvents() method.
|
75
81
|
* This provides token-level streaming and fine-grained event updates.
|
76
82
|
*/
|
77
83
|
streamEvents(query: string, maxSteps?: number, manageConnector?: boolean, externalHistory?: BaseMessage[]): AsyncGenerator<StreamEvent, void, void>;
|
84
|
+
/**
|
85
|
+
* Attempt to create structured output from raw result with validation.
|
86
|
+
*/
|
87
|
+
private _attemptStructuredOutput;
|
88
|
+
/**
|
89
|
+
* Enhance the query with schema information to make the agent aware of required fields.
|
90
|
+
*/
|
91
|
+
private _enhanceQueryWithSchema;
|
78
92
|
}
|
79
93
|
//# sourceMappingURL=mcp_agent.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"mcp_agent.d.ts","sourceRoot":"","sources":["../../../src/agents/mcp_agent.ts"],"names":[],"mappings":"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
|
1
|
+
{"version":3,"file":"mcp_agent.d.ts","sourceRoot":"","sources":["../../../src/agents/mcp_agent.ts"],"names":[],"mappings":"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"}
|
@@ -211,23 +211,54 @@ export class MCPAgent {
|
|
211
211
|
}
|
212
212
|
}
|
213
213
|
}
|
214
|
-
|
215
|
-
|
216
|
-
*/
|
217
|
-
async run(query, maxSteps, manageConnector, externalHistory) {
|
218
|
-
const generator = this.stream(query, maxSteps, manageConnector, externalHistory);
|
214
|
+
async run(query, maxSteps, manageConnector, externalHistory, outputSchema) {
|
215
|
+
const generator = this.stream(query, maxSteps, manageConnector, externalHistory, outputSchema);
|
219
216
|
return this._consumeAndReturn(generator);
|
220
217
|
}
|
221
218
|
/**
|
222
219
|
* Runs the agent and yields intermediate steps as an async generator.
|
220
|
+
* If outputSchema is provided, returns structured output of type T.
|
223
221
|
*/
|
224
|
-
async *stream(query, maxSteps, manageConnector = true, externalHistory) {
|
222
|
+
async *stream(query, maxSteps, manageConnector = true, externalHistory, outputSchema) {
|
225
223
|
let result = '';
|
226
224
|
let initializedHere = false;
|
227
225
|
const startTime = Date.now();
|
228
226
|
const toolsUsedNames = [];
|
229
227
|
let stepsTaken = 0;
|
230
228
|
let success = false;
|
229
|
+
// Schema-aware setup for structured output
|
230
|
+
let structuredLlm = null;
|
231
|
+
let schemaDescription = '';
|
232
|
+
if (outputSchema) {
|
233
|
+
query = this._enhanceQueryWithSchema(query, outputSchema);
|
234
|
+
// Check if withStructuredOutput method exists
|
235
|
+
if ('withStructuredOutput' in this.llm && typeof this.llm.withStructuredOutput === 'function') {
|
236
|
+
structuredLlm = this.llm.withStructuredOutput(outputSchema);
|
237
|
+
}
|
238
|
+
else {
|
239
|
+
// Fallback: use the same LLM but we'll handle structure in our helper method
|
240
|
+
structuredLlm = this.llm;
|
241
|
+
}
|
242
|
+
// Get schema description for feedback
|
243
|
+
try {
|
244
|
+
const schemaType = outputSchema;
|
245
|
+
if (schemaType._def && schemaType._def.shape) {
|
246
|
+
const fields = [];
|
247
|
+
for (const [key, fieldSchema] of Object.entries(schemaType._def.shape)) {
|
248
|
+
const field = fieldSchema;
|
249
|
+
const isOptional = field.isOptional?.() ?? field._def?.typeName === 'ZodOptional';
|
250
|
+
const isNullable = field.isNullable?.() ?? field._def?.typeName === 'ZodNullable';
|
251
|
+
const description = field._def?.description || field.description || key;
|
252
|
+
fields.push(`- ${key}: ${description} ${(isOptional || isNullable) ? '(optional)' : '(required)'}`);
|
253
|
+
}
|
254
|
+
schemaDescription = fields.join('\n');
|
255
|
+
}
|
256
|
+
}
|
257
|
+
catch (e) {
|
258
|
+
logger.warn(`Could not extract schema details: ${e}`);
|
259
|
+
schemaDescription = `Schema: ${outputSchema.constructor.name}`;
|
260
|
+
}
|
261
|
+
}
|
231
262
|
try {
|
232
263
|
if (manageConnector && !this._initialized) {
|
233
264
|
await this.initialize();
|
@@ -284,7 +315,46 @@ export class MCPAgent {
|
|
284
315
|
if (nextStepOutput.returnValues) {
|
285
316
|
logger.info(`✅ Agent finished at step ${stepNum + 1}`);
|
286
317
|
result = nextStepOutput.returnValues?.output ?? 'No output generated';
|
287
|
-
|
318
|
+
// If structured output is requested, attempt to create it
|
319
|
+
if (outputSchema && structuredLlm) {
|
320
|
+
try {
|
321
|
+
logger.info('🔧 Attempting structured output...');
|
322
|
+
const structuredResult = await this._attemptStructuredOutput(result, structuredLlm, outputSchema, schemaDescription);
|
323
|
+
// Add the final response to conversation history if memory is enabled
|
324
|
+
if (this.memoryEnabled) {
|
325
|
+
this.addToHistory(new AIMessage(`Structured result: ${JSON.stringify(structuredResult)}`));
|
326
|
+
}
|
327
|
+
logger.info('✅ Structured output successful');
|
328
|
+
success = true;
|
329
|
+
return structuredResult;
|
330
|
+
}
|
331
|
+
catch (e) {
|
332
|
+
logger.warn(`⚠️ Structured output failed: ${e}`);
|
333
|
+
// Continue execution to gather missing information
|
334
|
+
const missingInfoPrompt = `
|
335
|
+
The current result cannot be formatted into the required structure.
|
336
|
+
Error: ${String(e)}
|
337
|
+
|
338
|
+
Current information: ${result}
|
339
|
+
|
340
|
+
Please continue working to gather the missing information needed for:
|
341
|
+
${schemaDescription}
|
342
|
+
|
343
|
+
Focus on finding the specific missing details.
|
344
|
+
`;
|
345
|
+
// Add this as feedback and continue the loop
|
346
|
+
inputs.input = missingInfoPrompt;
|
347
|
+
if (this.memoryEnabled) {
|
348
|
+
this.addToHistory(new HumanMessage(missingInfoPrompt));
|
349
|
+
}
|
350
|
+
logger.info('🔄 Continuing execution to gather missing information...');
|
351
|
+
continue;
|
352
|
+
}
|
353
|
+
}
|
354
|
+
else {
|
355
|
+
// Regular execution without structured output
|
356
|
+
break;
|
357
|
+
}
|
288
358
|
}
|
289
359
|
const stepArray = nextStepOutput;
|
290
360
|
intermediateSteps.push(...stepArray);
|
@@ -333,11 +403,31 @@ export class MCPAgent {
|
|
333
403
|
logger.warn(`⚠️ Agent stopped after reaching max iterations (${steps})`);
|
334
404
|
result = `Agent stopped after reaching the maximum number of steps (${steps}).`;
|
335
405
|
}
|
336
|
-
|
406
|
+
// If structured output was requested but not achieved, attempt one final time
|
407
|
+
if (outputSchema && structuredLlm && !success) {
|
408
|
+
try {
|
409
|
+
logger.info('🔧 Final attempt at structured output...');
|
410
|
+
const structuredResult = await this._attemptStructuredOutput(result, structuredLlm, outputSchema, schemaDescription);
|
411
|
+
// Add the final response to conversation history if memory is enabled
|
412
|
+
if (this.memoryEnabled) {
|
413
|
+
this.addToHistory(new AIMessage(`Structured result: ${JSON.stringify(structuredResult)}`));
|
414
|
+
}
|
415
|
+
logger.info('✅ Final structured output successful');
|
416
|
+
success = true;
|
417
|
+
return structuredResult;
|
418
|
+
}
|
419
|
+
catch (e) {
|
420
|
+
logger.error(`❌ Final structured output attempt failed: ${e}`);
|
421
|
+
throw new Error(`Failed to generate structured output after ${steps} steps: ${e}`);
|
422
|
+
}
|
423
|
+
}
|
424
|
+
// Add the final response to conversation history if memory is enabled (regular case)
|
425
|
+
if (this.memoryEnabled && !outputSchema) {
|
337
426
|
this.addToHistory(new AIMessage(result));
|
338
427
|
}
|
339
428
|
logger.info('🎉 Agent execution complete');
|
340
429
|
success = true;
|
430
|
+
// Return regular result
|
341
431
|
return result;
|
342
432
|
}
|
343
433
|
catch (e) {
|
@@ -424,6 +514,7 @@ export class MCPAgent {
|
|
424
514
|
let success = false;
|
425
515
|
let eventCount = 0;
|
426
516
|
let totalResponseLength = 0;
|
517
|
+
let finalResponse = '';
|
427
518
|
try {
|
428
519
|
// Initialize if needed
|
429
520
|
if (manageConnector && !this._initialized) {
|
@@ -471,17 +562,21 @@ export class MCPAgent {
|
|
471
562
|
totalResponseLength += event.data.chunk.content.length;
|
472
563
|
}
|
473
564
|
yield event;
|
474
|
-
//
|
565
|
+
// Capture final response from chain end event
|
475
566
|
if (event.event === 'on_chain_end' && event.data?.output) {
|
476
567
|
const output = event.data.output;
|
477
|
-
if (typeof output === 'string'
|
478
|
-
|
568
|
+
if (typeof output === 'string') {
|
569
|
+
finalResponse = output;
|
479
570
|
}
|
480
|
-
else if (output?.output && typeof output.output === 'string'
|
481
|
-
|
571
|
+
else if (output?.output && typeof output.output === 'string') {
|
572
|
+
finalResponse = output.output;
|
482
573
|
}
|
483
574
|
}
|
484
575
|
}
|
576
|
+
// Add the final AI response to conversation history if memory is enabled
|
577
|
+
if (this.memoryEnabled && finalResponse) {
|
578
|
+
this.addToHistory(new AIMessage(finalResponse));
|
579
|
+
}
|
485
580
|
logger.info(`🎉 StreamEvents complete - ${eventCount} events emitted`);
|
486
581
|
success = true;
|
487
582
|
}
|
@@ -532,4 +627,86 @@ export class MCPAgent {
|
|
532
627
|
}
|
533
628
|
}
|
534
629
|
}
|
630
|
+
/**
|
631
|
+
* Attempt to create structured output from raw result with validation.
|
632
|
+
*/
|
633
|
+
async _attemptStructuredOutput(rawResult, structuredLlm, outputSchema, schemaDescription) {
|
634
|
+
const formatPrompt = `
|
635
|
+
Please format the following information according to the specified schema.
|
636
|
+
Extract and structure the relevant information from the content below.
|
637
|
+
|
638
|
+
Required schema fields:
|
639
|
+
${schemaDescription}
|
640
|
+
|
641
|
+
Content to format:
|
642
|
+
${rawResult}
|
643
|
+
|
644
|
+
Please provide the information in the requested structured format.
|
645
|
+
If any required information is missing, you must indicate this clearly.
|
646
|
+
`;
|
647
|
+
const structuredResult = await structuredLlm.invoke(formatPrompt);
|
648
|
+
// Validate that the result is complete (basic check)
|
649
|
+
try {
|
650
|
+
// Use Zod to validate the structured result
|
651
|
+
const validatedResult = outputSchema.parse(structuredResult);
|
652
|
+
// Additional validation for required fields
|
653
|
+
const schemaType = outputSchema;
|
654
|
+
if (schemaType._def && schemaType._def.shape) {
|
655
|
+
for (const [fieldName, fieldSchema] of Object.entries(schemaType._def.shape)) {
|
656
|
+
const field = fieldSchema;
|
657
|
+
const isOptional = field.isOptional?.() ?? field._def?.typeName === 'ZodOptional';
|
658
|
+
const isNullable = field.isNullable?.() ?? field._def?.typeName === 'ZodNullable';
|
659
|
+
if (!isOptional && !isNullable) {
|
660
|
+
const value = validatedResult[fieldName];
|
661
|
+
if (value === null || value === undefined
|
662
|
+
|| (typeof value === 'string' && !value.trim())
|
663
|
+
|| (Array.isArray(value) && value.length === 0)) {
|
664
|
+
throw new Error(`Required field '${fieldName}' is missing or empty`);
|
665
|
+
}
|
666
|
+
}
|
667
|
+
}
|
668
|
+
}
|
669
|
+
return validatedResult;
|
670
|
+
}
|
671
|
+
catch (e) {
|
672
|
+
logger.debug(`Validation details: ${e}`);
|
673
|
+
throw e; // Re-raise to trigger retry logic
|
674
|
+
}
|
675
|
+
}
|
676
|
+
/**
|
677
|
+
* Enhance the query with schema information to make the agent aware of required fields.
|
678
|
+
*/
|
679
|
+
_enhanceQueryWithSchema(query, outputSchema) {
|
680
|
+
const schemaFields = [];
|
681
|
+
try {
|
682
|
+
// Get field information from the schema
|
683
|
+
const schemaType = outputSchema;
|
684
|
+
if (schemaType._def && schemaType._def.shape) {
|
685
|
+
for (const [fieldName, fieldSchema] of Object.entries(schemaType._def.shape)) {
|
686
|
+
const field = fieldSchema;
|
687
|
+
const description = field._def?.description || field.description || fieldName;
|
688
|
+
const isOptional = field.isOptional?.() ?? field._def?.typeName === 'ZodOptional';
|
689
|
+
const isNullable = field.isNullable?.() ?? field._def?.typeName === 'ZodNullable';
|
690
|
+
schemaFields.push(`- ${fieldName}: ${description} ${(isOptional || isNullable) ? '(optional)' : '(required)'}`);
|
691
|
+
}
|
692
|
+
}
|
693
|
+
const schemaDescription = schemaFields.join('\n');
|
694
|
+
// Enhance the query with schema awareness
|
695
|
+
const enhancedQuery = `
|
696
|
+
${query}
|
697
|
+
|
698
|
+
IMPORTANT: Your response must include sufficient information to populate the following structured output:
|
699
|
+
|
700
|
+
${schemaDescription}
|
701
|
+
|
702
|
+
Make sure you gather ALL the required information during your task execution.
|
703
|
+
If any required information is missing, continue working to find it.
|
704
|
+
`;
|
705
|
+
return enhancedQuery;
|
706
|
+
}
|
707
|
+
catch (e) {
|
708
|
+
logger.warn(`Could not extract schema details: ${e}`);
|
709
|
+
return query;
|
710
|
+
}
|
711
|
+
}
|
535
712
|
}
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "mcp-use",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.1.
|
4
|
+
"version": "0.1.10",
|
5
5
|
"packageManager": "pnpm@10.6.1",
|
6
6
|
"description": "A utility library for integrating Model Context Protocol (MCP) with LangChain, Zod, and related tools. Provides helpers for schema conversion, event streaming, and SDK usage.",
|
7
7
|
"author": "Zane",
|
@@ -73,7 +73,8 @@
|
|
73
73
|
"example:sandbox": "npm run build && node dist/examples/sandbox_everything.js",
|
74
74
|
"example:oauth": "npm run build && node dist/examples/simple_oauth_example.js",
|
75
75
|
"example:blender": "npm run build && node dist/examples/blender_use.js",
|
76
|
-
"example:add_server": "npm run build && node dist/examples/add_server_tool.js"
|
76
|
+
"example:add_server": "npm run build && node dist/examples/add_server_tool.js",
|
77
|
+
"example:structured": "npm run build && node dist/examples/structured_output.js"
|
77
78
|
},
|
78
79
|
"dependencies": {
|
79
80
|
"@dmitryrechkin/json-schema-to-zod": "^1.0.1",
|