@agiflowai/one-mcp 0.3.15 → 0.3.17
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/dist/cli.cjs +15 -5
- package/dist/cli.mjs +15 -5
- package/dist/index.cjs +4 -2
- package/dist/index.d.cts +193 -155
- package/dist/index.d.mts +193 -155
- package/dist/index.mjs +2 -2
- package/dist/{src-CWShQS8u.cjs → src-B8Rb84GQ.cjs} +153 -53
- package/dist/{src-CH93aUm2.mjs → src-D5YMjGgs.mjs} +142 -54
- package/package.json +1 -1
|
@@ -1424,6 +1424,14 @@ var DefinitionsCacheService = class {
|
|
|
1424
1424
|
/** Default connection timeout in milliseconds (30 seconds) */
|
|
1425
1425
|
const DEFAULT_CONNECTION_TIMEOUT_MS = 3e4;
|
|
1426
1426
|
/**
|
|
1427
|
+
* Checks if an error is a session-related error from an HTTP backend
|
|
1428
|
+
* (e.g., downstream server restarted and no longer recognizes the session ID).
|
|
1429
|
+
*/
|
|
1430
|
+
function isSessionError(error) {
|
|
1431
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1432
|
+
return message.includes("unknown session") || message.includes("Session not found");
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1427
1435
|
* MCP Client wrapper for managing individual server connections
|
|
1428
1436
|
* This is an internal class used by McpClientManagerService
|
|
1429
1437
|
*/
|
|
@@ -1437,6 +1445,7 @@ var McpClient = class {
|
|
|
1437
1445
|
client;
|
|
1438
1446
|
childProcess;
|
|
1439
1447
|
connected = false;
|
|
1448
|
+
reconnectFn;
|
|
1440
1449
|
constructor(serverName, transport, client, config) {
|
|
1441
1450
|
this.serverName = serverName;
|
|
1442
1451
|
this.serverInstruction = config.instruction;
|
|
@@ -1452,34 +1461,76 @@ var McpClient = class {
|
|
|
1452
1461
|
setConnected(connected) {
|
|
1453
1462
|
this.connected = connected;
|
|
1454
1463
|
}
|
|
1464
|
+
/**
|
|
1465
|
+
* Sets a reconnection function that creates a fresh Client and transport.
|
|
1466
|
+
* Called automatically by withSessionRetry when a session error is detected
|
|
1467
|
+
* (e.g., downstream HTTP server restarted and the old session ID is invalid).
|
|
1468
|
+
*/
|
|
1469
|
+
setReconnectFn(fn) {
|
|
1470
|
+
this.reconnectFn = fn;
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* Wraps an operation with automatic retry on session errors.
|
|
1474
|
+
* If the operation fails with a session error (e.g., downstream server restarted),
|
|
1475
|
+
* reconnects and retries once.
|
|
1476
|
+
*/
|
|
1477
|
+
async withSessionRetry(operation) {
|
|
1478
|
+
try {
|
|
1479
|
+
return await operation();
|
|
1480
|
+
} catch (error) {
|
|
1481
|
+
if (!this.reconnectFn || !isSessionError(error)) throw error;
|
|
1482
|
+
console.error(`Session error for ${this.serverName}, reconnecting: ${error instanceof Error ? error.message : String(error)}`);
|
|
1483
|
+
try {
|
|
1484
|
+
await this.client.close();
|
|
1485
|
+
} catch (closeError) {
|
|
1486
|
+
console.error(`Failed to close stale client for ${this.serverName}:`, closeError);
|
|
1487
|
+
}
|
|
1488
|
+
const result = await this.reconnectFn();
|
|
1489
|
+
this.client = result.client;
|
|
1490
|
+
if (result.childProcess) this.childProcess = result.childProcess;
|
|
1491
|
+
return await operation();
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1455
1494
|
async listTools() {
|
|
1456
1495
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1457
|
-
return
|
|
1496
|
+
return this.withSessionRetry(async () => {
|
|
1497
|
+
return (await this.client.listTools()).tools;
|
|
1498
|
+
});
|
|
1458
1499
|
}
|
|
1459
1500
|
async listResources() {
|
|
1460
1501
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1461
|
-
return
|
|
1502
|
+
return this.withSessionRetry(async () => {
|
|
1503
|
+
return (await this.client.listResources()).resources;
|
|
1504
|
+
});
|
|
1462
1505
|
}
|
|
1463
1506
|
async listPrompts() {
|
|
1464
1507
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1465
|
-
return
|
|
1508
|
+
return this.withSessionRetry(async () => {
|
|
1509
|
+
return (await this.client.listPrompts()).prompts;
|
|
1510
|
+
});
|
|
1466
1511
|
}
|
|
1467
1512
|
async callTool(name, args) {
|
|
1468
1513
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1469
|
-
return
|
|
1470
|
-
|
|
1471
|
-
|
|
1514
|
+
return this.withSessionRetry(async () => {
|
|
1515
|
+
return await this.client.callTool({
|
|
1516
|
+
name,
|
|
1517
|
+
arguments: args
|
|
1518
|
+
});
|
|
1472
1519
|
});
|
|
1473
1520
|
}
|
|
1474
1521
|
async readResource(uri) {
|
|
1475
1522
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1476
|
-
return
|
|
1523
|
+
return this.withSessionRetry(async () => {
|
|
1524
|
+
return await this.client.readResource({ uri });
|
|
1525
|
+
});
|
|
1477
1526
|
}
|
|
1478
1527
|
async getPrompt(name, args) {
|
|
1479
1528
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1480
|
-
return
|
|
1481
|
-
|
|
1482
|
-
|
|
1529
|
+
return this.withSessionRetry(async () => {
|
|
1530
|
+
return await this.client.getPrompt({
|
|
1531
|
+
name,
|
|
1532
|
+
arguments: args
|
|
1533
|
+
});
|
|
1483
1534
|
});
|
|
1484
1535
|
}
|
|
1485
1536
|
async close() {
|
|
@@ -1495,23 +1546,11 @@ var McpClientManagerService = class {
|
|
|
1495
1546
|
clients = /* @__PURE__ */ new Map();
|
|
1496
1547
|
serverConfigs = /* @__PURE__ */ new Map();
|
|
1497
1548
|
connectionPromises = /* @__PURE__ */ new Map();
|
|
1498
|
-
constructor() {
|
|
1499
|
-
process.on("exit", () => {
|
|
1500
|
-
this.cleanupOnExit();
|
|
1501
|
-
});
|
|
1502
|
-
process.on("SIGINT", () => {
|
|
1503
|
-
this.cleanupOnExit();
|
|
1504
|
-
process.exit(0);
|
|
1505
|
-
});
|
|
1506
|
-
process.on("SIGTERM", () => {
|
|
1507
|
-
this.cleanupOnExit();
|
|
1508
|
-
process.exit(0);
|
|
1509
|
-
});
|
|
1510
|
-
}
|
|
1511
1549
|
/**
|
|
1512
|
-
*
|
|
1550
|
+
* Synchronously kill all stdio MCP server child processes.
|
|
1551
|
+
* Must be called by the owner (e.g. transport/command layer) during shutdown.
|
|
1513
1552
|
*/
|
|
1514
|
-
|
|
1553
|
+
cleanupChildProcesses() {
|
|
1515
1554
|
for (const [serverName, client] of this.clients) try {
|
|
1516
1555
|
const childProcess = client["childProcess"];
|
|
1517
1556
|
if (childProcess && !childProcess.killed) {
|
|
@@ -1572,6 +1611,20 @@ var McpClientManagerService = class {
|
|
|
1572
1611
|
try {
|
|
1573
1612
|
await Promise.race([this.performConnection(mcpClient, config), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`Connection timeout after ${timeoutMs}ms`)), timeoutMs))]);
|
|
1574
1613
|
mcpClient.setConnected(true);
|
|
1614
|
+
if (config.transport === "http" || config.transport === "sse") mcpClient.setReconnectFn(async () => {
|
|
1615
|
+
try {
|
|
1616
|
+
const newClient = new Client({
|
|
1617
|
+
name: "@agiflowai/one-mcp-client",
|
|
1618
|
+
version: "0.1.0"
|
|
1619
|
+
}, { capabilities: {} });
|
|
1620
|
+
const newMcpClient = new McpClient(serverName, config.transport, newClient, {});
|
|
1621
|
+
await this.performConnection(newMcpClient, config);
|
|
1622
|
+
return { client: newClient };
|
|
1623
|
+
} catch (error) {
|
|
1624
|
+
console.error(`Failed to reconnect to ${serverName}:`, error);
|
|
1625
|
+
throw error;
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1575
1628
|
if (!mcpClient.serverInstruction) try {
|
|
1576
1629
|
const serverInstruction = mcpClient["client"].getInstructions();
|
|
1577
1630
|
if (serverInstruction) mcpClient.serverInstruction = serverInstruction;
|
|
@@ -2779,7 +2832,7 @@ IMPORTANT: Only use tools discovered from describe_tools with id="${this.serverI
|
|
|
2779
2832
|
|
|
2780
2833
|
//#endregion
|
|
2781
2834
|
//#region package.json
|
|
2782
|
-
var version = "0.3.
|
|
2835
|
+
var version = "0.3.16";
|
|
2783
2836
|
|
|
2784
2837
|
//#endregion
|
|
2785
2838
|
//#region src/server/index.ts
|
|
@@ -2790,6 +2843,7 @@ var version = "0.3.14";
|
|
|
2790
2843
|
* - Factory pattern for server creation
|
|
2791
2844
|
* - Tool registration pattern
|
|
2792
2845
|
* - Dependency injection for services
|
|
2846
|
+
* - Shared services pattern for multi-session HTTP transport
|
|
2793
2847
|
*
|
|
2794
2848
|
* CODING STANDARDS:
|
|
2795
2849
|
* - Register all tools, resources, and prompts here
|
|
@@ -2893,7 +2947,13 @@ function buildProxyInstructions(serverDefinitions, mode, includeSkillsTool) {
|
|
|
2893
2947
|
"Use describe_tools to inspect capabilities and use_tool to execute them."
|
|
2894
2948
|
].join("\n\n");
|
|
2895
2949
|
}
|
|
2896
|
-
|
|
2950
|
+
/**
|
|
2951
|
+
* Initialize shared services and tools once for use across multiple sessions.
|
|
2952
|
+
* Use with createSessionServer() for HTTP transport where multiple agents
|
|
2953
|
+
* connect concurrently. This avoids duplicating downstream connections,
|
|
2954
|
+
* file watchers, caches, and tool instances per session.
|
|
2955
|
+
*/
|
|
2956
|
+
async function initializeSharedServices(options) {
|
|
2897
2957
|
const clientManager = new McpClientManagerService();
|
|
2898
2958
|
let configSkills;
|
|
2899
2959
|
let configId;
|
|
@@ -2966,13 +3026,47 @@ async function createServer(options) {
|
|
|
2966
3026
|
definitionsCacheService = new DefinitionsCacheService(clientManager, skillService);
|
|
2967
3027
|
}
|
|
2968
3028
|
else definitionsCacheService = new DefinitionsCacheService(clientManager, skillService);
|
|
3029
|
+
const proxyMode = options?.proxyMode || "meta";
|
|
2969
3030
|
const describeTools = new DescribeToolsTool(clientManager, skillService, serverId, definitionsCacheService);
|
|
2970
|
-
const
|
|
3031
|
+
const useTool = new UseToolTool(clientManager, skillService, serverId, definitionsCacheService);
|
|
2971
3032
|
const searchListTools = new SearchListToolsTool(clientManager, definitionsCacheService);
|
|
2972
3033
|
toolsRef.describeTools = describeTools;
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
3034
|
+
if (skillService) skillService.startWatching().catch((error) => {
|
|
3035
|
+
console.error(`[skill-watcher] File watcher failed (non-critical): ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3036
|
+
});
|
|
3037
|
+
if (!shouldStartFromCache && effectiveDefinitionsCachePath && options?.configFilePath) definitionsCacheService.collectForCache({
|
|
3038
|
+
configPath: options.configFilePath,
|
|
3039
|
+
configHash,
|
|
3040
|
+
oneMcpVersion: version,
|
|
3041
|
+
serverId
|
|
3042
|
+
}).then((definitionsCache) => DefinitionsCacheService.writeToFile(effectiveDefinitionsCachePath, definitionsCache)).then(() => {
|
|
3043
|
+
console.error(`[definitions-cache] Wrote ${effectiveDefinitionsCachePath}`);
|
|
3044
|
+
}).catch((error) => {
|
|
3045
|
+
console.error(`[definitions-cache] Failed to persist ${effectiveDefinitionsCachePath}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3046
|
+
});
|
|
3047
|
+
const dispose = async () => {
|
|
3048
|
+
await clientManager.disconnectAll();
|
|
3049
|
+
if (skillService) skillService.stopWatching();
|
|
3050
|
+
};
|
|
3051
|
+
return {
|
|
3052
|
+
clientManager,
|
|
3053
|
+
definitionsCacheService,
|
|
3054
|
+
skillService,
|
|
3055
|
+
describeTools,
|
|
3056
|
+
useTool,
|
|
3057
|
+
searchListTools,
|
|
3058
|
+
serverId,
|
|
3059
|
+
proxyMode,
|
|
3060
|
+
dispose
|
|
3061
|
+
};
|
|
3062
|
+
}
|
|
3063
|
+
/**
|
|
3064
|
+
* Create a lightweight per-session MCP Server instance that delegates
|
|
3065
|
+
* to shared services and tools. Use with initializeSharedServices()
|
|
3066
|
+
* for multi-session HTTP transport.
|
|
3067
|
+
*/
|
|
3068
|
+
async function createSessionServer(shared) {
|
|
3069
|
+
const { clientManager, definitionsCacheService, skillService, describeTools, useTool: useToolWithCache, searchListTools, serverId, proxyMode } = shared;
|
|
2976
3070
|
const server = new Server({
|
|
2977
3071
|
name: "@agiflowai/one-mcp",
|
|
2978
3072
|
version: "0.1.0"
|
|
@@ -2982,10 +3076,7 @@ async function createServer(options) {
|
|
|
2982
3076
|
resources: {},
|
|
2983
3077
|
prompts: {}
|
|
2984
3078
|
},
|
|
2985
|
-
instructions: buildProxyInstructions(
|
|
2986
|
-
});
|
|
2987
|
-
if (skillService) skillService.startWatching().catch((error) => {
|
|
2988
|
-
console.error(`[skill-watcher] File watcher failed (non-critical): ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3079
|
+
instructions: buildProxyInstructions(await definitionsCacheService.getServerDefinitions(), proxyMode, await hasAnySkills(definitionsCacheService, skillService))
|
|
2989
3080
|
});
|
|
2990
3081
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: proxyMode === "flat" ? await (async () => {
|
|
2991
3082
|
const currentServerDefinitions = await definitionsCacheService.getServerDefinitions();
|
|
@@ -3022,14 +3113,14 @@ async function createServer(options) {
|
|
|
3022
3113
|
throw new Error(`Unknown tool: ${name}`);
|
|
3023
3114
|
});
|
|
3024
3115
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
3025
|
-
const
|
|
3116
|
+
const currentServerDefinitions = await definitionsCacheService.getServerDefinitions();
|
|
3026
3117
|
const resourceToServers = /* @__PURE__ */ new Map();
|
|
3027
|
-
for (const serverDefinition of
|
|
3118
|
+
for (const serverDefinition of currentServerDefinitions) for (const resource of serverDefinition.resources) {
|
|
3028
3119
|
if (!resourceToServers.has(resource.uri)) resourceToServers.set(resource.uri, []);
|
|
3029
3120
|
resourceToServers.get(resource.uri)?.push(serverDefinition.serverName);
|
|
3030
3121
|
}
|
|
3031
3122
|
const resources = [];
|
|
3032
|
-
for (const serverDefinition of
|
|
3123
|
+
for (const serverDefinition of currentServerDefinitions) for (const resource of serverDefinition.resources) {
|
|
3033
3124
|
const hasClash = (resourceToServers.get(resource.uri) || []).length > 1;
|
|
3034
3125
|
resources.push({
|
|
3035
3126
|
...resource,
|
|
@@ -3048,10 +3139,10 @@ async function createServer(options) {
|
|
|
3048
3139
|
return await (await clientManager.ensureConnected(matchingServers[0])).readResource(actualUri);
|
|
3049
3140
|
});
|
|
3050
3141
|
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
3051
|
-
const
|
|
3142
|
+
const currentServerDefinitions = await definitionsCacheService.getServerDefinitions();
|
|
3052
3143
|
const promptToServers = /* @__PURE__ */ new Map();
|
|
3053
3144
|
const serverPromptsMap = /* @__PURE__ */ new Map();
|
|
3054
|
-
for (const serverDefinition of
|
|
3145
|
+
for (const serverDefinition of currentServerDefinitions) {
|
|
3055
3146
|
serverPromptsMap.set(serverDefinition.serverName, serverDefinition.prompts);
|
|
3056
3147
|
for (const prompt of serverDefinition.prompts) {
|
|
3057
3148
|
if (!promptToServers.has(prompt.name)) promptToServers.set(prompt.name, []);
|
|
@@ -3059,7 +3150,7 @@ async function createServer(options) {
|
|
|
3059
3150
|
}
|
|
3060
3151
|
}
|
|
3061
3152
|
const aggregatedPrompts = [];
|
|
3062
|
-
for (const serverDefinition of
|
|
3153
|
+
for (const serverDefinition of currentServerDefinitions) {
|
|
3063
3154
|
const prompts = serverPromptsMap.get(serverDefinition.serverName) || [];
|
|
3064
3155
|
for (const prompt of prompts) {
|
|
3065
3156
|
const hasClash = (promptToServers.get(prompt.name) || []).length > 1;
|
|
@@ -3074,29 +3165,26 @@ async function createServer(options) {
|
|
|
3074
3165
|
});
|
|
3075
3166
|
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
3076
3167
|
const { name, arguments: args } = request.params;
|
|
3077
|
-
const
|
|
3168
|
+
const currentServerDefinitions = await definitionsCacheService.getServerDefinitions();
|
|
3078
3169
|
const { serverName, actualToolName: actualPromptName } = parseToolName(name);
|
|
3079
3170
|
if (serverName) return await (await clientManager.ensureConnected(serverName)).getPrompt(actualPromptName, args);
|
|
3080
3171
|
const serversWithPrompt = [];
|
|
3081
|
-
for (const serverDefinition of
|
|
3172
|
+
for (const serverDefinition of currentServerDefinitions) if (serverDefinition.prompts.some((prompt) => prompt.name === name)) serversWithPrompt.push(serverDefinition.serverName);
|
|
3082
3173
|
if (serversWithPrompt.length === 0) throw new Error(`Prompt not found: ${name}`);
|
|
3083
3174
|
if (serversWithPrompt.length > 1) throw new Error(`Prompt "${name}" exists on multiple servers: ${serversWithPrompt.join(", ")}. Use the prefixed format (e.g., "${serversWithPrompt[0]}__${name}") to specify which server to use.`);
|
|
3084
3175
|
const client = clientManager.getClient(serversWithPrompt[0]);
|
|
3085
3176
|
if (!client) return await (await clientManager.ensureConnected(serversWithPrompt[0])).getPrompt(name, args);
|
|
3086
3177
|
return await client.getPrompt(name, args);
|
|
3087
3178
|
});
|
|
3088
|
-
if (!shouldStartFromCache && effectiveDefinitionsCachePath && options?.configFilePath) definitionsCacheService.collectForCache({
|
|
3089
|
-
configPath: options.configFilePath,
|
|
3090
|
-
configHash,
|
|
3091
|
-
oneMcpVersion: version,
|
|
3092
|
-
serverId
|
|
3093
|
-
}).then((definitionsCache) => DefinitionsCacheService.writeToFile(effectiveDefinitionsCachePath, definitionsCache)).then(() => {
|
|
3094
|
-
console.error(`[definitions-cache] Wrote ${effectiveDefinitionsCachePath}`);
|
|
3095
|
-
}).catch((error) => {
|
|
3096
|
-
console.error(`[definitions-cache] Failed to persist ${effectiveDefinitionsCachePath}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3097
|
-
});
|
|
3098
3179
|
return server;
|
|
3099
3180
|
}
|
|
3181
|
+
/**
|
|
3182
|
+
* Create a single MCP server instance (backward-compatible wrapper).
|
|
3183
|
+
* For multi-session HTTP transport, use initializeSharedServices() + createSessionServer() instead.
|
|
3184
|
+
*/
|
|
3185
|
+
async function createServer(options) {
|
|
3186
|
+
return createSessionServer(await initializeSharedServices(options));
|
|
3187
|
+
}
|
|
3100
3188
|
|
|
3101
3189
|
//#endregion
|
|
3102
3190
|
//#region src/types/index.ts
|
|
@@ -4080,4 +4168,4 @@ var StopServerService = class {
|
|
|
4080
4168
|
};
|
|
4081
4169
|
|
|
4082
4170
|
//#endregion
|
|
4083
|
-
export {
|
|
4171
|
+
export { DefinitionsCacheService as _, SseTransportHandler as a, ConfigFetcherService as b, createServer as c, version as d, UseToolTool as f, McpClientManagerService as g, SkillService as h, StdioTransportHandler as i, createSessionServer as l, DescribeToolsTool as m, RuntimeStateService as n, HttpTransportHandler as o, SearchListToolsTool as p, StdioHttpTransportHandler as r, TRANSPORT_MODE as s, StopServerService as t, initializeSharedServices as u, generateServerId as v, findConfigFile as y };
|