@elizaos/plugin-mcp 1.3.5 → 2.0.0-alpha.1

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 (114) hide show
  1. package/LICENSE +23 -0
  2. package/dist/cjs/index.cjs +861 -1101
  3. package/dist/cjs/index.d.ts +2 -0
  4. package/dist/cjs/index.js.map +25 -27
  5. package/dist/index.d.ts +2 -7
  6. package/dist/node/actions/callToolAction.d.ts +3 -0
  7. package/dist/node/actions/callToolAction.d.ts.map +1 -0
  8. package/dist/node/actions/readResourceAction.d.ts +3 -0
  9. package/dist/node/actions/readResourceAction.d.ts.map +1 -0
  10. package/dist/node/generated/prompts/typescript/prompts.d.ts +24 -0
  11. package/dist/node/generated/prompts/typescript/prompts.d.ts.map +1 -0
  12. package/dist/node/index.d.ts +4 -0
  13. package/dist/node/index.d.ts.map +1 -0
  14. package/dist/{index.js → node/index.js} +878 -1106
  15. package/dist/node/index.js.map +31 -0
  16. package/dist/node/provider.d.ts.map +1 -0
  17. package/dist/{service.d.ts → node/service.d.ts} +6 -8
  18. package/dist/node/service.d.ts.map +1 -0
  19. package/dist/node/templates/errorAnalysisPrompt.d.ts +2 -0
  20. package/dist/node/templates/errorAnalysisPrompt.d.ts.map +1 -0
  21. package/dist/node/templates/feedbackTemplate.d.ts +8 -0
  22. package/dist/node/templates/feedbackTemplate.d.ts.map +1 -0
  23. package/dist/node/templates/resourceAnalysisTemplate.d.ts +8 -0
  24. package/dist/node/templates/resourceAnalysisTemplate.d.ts.map +1 -0
  25. package/dist/node/templates/resourceSelectionTemplate.d.ts +8 -0
  26. package/dist/node/templates/resourceSelectionTemplate.d.ts.map +1 -0
  27. package/dist/node/templates/toolReasoningTemplate.d.ts +8 -0
  28. package/dist/node/templates/toolReasoningTemplate.d.ts.map +1 -0
  29. package/dist/node/templates/toolSelectionTemplate.d.ts +8 -0
  30. package/dist/node/templates/toolSelectionTemplate.d.ts.map +1 -0
  31. package/dist/{tool-compatibility/index.d.ts → node/tool-compatibility/base.d.ts} +15 -16
  32. package/dist/node/tool-compatibility/base.d.ts.map +1 -0
  33. package/dist/node/tool-compatibility/index.d.ts +7 -0
  34. package/dist/node/tool-compatibility/index.d.ts.map +1 -0
  35. package/dist/node/tool-compatibility/integration-test.d.ts +10 -0
  36. package/dist/node/tool-compatibility/integration-test.d.ts.map +1 -0
  37. package/dist/node/tool-compatibility/providers/anthropic.d.ts +11 -0
  38. package/dist/node/tool-compatibility/providers/anthropic.d.ts.map +1 -0
  39. package/dist/node/tool-compatibility/providers/google.d.ts +11 -0
  40. package/dist/node/tool-compatibility/providers/google.d.ts.map +1 -0
  41. package/dist/node/tool-compatibility/providers/openai.d.ts +18 -0
  42. package/dist/node/tool-compatibility/providers/openai.d.ts.map +1 -0
  43. package/dist/node/tool-compatibility/test-example.d.ts +4 -0
  44. package/dist/node/tool-compatibility/test-example.d.ts.map +1 -0
  45. package/dist/node/types.d.ts +191 -0
  46. package/dist/node/types.d.ts.map +1 -0
  47. package/dist/{utils → node/utils}/error.d.ts +4 -4
  48. package/dist/node/utils/error.d.ts.map +1 -0
  49. package/dist/node/utils/handler.d.ts +8 -0
  50. package/dist/node/utils/handler.d.ts.map +1 -0
  51. package/dist/node/utils/json.d.ts +11 -0
  52. package/dist/node/utils/json.d.ts.map +1 -0
  53. package/dist/node/utils/mcp.d.ts +5 -0
  54. package/dist/node/utils/mcp.d.ts.map +1 -0
  55. package/dist/node/utils/processing.d.ts +43 -0
  56. package/dist/node/utils/processing.d.ts.map +1 -0
  57. package/dist/node/utils/schemas.d.ts +72 -0
  58. package/dist/node/utils/schemas.d.ts.map +1 -0
  59. package/dist/node/utils/selection.d.ts +14 -0
  60. package/dist/node/utils/selection.d.ts.map +1 -0
  61. package/dist/node/utils/validation.d.ts +17 -0
  62. package/dist/node/utils/validation.d.ts.map +1 -0
  63. package/dist/node/utils/wrapper.d.ts +18 -0
  64. package/dist/node/utils/wrapper.d.ts.map +1 -0
  65. package/dist/tsconfig.build.tsbuildinfo +1 -0
  66. package/package.json +35 -44
  67. package/README.md +0 -275
  68. package/dist/actions/callToolAction.d.ts +0 -3
  69. package/dist/actions/callToolAction.d.ts.map +0 -1
  70. package/dist/actions/readResourceAction.d.ts +0 -3
  71. package/dist/actions/readResourceAction.d.ts.map +0 -1
  72. package/dist/index.d.ts.map +0 -1
  73. package/dist/index.js.map +0 -33
  74. package/dist/provider.d.ts.map +0 -1
  75. package/dist/service.d.ts.map +0 -1
  76. package/dist/templates/errorAnalysisPrompt.d.ts +0 -2
  77. package/dist/templates/errorAnalysisPrompt.d.ts.map +0 -1
  78. package/dist/templates/feedbackTemplate.d.ts +0 -2
  79. package/dist/templates/feedbackTemplate.d.ts.map +0 -1
  80. package/dist/templates/resourceAnalysisTemplate.d.ts +0 -2
  81. package/dist/templates/resourceAnalysisTemplate.d.ts.map +0 -1
  82. package/dist/templates/resourceSelectionTemplate.d.ts +0 -2
  83. package/dist/templates/resourceSelectionTemplate.d.ts.map +0 -1
  84. package/dist/templates/toolReasoningTemplate.d.ts +0 -2
  85. package/dist/templates/toolReasoningTemplate.d.ts.map +0 -1
  86. package/dist/templates/toolSelectionTemplate.d.ts +0 -3
  87. package/dist/templates/toolSelectionTemplate.d.ts.map +0 -1
  88. package/dist/tool-compatibility/index.d.ts.map +0 -1
  89. package/dist/tool-compatibility/providers/anthropic.d.ts +0 -12
  90. package/dist/tool-compatibility/providers/anthropic.d.ts.map +0 -1
  91. package/dist/tool-compatibility/providers/google.d.ts +0 -12
  92. package/dist/tool-compatibility/providers/google.d.ts.map +0 -1
  93. package/dist/tool-compatibility/providers/openai.d.ts +0 -20
  94. package/dist/tool-compatibility/providers/openai.d.ts.map +0 -1
  95. package/dist/types.d.ts +0 -166
  96. package/dist/types.d.ts.map +0 -1
  97. package/dist/utils/error.d.ts.map +0 -1
  98. package/dist/utils/handler.d.ts +0 -3
  99. package/dist/utils/handler.d.ts.map +0 -1
  100. package/dist/utils/json.d.ts +0 -9
  101. package/dist/utils/json.d.ts.map +0 -1
  102. package/dist/utils/mcp.d.ts +0 -5
  103. package/dist/utils/mcp.d.ts.map +0 -1
  104. package/dist/utils/processing.d.ts +0 -43
  105. package/dist/utils/processing.d.ts.map +0 -1
  106. package/dist/utils/schemas.d.ts +0 -69
  107. package/dist/utils/schemas.d.ts.map +0 -1
  108. package/dist/utils/selection.d.ts +0 -38
  109. package/dist/utils/selection.d.ts.map +0 -1
  110. package/dist/utils/validation.d.ts +0 -34
  111. package/dist/utils/validation.d.ts.map +0 -1
  112. package/dist/utils/wrapper.d.ts +0 -27
  113. package/dist/utils/wrapper.d.ts.map +0 -1
  114. /package/dist/{provider.d.ts → node/provider.d.ts} +0 -0
@@ -40,18 +40,226 @@ var __export = (target, all) => {
40
40
  };
41
41
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
42
42
 
43
+ // src/tool-compatibility/base.ts
44
+ class McpToolCompatibility {
45
+ modelInfo;
46
+ constructor(modelInfo) {
47
+ this.modelInfo = modelInfo;
48
+ }
49
+ transformToolSchema(toolSchema) {
50
+ if (!this.shouldApply()) {
51
+ return toolSchema;
52
+ }
53
+ return this.processSchema(toolSchema);
54
+ }
55
+ processSchema(schema) {
56
+ const processed = { ...schema };
57
+ switch (processed.type) {
58
+ case "string":
59
+ return this.processStringSchema(processed);
60
+ case "number":
61
+ case "integer":
62
+ return this.processNumberSchema(processed);
63
+ case "array":
64
+ return this.processArraySchema(processed);
65
+ case "object":
66
+ return this.processObjectSchema(processed);
67
+ default:
68
+ return this.processGenericSchema(processed);
69
+ }
70
+ }
71
+ processStringSchema(schema) {
72
+ const constraints = {};
73
+ const processed = { ...schema };
74
+ if (typeof schema.minLength === "number") {
75
+ constraints.minLength = schema.minLength;
76
+ }
77
+ if (typeof schema.maxLength === "number") {
78
+ constraints.maxLength = schema.maxLength;
79
+ }
80
+ if (typeof schema.pattern === "string") {
81
+ constraints.pattern = schema.pattern;
82
+ }
83
+ if (typeof schema.format === "string") {
84
+ constraints.format = schema.format;
85
+ }
86
+ if (Array.isArray(schema.enum)) {
87
+ constraints.enum = schema.enum;
88
+ }
89
+ const unsupportedProps = this.getUnsupportedStringProperties();
90
+ for (const prop of unsupportedProps) {
91
+ if (prop in processed) {
92
+ delete processed[prop];
93
+ }
94
+ }
95
+ if (Object.keys(constraints).length > 0) {
96
+ processed.description = this.mergeDescription(schema.description, constraints);
97
+ }
98
+ return processed;
99
+ }
100
+ processNumberSchema(schema) {
101
+ const constraints = {};
102
+ const processed = { ...schema };
103
+ if (typeof schema.minimum === "number") {
104
+ constraints.minimum = schema.minimum;
105
+ }
106
+ if (typeof schema.maximum === "number") {
107
+ constraints.maximum = schema.maximum;
108
+ }
109
+ if (typeof schema.exclusiveMinimum === "number") {
110
+ constraints.exclusiveMinimum = schema.exclusiveMinimum;
111
+ }
112
+ if (typeof schema.exclusiveMaximum === "number") {
113
+ constraints.exclusiveMaximum = schema.exclusiveMaximum;
114
+ }
115
+ if (typeof schema.multipleOf === "number") {
116
+ constraints.multipleOf = schema.multipleOf;
117
+ }
118
+ const unsupportedProps = this.getUnsupportedNumberProperties();
119
+ for (const prop of unsupportedProps) {
120
+ if (prop in processed) {
121
+ delete processed[prop];
122
+ }
123
+ }
124
+ if (Object.keys(constraints).length > 0) {
125
+ processed.description = this.mergeDescription(schema.description, constraints);
126
+ }
127
+ return processed;
128
+ }
129
+ processArraySchema(schema) {
130
+ const constraints = {};
131
+ const processed = { ...schema };
132
+ if (typeof schema.minItems === "number") {
133
+ constraints.minItems = schema.minItems;
134
+ }
135
+ if (typeof schema.maxItems === "number") {
136
+ constraints.maxItems = schema.maxItems;
137
+ }
138
+ if (typeof schema.uniqueItems === "boolean") {
139
+ constraints.uniqueItems = schema.uniqueItems;
140
+ }
141
+ if (schema.items && typeof schema.items === "object" && !Array.isArray(schema.items)) {
142
+ processed.items = this.processSchema(schema.items);
143
+ }
144
+ const unsupportedProps = this.getUnsupportedArrayProperties();
145
+ for (const prop of unsupportedProps) {
146
+ if (prop in processed) {
147
+ delete processed[prop];
148
+ }
149
+ }
150
+ if (Object.keys(constraints).length > 0) {
151
+ processed.description = this.mergeDescription(schema.description, constraints);
152
+ }
153
+ return processed;
154
+ }
155
+ processObjectSchema(schema) {
156
+ const constraints = {};
157
+ const processed = { ...schema };
158
+ if (typeof schema.minProperties === "number") {
159
+ constraints.minProperties = schema.minProperties;
160
+ }
161
+ if (typeof schema.maxProperties === "number") {
162
+ constraints.maxProperties = schema.maxProperties;
163
+ }
164
+ if (typeof schema.additionalProperties === "boolean") {
165
+ constraints.additionalProperties = schema.additionalProperties;
166
+ }
167
+ if (schema.properties && typeof schema.properties === "object") {
168
+ const newProperties = {};
169
+ for (const [key, prop] of Object.entries(schema.properties)) {
170
+ if (typeof prop === "object" && !Array.isArray(prop)) {
171
+ newProperties[key] = this.processSchema(prop);
172
+ } else {
173
+ newProperties[key] = prop;
174
+ }
175
+ }
176
+ processed.properties = newProperties;
177
+ }
178
+ const unsupportedProps = this.getUnsupportedObjectProperties();
179
+ for (const prop of unsupportedProps) {
180
+ if (prop in processed) {
181
+ delete processed[prop];
182
+ }
183
+ }
184
+ if (Object.keys(constraints).length > 0) {
185
+ processed.description = this.mergeDescription(schema.description, constraints);
186
+ }
187
+ return processed;
188
+ }
189
+ processGenericSchema(schema) {
190
+ const processed = { ...schema };
191
+ if (Array.isArray(schema.oneOf)) {
192
+ processed.oneOf = schema.oneOf.map((s) => typeof s === "object" ? this.processSchema(s) : s);
193
+ }
194
+ if (Array.isArray(schema.anyOf)) {
195
+ processed.anyOf = schema.anyOf.map((s) => typeof s === "object" ? this.processSchema(s) : s);
196
+ }
197
+ if (Array.isArray(schema.allOf)) {
198
+ processed.allOf = schema.allOf.map((s) => typeof s === "object" ? this.processSchema(s) : s);
199
+ }
200
+ return processed;
201
+ }
202
+ mergeDescription(originalDescription, constraints) {
203
+ const constraintJson = JSON.stringify(constraints);
204
+ if (originalDescription) {
205
+ return `${originalDescription}
206
+ ${constraintJson}`;
207
+ }
208
+ return constraintJson;
209
+ }
210
+ }
211
+ function hasModelInfo(runtime) {
212
+ return typeof runtime === "object" && runtime !== null && (("modelProvider" in runtime) || ("model" in runtime));
213
+ }
214
+ function getModelString(runtime) {
215
+ if (hasModelInfo(runtime)) {
216
+ return runtime.modelProvider ?? runtime.model ?? "";
217
+ }
218
+ if (runtime.character && typeof runtime.character === "object" && "settings" in runtime.character && runtime.character.settings && typeof runtime.character.settings === "object") {
219
+ const settings = runtime.character.settings;
220
+ const modelProvider = settings.MODEL_PROVIDER ?? settings.modelProvider;
221
+ const model = settings.MODEL ?? settings.model;
222
+ return String(modelProvider ?? model ?? "");
223
+ }
224
+ return "";
225
+ }
226
+ function detectModelProvider(runtime) {
227
+ const modelString = getModelString(runtime);
228
+ const modelId = String(modelString).toLowerCase();
229
+ let provider2 = "openrouter";
230
+ let supportsStructuredOutputs = false;
231
+ let isReasoningModel = false;
232
+ if (modelId.includes("openai") || modelId.includes("gpt-") || modelId.includes("o1-") || modelId.includes("o3-")) {
233
+ provider2 = "openai";
234
+ supportsStructuredOutputs = modelId.includes("gpt-4") || modelId.includes("o1") || modelId.includes("o3");
235
+ isReasoningModel = modelId.includes("o1") || modelId.includes("o3");
236
+ } else if (modelId.includes("anthropic") || modelId.includes("claude")) {
237
+ provider2 = "anthropic";
238
+ supportsStructuredOutputs = true;
239
+ } else if (modelId.includes("google") || modelId.includes("gemini")) {
240
+ provider2 = "google";
241
+ supportsStructuredOutputs = true;
242
+ } else if (modelId.includes("openrouter")) {
243
+ provider2 = "openrouter";
244
+ supportsStructuredOutputs = false;
245
+ }
246
+ return {
247
+ provider: provider2,
248
+ modelId,
249
+ supportsStructuredOutputs,
250
+ isReasoningModel
251
+ };
252
+ }
253
+
43
254
  // src/tool-compatibility/providers/openai.ts
