@copilotkit/runtime 1.9.2-next.21 → 1.9.2-next.23

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.
Files changed (41) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/{chunk-UPC6N4MV.mjs → chunk-C6PCDSTD.mjs} +2 -2
  3. package/dist/{chunk-IBYPYIVX.mjs → chunk-FIA5HRU2.mjs} +57 -18
  4. package/dist/chunk-FIA5HRU2.mjs.map +1 -0
  5. package/dist/{chunk-IXK4UOV6.mjs → chunk-HZW6X63M.mjs} +2 -2
  6. package/dist/{chunk-P3HORCYJ.mjs → chunk-LYXJJDV3.mjs} +2 -2
  7. package/dist/{chunk-47L6Z7PJ.mjs → chunk-ZQUGWRVU.mjs} +2 -2
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.js +56 -17
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +5 -5
  12. package/dist/lib/index.d.ts +1 -1
  13. package/dist/lib/index.js +56 -17
  14. package/dist/lib/index.js.map +1 -1
  15. package/dist/lib/index.mjs +5 -5
  16. package/dist/lib/integrations/index.d.ts +2 -2
  17. package/dist/lib/integrations/index.js +1 -1
  18. package/dist/lib/integrations/index.js.map +1 -1
  19. package/dist/lib/integrations/index.mjs +4 -4
  20. package/dist/lib/integrations/nest/index.d.ts +1 -1
  21. package/dist/lib/integrations/nest/index.js +1 -1
  22. package/dist/lib/integrations/nest/index.js.map +1 -1
  23. package/dist/lib/integrations/nest/index.mjs +2 -2
  24. package/dist/lib/integrations/node-express/index.d.ts +1 -1
  25. package/dist/lib/integrations/node-express/index.js +1 -1
  26. package/dist/lib/integrations/node-express/index.js.map +1 -1
  27. package/dist/lib/integrations/node-express/index.mjs +2 -2
  28. package/dist/lib/integrations/node-http/index.d.ts +1 -1
  29. package/dist/lib/integrations/node-http/index.js +1 -1
  30. package/dist/lib/integrations/node-http/index.js.map +1 -1
  31. package/dist/lib/integrations/node-http/index.mjs +1 -1
  32. package/dist/{shared-41d4988d.d.ts → shared-6b6dbf8b.d.ts} +1 -3
  33. package/package.json +2 -2
  34. package/src/lib/runtime/__tests__/mcp-tools-utils.test.ts +464 -0
  35. package/src/lib/runtime/copilot-runtime.ts +1 -3
  36. package/src/lib/runtime/mcp-tools-utils.ts +84 -18
  37. package/dist/chunk-IBYPYIVX.mjs.map +0 -1
  38. /package/dist/{chunk-UPC6N4MV.mjs.map → chunk-C6PCDSTD.mjs.map} +0 -0
  39. /package/dist/{chunk-IXK4UOV6.mjs.map → chunk-HZW6X63M.mjs.map} +0 -0
  40. /package/dist/{chunk-P3HORCYJ.mjs.map → chunk-LYXJJDV3.mjs.map} +0 -0
  41. /package/dist/{chunk-47L6Z7PJ.mjs.map → chunk-ZQUGWRVU.mjs.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  copilotRuntimeNodeHttpEndpoint
3
- } from "../../../chunk-IBYPYIVX.mjs";
3
+ } from "../../../chunk-FIA5HRU2.mjs";
4
4
  import "../../../chunk-SHBDMA63.mjs";
5
5
  import "../../../chunk-QLLV2QVK.mjs";
6
6
  import "../../../chunk-XWBDEXDA.mjs";
@@ -142,9 +142,7 @@ interface MCPTool {
142
142
  };
143
143
  };
144
144
  /** The function to call to execute the tool on the MCP server. */
145
- execute(options: {
146
- params: any;
147
- }): Promise<any>;
145
+ execute(params: any): Promise<any>;
148
146
  }
