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