44
255
  var exports_openai = {};
45
256
  __export(exports_openai, {
46
257
  OpenAIReasoningMcpCompatibility: () => OpenAIReasoningMcpCompatibility,
47
- OpenAIMcpCompatibility: () => OpenAIMcpCompatibility2
258
+ OpenAIMcpCompatibility: () => OpenAIMcpCompatibility
48
259
  });
49
- var OpenAIMcpCompatibility2, OpenAIReasoningMcpCompatibility;
260
+ var OpenAIMcpCompatibility, OpenAIReasoningMcpCompatibility;
50
261
  var init_openai = __esm(() => {
51
- OpenAIMcpCompatibility2 = class OpenAIMcpCompatibility2 extends McpToolCompatibility {
52
- constructor(modelInfo2) {
53
- super(modelInfo2);
54
- }
262
+ OpenAIMcpCompatibility = class OpenAIMcpCompatibility extends McpToolCompatibility {
55
263
  shouldApply() {
56
264
  return this.modelInfo.provider === "openai" && (!this.modelInfo.supportsStructuredOutputs || this.modelInfo.isReasoningModel === true);
57
265
  }
@@ -82,9 +290,6 @@ var init_openai = __esm(() => {
82
290
  }
83
291
  };
84
292
  OpenAIReasoningMcpCompatibility = class OpenAIReasoningMcpCompatibility extends McpToolCompatibility {
85
- constructor(modelInfo2) {
86
- super(modelInfo2);
87
- }
88
293
  shouldApply() {
89
294
  return this.modelInfo.provider === "openai" && this.modelInfo.isReasoningModel === true;
90
295
  }
@@ -152,14 +357,11 @@ IMPORTANT: ${constraintText}`;
152
357
  // src/tool-compatibility/providers/anthropic.ts
153
358
  var exports_anthropic = {};
154
359
  __export(exports_anthropic, {
155
- AnthropicMcpCompatibility: () => AnthropicMcpCompatibility2
360
+ AnthropicMcpCompatibility: () => AnthropicMcpCompatibility
156
361
  });
157
- var AnthropicMcpCompatibility2;
362
+ var AnthropicMcpCompatibility;
158
363
  var init_anthropic = __esm(() => {
159
- AnthropicMcpCompatibility2 = class AnthropicMcpCompatibility2 extends McpToolCompatibility {
160
- constructor(modelInfo2) {
161
- super(modelInfo2);
162
- }
364
+ AnthropicMcpCompatibility = class AnthropicMcpCompatibility extends McpToolCompatibility {
163
365
  shouldApply() {
164
366
  return this.modelInfo.provider === "anthropic";
165
367
  }
@@ -182,7 +384,7 @@ var init_anthropic = __esm(() => {
182
384
  } else if (constraintHints) {
183
385
  return constraintHints;
184
386
  }
185
- return originalDescription || "";
387
+ return originalDescription ?? "";
186
388
  }
187
389
  formatConstraintsForAnthropic(constraints) {
188
390
  const hints = [];
@@ -203,14 +405,11 @@ var init_anthropic = __esm(() => {
203
405
  // src/tool-compatibility/providers/google.ts
204
406
  var exports_google = {};
205
407
  __export(exports_google, {
206
- GoogleMcpCompatibility: () => GoogleMcpCompatibility2
408
+ GoogleMcpCompatibility: () => GoogleMcpCompatibility
207
409
  });
208
- var GoogleMcpCompatibility2;
410
+ var GoogleMcpCompatibility;
209
411
  var init_google = __esm(() => {
210
- GoogleMcpCompatibility2 = class GoogleMcpCompatibility2 extends McpToolCompatibility {
211
- constructor(modelInfo2) {
212
- super(modelInfo2);
213
- }
412
+ GoogleMcpCompatibility = class GoogleMcpCompatibility extends McpToolCompatibility {
214
413
  shouldApply() {
215
414
  return this.modelInfo.provider === "google";
216
415
  }
@@ -235,7 +434,7 @@ Constraints: ${constraintText}`;
235
434
  } else if (constraintText) {
236
435
  return `Constraints: ${constraintText}`;
237
436
  }
238
- return originalDescription || "";
437
+ return originalDescription ?? "";
239
438
  }
240
439
  formatConstraintsForGoogle(constraints) {
241
440
  const rules = [];
@@ -301,321 +500,37 @@ Constraints: ${constraintText}`;
301
500
  };
302
501
  });
303
502
 
304
- // src/tool-compatibility/index.ts
305
- class McpToolCompatibility {
306
- modelInfo;
307
- constructor(modelInfo2) {
308
- this.modelInfo = modelInfo2;
309
- }
310
- transformToolSchema(toolSchema) {
311
- if (!this.shouldApply()) {
312
- return toolSchema;
313
- }
314
- return this.processSchema(toolSchema);
315
- }
316
- processSchema(schema) {
317
- const processed = { ...schema };
318
- switch (processed.type) {
319
- case "string":
320
- return this.processStringSchema(processed);
321
- case "number":
322
- case "integer":
323
- return this.processNumberSchema(processed);
324
- case "array":
325
- return this.processArraySchema(processed);
326
- case "object":
327
- return this.processObjectSchema(processed);
328
- default:
329
- return this.processGenericSchema(processed);
330
- }
331
- }
332
- processStringSchema(schema) {
333
- const constraints = {};
334
- const processed = { ...schema };
335
- if (typeof schema.minLength === "number") {
336
- constraints.minLength = schema.minLength;
337
- }
338
- if (typeof schema.maxLength === "number") {
339
- constraints.maxLength = schema.maxLength;
340
- }
341
- if (typeof schema.pattern === "string") {
342
- constraints.pattern = schema.pattern;
343
- }
344
- if (typeof schema.format === "string") {
345
- constraints.format = schema.format;
346
- }
347
- if (Array.isArray(schema.enum)) {
348
- constraints.enum = schema.enum;
349
- }
350
- const unsupportedProps = this.getUnsupportedStringProperties();
351
- for (const prop of unsupportedProps) {
352
- if (prop in processed) {
353
- delete processed[prop];
354
- }
355
- }
356
- if (Object.keys(constraints).length > 0) {
357
- processed.description = this.mergeDescription(schema.description, constraints);
358
- }
359
- return processed;
360
- }
361
- processNumberSchema(schema) {
362
- const constraints = {};
363
- const processed = { ...schema };
364
- if (typeof schema.minimum === "number") {
365
- constraints.minimum = schema.minimum;
366
- }
367
- if (typeof schema.maximum === "number") {
368
- constraints.maximum = schema.maximum;
369
- }
370
- if (typeof schema.exclusiveMinimum === "number") {
371
- constraints.exclusiveMinimum = schema.exclusiveMinimum;
372
- }
373
- if (typeof schema.exclusiveMaximum === "number") {
374
- constraints.exclusiveMaximum = schema.exclusiveMaximum;
375
- }
376
- if (typeof schema.multipleOf === "number") {
377
- constraints.multipleOf = schema.multipleOf;
378
- }
379
- const unsupportedProps = this.getUnsupportedNumberProperties();
380
- for (const prop of unsupportedProps) {
381
- if (prop in processed) {
382
- delete processed[prop];
383
- }
384
- }
385
- if (Object.keys(constraints).length > 0) {
386
- processed.description = this.mergeDescription(schema.description, constraints);
387
- }
388
- return processed;
389
- }
390
- processArraySchema(schema) {
391
- const constraints = {};
392
- const processed = { ...schema };
393
- if (typeof schema.minItems === "number") {
394
- constraints.minItems = schema.minItems;
395
- }
396
- if (typeof schema.maxItems === "number") {
397
- constraints.maxItems = schema.maxItems;
398
- }
399
- if (typeof schema.uniqueItems === "boolean") {
400
- constraints.uniqueItems = schema.uniqueItems;
401
- }
402
- if (schema.items && typeof schema.items === "object" && !Array.isArray(schema.items)) {
403
- processed.items = this.processSchema(schema.items);
404
- }
405
- const unsupportedProps = this.getUnsupportedArrayProperties();
406
- for (const prop of unsupportedProps) {
407
- if (prop in processed) {
408
- delete processed[prop];
409
- }
410
- }
411
- if (Object.keys(constraints).length > 0) {
412
- processed.description = this.mergeDescription(schema.description, constraints);
413
- }
414
- return processed;
415
- }
416
- processObjectSchema(schema) {
417
- const constraints = {};
418
- const processed = { ...schema };
419
- if (typeof schema.minProperties === "number") {
420
- constraints.minProperties = schema.minProperties;
421
- }
422
- if (typeof schema.maxProperties === "number") {
423
- constraints.maxProperties = schema.maxProperties;
424
- }
425
- if (typeof schema.additionalProperties === "boolean") {
426
- constraints.additionalProperties = schema.additionalProperties;
427
- }
428
- if (schema.properties && typeof schema.properties === "object") {
429
- processed.properties = {};
430
- for (const [key, prop] of Object.entries(schema.properties)) {
431
- if (typeof prop === "object" && !Array.isArray(prop)) {
432
- processed.properties[key] = this.processSchema(prop);
433
- } else {
434
- processed.properties[key] = prop;
435
- }
436
- }
437
- }
438
- const unsupportedProps = this.getUnsupportedObjectProperties();
439
- for (const prop of unsupportedProps) {
440
- if (prop in processed) {
441
- delete processed[prop];
442
- }
443
- }
444
- if (Object.keys(constraints).length > 0) {
445
- processed.description = this.mergeDescription(schema.description, constraints);
446
- }
447
- return processed;
448
- }
449
- processGenericSchema(schema) {
450
- const processed = { ...schema };
451
- if (Array.isArray(schema.oneOf)) {
452
- processed.oneOf = schema.oneOf.map((s) => typeof s === "object" ? this.processSchema(s) : s);
453
- }
454
- if (Array.isArray(schema.anyOf)) {
455
- processed.anyOf = schema.anyOf.map((s) => typeof s === "object" ? this.processSchema(s) : s);
456
- }
457
- if (Array.isArray(schema.allOf)) {
458
- processed.allOf = schema.allOf.map((s) => typeof s === "object" ? this.processSchema(s) : s);
459
- }
460
- return processed;
461
- }
462
- mergeDescription(originalDescription, constraints) {
463
- const constraintJson = JSON.stringify(constraints);
464
- if (originalDescription) {
465
- return `${originalDescription}
466
- ${constraintJson}`;
467
- }
468
- return constraintJson;
469
- }
470
- }
471
- function detectModelProvider(runtime2) {
472
- const modelString = runtime2?.modelProvider || runtime2?.model || "";
473
- const modelId = String(modelString).toLowerCase();
474
- let provider2 = "unknown";
475
- let supportsStructuredOutputs = false;
476
- let isReasoningModel = false;
477
- if (modelId.includes("openai") || modelId.includes("gpt-") || modelId.includes("o1-") || modelId.includes("o3-")) {
478
- provider2 = "openai";
479
- supportsStructuredOutputs = modelId.includes("gpt-4") || modelId.includes("o1") || modelId.includes("o3");
480
- isReasoningModel = modelId.includes("o1") || modelId.includes("o3");
481
- } else if (modelId.includes("anthropic") || modelId.includes("claude")) {
482
- provider2 = "anthropic";
483
- supportsStructuredOutputs = true;
484
- } else if (modelId.includes("google") || modelId.includes("gemini")) {
485
- provider2 = "google";
486
- supportsStructuredOutputs = true;
487
- } else if (modelId.includes("openrouter")) {
488
- provider2 = "openrouter";
489
- supportsStructuredOutputs = false;
490
- }
491
- return {
492
- provider: provider2,
493
- modelId,
494
- supportsStructuredOutputs,
495
- isReasoningModel
496
- };
497
- }
498
- async function createMcpToolCompatibility(runtime2) {
499
- const modelInfo2 = detectModelProvider(runtime2);
500
- try {
501
- switch (modelInfo2.provider) {
502
- case "openai":
503
- const { OpenAIMcpCompatibility: OpenAIMcpCompatibility3 } = await Promise.resolve().then(() => (init_openai(), exports_openai));
504
- return new OpenAIMcpCompatibility3(modelInfo2);
505
- case "anthropic":
506
- const { AnthropicMcpCompatibility: AnthropicMcpCompatibility3 } = await Promise.resolve().then(() => (init_anthropic(), exports_anthropic));
507
- return new AnthropicMcpCompatibility3(modelInfo2);
508
- case "google":
509
- const { GoogleMcpCompatibility: GoogleMcpCompatibility3 } = await Promise.resolve().then(() => (init_google(), exports_google));
510
- return new GoogleMcpCompatibility3(modelInfo2);
511
- default:
512
- return null;
513
- }
514
- } catch (error) {
515
- console.warn("Failed to load compatibility provider:", error);
516
- return null;
517
- }
518
- }
519
- function createMcpToolCompatibilitySync(runtime) {
520
- const modelInfo = detectModelProvider(runtime);
521
- try {
522
- switch (modelInfo.provider) {
523
- case "openai":
524
- const OpenAIModule = eval("require")("./providers/openai");
525
- const { OpenAIMcpCompatibility } = OpenAIModule;
526
- return new OpenAIMcpCompatibility(modelInfo);
527
- case "anthropic":
528
- const AnthropicModule = eval("require")("./providers/anthropic");
529
- const { AnthropicMcpCompatibility } = AnthropicModule;
530
- return new AnthropicMcpCompatibility(modelInfo);
531
- case "google":
532
- const GoogleModule = eval("require")("./providers/google");
533
- const { GoogleMcpCompatibility } = GoogleModule;
534
- return new GoogleMcpCompatibility(modelInfo);
535
- default:
536
- return null;
537
- }
538
- } catch (error) {
539
- console.warn("Failed to load compatibility provider:", error);
540
- return null;
541
- }
542
- }
543
-
544
- // src/index.ts
545
- var exports_src = {};
546
- __export(exports_src, {
547
- detectModelProvider: () => detectModelProvider,
548
- default: () => src_default,
549
- createMcpToolCompatibilitySync: () => createMcpToolCompatibilitySync,
550
- createMcpToolCompatibility: () => createMcpToolCompatibility,
551
- ToolSelectionSchema: () => ToolSelectionSchema,
552
- ResourceSelectionSchema: () => ResourceSelectionSchema,
553
- McpToolCompatibility: () => McpToolCompatibility,
554
- McpService: () => McpService,
555
- MIN_MCP_TIMEOUT_SECONDS: () => MIN_MCP_TIMEOUT_SECONDS,
556
- MCP_SERVICE_NAME: () => MCP_SERVICE_NAME,
557
- MAX_RECONNECT_ATTEMPTS: () => MAX_RECONNECT_ATTEMPTS,
558
- INITIAL_RETRY_DELAY: () => INITIAL_RETRY_DELAY,
559
- DEFAULT_PING_CONFIG: () => DEFAULT_PING_CONFIG,
560
- DEFAULT_MCP_TIMEOUT_SECONDS: () => DEFAULT_MCP_TIMEOUT_SECONDS,
561
- DEFAULT_MAX_RETRIES: () => DEFAULT_MAX_RETRIES,
562
- BACKOFF_MULTIPLIER: () => BACKOFF_MULTIPLIER
563
- });
564
- module.exports = __toCommonJS(exports_src);
565
- var import_core9 = require("@elizaos/core");
566
-
567
- // src/actions/callToolAction.ts
568
- var import_core6 = require("@elizaos/core");
569
-
570
- // src/types.ts
571
- var MCP_SERVICE_NAME = "mcp";
572
- var DEFAULT_MCP_TIMEOUT_SECONDS = 60000;
573
- var MIN_MCP_TIMEOUT_SECONDS = 1;
574
- var DEFAULT_MAX_RETRIES = 2;
575
- var ToolSelectionSchema = {
576
- type: "object",
577
- required: ["serverName", "toolName", "arguments"],
578
- properties: {
579
- serverName: {
580
- type: "string",
581
- minLength: 1,
582
- errorMessage: "serverName must not be empty"
583
- },
584
- toolName: {
585
- type: "string",
586
- minLength: 1,
587
- errorMessage: "toolName must not be empty"
588
- },
589
- arguments: {
590
- type: "object"
591
- },
592
- reasoning: {
593
- type: "string"
594
- },
595
- noToolAvailable: {
596
- type: "boolean"
597
- }
598
- }
599
- };
600
- var ResourceSelectionSchema = {
601
- type: "object",
602
- required: ["serverName", "uri"],
603
- properties: {
604
- serverName: {
605
- type: "string",
606
- minLength: 1,
607
- errorMessage: "serverName must not be empty"
608
- },
609
- uri: {
610
- type: "string",
611
- minLength: 1,
612
- errorMessage: "uri must not be empty"
613
- },
614
- reasoning: {
615
- type: "string"
616
- },
617
- noResourceAvailable: {
618
- type: "boolean"
503
+ // src/index.ts
504
+ var exports_src = {};
505
+ __export(exports_src, {
506
+ default: () => src_default
507
+ });
508
+ module.exports = __toCommonJS(exports_src);
509
+ var import_core7 = require("@elizaos/core");
510
+
511
+ // src/types.ts
512
+ var MCP_SERVICE_NAME = "mcp";
513
+ var DEFAULT_MCP_TIMEOUT_SECONDS = 60000;
514
+ var DEFAULT_MAX_RETRIES = 2;
515
+ var ResourceSelectionSchema = {
516
+ type: "object",
517
+ required: ["serverName", "uri"],
518
+ properties: {
519
+ serverName: {
520
+ type: "string",
521
+ minLength: 1,
522
+ errorMessage: "serverName must not be empty"
523
+ },
524
+ uri: {
525
+ type: "string",
526
+ minLength: 1,
527
+ errorMessage: "uri must not be empty"
528
+ },
529
+ reasoning: {
530
+ type: "string"
531
+ },
532
+ noResourceAvailable: {
533
+ type: "boolean"
619
534
  }
620
535
  }
621
536
  };
@@ -629,44 +544,234 @@ var MAX_RECONNECT_ATTEMPTS = 5;
629
544
  var BACKOFF_MULTIPLIER = 2;
630
545
  var INITIAL_RETRY_DELAY = 2000;
631
546
 
632
- // src/utils/error.ts
633
- var import_core = require("@elizaos/core");
547
+ // src/utils/error.ts
548
+ var import_core = require("@elizaos/core");
549
+
550
+ // src/generated/prompts/typescript/prompts.ts
551
+ var errorAnalysisTemplate = `{{{mcpProvider.text}}}
552
+
553
+ {{{recentMessages}}}
554
+
555
+ # Prompt
556
+
557
+ You're an assistant helping a user, but there was an error accessing the resource you tried to use.
558
+
559
+ User request: "{{{userMessage}}}"
560
+ Error message: {{{error}}}
561
+
562
+ Create a helpful response that:
563
+ 1. Acknowledges the issue in user-friendly terms
564
+ 2. Offers alternative approaches to help if possible
565
+ 3. Doesn't expose technical error details unless they're truly helpful
566
+ 4. Maintains a helpful, conversational tone
567
+
568
+ Your response:`;
569
+ var resourceAnalysisTemplate = `{{{mcpProvider.text}}}
570
+
571
+ {{{recentMessages}}}
572
+
573
+ # Prompt
574
+
575
+ You are a helpful assistant responding to a user's request. You've just accessed the resource "{{{uri}}}" to help answer this request.
576
+
577
+ Original user request: "{{{userMessage}}}"
578
+
579
+ Resource metadata:
580
+ {{{resourceMeta}}
581
+
582
+ Resource content:
583
+ {{{resourceContent}}
584
+
585
+ Instructions:
586
+ 1. Analyze how well the resource's content addresses the user's specific question or need
587
+ 2. Identify the most relevant information from the resource
588
+ 3. Create a natural, conversational response that incorporates this information
589
+ 4. If the resource content is insufficient, acknowledge its limitations and explain what you can determine
590
+ 5. Do not start with phrases like "According to the resource" or "Here's what I found" - instead, integrate the information naturally
591
+ 6. Maintain your helpful, intelligent assistant personality while presenting the information
592
+
593
+ Your response (written as if directly to the user):`;
594
+ var resourceSelectionTemplate = `{{{mcpProvider.text}}}
595
+
596
+ {{{recentMessages}}}
597
+
598
+ # Prompt
599
+
600
+ You are an intelligent assistant helping select the right resource to address a user's request.
601
+
602
+ CRITICAL INSTRUCTIONS:
603
+ 1. You MUST specify both a valid serverName AND uri from the list above
604
+ 2. The serverName value should match EXACTLY the server name shown in parentheses (Server: X)
605
+ CORRECT: "serverName": "github" (if the server is called "github")
606
+ WRONG: "serverName": "GitHub" or "Github" or any other variation
607
+ 3. The uri value should match EXACTLY the resource uri listed
608
+ CORRECT: "uri": "weather://San Francisco/current" (if that's the exact uri)
609
+ WRONG: "uri": "weather://sanfrancisco/current" or any variation
610
+ 4. Identify the user's information need from the conversation context
611
+ 5. Select the most appropriate resource based on its description and the request
612
+ 6. If no resource seems appropriate, output {"noResourceAvailable": true}
613
+
614
+ !!! YOUR RESPONSE MUST BE A VALID JSON OBJECT ONLY !!!
615
+
616
+ STRICT FORMAT REQUIREMENTS:
617
+ - NO code block formatting (NO backticks or \`\`\`)
618
+ - NO comments (NO // or /* */)
619
+ - NO placeholders like "replace with...", "example", "your...", "actual", etc.
620
+ - Every parameter value must be a concrete, usable value (not instructions to replace)
621
+ - Use proper JSON syntax with double quotes for strings
622
+ - NO explanatory text before or after the JSON object
623
+
624
+ EXAMPLE RESPONSE:
625
+ {
626
+ "serverName": "weather-server",
627
+ "uri": "weather://San Francisco/current",
628
+ "reasoning": "Based on the conversation, the user is asking about current weather in San Francisco. This resource provides up-to-date weather information for that city."
629
+ }
630
+
631
+ REMEMBER: Your response will be parsed directly as JSON. If it fails to parse, the operation will fail completely!`;
632
+ var toolReasoningTemplate = `{{{mcpProvider.text}}}
633
+
634
+ {{{recentMessages}}}
635
+
636
+ # Prompt
637
+
638
+ You are a helpful assistant responding to a user's request. You've just used the "{{{toolName}}}" tool from the "{{{serverName}}}" server to help answer this request.
639
+
640
+ Original user request: "{{{userMessage}}}"
641
+
642
+ Tool response:
643
+ {{{toolOutput}}}
644
+
645
+ {{#if hasAttachments}}
646
+ The tool also returned images or other media that will be shared with the user.
647
+ {{/if}}
648
+
649
+ Instructions:
650
+ 1. Analyze how well the tool's response addresses the user's specific question or need
651
+ 2. Identify the most relevant information from the tool's output
652
+ 3. Create a natural, conversational response that incorporates this information
653
+ 4. If the tool's response is insufficient, acknowledge its limitations and explain what you can determine
654
+ 5. Do not start with phrases like "I used the X tool" or "Here's what I found" - instead, integrate the information naturally
655
+ 6. Maintain your helpful, intelligent assistant personality while presenting the information
656
+
657
+ Your response (written as if directly to the user):`;
658
+ var toolSelectionArgumentTemplate = `{{recentMessages}}
659
+
660
+ # TASK: Generate a Strictly Valid JSON Object for Tool Execution
661
+
662
+ You have chosen the "{{toolSelectionName.toolName}}" tool from the "{{toolSelectionName.serverName}}" server to address the user's request.
663
+ The reasoning behind this selection is: "{{toolSelectionName.reasoning}}"
664
+
665
+ ## CRITICAL INSTRUCTIONS
666
+ 1. Ensure the "toolArguments" object strictly adheres to the structure and requirements defined in the schema.
667
+ 2. All parameter values must be extracted from the conversation context and must be concrete, usable values.
668
+ 3. Avoid placeholders or generic terms unless explicitly provided by the user.
669
+
670
+ !!! YOUR RESPONSE MUST BE A VALID JSON OBJECT ONLY !!!
671
+
672
+ ## STRICT FORMAT REQUIREMENTS
673
+ - The response MUST be a single valid JSON object.
674
+ - DO NOT wrap the JSON in triple backticks (\`\`\`), code blocks, or include any explanatory text.
675
+ - DO NOT include comments (// or /* */) anywhere.
676
+ - DO NOT use placeholders (e.g., "replace with...", "example", "your...", etc.)
677
+ - ALL strings must use double quotes
678
+
679
+ ## CRITICAL NOTES
680
+ - All values must be fully grounded in user input or inferred contextually.
681
+ - No missing fields unless they are explicitly optional in the schema.
682
+ - All types must match the schema (strings, numbers, booleans).
683
+
684
+ ## JSON OBJECT STRUCTURE
685
+ Your response MUST contain ONLY these two top-level keys:
686
+ 1. "toolArguments" — An object matching the input schema: {{toolInputSchema}}
687
+ 2. "reasoning" — A string explaining how the values were inferred from the conversation.
688
+
689
+ ## EXAMPLE RESPONSE
690
+ {
691
+ "toolArguments": {
692
+ "owner": "facebook",
693
+ "repo": "react",
694
+ "path": "README.md",
695
+ "branch": "main"
696
+ },
697
+ "reasoning": "The user wants to see the README from the facebook/react repository based on our conversation."
698
+ }
699
+
700
+ REMEMBER: Your response will be parsed directly as JSON. If it fails to parse, the operation will fail completely.`;
701
+ var toolSelectionNameTemplate = `{{mcpProvider.text}}
702
+
703
+ {{recentMessages}}
704
+
705
+ # TASK: Select the Most Appropriate Tool and Server
706
+
707
+ You must select the most appropriate tool from the list above to fulfill the user's request. Your response must be a valid JSON object with the required properties.
708
+
709
+ ## CRITICAL INSTRUCTIONS
710
+ 1. Provide both "serverName" and "toolName" from the options listed above.
711
+ 2. Each name must match EXACTLY as shown in the list:
712
+ - Example (correct): "serverName": "github"
713
+ - Example (incorrect): "serverName": "GitHub", "Github", or variations
714
+ 3. Extract ACTUAL parameter values from the conversation context.
715
+ - Do not invent or use placeholders like "octocat" or "Hello-World" unless the user said so.
716
+ 4. Include a "reasoning" field explaining why the selected tool fits the request.
717
+ 5. If no tool is appropriate, respond with:
718
+ {
719
+ "noToolAvailable": true
720
+ }
634
721
 
635
- // src/templates/errorAnalysisPrompt.ts
636
- var errorAnalysisPrompt = `
637
- {{{mcpProvider.text}}}
722
+ !!! YOUR RESPONSE MUST BE A VALID JSON OBJECT ONLY !!!
638
723
 
639
- {{{recentMessages}}}
724
+ CRITICAL: Your response must START with { and END with }. DO NOT include ANY text before or after the JSON.
640
725
 
641
- # Prompt
726
+ ## STRICT FORMAT REQUIREMENTS
727
+ - The response MUST be a single valid JSON object.
728
+ - DO NOT wrap the JSON in triple backticks (\`\`\`), code blocks, or include any explanatory text.
729
+ - DO NOT include comments (// or /* */) anywhere.
730
+ - DO NOT use placeholders (e.g., "replace with...", "example", "your...", etc.)
731
+ - ALL strings must use double quotes.
642
732
 
643
- You're an assistant helping a user, but there was an error accessing the resource you tried to use.
733
+ ## CRITICAL NOTES
734
+ - All values must be fully grounded in user input or inferred contextually.
735
+ - No missing fields unless they are explicitly optional in the schema.
736
+ - All types must match the schema (strings, numbers, booleans).
644
737
 
645
- User request: "{{{userMessage}}}"
646
- Error message: {{{error}}}
738
+ ## JSON OBJECT STRUCTURE
739
+ Your response MUST contain ONLY these top-level keys:
740
+ 1. "serverName" — The name of the server (e.g., "github", "notion")
741
+ 2. "toolName" — The name of the tool (e.g., "get_file_contents", "search")
742
+ 3. "reasoning" — A string explaining how the values were inferred from the conversation.
743
+ 4. "noToolAvailable" — A boolean indicating if no tool is available (true/false)
647
744
 
648
- Create a helpful response that:
649
- 1. Acknowledges the issue in user-friendly terms
650
- 2. Offers alternative approaches to help if possible
651
- 3. Doesn't expose technical error details unless they're truly helpful
652
- 4. Maintains a helpful, conversational tone
745
+ ## EXAMPLE RESPONSE
746
+ {
747
+ "serverName": "github",
748
+ "toolName": "get_file_contents",
749
+ "reasoning": "The user wants to retrieve the README from the facebook/react repository.",
750
+ "noToolAvailable": false
751
+ }
653
752
 
654
- Your response:
655
- `;
753
+ ## REMINDERS
754
+ - Use "github" as serverName for GitHub tools.
755
+ - Use "notion" as serverName for Notion tools.
756
+ - For search and knowledge-based tasks, MCP tools are often appropriate.
757
+
758
+ REMEMBER: This output will be parsed directly as JSON. If the format is incorrect, the operation will fail.`;
759
+
760
+ // src/templates/errorAnalysisPrompt.ts
761
+ var errorAnalysisPrompt = errorAnalysisTemplate;
656
762
 
657
763
  // src/utils/error.ts
658
- async function handleMcpError(state, mcpProvider, error, runtime2, message, type, callback) {
764
+ async function handleMcpError(state, mcpProvider, error, runtime, message, type, callback) {
659
765
  const errorMessage = error instanceof Error ? error.message : String(error);
660
766
  import_core.logger.error({ error, mcpType: type }, `Error executing MCP ${type}: ${errorMessage}`);
661
767
  let responseText = `I'm sorry, I wasn't able to get the information you requested. There seems to be an issue with the ${type} right now. Is there something else I can help you with?`;
662
- let thoughtText = `Error calling MCP ${type} and failed to generate a custom response. Providing a generic fallback response.`;
663
768
  if (callback) {
664
769
  const enhancedState = {
665
770
  ...state,
666
771
  values: {
667
772
  ...state.values,
668
773
  mcpProvider,
669
- userMessage: message.content.text || "",
774
+ userMessage: message.content.text ?? "",
670
775
  error: errorMessage
671
776
  }
672
777
  };
@@ -674,25 +779,14 @@ async function handleMcpError(state, mcpProvider, error, runtime2, message, type
674
779
  state: enhancedState,
675
780
  template: errorAnalysisPrompt
676
781
  });
677
- try {
678
- const errorResponse = await runtime2.useModel(import_core.ModelType.TEXT_SMALL, {
679
- prompt
680
- });
681
- responseText = errorResponse;
682
- thoughtText = `Error calling MCP ${type}: ${errorMessage}. Providing a helpful response to the user.`;
683
- await callback({
684
- thought: thoughtText,
685
- text: responseText,
686
- actions: ["REPLY"]
687
- });
688
- } catch (modelError) {
689
- import_core.logger.error({ error: modelError instanceof Error ? modelError.message : String(modelError) }, "Failed to generate error response");
690
- await callback({
691
- thought: thoughtText,
692
- text: responseText,
693
- actions: ["REPLY"]
694
- });
695
- }
782
+ const errorResponse = await runtime.useModel(import_core.ModelType.TEXT_SMALL, {
783
+ prompt
784
+ });
785
+ responseText = errorResponse;
786
+ await callback({
787
+ text: responseText,
788
+ actions: ["REPLY"]
789
+ });
696
790
  }
697
791
  return {
698
792
  text: `Failed to execute MCP ${type}`,
@@ -711,74 +805,39 @@ async function handleMcpError(state, mcpProvider, error, runtime2, message, type
711
805
  };
712
806
  }
713
807
 
808
+ // src/utils/handler.ts
809
+ async function handleNoToolAvailable(callback, toolSelection) {
810
+ const responseText = "I don't have a specific tool that can help with that request. Let me try to assist you directly instead.";
811
+ if (callback && toolSelection?.noToolAvailable) {
812
+ await callback({
813
+ text: responseText,
814
+ actions: ["REPLY"]
815
+ });
816
+ }
817
+ return {
818
+ text: responseText,
819
+ values: {
820
+ success: true,
821
+ noToolAvailable: true,
822
+ fallbackToDirectAssistance: true
823
+ },
824
+ data: {
825
+ actionName: "CALL_MCP_TOOL",
826
+ noToolAvailable: true,
827
+ reason: toolSelection?.reasoning ?? "No appropriate tool available"
828
+ },
829
+ success: true
830
+ };
831
+ }
832
+
714
833
  // src/utils/processing.ts
715
834
  var import_core2 = require("@elizaos/core");
716
- var import_core3 = require("@elizaos/core");
717
-
718
- // src/templates/resourceAnalysisTemplate.ts
719
- var resourceAnalysisTemplate = `
720
- {{{mcpProvider.text}}}
721
-
722
- {{{recentMessages}}}
723
-
724
- # Prompt
725
-
726
- You are a helpful assistant responding to a user's request. You've just accessed the resource "{{{uri}}}" to help answer this request.
727
-
728
- Original user request: "{{{userMessage}}}"
729
-
730
- Resource metadata:
731
- {{{resourceMeta}}
732
-
733
- Resource content:
734
- {{{resourceContent}}
735
-
736
- Instructions:
737
- 1. Analyze how well the resource's content addresses the user's specific question or need
738
- 2. Identify the most relevant information from the resource
739
- 3. Create a natural, conversational response that incorporates this information
740
- 4. If the resource content is insufficient, acknowledge its limitations and explain what you can determine
741
- 5. Do not start with phrases like "According to the resource" or "Here's what I found" - instead, integrate the information naturally
742
- 6. Maintain your helpful, intelligent assistant personality while presenting the information
743
-
744
- Your response (written as if directly to the user):
745
- `;
746
-
747
- // src/templates/toolReasoningTemplate.ts
748
- var toolReasoningTemplate = `
749
- {{{mcpProvider.text}}}
750
-
751
- {{{recentMessages}}}
752
-
753
- # Prompt
754
-
755
- You are a helpful assistant responding to a user's request. You've just used the "{{{toolName}}}" tool from the "{{{serverName}}}" server to help answer this request.
756
-
757
- Original user request: "{{{userMessage}}}"
758
-
759
- Tool response:
760
- {{{toolOutput}}}
761
-
762
- {{#if hasAttachments}}
763
- The tool also returned images or other media that will be shared with the user.
764
- {{/if}}
765
-
766
- Instructions:
767
- 1. Analyze how well the tool's response addresses the user's specific question or need
768
- 2. Identify the most relevant information from the tool's output
769
- 3. Create a natural, conversational response that incorporates this information
770
- 4. If the tool's response is insufficient, acknowledge its limitations and explain what you can determine
771
- 5. Do not start with phrases like "I used the X tool" or "Here's what I found" - instead, integrate the information naturally
772
- 6. Maintain your helpful, intelligent assistant personality while presenting the information
773
-
774
- Your response (written as if directly to the user):
775
- `;
776
835
 
777
836
  // src/utils/mcp.ts
778
- async function createMcpMemory(runtime2, message, type, serverName, content, metadata) {
779
- const memory = await runtime2.addEmbeddingToMemory({
837
+ async function createMcpMemory(runtime, message, type, serverName, content, metadata) {
838
+ const memory = await runtime.addEmbeddingToMemory({
780
839
  entityId: message.entityId,
781
- agentId: runtime2.agentId,
840
+ agentId: runtime.agentId,
782
841
  roomId: message.roomId,
783
842
  content: {
784
843
  text: `Used the "${type}" from "${serverName}" server.
@@ -789,7 +848,7 @@ async function createMcpMemory(runtime2, message, type, serverName, content, met
789
848
  }
790
849
  }
791
850
  });
792
- await runtime2.createMemory(memory, type === "resource" ? "resources" : "tools", true);
851
+ await runtime.createMemory(memory, type === "resource" ? "resources" : "tools", true);
793
852
  }
794
853
  function buildMcpProviderData(servers) {
795
854
  const mcpData = {};
@@ -802,10 +861,12 @@ function buildMcpProviderData(servers) {
802
861
  };
803
862
  }
804
863
  for (const server of servers) {
864
+ const tools = {};
865
+ const resources = {};
805
866
  mcpData[server.name] = {
806
867
  status: server.status,
807
- tools: {},
808
- resources: {}
868
+ tools,
869
+ resources
809
870
  };
810
871
  textContent += `## Server: ${server.name} (${server.status})
811
872
 
@@ -815,11 +876,11 @@ function buildMcpProviderData(servers) {
815
876
 
816
877
  `;
817
878
  for (const tool of server.tools) {
818
- mcpData[server.name].tools[tool.name] = {
819
- description: tool.description || "No description available",
820
- inputSchema: tool.inputSchema || {}
879
+ tools[tool.name] = {
880
+ description: tool.description ?? "No description available",
881
+ inputSchema: tool.inputSchema
821
882
  };
822
- textContent += `- **${tool.name}**: ${tool.description || "No description available"}
883
+ textContent += `- **${tool.name}**: ${tool.description ?? "No description available"}
823
884
  `;
824
885
  }
825
886
  textContent += `
@@ -830,12 +891,12 @@ function buildMcpProviderData(servers) {
830
891
 
831
892
  `;
832
893
  for (const resource of server.resources) {
833
- mcpData[server.name].resources[resource.uri] = {
894
+ resources[resource.uri] = {
834
895
  name: resource.name,
835
- description: resource.description || "No description available",
896
+ description: resource.description ?? "No description available",
836
897
  mimeType: resource.mimeType
837
898
  };
838
- textContent += `- **${resource.name}** (${resource.uri}): ${resource.description || "No description available"}
899
+ textContent += `- **${resource.name}** (${resource.uri}): ${resource.description ?? "No description available"}
839
900
  `;
840
901
  }
841
902
  textContent += `
@@ -874,9 +935,9 @@ function processResourceResult(result, uri) {
874
935
  if (content.text) {
875
936
  resourceContent += content.text;
876
937
  } else if (content.blob) {
877
- resourceContent += `[Binary data - ${content.mimeType || "unknown type"}]`;
938
+ resourceContent += `[Binary data${content.mimeType ? ` - ${content.mimeType}` : ""}]`;
878
939
  }
879
- resourceMeta += `Resource: ${content.uri || uri}
940
+ resourceMeta += `Resource: ${content.uri ?? uri}
880
941
  `;
881
942
  if (content.mimeType) {
882
943
  resourceMeta += `Type: ${content.mimeType}
@@ -885,32 +946,32 @@ function processResourceResult(result, uri) {
885
946
  }
886
947
  return { resourceContent, resourceMeta };
887
948
  }
888
- function processToolResult(result, serverName, toolName, runtime2, messageEntityId) {
949
+ function processToolResult(result, serverName, toolName, runtime, messageEntityId) {
889
950
  let toolOutput = "";
890
951
  let hasAttachments = false;
891
952
  const attachments = [];
892
953
  for (const content of result.content) {
893
- if (content.type === "text") {
954
+ if (content.type === "text" && content.text) {
894
955
  toolOutput += content.text;
895
- } else if (content.type === "image") {
956
+ } else if (content.type === "image" && content.data && content.mimeType) {
896
957
  hasAttachments = true;
897
958
  attachments.push({
898
959
  contentType: getMimeTypeToContentType(content.mimeType),
899
960
  url: `data:${content.mimeType};base64,${content.data}`,
900
- id: import_core2.createUniqueUuid(runtime2, messageEntityId),
961
+ id: import_core2.createUniqueUuid(runtime, messageEntityId),
901
962
  title: "Generated image",
902
963
  source: `${serverName}/${toolName}`,
903
964
  description: "Tool-generated image",
904
965
  text: "Generated image"
905
966
  });
906
- } else if (content.type === "resource") {
967
+ } else if (content.type === "resource" && content.resource) {
907
968
  const resource = content.resource;
908
- if (resource && "text" in resource) {
969
+ if ("text" in resource && resource.text) {
909
970
  toolOutput += `
910
971
 
911
972
  Resource (${resource.uri}):
912
973
  ${resource.text}`;
913
- } else if (resource && "blob" in resource) {
974
+ } else if ("blob" in resource) {
914
975
  toolOutput += `
915
976
 
916
977
  Resource (${resource.uri}): [Binary data]`;
@@ -919,53 +980,49 @@ Resource (${resource.uri}): [Binary data]`;
919
980
  }
920
981
  return { toolOutput, hasAttachments, attachments };
921
982
  }
922
- async function handleResourceAnalysis(runtime2, message, uri, serverName, resourceContent, resourceMeta, callback) {
923
- await createMcpMemory(runtime2, message, "resource", serverName, resourceContent, {
983
+ async function handleResourceAnalysis(runtime, message, uri, serverName, resourceContent, resourceMeta, callback) {
984
+ await createMcpMemory(runtime, message, "resource", serverName, resourceContent, {
924
985
  uri,
925
986
  isResourceAccess: true
926
987
  });
927
- const analysisPrompt = createAnalysisPrompt(uri, message.content.text || "", resourceContent, resourceMeta);
928
- const analyzedResponse = await runtime2.useModel(import_core2.ModelType.TEXT_SMALL, {
988
+ const analysisPrompt = createAnalysisPrompt(uri, message.content.text ?? "", resourceContent, resourceMeta);
989
+ const analyzedResponse = await runtime.useModel(import_core2.ModelType.TEXT_SMALL, {
929
990
  prompt: analysisPrompt
930
991
  });
931
992
  if (callback) {
932
993
  await callback({
933
994
  text: analyzedResponse,
934
- thought: `I analyzed the content from the ${uri} resource on ${serverName} and crafted a thoughtful response that addresses the user's request while maintaining my conversational style.`,
935
995
  actions: ["READ_MCP_RESOURCE"]
936
996
  });
937
997
  }
938
998
  }
939
- async function handleToolResponse(runtime2, message, serverName, toolName, toolArgs, toolOutput, hasAttachments, attachments, state, mcpProvider, callback) {
940
- await createMcpMemory(runtime2, message, "tool", serverName, toolOutput, {
999
+ async function handleToolResponse(runtime, message, serverName, toolName, toolArgs, toolOutput, hasAttachments, attachments, state, mcpProvider, callback) {
1000
+ await createMcpMemory(runtime, message, "tool", serverName, toolOutput, {
941
1001
  toolName,
942
1002
  arguments: toolArgs,
943
1003
  isToolCall: true
944
1004
  });
945
- const reasoningPrompt = createReasoningPrompt(state, mcpProvider, toolName, serverName, message.content.text || "", toolOutput, hasAttachments);
946
- import_core2.logger.info({ reasoningPrompt }, "reasoning prompt");
947
- const reasonedResponse = await runtime2.useModel(import_core2.ModelType.TEXT_SMALL, {
1005
+ const reasoningPrompt = createReasoningPrompt(state, mcpProvider, toolName, serverName, message.content.text ?? "", toolOutput, hasAttachments);
1006
+ const reasonedResponse = await runtime.useModel(import_core2.ModelType.TEXT_SMALL, {
948
1007
  prompt: reasoningPrompt
949
1008
  });
950
- const agentId = message.agentId || runtime2.agentId;
1009
+ const agentId = message.agentId ?? runtime.agentId;
951
1010
  const replyMemory = {
952
1011
  entityId: agentId,
953
1012
  roomId: message.roomId,
954
1013
  worldId: message.worldId,
955
1014
  content: {
956
1015
  text: reasonedResponse,
957
- thought: `I analyzed the output from the ${toolName} tool on ${serverName} and crafted a thoughtful response that addresses the user's request while maintaining my conversational style.`,
958
1016
  actions: ["CALL_MCP_TOOL"],
959
- attachments: hasAttachments && attachments.length > 0 ? attachments : undefined
1017
+ attachments: hasAttachments && attachments.length > 0 ? [...attachments] : undefined
960
1018
  }
961
1019
  };
962
- await runtime2.createMemory(replyMemory, "messages");
1020
+ await runtime.createMemory(replyMemory, "messages");
963
1021
  if (callback) {
964
1022
  await callback({
965
1023
  text: reasonedResponse,
966
- thought: `I analyzed the output from the ${toolName} tool on ${serverName} and crafted a thoughtful response that addresses the user's request while maintaining my conversational style.`,
967
1024
  actions: ["CALL_MCP_TOOL"],
968
- attachments: hasAttachments && attachments.length > 0 ? attachments : undefined
1025
+ attachments: hasAttachments && attachments.length > 0 ? [...attachments] : undefined
969
1026
  });
970
1027
  }
971
1028
  return replyMemory;
@@ -973,7 +1030,6 @@ async function handleToolResponse(runtime2, message, serverName, toolName, toolA
973
1030
  async function sendInitialResponse(callback) {
974
1031
  if (callback) {
975
1032
  const responseContent = {
976
- thought: "The user is asking for information that can be found in an MCP resource. I will retrieve and analyze the appropriate resource.",
977
1033
  text: "I'll retrieve that information for you. Let me access the resource...",
978
1034
  actions: ["READ_MCP_RESOURCE"]
979
1035
  };
@@ -991,7 +1047,7 @@ function createAnalysisPrompt(uri, userMessage, resourceContent, resourceMeta) {
991
1047
  resourceMeta
992
1048
  }
993
1049
  };
994
- return import_core3.composePromptFromState({
1050
+ return import_core2.composePromptFromState({
995
1051
  state: enhancedState,
996
1052
  template: resourceAnalysisTemplate
997
1053
  });
@@ -1007,231 +1063,50 @@ function createReasoningPrompt(state, mcpProvider, toolName, serverName, userMes
1007
1063
  userMessage,
1008
1064
  toolOutput,
1009
1065
  hasAttachments
1010
- }
1011
- };
1012
- return import_core3.composePromptFromState({
1013
- state: enhancedState,
1014
- template: toolReasoningTemplate
1015
- });
1016
- }
1017
-
1018
- // src/utils/selection.ts
1019
- var import_core5 = require("@elizaos/core");
1020
-
1021
- // src/utils/json.ts
1022
- var import_ajv = __toESM(require("ajv"));
1023
- var import_json5 = __toESM(require("json5"));
1024
- function parseJSON(input) {
1025
- let cleanedInput = input.replace(/^```(?:json)?\s*|\s*```$/g, "").trim();
1026
- const firstBrace = cleanedInput.indexOf("{");
1027
- const lastBrace = cleanedInput.lastIndexOf("}");
1028
- if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {
1029
- cleanedInput = cleanedInput.substring(firstBrace, lastBrace + 1);
1030
- }
1031
- return import_json5.default.parse(cleanedInput);
1032
- }
1033
- var ajv = new import_ajv.default({
1034
- allErrors: true,
1035
- strict: false
1036
- });
1037
- function validateJsonSchema(data, schema) {
1038
- try {
1039
- const validate = ajv.compile(schema);
1040
- const valid = validate(data);
1041
- if (!valid) {
1042
- const errors = (validate.errors || []).map((err) => {
1043
- const path = err.instancePath ? `${err.instancePath.replace(/^\//, "")}` : "value";
1044
- return `${path}: ${err.message}`;
1045
- });
1046
- return { success: false, error: errors.join(", ") };
1047
- }
1048
- return { success: true, data };
1049
- } catch (error) {
1050
- return {
1051
- success: false,
1052
- error: `Schema validation error: ${error instanceof Error ? error.message : String(error)}`
1053
- };
1054
- }
1055
- }
1056
-
1057
- // src/utils/wrapper.ts
1058
- var import_core4 = require("@elizaos/core");
1059
- async function withModelRetry({
1060
- runtime: runtime2,
1061
- message,
1062
- state,
1063
- callback,
1064
- input,
1065
- validationFn,
1066
- createFeedbackPromptFn,
1067
- failureMsg,
1068
- retryCount = 0
1069
- }) {
1070
- const maxRetries = getMaxRetries(runtime2);
1071
- try {
1072
- import_core4.logger.info(`[WITH-MODEL-RETRY] Raw selection input:
1073
- ${input}`);
1074
- const parsedJson = typeof input === "string" ? parseJSON(input) : input;
1075
- import_core4.logger.debug(`[WITH-MODEL-RETRY] Parsed selection input:
1076
- ${JSON.stringify(parsedJson, null, 2)}`);
1077
- const validationResult = validationFn(parsedJson);
1078
- if (validationResult.success === false) {
1079
- throw new Error(validationResult.error);
1080
- }
1081
- return validationResult.data;
1082
- } catch (parseError) {
1083
- const errorMessage = parseError instanceof Error ? parseError.message : "Unknown parsing error";
1084
- import_core4.logger.error({ errorMessage }, `[WITH-MODEL-RETRY] Failed to parse response: ${errorMessage}`);
1085
- if (retryCount < maxRetries) {
1086
- import_core4.logger.debug(`[WITH-MODEL-RETRY] Retrying (attempt ${retryCount + 1}/${maxRetries})`);
1087
- const feedbackPrompt = createFeedbackPromptFn(input, errorMessage, state, message.content.text || "");
1088
- const retrySelection = await runtime2.useModel(import_core4.ModelType.OBJECT_LARGE, {
1089
- prompt: feedbackPrompt
1090
- });
1091
- return withModelRetry({
1092
- runtime: runtime2,
1093
- input: retrySelection,
1094
- validationFn,
1095
- message,
1096
- state,
1097
- createFeedbackPromptFn,
1098
- callback,
1099
- failureMsg,
1100
- retryCount: retryCount + 1
1101
- });
1102
- }
1103
- if (callback && failureMsg) {
1104
- await callback({
1105
- text: failureMsg,
1106
- thought: "Failed to parse response after multiple retries. Requesting clarification from user.",
1107
- actions: ["REPLY"]
1108
- });
1109
- }
1110
- return null;
1111
- }
1112
- }
1113
- function getMaxRetries(runtime2) {
1114
- try {
1115
- const settings = runtime2.getSetting("mcp");
1116
- if (settings && "maxRetries" in settings && settings.maxRetries !== undefined) {
1117
- const configValue = Number(settings.maxRetries);
1118
- if (!Number.isNaN(configValue) && configValue >= 0) {
1119
- import_core4.logger.debug(`[WITH-MODEL-RETRY] Using configured selection retries: ${configValue}`);
1120
- return configValue;
1121
- }
1122
- }
1123
- } catch (error) {
1124
- import_core4.logger.debug({ error: error instanceof Error ? error.message : String(error) }, "[WITH-MODEL-RETRY] Error reading selection retries config");
1125
- }
1126
- return DEFAULT_MAX_RETRIES;
1127
- }
1128
-
1129
- // src/templates/toolSelectionTemplate.ts
1130
- var toolSelectionNameTemplate = `
1131
- {{mcpProvider.text}}
1132
-
1133
- {{recentMessages}}
1134
-
1135
- # TASK: Select the Most Appropriate Tool and Server
1136
-
1137
- You must select the most appropriate tool from the list above to fulfill the user's request. Your response must be a valid JSON object with the required properties.
1138
-
1139
- ## CRITICAL INSTRUCTIONS
1140
- 1. Provide both "serverName" and "toolName" from the options listed above.
1141
- 2. Each name must match EXACTLY as shown in the list:
1142
- - Example (correct): "serverName": "github"
1143
- - Example (incorrect): "serverName": "GitHub", "Github", or variations
1144
- 3. Extract ACTUAL parameter values from the conversation context.
1145
- - Do not invent or use placeholders like "octocat" or "Hello-World" unless the user said so.
1146
- 4. Include a "reasoning" field explaining why the selected tool fits the request.
1147
- 5. If no tool is appropriate, respond with:
1148
- {
1149
- "noToolAvailable": true
1150
- }
1151
-
1152
- !!! YOUR RESPONSE MUST BE A VALID JSON OBJECT ONLY !!!
1153
-
1154
- CRITICAL: Your response must START with { and END with }. DO NOT include ANY text before or after the JSON.
1155
-
1156
- ## STRICT FORMAT REQUIREMENTS
1157
- - The response MUST be a single valid JSON object.
1158
- - DO NOT wrap the JSON in triple backticks (\`\`\`), code blocks, or include any explanatory text.
1159
- - DO NOT include comments (// or /* */) anywhere.
1160
- - DO NOT use placeholders (e.g., "replace with...", "example", "your...", etc.)
1161
- - ALL strings must use double quotes.
1162
-
1163
- ## CRITICAL NOTES
1164
- - All values must be fully grounded in user input or inferred contextually.
1165
- - No missing fields unless they are explicitly optional in the schema.
1166
- - All types must match the schema (strings, numbers, booleans).
1167
-
1168
- ## JSON OBJECT STRUCTURE
1169
- Your response MUST contain ONLY these top-level keys:
1170
- 1. "serverName" — The name of the server (e.g., "github", "notion")
1171
- 2. "toolName" — The name of the tool (e.g., "get_file_contents", "search")
1172
- 3. "reasoning" — A string explaining how the values were inferred from the conversation.
1173
- 4. "noToolAvailable" — A boolean indicating if no tool is available (true/false)
1174
-
1175
- ## EXAMPLE RESPONSE
1176
- {
1177
- "serverName": "github",
1178
- "toolName": "get_file_contents",
1179
- "reasoning": "The user wants to retrieve the README from the facebook/react repository.",
1180
- "noToolAvailable": false
1066
+ }
1067
+ };
1068
+ return import_core2.composePromptFromState({
1069
+ state: enhancedState,
1070
+ template: toolReasoningTemplate
1071
+ });
1181
1072
  }
1182
1073
 
1183
- ## REMINDERS
1184
- - Use "github" as serverName for GitHub tools.
1185
- - Use "notion" as serverName for Notion tools.
1186
- - For search and knowledge-based tasks, MCP tools are often appropriate.
1187
-
1188
- REMEMBER: This output will be parsed directly as JSON. If the format is incorrect, the operation will fail.
1189
- `;
1190
- var toolSelectionArgumentTemplate = `
1191
- {{recentMessages}}
1192
-
1193
- # TASK: Generate a Strictly Valid JSON Object for Tool Execution
1194
-
1195
- You have chosen the "{{toolSelectionName.toolName}}" tool from the "{{toolSelectionName.serverName}}" server to address the user's request.
1196
- The reasoning behind this selection is: "{{toolSelectionName.reasoning}}"
1197
-
1198
- ## CRITICAL INSTRUCTIONS
1199
- 1. Ensure the "toolArguments" object strictly adheres to the structure and requirements defined in the schema.
1200
- 2. All parameter values must be extracted from the conversation context and must be concrete, usable values.
1201
- 3. Avoid placeholders or generic terms unless explicitly provided by the user.
1202
-
1203
- !!! YOUR RESPONSE MUST BE A VALID JSON OBJECT ONLY !!!
1204
-
1205
- ## STRICT FORMAT REQUIREMENTS
1206
- - The response MUST be a single valid JSON object.
1207
- - DO NOT wrap the JSON in triple backticks (\`\`\`), code blocks, or include any explanatory text.
1208
- - DO NOT include comments (// or /* */) anywhere.
1209
- - DO NOT use placeholders (e.g., "replace with...", "example", "your...", etc.)
1210
- - ALL strings must use double quotes
1211
-
1212
- ## CRITICAL NOTES
1213
- - All values must be fully grounded in user input or inferred contextually.
1214
- - No missing fields unless they are explicitly optional in the schema.
1215
- - All types must match the schema (strings, numbers, booleans).
1216
-
1217
- ## JSON OBJECT STRUCTURE
1218
- Your response MUST contain ONLY these two top-level keys:
1219
- 1. "toolArguments" — An object matching the input schema: {{toolInputSchema}}
1220
- 2. "reasoning" — A string explaining how the values were inferred from the conversation.
1074
+ // src/utils/selection.ts
1075
+ var import_core4 = require("@elizaos/core");
1221
1076
 
1222
- ## EXAMPLE RESPONSE
1223
- {
1224
- "toolArguments": {
1225
- "owner": "facebook",
1226
- "repo": "react",
1227
- "path": "README.md",
1228
- "branch": "main"
1229
- },
1230
- "reasoning": "The user wants to see the README from the facebook/react repository based on our conversation."
1077
+ // src/utils/json.ts
1078
+ var import_ajv = __toESM(require("ajv"));
1079
+ var import_json5 = __toESM(require("json5"));
1080
+ function parseJSON(input) {
1081
+ let cleanedInput = input.replace(/^```(?:json)?\s*|\s*```$/g, "").trim();
1082
+ const firstBrace = cleanedInput.indexOf("{");
1083
+ const lastBrace = cleanedInput.lastIndexOf("}");
1084
+ if (firstBrace === -1 || lastBrace === -1 || lastBrace <= firstBrace) {
1085
+ throw new Error("No valid JSON object found in input");
1086
+ }
1087
+ cleanedInput = cleanedInput.substring(firstBrace, lastBrace + 1);
1088
+ return import_json5.default.parse(cleanedInput);
1089
+ }
1090
+ var ajv = new import_ajv.default({
1091
+ allErrors: true,
1092
+ strict: false
1093
+ });
1094
+ function formatAjvErrors(errors) {
1095
+ return errors.map((err) => {
1096
+ const path = err.instancePath ? `${err.instancePath.replace(/^\//, "")}` : "value";
1097
+ return `${path}: ${err.message ?? "validation failed"}`;
1098
+ }).join(", ");
1099
+ }
1100
+ function validateJsonSchema(data, schema) {
1101
+ const validate = ajv.compile(schema);
1102
+ const valid = validate(data);
1103
+ if (!valid) {
1104
+ const errors = validate.errors ?? [];
1105
+ const errorMessage = formatAjvErrors(errors);
1106
+ return { success: false, error: errorMessage };
1107
+ }
1108
+ return { success: true, data };
1231
1109
  }
1232
-
1233
- REMEMBER: Your response will be parsed directly as JSON. If it fails to parse, the operation will fail completely.
1234
- `;
1235
1110
 
1236
1111
  // src/utils/schemas.ts
1237
1112
  var toolSelectionNameSchema = {
@@ -1273,7 +1148,7 @@ function validateToolSelectionName(parsed, state) {
1273
1148
  return { success: false, error: basicResult.error };
1274
1149
  }
1275
1150
  const data = basicResult.data;
1276
- const mcpData = state.values.mcp || {};
1151
+ const mcpData = state.values.mcp ?? {};
1277
1152
  const server = mcpData[data.serverName];
1278
1153
  if (!server || server.status !== "connected") {
1279
1154
  return {
@@ -1308,19 +1183,46 @@ function validateToolSelectionArgument(parsed, toolInputSchema) {
1308
1183
  function validateResourceSelection(selection) {
1309
1184
  return validateJsonSchema(selection, ResourceSelectionSchema);
1310
1185
  }
1186
+ function createToolSelectionFeedbackPrompt(originalResponse, errorMessage, composedState, userMessage) {
1187
+ let toolsDescription = "";
1188
+ const mcpData = composedState.values.mcp;
1189
+ if (mcpData) {
1190
+ for (const [serverName, server] of Object.entries(mcpData)) {
1191
+ if (server.status !== "connected")
1192
+ continue;
1193
+ const tools = server.tools;
1194
+ if (tools) {
1195
+ for (const [toolName, tool] of Object.entries(tools)) {
1196
+ toolsDescription += `Tool: ${toolName} (Server: ${serverName})
1197
+ `;
1198
+ toolsDescription += `Description: ${tool.description ?? "No description available"}
1199
+
1200
+ `;
1201
+ }
1202
+ }
1203
+ }
1204
+ }
1205
+ return createFeedbackPrompt(originalResponse, errorMessage, "tool", toolsDescription, userMessage);
1206
+ }
1311
1207
  function createResourceSelectionFeedbackPrompt(originalResponse, errorMessage, composedState, userMessage) {
1312
1208
  let resourcesDescription = "";
1313
- for (const [serverName, server] of Object.entries(composedState.values.mcp || {})) {
1314
- if (server.status !== "connected")
1315
- continue;
1316
- for (const [uri, resource] of Object.entries(server.resources || {})) {
1317
- resourcesDescription += `Resource: ${uri} (Server: ${serverName})
1209
+ const mcpData = composedState.values.mcp;
1210
+ if (mcpData) {
1211
+ for (const [serverName, server] of Object.entries(mcpData)) {
1212
+ if (server.status !== "connected")
1213
+ continue;
1214
+ const resources = server.resources;
1215
+ if (resources) {
1216
+ for (const [uri, resource] of Object.entries(resources)) {
1217
+ resourcesDescription += `Resource: ${uri} (Server: ${serverName})
1318
1218
  `;
1319
- resourcesDescription += `Name: ${resource.name || "No name available"}
1219
+ resourcesDescription += `Name: ${resource.name ?? "No name available"}
1320
1220
  `;
1321
- resourcesDescription += `Description: ${resource.description || "No description available"}
1221
+ resourcesDescription += `Description: ${resource.description ?? "No description available"}
1322
1222
 
1323
1223
  `;
1224
+ }
1225
+ }
1324
1226
  }
1325
1227
  }
1326
1228
  return createFeedbackPrompt(originalResponse, errorMessage, "resource", resourcesDescription, userMessage);
@@ -1338,38 +1240,90 @@ ${itemsDescription}
1338
1240
  User request: ${userMessage}`;
1339
1241
  }
1340
1242
 
1243
+ // src/utils/wrapper.ts
1244
+ var import_core3 = require("@elizaos/core");
1245
+ async function withModelRetry({
1246
+ runtime,
1247
+ message,
1248
+ state,
1249
+ callback,
1250
+ input,
1251
+ validationFn,
1252
+ createFeedbackPromptFn,
1253
+ failureMsg,
1254
+ retryCount = 0
1255
+ }) {
1256
+ const maxRetries = getMaxRetries(runtime);
1257
+ const parsedJson = typeof input === "string" ? parseJSON(input) : input;
1258
+ const validationResult = validationFn(parsedJson);
1259
+ if (validationResult.success) {
1260
+ return validationResult.data;
1261
+ }
1262
+ const errorMessage = validationResult.error;
1263
+ if (retryCount < maxRetries) {
1264
+ const feedbackPrompt = createFeedbackPromptFn(input, errorMessage, state, message.content.text ?? "");
1265
+ const retrySelection = await runtime.useModel(import_core3.ModelType.OBJECT_LARGE, {
1266
+ prompt: feedbackPrompt
1267
+ });
1268
+ return withModelRetry({
1269
+ runtime,
1270
+ input: retrySelection,
1271
+ validationFn,
1272
+ message,
1273
+ state,
1274
+ createFeedbackPromptFn,
1275
+ callback,
1276
+ failureMsg,
1277
+ retryCount: retryCount + 1
1278
+ });
1279
+ }
1280
+ if (callback && failureMsg) {
1281
+ await callback({
1282
+ text: failureMsg,
1283
+ actions: ["REPLY"]
1284
+ });
1285
+ }
1286
+ return null;
1287
+ }
1288
+ function getMaxRetries(runtime) {
1289
+ const rawSettings = runtime.getSetting("mcp");
1290
+ if (rawSettings && typeof rawSettings === "object") {
1291
+ const settings = rawSettings;
1292
+ if (typeof settings.maxRetries === "number" && settings.maxRetries >= 0) {
1293
+ return settings.maxRetries;
1294
+ }
1295
+ }
1296
+ return DEFAULT_MAX_RETRIES;
1297
+ }
1298
+
1341
1299
  // src/utils/selection.ts
1342
1300
  async function createToolSelectionName({
1343
- runtime: runtime2,
1301
+ runtime,
1344
1302
  state,
1345
1303
  message,
1346
1304
  callback,
1347
1305
  mcpProvider
1348
1306
  }) {
1349
- const toolSelectionPrompt = import_core5.composePromptFromState({
1307
+ const toolSelectionPrompt = import_core4.composePromptFromState({
1350
1308
  state: { ...state, values: { ...state.values, mcpProvider } },
1351
1309
  template: toolSelectionNameTemplate
1352
1310
  });
1353
- import_core5.logger.debug(`[SELECTION] Tool Selection Name Prompt:
1354
- ${toolSelectionPrompt}`);
1355
- const toolSelectionName = await runtime2.useModel(import_core5.ModelType.TEXT_LARGE, {
1311
+ const toolSelectionName = await runtime.useModel(import_core4.ModelType.TEXT_LARGE, {
1356
1312
  prompt: toolSelectionPrompt
1357
1313
  });
1358
- import_core5.logger.debug(`[SELECTION] Tool Selection Name Response:
1359
- ${toolSelectionName}`);
1360
1314
  return await withModelRetry({
1361
- runtime: runtime2,
1315
+ runtime,
1362
1316
  message,
1363
1317
  state,
1364
1318
  callback,
1365
1319
  input: toolSelectionName,
1366
1320
  validationFn: (parsed) => validateToolSelectionName(parsed, state),
1367
- createFeedbackPromptFn: (originalResponse, errorMessage, state2, userMessage) => createToolSelectionFeedbackPrompt(originalResponse, errorMessage, state2, userMessage),
1321
+ createFeedbackPromptFn: (originalResponse, errorMessage, composedState, userMessage) => createToolSelectionFeedbackPrompt(typeof originalResponse === "string" ? originalResponse : JSON.stringify(originalResponse), errorMessage, composedState, userMessage),
1368
1322
  failureMsg: "I'm having trouble figuring out the best way to help with your request."
1369
1323
  });
1370
1324
  }
1371
1325
  async function createToolSelectionArgument({
1372
- runtime: runtime2,
1326
+ runtime,
1373
1327
  state,
1374
1328
  message,
1375
1329
  callback,
@@ -1377,14 +1331,19 @@ async function createToolSelectionArgument({
1377
1331
  toolSelectionName
1378
1332
  }) {
1379
1333
  if (!toolSelectionName) {
1380
- import_core5.logger.warn("[SELECTION] Tool selection name is not provided. Cannot create tool selection argument.");
1381
- return null;
1334
+ throw new Error("Tool selection name is required to create tool selection argument");
1382
1335
  }
1383
1336
  const { serverName, toolName } = toolSelectionName;
1384
- const toolInputSchema = mcpProvider.data.mcp[serverName].tools[toolName].inputSchema;
1385
- import_core5.logger.trace(`[SELECTION] Tool Input Schema:
1386
- ${JSON.stringify({ toolInputSchema }, null, 2)}`);
1387
- const toolSelectionArgumentPrompt = import_core5.composePromptFromState({
1337
+ const serverData = mcpProvider.data.mcp[serverName];
1338
+ if (!serverData) {
1339
+ throw new Error(`Server "${serverName}" not found in MCP provider data`);
1340
+ }
1341
+ const toolData = serverData.tools[toolName];
1342
+ if (!toolData) {
1343
+ throw new Error(`Tool "${toolName}" not found on server "${serverName}"`);
1344
+ }
1345
+ const toolInputSchema = toolData.inputSchema ?? {};
1346
+ const toolSelectionArgumentPrompt = import_core4.composePromptFromState({
1388
1347
  state: {
1389
1348
  ...state,
1390
1349
  values: {
@@ -1395,81 +1354,20 @@ ${JSON.stringify({ toolInputSchema }, null, 2)}`);
1395
1354
  },
1396
1355
  template: toolSelectionArgumentTemplate
1397
1356
  });
1398
- import_core5.logger.debug(`[SELECTION] Tool Selection Prompt:
1399
- ${toolSelectionArgumentPrompt}`);
1400
- const toolSelectionArgument = await runtime2.useModel(import_core5.ModelType.TEXT_LARGE, {
1357
+ const toolSelectionArgument = await runtime.useModel(import_core4.ModelType.TEXT_LARGE, {
1401
1358
  prompt: toolSelectionArgumentPrompt
1402
1359
  });
1403
- import_core5.logger.debug(`[SELECTION] Tool Selection Argument Response:
1404
- ${toolSelectionArgument}`);
1405
1360
  return await withModelRetry({
1406
- runtime: runtime2,
1361
+ runtime,
1407
1362
  message,
1408
1363
  state,
1409
1364
  callback,
1410
1365
  input: toolSelectionArgument,
1411
- validationFn: (parsed) => validateToolSelectionArgument(parsed, state),
1412
- createFeedbackPromptFn: (originalResponse, errorMessage, state2, userMessage) => createToolSelectionFeedbackPrompt(originalResponse, errorMessage, state2, userMessage),
1366
+ validationFn: (parsed) => validateToolSelectionArgument(parsed, toolInputSchema),
1367
+ createFeedbackPromptFn: (originalResponse, errorMessage, composedState, userMessage) => createToolSelectionFeedbackPrompt(typeof originalResponse === "string" ? originalResponse : JSON.stringify(originalResponse), errorMessage, composedState, userMessage),
1413
1368
  failureMsg: "I'm having trouble figuring out the best way to help with your request."
1414
1369
  });
1415
1370
  }
1416
- function createToolSelectionFeedbackPrompt(originalResponse, errorMessage, state, userMessage) {
1417
- let toolsDescription = "";
1418
- for (const [serverName, server] of Object.entries(state.values.mcp || {})) {
1419
- if (server.status !== "connected")
1420
- continue;
1421
- for (const [toolName, tool] of Object.entries(server.tools || {})) {
1422
- toolsDescription += `Tool: ${toolName} (Server: ${serverName})
1423
- `;
1424
- toolsDescription += `Description: ${tool.description || "No description available"}
1425
-
1426
- `;
1427
- }
1428
- }
1429
- const feedbackPrompt = createFeedbackPrompt2(originalResponse, errorMessage, "tool", toolsDescription, userMessage);
1430
- import_core5.logger.debug(`[SELECTION] Tool Selection Feedback Prompt:
1431
- ${feedbackPrompt}`);
1432
- return feedbackPrompt;
1433
- }
1434
- function createFeedbackPrompt2(originalResponse, errorMessage, itemType, itemsDescription, userMessage) {
1435
- return `Error parsing JSON: ${errorMessage}
1436
-
1437
- Your original response:
1438
- ${originalResponse}
1439
-
1440
- Please try again with valid JSON for ${itemType} selection.
1441
- Available ${itemType}s:
1442
- ${itemsDescription}
1443
-
1444
- User request: ${userMessage}`;
1445
- }
1446
-
1447
- // src/utils/handler.ts
1448
- async function handleNoToolAvailable(callback, toolSelection) {
1449
- const responseText = "I don't have a specific tool that can help with that request. Let me try to assist you directly instead.";
1450
- const thoughtText = "No appropriate MCP tool available for this request. Falling back to direct assistance.";
1451
- if (callback && toolSelection?.noToolAvailable) {
1452
- await callback({
1453
- text: responseText,
1454
- thought: thoughtText,
1455
- actions: ["REPLY"]
1456
- });
1457
- }
1458
- return {
1459
- text: responseText,
1460
- values: {
1461
- success: true,
1462
- noToolAvailable: true,
1463
- fallbackToDirectAssistance: true
1464
- },
1465
- data: {
1466
- actionName: "CALL_MCP_TOOL",
1467
- noToolAvailable: true,
1468
- reason: toolSelection?.reasoning || "No appropriate tool available"
1469
- },
1470
- success: true
1471
- };
1472
- }
1473
1371
 
1474
1372
  // src/actions/callToolAction.ts
1475
1373
  var callToolAction = {
@@ -1487,36 +1385,34 @@ var callToolAction = {
1487
1385
  "INVOKE_MCP_TOOL"
1488
1386
  ],
1489
1387
  description: "Calls a tool from an MCP server to perform a specific task",
1490
- validate: async (runtime2, _message, _state) => {
1491
- const mcpService = runtime2.getService(MCP_SERVICE_NAME);
1388
+ validate: async (runtime, _message, _state) => {
1389
+ const mcpService = runtime.getService(MCP_SERVICE_NAME);
1492
1390
  if (!mcpService)
1493
1391
  return false;
1494
1392
  const servers = mcpService.getServers();
1495
1393
  return servers.length > 0 && servers.some((server) => server.status === "connected" && server.tools && server.tools.length > 0);
1496
1394
  },
1497
- handler: async (runtime2, message, _state, _options, callback) => {
1498
- const composedState = await runtime2.composeState(message, ["RECENT_MESSAGES", "MCP"]);
1499
- const mcpService = runtime2.getService(MCP_SERVICE_NAME);
1395
+ handler: async (runtime, message, _state, _options, callback) => {
1396
+ const composedState = await runtime.composeState(message, ["RECENT_MESSAGES", "MCP"]);
1397
+ const mcpService = runtime.getService(MCP_SERVICE_NAME);
1500
1398
  if (!mcpService) {
1501
1399
  throw new Error("MCP service not available");
1502
1400
  }
1503
1401
  const mcpProvider = mcpService.getProviderData();
1504
1402
  try {
1505
1403
  const toolSelectionName = await createToolSelectionName({
1506
- runtime: runtime2,
1404
+ runtime,
1507
1405
  state: composedState,
1508
1406
  message,
1509
1407
  callback,
1510
1408
  mcpProvider
1511
1409
  });
1512
1410
  if (!toolSelectionName || toolSelectionName.noToolAvailable) {
1513
- import_core6.logger.warn("[NO_TOOL_AVAILABLE] No appropriate tool available for the request");
1514
1411
  return await handleNoToolAvailable(callback, toolSelectionName);
1515
1412
  }
1516
- const { serverName, toolName, reasoning } = toolSelectionName;
1517
- import_core6.logger.info(`[CALLING] Calling tool "${serverName}/${toolName}" on server with reasoning: "${reasoning}"`);
1413
+ const { serverName, toolName } = toolSelectionName;
1518
1414
  const toolSelectionArgument = await createToolSelectionArgument({
1519
- runtime: runtime2,
1415
+ runtime,
1520
1416
  state: composedState,
1521
1417
  message,
1522
1418
  callback,
@@ -1524,14 +1420,11 @@ var callToolAction = {
1524
1420
  toolSelectionName
1525
1421
  });
1526
1422
  if (!toolSelectionArgument) {
1527
- import_core6.logger.warn("[NO_TOOL_SELECTION_ARGUMENT] No appropriate tool selection argument available");
1528
1423
  return await handleNoToolAvailable(callback, toolSelectionName);
1529
1424
  }
1530
- import_core6.logger.info(`[SELECTED] Tool Selection result:
1531
- ${JSON.stringify(toolSelectionArgument, null, 2)}`);
1532
1425
  const result = await mcpService.callTool(serverName, toolName, toolSelectionArgument.toolArguments);
1533
- const { toolOutput, hasAttachments, attachments } = processToolResult(result, serverName, toolName, runtime2, message.entityId);
1534
- const replyMemory = await handleToolResponse(runtime2, message, serverName, toolName, toolSelectionArgument.toolArguments, toolOutput, hasAttachments, attachments, composedState, mcpProvider, callback);
1426
+ const { toolOutput, hasAttachments, attachments } = processToolResult(result, serverName, toolName, runtime, message.entityId);
1427
+ const replyMemory = await handleToolResponse(runtime, message, serverName, toolName, toolSelectionArgument.toolArguments, toolOutput, hasAttachments, attachments, composedState, mcpProvider, callback);
1535
1428
  return {
1536
1429
  text: `Successfully called tool: ${serverName}/${toolName}. Reasoned response: ${replyMemory.content.text}`,
1537
1430
  values: {
@@ -1546,15 +1439,15 @@ ${JSON.stringify(toolSelectionArgument, null, 2)}`);
1546
1439
  actionName: "CALL_MCP_TOOL",
1547
1440
  serverName,
1548
1441
  toolName,
1549
- toolArguments: toolSelectionArgument.toolArguments,
1442
+ toolArgumentsJson: JSON.stringify(toolSelectionArgument.toolArguments),
1550
1443
  reasoning: toolSelectionName.reasoning,
1551
1444
  output: toolOutput,
1552
- attachments: attachments || []
1445
+ attachmentCount: attachments?.length ?? 0
1553
1446
  },
1554
1447
  success: true
1555
1448
  };
1556
1449
  } catch (error) {
1557
- return await handleMcpError(composedState, mcpProvider, error, runtime2, message, "tool", callback);
1450
+ return await handleMcpError(composedState, mcpProvider, error, runtime, message, "tool", callback);
1558
1451
  }
1559
1452
  },
1560
1453
  examples: [
@@ -1586,69 +1479,25 @@ Climate change refers to long-term shifts in temperatures and weather patterns.
1586
1479
  };
1587
1480
 
1588
1481
  // src/actions/readResourceAction.ts
1589
- var import_core7 = require("@elizaos/core");
1590
-
1591
- // src/templates/resourceSelectionTemplate.ts
1592
- var resourceSelectionTemplate = `
1593
- {{{mcpProvider.text}}}
1594
-
1595
- {{{recentMessages}}}
1596
-
1597
- # Prompt
1598
-
1599
- You are an intelligent assistant helping select the right resource to address a user's request.
1600
-
1601
- CRITICAL INSTRUCTIONS:
1602
- 1. You MUST specify both a valid serverName AND uri from the list above
1603
- 2. The serverName value should match EXACTLY the server name shown in parentheses (Server: X)
1604
- CORRECT: "serverName": "github" (if the server is called "github")
1605
- WRONG: "serverName": "GitHub" or "Github" or any other variation
1606
- 3. The uri value should match EXACTLY the resource uri listed
1607
- CORRECT: "uri": "weather://San Francisco/current" (if that's the exact uri)
1608
- WRONG: "uri": "weather://sanfrancisco/current" or any variation
1609
- 4. Identify the user's information need from the conversation context
1610
- 5. Select the most appropriate resource based on its description and the request
1611
- 6. If no resource seems appropriate, output {"noResourceAvailable": true}
1612
-
1613
- !!! YOUR RESPONSE MUST BE A VALID JSON OBJECT ONLY !!!
1614
-
1615
- STRICT FORMAT REQUIREMENTS:
1616
- - NO code block formatting (NO backticks or \`\`\`)
1617
- - NO comments (NO // or /* */)
1618
- - NO placeholders like "replace with...", "example", "your...", "actual", etc.
1619
- - Every parameter value must be a concrete, usable value (not instructions to replace)
1620
- - Use proper JSON syntax with double quotes for strings
1621
- - NO explanatory text before or after the JSON object
1622
-
1623
- EXAMPLE RESPONSE:
1624
- {
1625
- "serverName": "weather-server",
1626
- "uri": "weather://San Francisco/current",
1627
- "reasoning": "Based on the conversation, the user is asking about current weather in San Francisco. This resource provides up-to-date weather information for that city."
1628
- }
1629
-
1630
- REMEMBER: Your response will be parsed directly as JSON. If it fails to parse, the operation will fail completely!
1631
- `;
1632
-
1633
- // src/actions/readResourceAction.ts
1482
+ var import_core5 = require("@elizaos/core");
1634
1483
  function createResourceSelectionPrompt(composedState, userMessage) {
1635
- const mcpData = composedState.values.mcp || {};
1484
+ const mcpData = composedState.values.mcp ?? {};
1636
1485
  const serverNames = Object.keys(mcpData);
1637
1486
  let resourcesDescription = "";
1638
1487
  for (const serverName of serverNames) {
1639
1488
  const server = mcpData[serverName];
1640
1489
  if (server.status !== "connected")
1641
1490
  continue;
1642
- const resourceUris = Object.keys(server.resources || {});
1491
+ const resourceUris = Object.keys(server.resources ?? {});
1643
1492
  for (const uri of resourceUris) {
1644
1493
  const resource = server.resources[uri];
1645
1494
  resourcesDescription += `Resource: ${uri} (Server: ${serverName})
1646
1495
  `;
1647
- resourcesDescription += `Name: ${resource.name || "No name available"}
1496
+ resourcesDescription += `Name: ${resource.name ?? "No name available"}
1648
1497
  `;
1649
- resourcesDescription += `Description: ${resource.description || "No description available"}
1498
+ resourcesDescription += `Description: ${resource.description ?? "No description available"}
1650
1499
  `;
1651
- resourcesDescription += `MIME Type: ${resource.mimeType || "Not specified"}
1500
+ resourcesDescription += `MIME Type: ${resource.mimeType ?? "Not specified"}
1652
1501
 
1653
1502
  `;
1654
1503
  }
@@ -1661,7 +1510,7 @@ function createResourceSelectionPrompt(composedState, userMessage) {
1661
1510
  userMessage
1662
1511
  }
1663
1512
  };
1664
- return import_core7.composePromptFromState({
1513
+ return import_core5.composePromptFromState({
1665
1514
  state: enhancedState,
1666
1515
  template: resourceSelectionTemplate
1667
1516
  });
@@ -1679,44 +1528,42 @@ var readResourceAction = {
1679
1528
  "ACCESS_MCP_RESOURCE"
1680
1529
  ],
1681
1530
  description: "Reads a resource from an MCP server",
1682
- validate: async (runtime2, _message, _state) => {
1683
- const mcpService = runtime2.getService(MCP_SERVICE_NAME);
1531
+ validate: async (runtime, _message, _state) => {
1532
+ const mcpService = runtime.getService(MCP_SERVICE_NAME);
1684
1533
  if (!mcpService)
1685
1534
  return false;
1686
1535
  const servers = mcpService.getServers();
1687
1536
  return servers.length > 0 && servers.some((server) => server.status === "connected" && server.resources && server.resources.length > 0);
1688
1537
  },
1689
- handler: async (runtime2, message, _state, _options, callback) => {
1690
- const composedState = await runtime2.composeState(message, ["RECENT_MESSAGES", "MCP"]);
1691
- const mcpService = runtime2.getService(MCP_SERVICE_NAME);
1538
+ handler: async (runtime, message, _state, _options, callback) => {
1539
+ const composedState = await runtime.composeState(message, ["RECENT_MESSAGES", "MCP"]);
1540
+ const mcpService = runtime.getService(MCP_SERVICE_NAME);
1692
1541
  if (!mcpService) {
1693
1542
  throw new Error("MCP service not available");
1694
1543
  }
1695
1544
  const mcpProvider = mcpService.getProviderData();
1696
1545
  try {
1697
1546
  await sendInitialResponse(callback);
1698
- const resourceSelectionPrompt = createResourceSelectionPrompt(composedState, message.content.text || "");
1699
- const resourceSelection = await runtime2.useModel(import_core7.ModelType.TEXT_SMALL, {
1547
+ const resourceSelectionPrompt = createResourceSelectionPrompt(composedState, message.content.text ?? "");
1548
+ const resourceSelection = await runtime.useModel(import_core5.ModelType.TEXT_SMALL, {
1700
1549
  prompt: resourceSelectionPrompt
1701
1550
  });
1702
1551
  const parsedSelection = await withModelRetry({
1703
- runtime: runtime2,
1552
+ runtime,
1704
1553
  state: composedState,
1705
1554
  message,
1706
1555
  callback,
1707
1556
  input: resourceSelection,
1708
1557
  validationFn: (data) => validateResourceSelection(data),
1709
- createFeedbackPromptFn: (originalResponse, errorMessage, state, userMessage) => createResourceSelectionFeedbackPrompt(originalResponse, errorMessage, state, userMessage),
1558
+ createFeedbackPromptFn: (originalResponse, errorMessage, state, userMessage) => createResourceSelectionFeedbackPrompt(typeof originalResponse === "string" ? originalResponse : JSON.stringify(originalResponse), errorMessage, state, userMessage),
1710
1559
  failureMsg: `I'm having trouble finding the resource you're looking for. Could you provide more details about what you need?`,
1711
1560
  retryCount: 0
1712
1561
  });
1713
1562
  if (!parsedSelection || parsedSelection.noResourceAvailable) {
1714
1563
  const responseText = "I don't have a specific resource that contains the information you're looking for. Let me try to assist you directly instead.";
1715
- const thoughtText = "No appropriate MCP resource available for this request. Falling back to direct assistance.";
1716
1564
  if (callback && parsedSelection?.noResourceAvailable) {
1717
1565
  await callback({
1718
1566
  text: responseText,
1719
- thought: thoughtText,
1720
1567
  actions: ["REPLY"]
1721
1568
  });
1722
1569
  }
@@ -1730,17 +1577,15 @@ var readResourceAction = {
1730
1577
  data: {
1731
1578
  actionName: "READ_MCP_RESOURCE",
1732
1579
  noResourceAvailable: true,
1733
- reason: parsedSelection?.reasoning || "No appropriate resource available"
1580
+ reason: parsedSelection?.reasoning ?? "No appropriate resource available"
1734
1581
  },
1735
1582
  success: true
1736
1583
  };
1737
1584
  }
1738
- const { serverName, uri, reasoning } = parsedSelection;
1739
- import_core7.logger.debug(`Selected resource "${uri}" on server "${serverName}" because: ${reasoning}`);
1585
+ const { serverName, uri } = parsedSelection;
1740
1586
  const result = await mcpService.readResource(serverName, uri);
1741
- import_core7.logger.debug(`Read resource ${uri} from server ${serverName}`);
1742
1587
  const { resourceContent, resourceMeta } = processResourceResult(result, uri);
1743
- await handleResourceAnalysis(runtime2, message, uri, serverName, resourceContent, resourceMeta, callback);
1588
+ await handleResourceAnalysis(runtime, message, uri, serverName, resourceContent, resourceMeta, callback);
1744
1589
  return {
1745
1590
  text: `Successfully read resource: ${uri}`,
1746
1591
  values: {
@@ -1753,14 +1598,14 @@ var readResourceAction = {
1753
1598
  actionName: "READ_MCP_RESOURCE",
1754
1599
  serverName,
1755
1600
  uri,
1756
- reasoning,
1601
+ reasoning: parsedSelection?.reasoning,
1757
1602
  resourceMeta,
1758
- contentLength: resourceContent?.length || 0
1603
+ contentLength: resourceContent?.length ?? 0
1759
1604
  },
1760
1605
  success: true
1761
1606
  };
1762
1607
  } catch (error) {
1763
- return await handleMcpError(composedState, mcpProvider, error, runtime2, message, "resource", callback);
1608
+ return await handleMcpError(composedState, mcpProvider, error, runtime, message, "resource", callback);
1764
1609
  }
1765
1610
  },
1766
1611
  examples: [
@@ -1768,7 +1613,7 @@ var readResourceAction = {
1768
1613
  {
1769
1614
  name: "{{user}}",
1770
1615
  content: {
1771
- text: "Can you get the documentation about installing ElizaOS?"
1616
+ text: "Can you get the documentation about installing elizaOS?"
1772
1617
  }
1773
1618
  },
1774
1619
  {
@@ -1781,7 +1626,7 @@ var readResourceAction = {
1781
1626
  {
1782
1627
  name: "{{assistant}}",
1783
1628
  content: {
1784
- text: `ElizaOS installation is straightforward. You'll need Node.js 23+ and Git installed. For Windows users, WSL 2 is required. The quickest way to get started is by cloning the ElizaOS starter repository with \`git clone https://github.com/elizaos/eliza-starter.git\`, then run \`cd eliza-starter && cp .env.example .env && bun i && bun run build && bun start\`. This will set up a development environment with the core features enabled. After starting, you can access the web interface at http://localhost:3000 to interact with your agent.`,
1629
+ text: `elizaOS installation is straightforward. You'll need Node.js 23+ and Git installed. For Windows users, WSL 2 is required. The quickest way to get started is by cloning the elizaOS starter repository with \`git clone https://github.com/elizaos/eliza-starter.git\`, then run \`cd eliza-starter && cp .env.example .env && bun i && bun run build && bun start\`. This will set up a development environment with the core features enabled. After starting, you can access the web interface at http://localhost:3000 to interact with your agent.`,
1785
1630
  actions: ["READ_MCP_RESOURCE"]
1786
1631
  }
1787
1632
  }
@@ -1793,25 +1638,52 @@ var readResourceAction = {
1793
1638
  var provider = {
1794
1639
  name: "MCP",
1795
1640
  description: "Information about connected MCP servers, tools, and resources",
1796
- get: async (runtime2, _message, _state) => {
1797
- const mcpService = runtime2.getService(MCP_SERVICE_NAME);
1641
+ get: async (runtime, _message, _state) => {
1642
+ const mcpService = runtime.getService(MCP_SERVICE_NAME);
1798
1643
  if (!mcpService) {
1799
1644
  return {
1800
- values: { mcp: {} },
1801
- data: { mcp: {} },
1645
+ values: {},
1646
+ data: {},
1802
1647
  text: "No MCP servers are available."
1803
1648
  };
1804
1649
  }
1805
- return mcpService.getProviderData();
1650
+ const providerData = mcpService.getProviderData();
1651
+ return {
1652
+ values: { mcpServers: JSON.stringify(providerData.values.mcp) },
1653
+ data: { mcpServerCount: Object.keys(providerData.data.mcp).length },
1654
+ text: providerData.text
1655
+ };
1806
1656
  }
1807
1657
  };
1808
1658
 
1809
1659
  // src/service.ts
1810
- var import_core8 = require("@elizaos/core");
1660
+ var import_core6 = require("@elizaos/core");
1811
1661
  var import_client = require("@modelcontextprotocol/sdk/client/index.js");
1812
1662
  var import_sse = require("@modelcontextprotocol/sdk/client/sse.js");
1813
1663
  var import_stdio = require("@modelcontextprotocol/sdk/client/stdio.js");
1814
- class McpService extends import_core8.Service {
1664
+ // src/tool-compatibility/index.ts
1665
+ function createMcpToolCompatibilitySync(runtime) {
1666
+ const modelInfo = detectModelProvider(runtime);
1667
+ switch (modelInfo.provider) {
1668
+ case "openai": {
1669
+ const { OpenAIMcpCompatibility: OpenAIMcpCompatibility2 } = (init_openai(), __toCommonJS(exports_openai));
1670
+ return new OpenAIMcpCompatibility2(modelInfo);
1671
+ }
1672
+ case "anthropic": {
1673
+ const { AnthropicMcpCompatibility: AnthropicMcpCompatibility2 } = (init_anthropic(), __toCommonJS(exports_anthropic));
1674
+ return new AnthropicMcpCompatibility2(modelInfo);
1675
+ }
1676
+ case "google": {
1677
+ const { GoogleMcpCompatibility: GoogleMcpCompatibility2 } = (init_google(), __toCommonJS(exports_google));
1678
+ return new GoogleMcpCompatibility2(modelInfo);
1679
+ }
1680
+ default:
1681
+ return null;
1682
+ }
1683
+ }
1684
+
1685
+ // src/service.ts
1686
+ class McpService extends import_core6.Service {
1815
1687
  static serviceType = MCP_SERVICE_NAME;
1816
1688
  capabilityDescription = "Enables the agent to interact with MCP (Model Context Protocol) servers";
1817
1689
  connections = new Map;
@@ -1825,13 +1697,12 @@ class McpService extends import_core8.Service {
1825
1697
  toolCompatibility = null;
1826
1698
  compatibilityInitialized = false;
1827
1699
  initializationPromise = null;
1828
- constructor(runtime2) {
1829
- super(runtime2);
1830
- import_core8.logger.info("[McpService] Constructor called, starting initialization...");
1700
+ constructor(runtime) {
1701
+ super(runtime);
1831
1702
  this.initializationPromise = this.initializeMcpServers();
1832
1703
  }
1833
- static async start(runtime2) {
1834
- const service = new McpService(runtime2);
1704
+ static async start(runtime) {
1705
+ const service = new McpService(runtime);
1835
1706
  if (service.initializationPromise) {
1836
1707
  await service.initializationPromise;
1837
1708
  }
@@ -1856,70 +1727,36 @@ class McpService extends import_core8.Service {
1856
1727
  this.connectionStates.clear();
1857
1728
  }
1858
1729
  async initializeMcpServers() {
1859
- import_core8.logger.info("[McpService] Starting MCP server initialization...");
1860
- try {
1861
- const mcpSettings = this.getMcpSettings();
1862
- const serverCount = mcpSettings?.servers ? Object.keys(mcpSettings.servers).length : 0;
1863
- const serverNames = mcpSettings?.servers ? Object.keys(mcpSettings.servers) : [];
1864
- import_core8.logger.info(`[McpService] Getting MCP settings... hasSettings=${!!mcpSettings} hasServers=${!!mcpSettings?.servers} serverCount=${serverCount} servers=${JSON.stringify(serverNames)}`);
1865
- if (!mcpSettings || !mcpSettings.servers) {
1866
- import_core8.logger.info("[McpService] No MCP servers configured.");
1867
- this.mcpProvider = buildMcpProviderData([]);
1868
- return;
1869
- }
1870
- if (Object.keys(mcpSettings.servers).length === 0) {
1871
- import_core8.logger.info("[McpService] MCP settings exist but no servers configured.");
1872
- this.mcpProvider = buildMcpProviderData([]);
1873
- return;
1874
- }
1875
- import_core8.logger.info(`[McpService] Connecting to ${Object.keys(mcpSettings.servers).length} MCP servers: ${JSON.stringify(Object.keys(mcpSettings.servers))}`);
1876
- const connectionStartTime = Date.now();
1877
- await this.updateServerConnections(mcpSettings.servers);
1878
- const connectionDuration = Date.now() - connectionStartTime;
1879
- const servers = this.getServers();
1880
- const connectedServers = servers.filter((s) => s.status === "connected");
1881
- const failedServers = servers.filter((s) => s.status !== "connected");
1882
- if (connectedServers.length > 0) {
1883
- const toolCounts = connectedServers.map((s) => `${s.name}:${s.tools?.length || 0}tools`).join(", ");
1884
- import_core8.logger.info(`[McpService] ✓ Successfully connected ${connectedServers.length}/${servers.length} servers in ${connectionDuration}ms: ${toolCounts}`);
1885
- }
1886
- if (failedServers.length > 0) {
1887
- const failedDetails = failedServers.map((s) => `${s.name}(${s.error || "unknown error"})`).join(", ");
1888
- import_core8.logger.warn(`[McpService] ⚠️ Failed to connect to ${failedServers.length}/${servers.length} servers: ${failedDetails}`);
1889
- }
1890
- if (connectedServers.length === 0 && servers.length > 0) {
1891
- import_core8.logger.error(`[McpService] ❌ ALL MCP servers failed to connect! MCP tools will NOT be available.`);
1892
- }
1893
- this.mcpProvider = buildMcpProviderData(servers);
1894
- const mcpDataKeys = Object.keys(this.mcpProvider.data?.mcp || {});
1895
- import_core8.logger.info(`[McpService] MCP provider data built: ${mcpDataKeys.length} server(s) available`);
1896
- } catch (error) {
1897
- import_core8.logger.error({ error: error instanceof Error ? error.message : String(error) }, "❌ Failed to initialize MCP servers - MCP tools will NOT be available");
1730
+ const mcpSettings = this.getMcpSettings();
1731
+ if (!mcpSettings || !mcpSettings.servers || Object.keys(mcpSettings.servers).length === 0) {
1898
1732
  this.mcpProvider = buildMcpProviderData([]);
1733
+ return;
1899
1734
  }
1735
+ await this.updateServerConnections(mcpSettings.servers);
1736
+ const servers = this.getServers();
1737
+ this.mcpProvider = buildMcpProviderData(servers);
1900
1738
  }
1901
1739
  getMcpSettings() {
1902
- let settings = this.runtime.getSetting("mcp");
1903
- import_core8.logger.info(`[McpService] getSetting("mcp") result: type=${typeof settings} isNull=${settings === null} hasServers=${!!settings?.servers}`);
1904
- if (!settings || typeof settings === "object" && !settings.servers) {
1905
- const characterSettings = this.runtime.character?.settings;
1906
- if (characterSettings?.mcp) {
1907
- import_core8.logger.info("[McpService] Found MCP settings in character.settings.mcp (fallback)");
1908
- settings = characterSettings.mcp;
1909
- }
1910
- }
1911
- if (!settings || typeof settings === "object" && !settings.servers) {
1912
- const runtimeSettings = this.runtime.settings;
1913
- if (runtimeSettings?.mcp) {
1914
- import_core8.logger.info("[McpService] Found MCP settings in runtime.settings.mcp (fallback)");
1915
- settings = runtimeSettings.mcp;
1740
+ const rawSettings = this.runtime.getSetting("mcp");
1741
+ let settings = null;
1742
+ if (rawSettings && typeof rawSettings === "object" && !Array.isArray(rawSettings)) {
1743
+ const parsed = rawSettings;
1744
+ if ("servers" in parsed && typeof parsed.servers === "object" && parsed.servers !== null) {
1745
+ settings = parsed;
1746
+ }
1747
+ }
1748
+ if (!settings || !settings.servers) {
1749
+ const characterSettings = this.runtime.character.settings;
1750
+ if (characterSettings && typeof characterSettings === "object" && "mcp" in characterSettings) {
1751
+ const characterMcpSettings = characterSettings.mcp;
1752
+ if (characterMcpSettings && typeof characterMcpSettings === "object" && "servers" in characterMcpSettings) {
1753
+ settings = characterMcpSettings;
1754
+ }
1916
1755
  }
1917
1756
  }
1918
1757
  if (settings && typeof settings === "object" && settings.servers) {
1919
- import_core8.logger.info(`[McpService] MCP settings found with ${Object.keys(settings.servers).length} server(s)`);
1920
1758
  return settings;
1921
1759
  }
1922
- import_core8.logger.info("[McpService] No valid MCP settings found");
1923
1760
  return;
1924
1761
  }
1925
1762
  async updateServerConnections(serverConfigs) {
@@ -1928,30 +1765,18 @@ class McpService extends import_core8.Service {
1928
1765
  for (const name of currentNames) {
1929
1766
  if (!newNames.has(name)) {
1930
1767
  await this.deleteConnection(name);
1931
- import_core8.logger.info(`Deleted MCP server: ${name}`);
1932
1768
  }
1933
1769
  }
1934
1770
  const connectionPromises = Object.entries(serverConfigs).map(async ([name, config]) => {
1935
1771
  const currentConnection = this.connections.get(name);
1936
1772
  if (!currentConnection) {
1937
- try {
1938
- await this.initializeConnection(name, config);
1939
- import_core8.logger.info(`✓ Connected to MCP server: ${name}`);
1940
- } catch (error) {
1941
- import_core8.logger.error({ error: error instanceof Error ? error.message : String(error), serverName: name }, `✗ Failed to connect to new MCP server ${name}`);
1942
- }
1773
+ await this.initializeConnection(name, config);
1943
1774
  } else if (JSON.stringify(config) !== currentConnection.server.config) {
1944
- try {
1945
- await this.deleteConnection(name);
1946
- await this.initializeConnection(name, config);
1947
- import_core8.logger.info(`✓ Reconnected MCP server with updated config: ${name}`);
1948
- } catch (error) {
1949
- import_core8.logger.error({ error: error instanceof Error ? error.message : String(error), serverName: name }, `✗ Failed to reconnect MCP server ${name}`);
1950
- }
1775
+ await this.deleteConnection(name);
1776
+ await this.initializeConnection(name, config);
1951
1777
  }
1952
1778
  });
1953
1779
  await Promise.allSettled(connectionPromises);
1954
- import_core8.logger.info(`[McpService] All server connection attempts completed`);
1955
1780
  }
1956
1781
  async initializeConnection(name, config) {
1957
1782
  await this.deleteConnection(name);
@@ -1961,58 +1786,47 @@ class McpService extends import_core8.Service {
1961
1786
  consecutivePingFailures: 0
1962
1787
  };
1963
1788
  this.connectionStates.set(name, state);
1964
- try {
1965
- const client = new import_client.Client({ name: "ElizaOS", version: "1.0.0" }, { capabilities: {} });
1966
- const transport = config.type === "stdio" ? await this.buildStdioClientTransport(name, config) : await this.buildHttpClientTransport(name, config);
1967
- const connection = {
1968
- server: {
1969
- name,
1970
- config: JSON.stringify(config),
1971
- status: "connecting"
1972
- },
1973
- client,
1974
- transport
1975
- };
1976
- this.connections.set(name, connection);
1977
- this.setupTransportHandlers(name, connection, state);
1978
- await client.connect(transport);
1979
- const capabilities = client.getServerCapabilities();
1980
- import_core8.logger.debug(`[${name}] Server capabilities:`, JSON.stringify(capabilities || {}));
1981
- const tools = await this.fetchToolsList(name);
1982
- const resources = capabilities?.resources ? await this.fetchResourcesList(name) : [];
1983
- const resourceTemplates = capabilities?.resources ? await this.fetchResourceTemplatesList(name) : [];
1984
- connection.server = {
1985
- status: "connected",
1789
+ const client = new import_client.Client({ name: "elizaOS", version: "1.0.0" }, { capabilities: {} });
1790
+ const transport = config.type === "stdio" ? await this.buildStdioClientTransport(name, config) : await this.buildHttpClientTransport(name, config);
1791
+ const connection = {
1792
+ server: {
1986
1793
  name,
1987
1794
  config: JSON.stringify(config),
1988
- error: "",
1989
- tools,
1990
- resources,
1991
- resourceTemplates
1992
- };
1993
- state.status = "connected";
1994
- state.lastConnected = new Date;
1995
- state.reconnectAttempts = 0;
1996
- state.consecutivePingFailures = 0;
1997
- this.startPingMonitoring(name);
1998
- import_core8.logger.info(`Successfully connected to MCP server: ${name}`);
1999
- } catch (error) {
2000
- state.status = "disconnected";
2001
- state.lastError = error instanceof Error ? error : new Error(String(error));
2002
- this.handleDisconnection(name, error);
2003
- throw error;
2004
- }
1795
+ status: "connecting"
1796
+ },
1797
+ client,
1798
+ transport
1799
+ };
1800
+ this.connections.set(name, connection);
1801
+ this.setupTransportHandlers(name, connection, state);
1802
+ await client.connect(transport);
1803
+ const capabilities = client.getServerCapabilities();
1804
+ const tools = await this.fetchToolsList(name);
1805
+ const resources = capabilities?.resources ? await this.fetchResourcesList(name) : [];
1806
+ const resourceTemplates = capabilities?.resources ? await this.fetchResourceTemplatesList(name) : [];
1807
+ connection.server = {
1808
+ status: "connected",
1809
+ name,
1810
+ config: JSON.stringify(config),
1811
+ error: "",
1812
+ tools,
1813
+ resources,
1814
+ resourceTemplates
1815
+ };
1816
+ state.status = "connected";
1817
+ state.lastConnected = new Date;
1818
+ state.reconnectAttempts = 0;
1819
+ state.consecutivePingFailures = 0;
1820
+ this.startPingMonitoring(name);
2005
1821
  }
2006
- setupTransportHandlers(name, connection, state) {
1822
+ setupTransportHandlers(name, connection, _state) {
2007
1823
  const config = JSON.parse(connection.server.config);
2008
1824
  const isHttpTransport = config.type !== "stdio";
2009
1825
  connection.transport.onerror = async (error) => {
2010
- const errorMessage = error?.message || String(error);
1826
+ const errorMessage = error?.message ?? String(error);
2011
1827
  const isExpectedTimeout = isHttpTransport && (errorMessage === "undefined" || errorMessage === "" || errorMessage.includes("SSE error") || errorMessage.includes("timeout"));
2012
- if (isExpectedTimeout) {
2013
- import_core8.logger.debug({ serverName: name }, `SSE connection timeout for "${name}" (expected, will reconnect)`);
2014
- } else {
2015
- import_core8.logger.error({ error, serverName: name }, `Transport error for "${name}"`);
1828
+ if (!isExpectedTimeout) {
1829
+ import_core6.logger.error({ error, serverName: name }, `Transport error for "${name}"`);
2016
1830
  connection.server.status = "disconnected";
2017
1831
  this.appendErrorMessage(connection, error.message);
2018
1832
  }
@@ -2021,10 +1835,7 @@ class McpService extends import_core8.Service {
2021
1835
  }
2022
1836
  };
2023
1837
  connection.transport.onclose = async () => {
2024
- if (isHttpTransport) {
2025
- import_core8.logger.debug({ serverName: name }, `SSE connection closed for "${name}" (stateless, will reconnect on demand)`);
2026
- } else {
2027
- import_core8.logger.warn({ serverName: name }, `Transport closed for "${name}"`);
1838
+ if (!isHttpTransport) {
2028
1839
  connection.server.status = "disconnected";
2029
1840
  this.handleDisconnection(name, new Error("Transport closed"));
2030
1841
  }
@@ -2037,7 +1848,6 @@ class McpService extends import_core8.Service {
2037
1848
  const config = JSON.parse(connection.server.config);
2038
1849
  const isHttpTransport = config.type !== "stdio";
2039
1850
  if (isHttpTransport) {
2040
- import_core8.logger.debug(`[McpService] Skipping ping monitoring for HTTP server: ${name}`);
2041
1851
  return;
2042
1852
  }
2043
1853
  const state = this.connectionStates.get(name);
@@ -2047,7 +1857,7 @@ class McpService extends import_core8.Service {
2047
1857
  clearInterval(state.pingInterval);
2048
1858
  state.pingInterval = setInterval(() => {
2049
1859
  this.sendPing(name).catch((err) => {
2050
- import_core8.logger.warn({ error: err instanceof Error ? err.message : String(err), serverName: name }, `Ping failed for ${name}`);
1860
+ import_core6.logger.warn({ error: err.message, serverName: name }, `Ping failed for ${name}`);
2051
1861
  this.handlePingFailure(name, err);
2052
1862
  });
2053
1863
  }, this.pingConfig.intervalMs);
@@ -2070,7 +1880,6 @@ class McpService extends import_core8.Service {
2070
1880
  return;
2071
1881
  state.consecutivePingFailures++;
2072
1882
  if (state.consecutivePingFailures >= this.pingConfig.failuresBeforeDisconnect) {
2073
- import_core8.logger.warn(`Ping failures exceeded for ${name}, disconnecting and attempting reconnect.`);
2074
1883
  this.handleDisconnection(name, error);
2075
1884
  }
2076
1885
  }
@@ -2085,19 +1894,17 @@ class McpService extends import_core8.Service {
2085
1894
  if (state.reconnectTimeout)
2086
1895
  clearTimeout(state.reconnectTimeout);
2087
1896
  if (state.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
2088
- import_core8.logger.error(`Max reconnect attempts reached for ${name}. Giving up.`);
2089
1897
  return;
2090
1898
  }
2091
- const delay = INITIAL_RETRY_DELAY * Math.pow(BACKOFF_MULTIPLIER, state.reconnectAttempts);
1899
+ const delay = INITIAL_RETRY_DELAY * BACKOFF_MULTIPLIER ** state.reconnectAttempts;
2092
1900
  state.reconnectTimeout = setTimeout(async () => {
2093
1901
  state.reconnectAttempts++;
2094
- import_core8.logger.info(`Attempting to reconnect to ${name} (attempt ${state.reconnectAttempts})...`);
2095
- const config = this.connections.get(name)?.server.config;
1902
+ const connection = this.connections.get(name);
1903
+ const config = connection?.server?.config;
2096
1904
  if (config) {
2097
1905
  try {
2098
1906
  await this.initializeConnection(name, JSON.parse(config));
2099
1907
  } catch (err) {
2100
- import_core8.logger.error({ error: err instanceof Error ? err.message : String(err), serverName: name }, `Reconnect attempt failed for ${name}`);
2101
1908
  this.handleDisconnection(name, err);
2102
1909
  }
2103
1910
  }
@@ -2106,12 +1913,8 @@ class McpService extends import_core8.Service {
2106
1913
  async deleteConnection(name) {
2107
1914
  const connection = this.connections.get(name);
2108
1915
  if (connection) {
2109
- try {
2110
- await connection.transport.close();
2111
- await connection.client.close();
2112
- } catch (error) {
2113
- import_core8.logger.error({ error: error instanceof Error ? error.message : String(error), serverName: name }, `Failed to close transport for ${name}`);
2114
- }
1916
+ await connection.transport.close();
1917
+ await connection.client.close();
2115
1918
  this.connections.delete(name);
2116
1919
  }
2117
1920
  const state = this.connectionStates.get(name);
@@ -2132,7 +1935,7 @@ class McpService extends import_core8.Service {
2132
1935
  }
2133
1936
  return new import_stdio.StdioClientTransport({
2134
1937
  command: config.command,
2135
- args: config.args,
1938
+ args: config.args ? [...config.args] : undefined,
2136
1939
  env: {
2137
1940
  ...config.env,
2138
1941
  ...process.env.PATH ? { PATH: process.env.PATH } : {}
@@ -2145,9 +1948,6 @@ class McpService extends import_core8.Service {
2145
1948
  if (!config.url) {
2146
1949
  throw new Error(`Missing URL for HTTP MCP server ${name}`);
2147
1950
  }
2148
- if (config.type === "sse") {
2149
- import_core8.logger.warn(`Server "${name}": "sse" transport type is deprecated. Use "streamable-http" or "http" instead for the modern Streamable HTTP transport.`);
2150
- }
2151
1951
  return new import_sse.SSEClientTransport(new URL(config.url));
2152
1952
  }
2153
1953
  appendErrorMessage(connection, error) {
@@ -2156,62 +1956,38 @@ ${error}` : error;
2156
1956
  connection.server.error = newError;
2157
1957
  }
2158
1958
  async fetchToolsList(serverName) {
2159
- try {
2160
- const connection = this.getServerConnection(serverName);
2161
- if (!connection) {
2162
- return [];
2163
- }
2164
- const response = await connection.client.listTools();
2165
- const tools = (response?.tools || []).map((tool) => {
2166
- let processedTool = { ...tool };
2167
- if (tool.inputSchema) {
2168
- try {
2169
- if (!this.compatibilityInitialized) {
2170
- this.initializeToolCompatibility();
2171
- }
2172
- processedTool.inputSchema = this.applyToolCompatibility(tool.inputSchema);
2173
- import_core8.logger.debug(`Applied tool compatibility for: ${tool.name} on server: ${serverName}`);
2174
- } catch (error) {
2175
- import_core8.logger.warn({ error, toolName: tool.name, serverName }, `Tool compatibility failed for ${tool.name} on ${serverName}`);
2176
- }
2177
- }
2178
- return processedTool;
2179
- });
2180
- import_core8.logger.info(`Fetched ${tools.length} tools for ${serverName}`);
2181
- for (const tool of tools) {
2182
- import_core8.logger.info(`[${serverName}] ${tool.name}: ${tool.description}`);
2183
- }
2184
- return tools;
2185
- } catch (error) {
2186
- import_core8.logger.error({ error: error instanceof Error ? error.message : String(error), serverName }, `Failed to fetch tools for ${serverName}`);
1959
+ const connection = this.getServerConnection(serverName);
1960
+ if (!connection) {
2187
1961
  return [];
2188
1962
  }
1963
+ const response = await connection.client.listTools();
1964
+ const tools = (response?.tools ?? []).map((tool) => {
1965
+ const processedTool = { ...tool };
1966
+ if (tool.inputSchema) {
1967
+ if (!this.compatibilityInitialized) {
1968
+ this.initializeToolCompatibility();
1969
+ }
1970
+ processedTool.inputSchema = this.applyToolCompatibility(tool.inputSchema);
1971
+ }
1972
+ return processedTool;
1973
+ });
1974
+ return tools;
2189
1975
  }
2190
1976
  async fetchResourcesList(serverName) {
2191
- try {
2192
- const connection = this.getServerConnection(serverName);
2193
- if (!connection) {
2194
- return [];
2195
- }
2196
- const response = await connection.client.listResources();
2197
- return response?.resources || [];
2198
- } catch (error) {
2199
- import_core8.logger.warn({ error: error instanceof Error ? error.message : String(error), serverName }, `No resources found for ${serverName}`);
1977
+ const connection = this.getServerConnection(serverName);
1978
+ if (!connection) {
2200
1979
  return [];
2201
1980
  }
1981
+ const response = await connection.client.listResources();
1982
+ return response?.resources ?? [];
2202
1983
  }
2203
1984
  async fetchResourceTemplatesList(serverName) {
2204
- try {
2205
- const connection = this.getServerConnection(serverName);
2206
- if (!connection) {
2207
- return [];
2208
- }
2209
- const response = await connection.client.listResourceTemplates();
2210
- return response?.resourceTemplates || [];
2211
- } catch (error) {
2212
- import_core8.logger.warn({ error: error instanceof Error ? error.message : String(error), serverName }, `No resource templates found for ${serverName}`);
1985
+ const connection = this.getServerConnection(serverName);
1986
+ if (!connection) {
2213
1987
  return [];
2214
1988
  }
1989
+ const response = await connection.client.listResourceTemplates();
1990
+ return response?.resourceTemplates ?? [];
2215
1991
  }
2216
1992
  getServers() {
2217
1993
  return Array.from(this.connections.values()).filter((conn) => !conn.server.disabled).map((conn) => conn.server);
@@ -2228,13 +2004,14 @@ ${error}` : error;
2228
2004
  throw new Error(`Server "${serverName}" is disabled`);
2229
2005
  }
2230
2006
  let timeout = DEFAULT_MCP_TIMEOUT_SECONDS;
2231
- try {
2232
- const config = JSON.parse(connection.server.config);
2233
- timeout = config.timeoutInMillis || DEFAULT_MCP_TIMEOUT_SECONDS;
2234
- } catch (error) {
2235
- import_core8.logger.error({ error: error instanceof Error ? error.message : String(error), serverName }, `Failed to parse timeout configuration for server ${serverName}`);
2007
+ const config = JSON.parse(connection.server.config);
2008
+ if (config.type === "stdio" && config.timeoutInMillis) {
2009
+ timeout = config.timeoutInMillis;
2236
2010
  }
2237
- const result = await connection.client.callTool({ name: toolName, arguments: toolArguments }, undefined, { timeout });
2011
+ const result = await connection.client.callTool({
2012
+ name: toolName,
2013
+ arguments: toolArguments ? { ...toolArguments } : undefined
2014
+ }, undefined, { timeout });
2238
2015
  if (!result.content) {
2239
2016
  throw new Error("Invalid tool result: missing content array");
2240
2017
  }
@@ -2252,19 +2029,12 @@ ${error}` : error;
2252
2029
  }
2253
2030
  async restartConnection(serverName) {
2254
2031
  const connection = this.connections.get(serverName);
2255
- const config = connection?.server.config;
2032
+ const config = connection?.server?.config;
2256
2033
  if (config) {
2257
- import_core8.logger.info(`Restarting ${serverName} MCP server...`);
2258
2034
  connection.server.status = "connecting";
2259
2035
  connection.server.error = "";
2260
- try {
2261
- await this.deleteConnection(serverName);
2262
- await this.initializeConnection(serverName, JSON.parse(config));
2263
- import_core8.logger.info(`${serverName} MCP server connected`);
2264
- } catch (error) {
2265
- import_core8.logger.error({ error: error instanceof Error ? error.message : String(error), serverName }, `Failed to restart connection for ${serverName}`);
2266
- throw new Error(`Failed to connect to ${serverName} MCP server`);
2267
- }
2036
+ await this.deleteConnection(serverName);
2037
+ await this.initializeConnection(serverName, JSON.parse(config));
2268
2038
  }
2269
2039
  }
2270
2040
  initializeToolCompatibility() {
@@ -2272,11 +2042,6 @@ ${error}` : error;
2272
2042
  return;
2273
2043
  this.toolCompatibility = createMcpToolCompatibilitySync(this.runtime);
2274
2044
  this.compatibilityInitialized = true;
2275
- if (this.toolCompatibility) {
2276
- import_core8.logger.info(`Tool compatibility enabled`);
2277
- } else {
2278
- import_core8.logger.info(`No tool compatibility needed`);
2279
- }
2280
2045
  }
2281
2046
  applyToolCompatibility(toolSchema) {
2282
2047
  if (!this.compatibilityInitialized) {
@@ -2285,12 +2050,7 @@ ${error}` : error;
2285
2050
  if (!this.toolCompatibility || !toolSchema) {
2286
2051
  return toolSchema;
2287
2052
  }
2288
- try {
2289
- return this.toolCompatibility.transformToolSchema(toolSchema);
2290
- } catch (error) {
2291
- import_core8.logger.warn({ error }, `Tool compatibility transformation failed`);
2292
- return toolSchema;
2293
- }
2053
+ return this.toolCompatibility.transformToolSchema(toolSchema);
2294
2054
  }
2295
2055
  }
2296
2056
 
@@ -2299,7 +2059,7 @@ var mcpPlugin = {
2299
2059
  name: "mcp",
2300
2060
  description: "Plugin for connecting to MCP (Model Context Protocol) servers",
2301
2061
  init: async (_config, _runtime) => {
2302
- import_core9.logger.info("Initializing MCP plugin...");
2062
+ import_core7.logger.info("Initializing MCP plugin...");
2303
2063
  },
2304
2064
  services: [McpService],
2305
2065
  actions: [callToolAction, readResourceAction],
@@ -2307,4 +2067,4 @@ var mcpPlugin = {
2307
2067
  };
2308
2068
  var src_default = mcpPlugin;
2309
2069
 
2310
- //# debugId=06B19883B039D4B264756E2164756E21
2070
+ //# debugId=67D36987F069B88A64756E2164756E21