149
147
  /**
150
148
  * Defines the contract for *any* MCP client implementation the user might provide.
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "publishConfig": {
10
10
  "access": "public"
11
11
  },
12
- "version": "1.9.2-next.21",
12
+ "version": "1.9.2-next.23",
13
13
  "sideEffects": false,
14
14
  "main": "./dist/index.js",
15
15
  "module": "./dist/index.mjs",
@@ -66,7 +66,7 @@
66
66
  "rxjs": "7.8.1",
67
67
  "type-graphql": "2.0.0-rc.1",
68
68
  "zod": "^3.23.3",
69
- "@copilotkit/shared": "1.9.2-next.21"
69
+ "@copilotkit/shared": "1.9.2-next.23"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "@ag-ui/client": ">=0.0.28",
@@ -0,0 +1,464 @@
1
+ import {
2
+ extractParametersFromSchema,
3
+ convertMCPToolsToActions,
4
+ generateMcpToolInstructions,
5
+ MCPTool,
6
+ } from "../mcp-tools-utils";
7
+
8
+ describe("MCP Tools Utils", () => {
9
+ describe("extractParametersFromSchema", () => {
10
+ it("should extract parameters from schema.parameters.properties", () => {
11
+ const tool: MCPTool = {
12
+ description: "Test tool",
13
+ schema: {
14
+ parameters: {
15
+ properties: {
16
+ name: { type: "string", description: "A name parameter" },
17
+ age: { type: "number", description: "An age parameter" },
18
+ },
19
+ required: ["name"],
20
+ },
21
+ },
22
+ execute: async () => ({}),
23
+ };
24
+
25
+ const result = extractParametersFromSchema(tool);
26
+ expect(result).toHaveLength(2);
27
+ expect(result[0]).toEqual({
28
+ name: "name",
29
+ type: "string",
30
+ description: "A name parameter",
31
+ required: true,
32
+ });
33
+ expect(result[1]).toEqual({
34
+ name: "age",
35
+ type: "number",
36
+ description: "An age parameter",
37
+ required: false,
38
+ });
39
+ });
40
+
41
+ it("should extract parameters from schema.parameters.jsonSchema", () => {
42
+ const tool: MCPTool = {
43
+ description: "Test tool with jsonSchema",
44
+ schema: {
45
+ parameters: {
46
+ jsonSchema: {
47
+ properties: {
48
+ title: { type: "string", description: "A title parameter" },
49
+ count: { type: "number", description: "A count parameter" },
50
+ },
51
+ required: ["title"],
52
+ },
53
+ },
54
+ },
55
+ execute: async () => ({}),
56
+ };
57
+
58
+ const result = extractParametersFromSchema(tool);
59
+ expect(result).toHaveLength(2);
60
+ expect(result[0]).toEqual({
61
+ name: "title",
62
+ type: "string",
63
+ description: "A title parameter",
64
+ required: true,
65
+ });
66
+ expect(result[1]).toEqual({
67
+ name: "count",
68
+ type: "number",
69
+ description: "A count parameter",
70
+ required: false,
71
+ });
72
+ });
73
+
74
+ it("should handle arrays with items", () => {
75
+ const tool: MCPTool = {
76
+ description: "Test tool with array parameters",
77
+ schema: {
78
+ parameters: {
79
+ properties: {
80
+ simpleArray: {
81
+ type: "array",
82
+ items: { type: "string" },
83
+ description: "Array of strings",
84
+ },
85
+ objectArray: {
86
+ type: "array",
87
+ items: {
88
+ type: "object",
89
+ properties: {
90
+ name: { type: "string" },
91
+ value: { type: "number" },
92
+ },
93
+ },
94
+ description: "Array of objects",
95
+ },
96
+ },
97
+ required: ["simpleArray"],
98
+ },
99
+ },
100
+ execute: async () => ({}),
101
+ };
102
+
103
+ const result = extractParametersFromSchema(tool);
104
+ expect(result).toHaveLength(2);
105
+ expect(result[0]).toEqual({
106
+ name: "simpleArray",
107
+ type: "array<string>",
108
+ description: "Array of strings",
109
+ required: true,
110
+ });
111
+ expect(result[1]).toEqual({
112
+ name: "objectArray",
113
+ type: "array",
114
+ description: "Array of objects Array of objects with properties: name, value",
115
+ required: false,
116
+ });
117
+ });
118
+
119
+ it("should handle enums", () => {
120
+ const tool: MCPTool = {
121
+ description: "Test tool with enum parameters",
122
+ schema: {
123
+ parameters: {
124
+ properties: {
125
+ status: {
126
+ type: "string",
127
+ enum: ["active", "inactive", "pending"],
128
+ description: "Status value",
129
+ },
130
+ priority: {
131
+ type: "number",
132
+ enum: [1, 2, 3],
133
+ description: "Priority level",
134
+ },
135
+ },
136
+ required: ["status"],
137
+ },
138
+ },
139
+ execute: async () => ({}),
140
+ };
141
+
142
+ const result = extractParametersFromSchema(tool);
143
+ expect(result).toHaveLength(2);
144
+ expect(result[0]).toEqual({
145
+ name: "status",
146
+ type: "string",
147
+ description: "Status value Allowed values: active | inactive | pending",
148
+ required: true,
149
+ });
150
+ expect(result[1]).toEqual({
151
+ name: "priority",
152
+ type: "number",
153
+ description: "Priority level Allowed values: 1 | 2 | 3",
154
+ required: false,
155
+ });
156
+ });
157
+
158
+ it("should handle nested objects", () => {
159
+ const tool: MCPTool = {
160
+ description: "Test tool with nested object parameters",
161
+ schema: {
162
+ parameters: {
163
+ properties: {
164
+ user: {
165
+ type: "object",
166
+ properties: {
167
+ name: { type: "string" },
168
+ email: { type: "string" },
169
+ preferences: {
170
+ type: "object",
171
+ properties: {
172
+ theme: { type: "string" },
173
+ notifications: { type: "boolean" },
174
+ },
175
+ },
176
+ },
177
+ description: "User object",
178
+ },
179
+ },
180
+ required: ["user"],
181
+ },
182
+ },
183
+ execute: async () => ({}),
184
+ };
185
+
186
+ const result = extractParametersFromSchema(tool);
187
+ expect(result).toHaveLength(1);
188
+ expect(result[0]).toEqual({
189
+ name: "user",
190
+ type: "object",
191
+ description: "User object Object with properties: name, email, preferences",
192
+ required: true,
193
+ });
194
+ });
195
+
196
+ it("should return empty array when no properties", () => {
197
+ const tool: MCPTool = {
198
+ description: "Test tool without properties",
199
+ schema: {
200
+ parameters: {},
201
+ },
202
+ execute: async () => ({}),
203
+ };
204
+
205
+ const result = extractParametersFromSchema(tool);
206
+ expect(result).toHaveLength(0);
207
+ });
208
+ });
209
+
210
+ describe("generateMcpToolInstructions", () => {
211
+ it("should generate instructions with correct parameter schema from schema.parameters.properties", () => {
212
+ const toolsMap: Record<string, MCPTool> = {
213
+ testTool: {
214
+ description: "A test tool",
215
+ schema: {
216
+ parameters: {
217
+ properties: {
218
+ name: { type: "string", description: "The name parameter" },
219
+ age: { type: "number", description: "The age parameter" },
220
+ },
221
+ required: ["name"],
222
+ },
223
+ },
224
+ execute: async () => ({}),
225
+ },
226
+ };
227
+
228
+ const result = generateMcpToolInstructions(toolsMap);
229
+ expect(result).toContain("testTool: A test tool");
230
+ expect(result).toContain("- name* (string) - The name parameter");
231
+ expect(result).toContain("- age (number) - The age parameter");
232
+ });
233
+
234
+ it("should generate instructions with correct parameter schema from schema.parameters.jsonSchema", () => {
235
+ const toolsMap: Record<string, MCPTool> = {
236
+ testTool: {
237
+ description: "A test tool with jsonSchema",
238
+ schema: {
239
+ parameters: {
240
+ jsonSchema: {
241
+ properties: {
242
+ title: { type: "string", description: "The title parameter" },
243
+ count: { type: "number", description: "The count parameter" },
244
+ },
245
+ required: ["title"],
246
+ },
247
+ },
248
+ },
249
+ execute: async () => ({}),
250
+ },
251
+ };
252
+
253
+ const result = generateMcpToolInstructions(toolsMap);
254
+ expect(result).toContain("testTool: A test tool with jsonSchema");
255
+ expect(result).toContain("- title* (string) - The title parameter");
256
+ expect(result).toContain("- count (number) - The count parameter");
257
+ });
258
+
259
+ it("should handle complex schemas with arrays and enums", () => {
260
+ const toolsMap: Record<string, MCPTool> = {
261
+ complexTool: {
262
+ description: "A complex tool",
263
+ schema: {
264
+ parameters: {
265
+ properties: {
266
+ items: {
267
+ type: "array",
268
+ items: {
269
+ type: "object",
270
+ properties: {
271
+ name: { type: "string" },
272
+ value: { type: "number" },
273
+ },
274
+ },
275
+ description: "Array of items",
276
+ },
277
+ status: {
278
+ type: "string",
279
+ enum: ["active", "inactive"],
280
+ description: "Status",
281
+ },
282
+ },
283
+ required: ["items"],
284
+ },
285
+ },
286
+ execute: async () => ({}),
287
+ },
288
+ };
289
+
290
+ const result = generateMcpToolInstructions(toolsMap);
291
+ expect(result).toContain("complexTool: A complex tool");
292
+ expect(result).toContain(
293
+ "- items* (array<object>) - Array of items Array of objects with properties: name, value",
294
+ );
295
+ expect(result).toContain("- status (string) - Status Allowed values: active | inactive");
296
+ });
297
+
298
+ it("should fallback to schema.properties for backward compatibility", () => {
299
+ const toolsMap: Record<string, MCPTool> = {
300
+ backwardCompatTool: {
301
+ description: "A backward compatible tool",
302
+ schema: {
303
+ // Direct properties without nested parameters
304
+ properties: {
305
+ name: { type: "string", description: "The name parameter" },
306
+ },
307
+ required: ["name"],
308
+ } as any,
309
+ execute: async () => ({}),
310
+ },
311
+ };
312
+
313
+ const result = generateMcpToolInstructions(toolsMap);
314
+ expect(result).toContain("backwardCompatTool: A backward compatible tool");
315
+ expect(result).toContain("- name* (string) - The name parameter");
316
+ });
317
+
318
+ it("should show 'No parameters required' when no schema properties", () => {
319
+ const toolsMap: Record<string, MCPTool> = {
320
+ noParamsTool: {
321
+ description: "A tool with no parameters",
322
+ schema: {
323
+ parameters: {},
324
+ },
325
+ execute: async () => ({}),
326
+ },
327
+ };
328
+
329
+ const result = generateMcpToolInstructions(toolsMap);
330
+ expect(result).toContain("noParamsTool: A tool with no parameters");
331
+ expect(result).toContain("No parameters required");
332
+ });
333
+
334
+ it("should handle tools with no schema", () => {
335
+ const toolsMap: Record<string, MCPTool> = {
336
+ noSchemaTool: {
337
+ description: "A tool with no schema",
338
+ execute: async () => ({}),
339
+ },
340
+ };
341
+
342
+ const result = generateMcpToolInstructions(toolsMap);
343
+ expect(result).toContain("noSchemaTool: A tool with no schema");
344
+ expect(result).toContain("No parameters required");
345
+ });
346
+
347
+ it("should return empty string for empty tools map", () => {
348
+ const result = generateMcpToolInstructions({});
349
+ expect(result).toBe("");
350
+ });
351
+ });
352
+
353
+ describe("convertMCPToolsToActions", () => {
354
+ it("should convert MCP tools to CopilotKit actions", () => {
355
+ const mcpTools: Record<string, MCPTool> = {
356
+ testTool: {
357
+ description: "A test tool",
358
+ schema: {
359
+ parameters: {
360
+ properties: {
361
+ name: { type: "string", description: "The name parameter" },
362
+ age: { type: "number", description: "The age parameter" },
363
+ },
364
+ required: ["name"],
365
+ },
366
+ },
367
+ execute: async () => "test result",
368
+ },
369
+ };
370
+
371
+ const result = convertMCPToolsToActions(mcpTools, "http://test-endpoint");
372
+ expect(result).toHaveLength(1);
373
+ expect(result[0].name).toBe("testTool");
374
+ expect(result[0].description).toBe("A test tool");
375
+ expect(result[0].parameters).toHaveLength(2);
376
+ expect(result[0].parameters[0]).toEqual({
377
+ name: "name",
378
+ type: "string",
379
+ description: "The name parameter",
380
+ required: true,
381
+ });
382
+ expect(result[0].parameters[1]).toEqual({
383
+ name: "age",
384
+ type: "number",
385
+ description: "The age parameter",
386
+ required: false,
387
+ });
388
+ });
389
+
390
+ it("should handle tool execution correctly", async () => {
391
+ const mockExecute = jest.fn().mockResolvedValue("mock result");
392
+ const mcpTools: Record<string, MCPTool> = {
393
+ testTool: {
394
+ description: "A test tool",
395
+ schema: {
396
+ parameters: {
397
+ properties: {
398
+ name: { type: "string", description: "The name parameter" },
399
+ },
400
+ required: ["name"],
401
+ },
402
+ },
403
+ execute: mockExecute,
404
+ },
405
+ };
406
+
407
+ const result = convertMCPToolsToActions(mcpTools, "http://test-endpoint");
408
+ const action = result[0];
409
+
410
+ const executeResult = await action.handler({ name: "test" });
411
+ expect(executeResult).toBe("mock result");
412
+ expect(mockExecute).toHaveBeenCalledWith({ name: "test" });
413
+ });
414
+
415
+ it("should stringify non-string results", async () => {
416
+ const mcpTools: Record<string, MCPTool> = {
417
+ testTool: {
418
+ description: "A test tool",
419
+ schema: {
420
+ parameters: {
421
+ properties: {
422
+ name: { type: "string", description: "The name parameter" },
423
+ },
424
+ required: ["name"],
425
+ },
426
+ },
427
+ execute: async () => ({ result: "complex object" }),
428
+ },
429
+ };
430
+
431
+ const result = convertMCPToolsToActions(mcpTools, "http://test-endpoint");
432
+ const action = result[0];
433
+
434
+ const executeResult = await action.handler({ name: "test" });
435
+ expect(executeResult).toBe('{"result":"complex object"}');
436
+ });
437
+
438
+ it("should handle execution errors", async () => {
439
+ const mcpTools: Record<string, MCPTool> = {
440
+ testTool: {
441
+ description: "A test tool",
442
+ schema: {
443
+ parameters: {
444
+ properties: {
445
+ name: { type: "string", description: "The name parameter" },
446
+ },
447
+ required: ["name"],
448
+ },
449
+ },
450
+ execute: async () => {
451
+ throw new Error("Test error");
452
+ },
453
+ },
454
+ };
455
+
456
+ const result = convertMCPToolsToActions(mcpTools, "http://test-endpoint");
457
+ const action = result[0];
458
+
459
+ await expect(action.handler({ name: "test" })).rejects.toThrow(
460
+ "Execution failed for MCP tool 'testTool': Test error",
461
+ );
462
+ });
463
+ });
464
+ });
@@ -439,9 +439,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
439
439
  }
440
440
 
441
441
  const instructions =
442
- "You have access to the following tools provided by external Model Context Protocol (MCP) servers:\n" +
443
- mcpToolInstructions +
444
- "\nUse them when appropriate to fulfill the user's request.";
442
+ mcpToolInstructions + "\nUse them when appropriate to fulfill the user's request.";
445
443
 
446
444
  const systemMessageIndex = messages.findIndex((msg) => msg.textMessage?.role === "system");
447
445
 
@@ -14,7 +14,7 @@ export interface MCPTool {
14
14
  };
15
15
  };
16
16
  /** The function to call to execute the tool on the MCP server. */
