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