@mozilla-ai/mcpd 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -6
- package/dist/client.d.ts +36 -47
- package/dist/client.d.ts.map +1 -1
- package/dist/functionBuilder.d.ts +6 -0
- package/dist/functionBuilder.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +241 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +241 -45
- package/dist/index.mjs.map +1 -1
- package/dist/logger.d.ts +93 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/types.d.ts +106 -19
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -941,6 +941,14 @@ class FunctionBuilder {
|
|
|
941
941
|
getCacheSize() {
|
|
942
942
|
return this.#functionCache.size;
|
|
943
943
|
}
|
|
944
|
+
/**
|
|
945
|
+
* Get all cached functions.
|
|
946
|
+
*
|
|
947
|
+
* @returns Array of all cached agent functions, or empty array if cache is empty
|
|
948
|
+
*/
|
|
949
|
+
getCachedFunctions() {
|
|
950
|
+
return Array.from(this.#functionCache.values());
|
|
951
|
+
}
|
|
944
952
|
}
|
|
945
953
|
const API_BASE = "/api/v1";
|
|
946
954
|
const SERVERS_BASE = `${API_BASE}/servers`;
|
|
@@ -971,13 +979,76 @@ const API_PATHS = {
|
|
|
971
979
|
HEALTH_ALL: HEALTH_SERVERS_BASE,
|
|
972
980
|
HEALTH_SERVER: (serverName) => `${HEALTH_SERVERS_BASE}/${encodeURIComponent(serverName)}`
|
|
973
981
|
};
|
|
982
|
+
const LogLevels = {
|
|
983
|
+
OFF: "off"
|
|
984
|
+
};
|
|
985
|
+
const ranks = {
|
|
986
|
+
trace: 5,
|
|
987
|
+
debug: 10,
|
|
988
|
+
info: 20,
|
|
989
|
+
warn: 30,
|
|
990
|
+
error: 40,
|
|
991
|
+
off: 1e3
|
|
992
|
+
};
|
|
993
|
+
function resolve(raw) {
|
|
994
|
+
const candidate = raw?.toLowerCase();
|
|
995
|
+
return candidate && candidate in ranks ? candidate : LogLevels.OFF;
|
|
996
|
+
}
|
|
997
|
+
function getLevel() {
|
|
998
|
+
return resolve(
|
|
999
|
+
typeof process !== "undefined" ? process.env.MCPD_LOG_LEVEL : void 0
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
function defaultLogger() {
|
|
1003
|
+
return {
|
|
1004
|
+
trace: (...args) => {
|
|
1005
|
+
const lvl = getLevel();
|
|
1006
|
+
if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.trace)
|
|
1007
|
+
console.trace(...args);
|
|
1008
|
+
},
|
|
1009
|
+
debug: (...args) => {
|
|
1010
|
+
const lvl = getLevel();
|
|
1011
|
+
if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.debug)
|
|
1012
|
+
console.debug(...args);
|
|
1013
|
+
},
|
|
1014
|
+
info: (...args) => {
|
|
1015
|
+
const lvl = getLevel();
|
|
1016
|
+
if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.info)
|
|
1017
|
+
console.info(...args);
|
|
1018
|
+
},
|
|
1019
|
+
warn: (...args) => {
|
|
1020
|
+
const lvl = getLevel();
|
|
1021
|
+
if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.warn)
|
|
1022
|
+
console.warn(...args);
|
|
1023
|
+
},
|
|
1024
|
+
error: (...args) => {
|
|
1025
|
+
const lvl = getLevel();
|
|
1026
|
+
if (lvl !== LogLevels.OFF && ranks[lvl] <= ranks.error)
|
|
1027
|
+
console.error(...args);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
function createLogger(impl) {
|
|
1032
|
+
const base = defaultLogger();
|
|
1033
|
+
return {
|
|
1034
|
+
trace: impl?.trace ?? base.trace,
|
|
1035
|
+
debug: impl?.debug ?? base.debug,
|
|
1036
|
+
info: impl?.info ?? base.info,
|
|
1037
|
+
warn: impl?.warn ?? base.warn,
|
|
1038
|
+
error: impl?.error ?? base.error
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
const REQUEST_TIMEOUT_SECONDS = 30;
|
|
1042
|
+
const SERVER_HEALTH_CACHE_TTL_SECONDS = 10;
|
|
974
1043
|
const SERVER_HEALTH_CACHE_MAXSIZE = 100;
|
|
1044
|
+
const TOOL_SEPARATOR = "__";
|
|
975
1045
|
class McpdClient {
|
|
976
1046
|
#endpoint;
|
|
977
1047
|
#apiKey;
|
|
978
1048
|
#timeout;
|
|
979
1049
|
#serverHealthCache;
|
|
980
1050
|
#functionBuilder;
|
|
1051
|
+
#logger;
|
|
981
1052
|
#cacheableExceptions = /* @__PURE__ */ new Set([
|
|
982
1053
|
ServerNotFoundError,
|
|
983
1054
|
ServerUnhealthyError,
|
|
@@ -993,14 +1064,18 @@ class McpdClient {
|
|
|
993
1064
|
* @param options - Configuration options for the client
|
|
994
1065
|
*/
|
|
995
1066
|
constructor(options) {
|
|
1067
|
+
const toMs = (s) => s * 1e3;
|
|
996
1068
|
this.#endpoint = options.apiEndpoint.replace(/\/$/, "");
|
|
997
1069
|
this.#apiKey = options.apiKey;
|
|
998
|
-
this.#timeout = options.timeout ??
|
|
999
|
-
const healthCacheTtlMs = (
|
|
1070
|
+
this.#timeout = options.timeout ?? toMs(REQUEST_TIMEOUT_SECONDS);
|
|
1071
|
+
const healthCacheTtlMs = toMs(
|
|
1072
|
+
options.healthCacheTtl ?? SERVER_HEALTH_CACHE_TTL_SECONDS
|
|
1073
|
+
);
|
|
1000
1074
|
this.#serverHealthCache = createCache({
|
|
1001
1075
|
max: SERVER_HEALTH_CACHE_MAXSIZE,
|
|
1002
1076
|
ttl: healthCacheTtlMs
|
|
1003
1077
|
});
|
|
1078
|
+
this.#logger = createLogger(options.logger);
|
|
1004
1079
|
this.servers = new ServersNamespace({
|
|
1005
1080
|
performCall: this.#performCall.bind(this),
|
|
1006
1081
|
getTools: this.#getToolsByServer.bind(this),
|
|
@@ -1017,8 +1092,15 @@ class McpdClient {
|
|
|
1017
1092
|
*
|
|
1018
1093
|
* @param path - The API path (e.g., '/servers', '/servers/{server_name}/tools')
|
|
1019
1094
|
* @param options - Request options
|
|
1095
|
+
*
|
|
1020
1096
|
* @returns The JSON response from the daemon
|
|
1097
|
+
*
|
|
1098
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1099
|
+
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1100
|
+
* @throws {TimeoutError} If the request times out
|
|
1021
1101
|
* @throws {McpdError} If the request fails
|
|
1102
|
+
*
|
|
1103
|
+
* @internal
|
|
1022
1104
|
*/
|
|
1023
1105
|
async #request(path, options = {}) {
|
|
1024
1106
|
const url = `${this.#endpoint}${path}`;
|
|
@@ -1098,6 +1180,10 @@ class McpdClient {
|
|
|
1098
1180
|
* Get a list of all configured MCP servers.
|
|
1099
1181
|
*
|
|
1100
1182
|
* @returns Array of server names
|
|
1183
|
+
*
|
|
1184
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1185
|
+
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1186
|
+
* @throws {TimeoutError} If the request times out
|
|
1101
1187
|
* @throws {McpdError} If the request fails
|
|
1102
1188
|
*
|
|
1103
1189
|
* @example
|
|
@@ -1110,16 +1196,23 @@ class McpdClient {
|
|
|
1110
1196
|
return await this.#request(API_PATHS.SERVERS);
|
|
1111
1197
|
}
|
|
1112
1198
|
/**
|
|
1113
|
-
*
|
|
1199
|
+
* Get tool schemas for a server.
|
|
1200
|
+
*
|
|
1201
|
+
* @privateRemarks
|
|
1114
1202
|
* Used by dependency injection for ServersNamespace and internally for getAgentTools.
|
|
1115
1203
|
*
|
|
1116
1204
|
* @param serverName - Server name to get tools for
|
|
1205
|
+
*
|
|
1117
1206
|
* @returns Tool schemas for the specified server
|
|
1207
|
+
*
|
|
1118
1208
|
* @throws {ServerNotFoundError} If the specified server doesn't exist
|
|
1119
1209
|
* @throws {ServerUnhealthyError} If the server is not healthy
|
|
1210
|
+
*
|
|
1211
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1120
1212
|
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1121
1213
|
* @throws {TimeoutError} If the request times out
|
|
1122
1214
|
* @throws {McpdError} If the request fails
|
|
1215
|
+
*
|
|
1123
1216
|
* @internal
|
|
1124
1217
|
*/
|
|
1125
1218
|
async #getToolsByServer(serverName) {
|
|
@@ -1135,17 +1228,24 @@ class McpdClient {
|
|
|
1135
1228
|
return response.tools;
|
|
1136
1229
|
}
|
|
1137
1230
|
/**
|
|
1138
|
-
*
|
|
1231
|
+
* Get prompt schemas for a server.
|
|
1232
|
+
*
|
|
1233
|
+
* @privateRemarks
|
|
1139
1234
|
* Used internally for getPromptSchemas.
|
|
1140
1235
|
*
|
|
1141
1236
|
* @param serverName - Server name to get prompts for
|
|
1142
|
-
* @param cursor -
|
|
1237
|
+
* @param cursor - Cursor for pagination
|
|
1238
|
+
*
|
|
1143
1239
|
* @returns Prompt schemas for the specified server
|
|
1240
|
+
*
|
|
1144
1241
|
* @throws {ServerNotFoundError} If the specified server doesn't exist
|
|
1145
1242
|
* @throws {ServerUnhealthyError} If the server is not healthy
|
|
1243
|
+
*
|
|
1244
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1146
1245
|
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1147
1246
|
* @throws {TimeoutError} If the request times out
|
|
1148
1247
|
* @throws {McpdError} If the request fails
|
|
1248
|
+
*
|
|
1149
1249
|
* @internal
|
|
1150
1250
|
*/
|
|
1151
1251
|
async #getPromptsByServer(serverName, cursor) {
|
|
@@ -1162,16 +1262,24 @@ class McpdClient {
|
|
|
1162
1262
|
}
|
|
1163
1263
|
}
|
|
1164
1264
|
/**
|
|
1165
|
-
*
|
|
1265
|
+
* Generate a prompt on a server.
|
|
1166
1266
|
*
|
|
1167
|
-
*
|
|
1267
|
+
* @privateRemarks
|
|
1268
|
+
* Used internally by:
|
|
1168
1269
|
* - PromptsNamespace (via dependency injection)
|
|
1169
1270
|
* - Server.generatePrompt() (via dependency injection)
|
|
1170
1271
|
*
|
|
1171
1272
|
* @param serverName - The name of the server
|
|
1172
1273
|
* @param promptName - The exact name of the prompt
|
|
1173
1274
|
* @param args - The prompt arguments
|
|
1275
|
+
*
|
|
1174
1276
|
* @returns The generated prompt response
|
|
1277
|
+
*
|
|
1278
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1279
|
+
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1280
|
+
* @throws {TimeoutError} If the request times out
|
|
1281
|
+
* @throws {McpdError} If the request fails
|
|
1282
|
+
*
|
|
1175
1283
|
* @internal
|
|
1176
1284
|
*/
|
|
1177
1285
|
async #generatePromptInternal(serverName, promptName, args) {
|
|
@@ -1187,17 +1295,24 @@ class McpdClient {
|
|
|
1187
1295
|
return response;
|
|
1188
1296
|
}
|
|
1189
1297
|
/**
|
|
1190
|
-
*
|
|
1298
|
+
* Get resource schemas for a server.
|
|
1299
|
+
*
|
|
1300
|
+
* @privateRemarks
|
|
1191
1301
|
* Used internally for getResources and by dependency injection for ServersNamespace.
|
|
1192
1302
|
*
|
|
1193
1303
|
* @param serverName - Server name to get resources for
|
|
1194
|
-
* @param cursor -
|
|
1304
|
+
* @param cursor - Cursor for pagination
|
|
1305
|
+
*
|
|
1195
1306
|
* @returns Resource schemas for the specified server
|
|
1307
|
+
*
|
|
1196
1308
|
* @throws {ServerNotFoundError} If the specified server doesn't exist
|
|
1197
1309
|
* @throws {ServerUnhealthyError} If the server is not healthy
|
|
1310
|
+
*
|
|
1311
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1198
1312
|
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1199
1313
|
* @throws {TimeoutError} If the request times out
|
|
1200
1314
|
* @throws {McpdError} If the request fails
|
|
1315
|
+
*
|
|
1201
1316
|
* @internal
|
|
1202
1317
|
*/
|
|
1203
1318
|
async #getResourcesByServer(serverName, cursor) {
|
|
@@ -1214,17 +1329,24 @@ class McpdClient {
|
|
|
1214
1329
|
}
|
|
1215
1330
|
}
|
|
1216
1331
|
/**
|
|
1217
|
-
*
|
|
1332
|
+
* Get resource template schemas for a server.
|
|
1333
|
+
*
|
|
1334
|
+
* @privateRemarks
|
|
1218
1335
|
* Used internally for getResourceTemplates and by dependency injection for ServersNamespace.
|
|
1219
1336
|
*
|
|
1220
1337
|
* @param serverName - Server name to get resource templates for
|
|
1221
|
-
* @param cursor -
|
|
1338
|
+
* @param cursor - Cursor for pagination
|
|
1339
|
+
*
|
|
1222
1340
|
* @returns Resource template schemas for the specified server
|
|
1341
|
+
*
|
|
1223
1342
|
* @throws {ServerNotFoundError} If the specified server doesn't exist
|
|
1224
1343
|
* @throws {ServerUnhealthyError} If the server is not healthy
|
|
1344
|
+
*
|
|
1345
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1225
1346
|
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1226
1347
|
* @throws {TimeoutError} If the request times out
|
|
1227
1348
|
* @throws {McpdError} If the request fails
|
|
1349
|
+
*
|
|
1228
1350
|
* @internal
|
|
1229
1351
|
*/
|
|
1230
1352
|
async #getResourceTemplatesByServer(serverName, cursor) {
|
|
@@ -1241,17 +1363,24 @@ class McpdClient {
|
|
|
1241
1363
|
}
|
|
1242
1364
|
}
|
|
1243
1365
|
/**
|
|
1244
|
-
*
|
|
1366
|
+
* Read resource content from a server.
|
|
1367
|
+
*
|
|
1368
|
+
* @privateRemarks
|
|
1245
1369
|
* Used by dependency injection for ServersNamespace.
|
|
1246
1370
|
*
|
|
1247
1371
|
* @param serverName - Server name to read resource from
|
|
1248
1372
|
* @param uri - The resource URI
|
|
1373
|
+
*
|
|
1249
1374
|
* @returns Array of resource contents (text or blob)
|
|
1375
|
+
*
|
|
1250
1376
|
* @throws {ServerNotFoundError} If the specified server doesn't exist
|
|
1251
1377
|
* @throws {ServerUnhealthyError} If the server is not healthy
|
|
1378
|
+
*
|
|
1379
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1252
1380
|
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1253
1381
|
* @throws {TimeoutError} If the request times out
|
|
1254
1382
|
* @throws {McpdError} If the request fails
|
|
1383
|
+
*
|
|
1255
1384
|
* @internal
|
|
1256
1385
|
*/
|
|
1257
1386
|
async #readResourceByServer(serverName, uri) {
|
|
@@ -1303,8 +1432,14 @@ class McpdClient {
|
|
|
1303
1432
|
* Check if a specific server is healthy.
|
|
1304
1433
|
*
|
|
1305
1434
|
* @param serverName - The name of the server to check
|
|
1435
|
+
*
|
|
1306
1436
|
* @returns True if the server is healthy, false otherwise
|
|
1307
1437
|
*
|
|
1438
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1439
|
+
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1440
|
+
* @throws {TimeoutError} If the request times out
|
|
1441
|
+
* @throws {McpdError} If the request fails
|
|
1442
|
+
*
|
|
1308
1443
|
* @example
|
|
1309
1444
|
* ```typescript
|
|
1310
1445
|
* if (await client.isServerHealthy('time')) {
|
|
@@ -1327,8 +1462,14 @@ class McpdClient {
|
|
|
1327
1462
|
* Ensure a server is healthy before performing an operation.
|
|
1328
1463
|
*
|
|
1329
1464
|
* @param serverName - The name of the server to check
|
|
1465
|
+
*
|
|
1330
1466
|
* @throws {ServerNotFoundError} If the server doesn't exist
|
|
1331
1467
|
* @throws {ServerUnhealthyError} If the server is not healthy
|
|
1468
|
+
*
|
|
1469
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1470
|
+
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1471
|
+
* @throws {TimeoutError} If the request times out
|
|
1472
|
+
* @throws {McpdError} If the request fails
|
|
1332
1473
|
*/
|
|
1333
1474
|
async #ensureServerHealthy(serverName) {
|
|
1334
1475
|
const health = await this.getServerHealth(serverName);
|
|
@@ -1347,35 +1488,60 @@ class McpdClient {
|
|
|
1347
1488
|
}
|
|
1348
1489
|
}
|
|
1349
1490
|
/**
|
|
1350
|
-
* Get list of healthy servers
|
|
1491
|
+
* Get list of healthy servers.
|
|
1351
1492
|
*
|
|
1352
|
-
*
|
|
1353
|
-
*
|
|
1493
|
+
* @remarks
|
|
1494
|
+
* If logging is enabled, warnings are logged for servers that do not exist or are unhealthy.
|
|
1354
1495
|
*
|
|
1355
|
-
* @param servers -
|
|
1356
|
-
*
|
|
1357
|
-
*
|
|
1496
|
+
* @param servers - List of server names to use for health checking.
|
|
1497
|
+
* If not provided, or empty, checks health for all servers.
|
|
1498
|
+
*
|
|
1499
|
+
* @returns List of server names with 'ok' health status.
|
|
1500
|
+
*
|
|
1501
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1502
|
+
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1503
|
+
* @throws {TimeoutError} If the request times out
|
|
1504
|
+
* @throws {McpdError} If the request fails
|
|
1358
1505
|
*/
|
|
1359
1506
|
async #getHealthyServers(servers) {
|
|
1360
|
-
const serverNames = servers
|
|
1507
|
+
const serverNames = servers?.length ? servers : await this.listServers();
|
|
1361
1508
|
const healthMap = await this.getServerHealth();
|
|
1362
1509
|
return serverNames.filter((name) => {
|
|
1363
1510
|
const health = healthMap[name];
|
|
1364
|
-
|
|
1511
|
+
if (!health) {
|
|
1512
|
+
this.#logger.warn(`Skipping non-existent server '${name}'`);
|
|
1513
|
+
return false;
|
|
1514
|
+
}
|
|
1515
|
+
if (!HealthStatusHelpers.isHealthy(health.status)) {
|
|
1516
|
+
this.#logger.warn(
|
|
1517
|
+
`Skipping unhealthy server '${name}' with status '${health.status}'`
|
|
1518
|
+
);
|
|
1519
|
+
return false;
|
|
1520
|
+
}
|
|
1521
|
+
return true;
|
|
1365
1522
|
});
|
|
1366
1523
|
}
|
|
1367
1524
|
/**
|
|
1368
|
-
*
|
|
1525
|
+
* Perform a tool call on a server.
|
|
1369
1526
|
*
|
|
1370
|
-
*
|
|
1527
|
+
* @privateRemarks
|
|
1528
|
+
* Used internally by:
|
|
1371
1529
|
* - ToolsNamespace (via dependency injection)
|
|
1372
1530
|
* - FunctionBuilder (via dependency injection)
|
|
1373
1531
|
*
|
|
1374
1532
|
* @param serverName - The name of the server
|
|
1375
1533
|
* @param toolName - The exact name of the tool
|
|
1376
1534
|
* @param args - The tool arguments
|
|
1535
|
+
*
|
|
1377
1536
|
* @returns The tool's response
|
|
1537
|
+
*
|
|
1378
1538
|
* @throws {ToolExecutionError} If the tool execution fails
|
|
1539
|
+
*
|
|
1540
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1541
|
+
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1542
|
+
* @throws {TimeoutError} If the request times out
|
|
1543
|
+
* @throws {McpdError} If the request fails
|
|
1544
|
+
*
|
|
1379
1545
|
* @internal
|
|
1380
1546
|
*/
|
|
1381
1547
|
async #performCall(serverName, toolName, args) {
|
|
@@ -1421,29 +1587,33 @@ class McpdClient {
|
|
|
1421
1587
|
this.#serverHealthCache.clear();
|
|
1422
1588
|
}
|
|
1423
1589
|
/**
|
|
1424
|
-
*
|
|
1590
|
+
* Fetch and cache callable functions from all healthy servers.
|
|
1425
1591
|
*
|
|
1426
|
-
* This method queries servers and creates self-contained, callable functions
|
|
1592
|
+
* This method queries all healthy servers and creates self-contained, callable functions
|
|
1427
1593
|
* that can be passed to AI agent frameworks. Each function includes its schema
|
|
1428
1594
|
* as metadata and handles the MCP communication internally.
|
|
1429
1595
|
*
|
|
1430
|
-
*
|
|
1431
|
-
*
|
|
1432
|
-
* the method returns quickly without waiting for timeouts on failed servers.
|
|
1596
|
+
* Unhealthy servers are automatically filtered out and skipped (with optional warnings
|
|
1597
|
+
* when logging is enabled) to ensure the method returns quickly without waiting for timeouts.
|
|
1433
1598
|
*
|
|
1434
1599
|
* Tool fetches from multiple servers are executed concurrently for optimal performance.
|
|
1600
|
+
* Functions are cached indefinitely until explicitly cleared.
|
|
1435
1601
|
*
|
|
1436
|
-
* @
|
|
1437
|
-
* @returns Array of callable functions with metadata. Only includes tools from healthy servers.
|
|
1602
|
+
* @returns Array of callable functions with metadata from all healthy servers.
|
|
1438
1603
|
*
|
|
1604
|
+
* @throws {AuthenticationError} If API key was present and authentication fails
|
|
1439
1605
|
* @throws {ConnectionError} If unable to connect to the mcpd daemon
|
|
1440
|
-
* @throws {TimeoutError} If
|
|
1441
|
-
* @throws {
|
|
1442
|
-
*
|
|
1606
|
+
* @throws {TimeoutError} If the request times out
|
|
1607
|
+
* @throws {McpdError} If the request fails
|
|
1608
|
+
*
|
|
1443
1609
|
* @internal
|
|
1444
1610
|
*/
|
|
1445
|
-
async agentTools(
|
|
1446
|
-
const
|
|
1611
|
+
async #agentTools() {
|
|
1612
|
+
const cachedFunctions = this.#functionBuilder.getCachedFunctions();
|
|
1613
|
+
if (cachedFunctions.length > 0) {
|
|
1614
|
+
return cachedFunctions;
|
|
1615
|
+
}
|
|
1616
|
+
const healthyServers = await this.#getHealthyServers();
|
|
1447
1617
|
const results = await Promise.allSettled(
|
|
1448
1618
|
healthyServers.map(async (serverName) => ({
|
|
1449
1619
|
serverName,
|
|
@@ -1462,17 +1632,43 @@ class McpdClient {
|
|
|
1462
1632
|
return agentTools;
|
|
1463
1633
|
}
|
|
1464
1634
|
async getAgentTools(options = {}) {
|
|
1465
|
-
const { servers, format = "array" } = options;
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1635
|
+
const { servers, tools, format = "array", refreshCache = false } = options;
|
|
1636
|
+
if (refreshCache) this.#functionBuilder.clearCache();
|
|
1637
|
+
const allTools = await this.#agentTools();
|
|
1638
|
+
const filteredTools = allTools.filter((tool) => !servers || servers.includes(tool._serverName)).filter((tool) => !tools || this.#matchesToolFilter(tool, tools));
|
|
1639
|
+
const formatters = {
|
|
1640
|
+
array: (t) => t,
|
|
1641
|
+
object: (t) => Object.fromEntries(t.map((tool) => [tool.name, tool])),
|
|
1642
|
+
map: (t) => new Map(t.map((tool) => [tool.name, tool]))
|
|
1643
|
+
};
|
|
1644
|
+
return formatters[format](filteredTools);
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* Check if a tool matches the tool filter.
|
|
1648
|
+
*
|
|
1649
|
+
* Supports two formats:
|
|
1650
|
+
* - Raw tool name: "get_current_time" (matches across all servers)
|
|
1651
|
+
* - Server-prefixed: "time__get_current_time" (matches specific server + tool)
|
|
1652
|
+
*
|
|
1653
|
+
* @remarks
|
|
1654
|
+
* When a filter contains "__", it's first checked as server-prefixed (exact match).
|
|
1655
|
+
* If that fails, it's checked as a raw tool name. This handles tools whose names
|
|
1656
|
+
* contain "__" (e.g., "my__special__tool").
|
|
1657
|
+
*
|
|
1658
|
+
* @param tool The tool to match.
|
|
1659
|
+
* @param tools List of tool names to match against.
|
|
1660
|
+
*
|
|
1661
|
+
* @returns True if a match is found in tools, based on the predicate.
|
|
1662
|
+
*
|
|
1663
|
+
* @internal
|
|
1664
|
+
*/
|
|
1665
|
+
#matchesToolFilter(tool, tools) {
|
|
1666
|
+
return tools.some((filterItem) => {
|
|
1667
|
+
if (filterItem.indexOf(TOOL_SEPARATOR) === -1) {
|
|
1668
|
+
return filterItem === tool._toolName;
|
|
1669
|
+
}
|
|
1670
|
+
return filterItem === tool.name || filterItem === tool._toolName;
|
|
1671
|
+
});
|
|
1476
1672
|
}
|
|
1477
1673
|
}
|
|
1478
1674
|
export {
|