17
- execute(options: { params: any }): Promise<any>;
17
+ execute(params: any): Promise<any>;
18
18
  }
19
19
 
20
20
  /**
@@ -51,7 +51,7 @@ export function extractParametersFromSchema(
51
51
  ? (toolOrSchema as MCPTool).schema
52
52
  : (toolOrSchema as MCPTool["schema"]);
53
53
 
54
- const toolParameters = schema?.parameters || schema?.parameters?.jsonSchema;
54
+ const toolParameters = schema?.parameters?.jsonSchema || schema?.parameters;
55
55
  const properties = toolParameters?.properties;
56
56
  const requiredParams = new Set(toolParameters?.required || []);
57
57
 
@@ -62,15 +62,45 @@ export function extractParametersFromSchema(
62
62
  for (const paramName in properties) {
63
63
  if (Object.prototype.hasOwnProperty.call(properties, paramName)) {
64
64
  const paramDef = properties[paramName];
65
+
66
+ // Enhanced type extraction with support for complex types
67
+ let type = paramDef.type || "string";
68
+ let description = paramDef.description || "";
69
+
70
+ // Handle arrays with items
71
+ if (type === "array" && paramDef.items) {
72
+ const itemType = paramDef.items.type || "object";
73
+ if (itemType === "object" && paramDef.items.properties) {
74
+ // For arrays of objects, describe the structure
75
+ const itemProperties = Object.keys(paramDef.items.properties).join(", ");
76
+ description =
77
+ description +
78
+ (description ? " " : "") +
79
+ `Array of objects with properties: ${itemProperties}`;
80
+ } else {
81
+ // For arrays of primitives
82
+ type = `array<${itemType}>`;
83
+ }
84
+ }
85
+
86
+ // Handle enums
87
+ if (paramDef.enum && Array.isArray(paramDef.enum)) {
88
+ const enumValues = paramDef.enum.join(" | ");
89
+ description = description + (description ? " " : "") + `Allowed values: ${enumValues}`;
90
+ }
91
+
92
+ // Handle objects with properties
93
+ if (type === "object" && paramDef.properties) {
94
+ const objectProperties = Object.keys(paramDef.properties).join(", ");
95
+ description =
96
+ description + (description ? " " : "") + `Object with properties: ${objectProperties}`;
97
+ }
98
+
65
99
  parameters.push({
66
100
  name: paramName,
67
- // Infer type, default to string. MCP schemas might have more complex types.
68
- // This might need refinement based on common MCP schema practices.
69
- type: paramDef.type || "string",
70
- description: paramDef.description,
101
+ type: type,
102
+ description: description,
71
103
  required: requiredParams.has(paramName),
72
- // Attributes might not directly map, handle if necessary
73
- // attributes: paramDef.attributes || undefined,
74
104
  });
75
105
  }
76
106
  }
@@ -95,7 +125,7 @@ export function convertMCPToolsToActions(
95
125
 
96
126
  const handler = async (params: any): Promise<any> => {
97
127
  try {
98
- const result = await tool.execute({ params });
128
+ const result = await tool.execute(params);
99
129
  // Ensure the result is a string or stringify it, as required by many LLMs.
100
130
  // This might need adjustment depending on how different LLMs handle tool results.
101
131
  return typeof result === "string" ? result : JSON.stringify(result);
@@ -148,16 +178,49 @@ export function generateMcpToolInstructions(toolsMap: Record<string, MCPTool>):
148
178
  if (tool.schema && typeof tool.schema === "object") {
149
179
  const schema = tool.schema as any;
150
180
 
151
- // Extract parameters from JSON Schema
152
- if (schema.properties) {
153
- const requiredParams = schema.required || [];
181
+ // Extract parameters from JSON Schema - check both schema.parameters.properties and schema.properties
182
+ const toolParameters = schema.parameters?.jsonSchema || schema.parameters;
183
+ const properties = toolParameters?.properties || schema.properties;
184
+ const requiredParams = toolParameters?.required || schema.required || [];
154
185
 
155
- // Build parameter documentation from properties
156
- const paramsList = Object.entries(schema.properties).map(([paramName, propSchema]) => {
186
+ if (properties) {
187
+ // Build parameter documentation from properties with enhanced type information
188
+ const paramsList = Object.entries(properties).map(([paramName, propSchema]) => {
157
189
  const propDetails = propSchema as any;
158
190
  const requiredMark = requiredParams.includes(paramName) ? "*" : "";
159
- const typeInfo = propDetails.type || "any";
160
- const description = propDetails.description ? ` - ${propDetails.description}` : "";
191
+ let typeInfo = propDetails.type || "any";
192
+ let description = propDetails.description ? ` - ${propDetails.description}` : "";
193
+
194
+ // Enhanced type display for complex schemas
195
+ if (typeInfo === "array" && propDetails.items) {
196
+ const itemType = propDetails.items.type || "object";
197
+ if (itemType === "object" && propDetails.items.properties) {
198
+ const itemProps = Object.keys(propDetails.items.properties).join(", ");
199
+ typeInfo = `array<object>`;
200
+ description =
201
+ description +
202
+ (description ? " " : " - ") +
203
+ `Array of objects with properties: ${itemProps}`;
204
+ } else {
205
+ typeInfo = `array<${itemType}>`;
206
+ }
207
+ }
208
+
209
+ // Handle enums
210
+ if (propDetails.enum && Array.isArray(propDetails.enum)) {
211
+ const enumValues = propDetails.enum.join(" | ");
212
+ description =
213
+ description + (description ? " " : " - ") + `Allowed values: ${enumValues}`;
214
+ }
215
+
216
+ // Handle objects
217
+ if (typeInfo === "object" && propDetails.properties) {
218
+ const objectProps = Object.keys(propDetails.properties).join(", ");
219
+ description =
220
+ description +
221
+ (description ? " " : " - ") +
222
+ `Object with properties: ${objectProps}`;
223
+ }
161
224
 
162
225
  return ` - ${paramName}${requiredMark} (${typeInfo})${description}`;
163
226
  });
@@ -183,6 +246,9 @@ ${toolsDoc}
183
246
  When using these tools:
184
247
  1. Only provide valid parameters according to their type requirements
185
248
  2. Required parameters are marked with *
186
- 3. Format API calls correctly with the expected parameter structure
187
- 4. Always check tool responses to determine your next action`;
249
+ 3. For array parameters, provide data in the correct array format
250
+ 4. For object parameters, include all required nested properties
251
+ 5. For enum parameters, use only the allowed values listed
252
+ 6. Format API calls correctly with the expected parameter structure
253
+ 7. Always check tool responses to determine your next action`;
188
254
  }