@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
|
@@ -1453,6 +1453,14 @@ var DefinitionsCacheService = class {
|
|
|
1453
1453
|
/** Default connection timeout in milliseconds (30 seconds) */
|
|
1454
1454
|
const DEFAULT_CONNECTION_TIMEOUT_MS = 3e4;
|
|
1455
1455
|
/**
|
|
1456
|
+
* Checks if an error is a session-related error from an HTTP backend
|
|
1457
|
+
* (e.g., downstream server restarted and no longer recognizes the session ID).
|
|
1458
|
+
*/
|
|
1459
|
+
function isSessionError(error) {
|
|
1460
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1461
|
+
return message.includes("unknown session") || message.includes("Session not found");
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1456
1464
|
* MCP Client wrapper for managing individual server connections
|
|
1457
1465
|
* This is an internal class used by McpClientManagerService
|
|
1458
1466
|
*/
|
|
@@ -1466,6 +1474,7 @@ var McpClient = class {
|
|
|
1466
1474
|
client;
|
|
1467
1475
|
childProcess;
|
|
1468
1476
|
connected = false;
|
|
1477
|
+
reconnectFn;
|
|
1469
1478
|
constructor(serverName, transport, client, config) {
|
|
1470
1479
|
this.serverName = serverName;
|
|
1471
1480
|
this.serverInstruction = config.instruction;
|
|
@@ -1481,34 +1490,76 @@ var McpClient = class {
|
|
|
1481
1490
|
setConnected(connected) {
|
|
1482
1491
|
this.connected = connected;
|
|
1483
1492
|
}
|
|
1493
|
+
/**
|
|
1494
|
+
* Sets a reconnection function that creates a fresh Client and transport.
|
|
1495
|
+
* Called automatically by withSessionRetry when a session error is detected
|
|
1496
|
+
* (e.g., downstream HTTP server restarted and the old session ID is invalid).
|
|
1497
|
+
*/
|
|
1498
|
+
setReconnectFn(fn) {
|
|
1499
|
+
this.reconnectFn = fn;
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Wraps an operation with automatic retry on session errors.
|
|
1503
|
+
* If the operation fails with a session error (e.g., downstream server restarted),
|
|
1504
|
+
* reconnects and retries once.
|
|
1505
|
+
*/
|
|
1506
|
+
async withSessionRetry(operation) {
|
|
1507
|
+
try {
|
|
1508
|
+
return await operation();
|
|
1509
|
+
} catch (error) {
|
|
1510
|
+
if (!this.reconnectFn || !isSessionError(error)) throw error;
|
|
1511
|
+
console.error(`Session error for ${this.serverName}, reconnecting: ${error instanceof Error ? error.message : String(error)}`);
|
|
1512
|
+
try {
|
|
1513
|
+
await this.client.close();
|
|
1514
|
+
} catch (closeError) {
|
|
1515
|
+
console.error(`Failed to close stale client for ${this.serverName}:`, closeError);
|
|
1516
|
+
}
|
|
1517
|
+
const result = await this.reconnectFn();
|
|
1518
|
+
this.client = result.client;
|
|
1519
|
+
if (result.childProcess) this.childProcess = result.childProcess;
|
|
1520
|
+
return await operation();
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1484
1523
|
async listTools() {
|
|
1485
1524
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1486
|
-
return
|
|
1525
|
+
return this.withSessionRetry(async () => {
|
|
1526
|
+
return (await this.client.listTools()).tools;
|
|
1527
|
+
});
|
|
1487
1528
|
}
|
|
1488
1529
|
async listResources() {
|
|
1489
1530
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1490
|
-
return
|
|
1531
|
+
return this.withSessionRetry(async () => {
|
|
1532
|
+
return (await this.client.listResources()).resources;
|
|
1533
|
+
});
|
|
1491
1534
|
}
|
|
1492
1535
|
async listPrompts() {
|
|
1493
1536
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1494
|
-
return
|
|
1537
|
+
return this.withSessionRetry(async () => {
|
|
1538
|
+
return (await this.client.listPrompts()).prompts;
|
|
1539
|
+
});
|
|
1495
1540
|
}
|
|
1496
1541
|
async callTool(name, args) {
|
|
1497
1542
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1498
|
-
return
|
|
1499
|
-
|
|
1500
|
-
|
|
1543
|
+
return this.withSessionRetry(async () => {
|
|
1544
|
+
return await this.client.callTool({
|
|
1545
|
+
name,
|
|
1546
|
+
arguments: args
|
|
1547
|
+
});
|
|
1501
1548
|
});
|
|
1502
1549
|
}
|
|
1503
1550
|
async readResource(uri) {
|
|
1504
1551
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1505
|
-
return
|
|
1552
|
+
return this.withSessionRetry(async () => {
|
|
1553
|
+
return await this.client.readResource({ uri });
|
|
1554
|
+
});
|
|
1506
1555
|
}
|
|
1507
1556
|
async getPrompt(name, args) {
|
|
1508
1557
|
if (!this.connected) throw new Error(`Client for ${this.serverName} is not connected`);
|
|
1509
|
-
return
|
|
1510
|
-
|
|
1511
|
-
|
|
1558
|
+
return this.withSessionRetry(async () => {
|
|
1559
|
+
return await this.client.getPrompt({
|
|
1560
|
+
name,
|
|
1561
|
+
arguments: args
|
|
1562
|
+
});
|
|
1512
1563
|
});
|
|
1513
1564
|
}
|
|
1514
1565
|
async close() {
|
|
@@ -1524,23 +1575,11 @@ var McpClientManagerService = class {
|
|
|
1524
1575
|
clients = /* @__PURE__ */ new Map();
|
|
1525
1576
|
serverConfigs = /* @__PURE__ */ new Map();
|
|
1526
1577
|
connectionPromises = /* @__PURE__ */ new Map();
|
|
1527
|
-
constructor() {
|
|
1528
|
-
process.on("exit", () => {
|
|
1529
|
-
this.cleanupOnExit();
|
|
1530
|
-
});
|
|
1531
|
-
process.on("SIGINT", () => {
|
|
1532
|
-
this.cleanupOnExit();
|
|
1533
|
-
process.exit(0);
|
|
1534
|
-
});
|
|
1535
|
-
process.on("SIGTERM", () => {
|
|
1536
|
-
this.cleanupOnExit();
|
|
1537
|
-
process.exit(0);
|
|
1538
|
-
});
|
|
1539
|
-
}
|
|
1540
1578
|
/**
|
|
1541
|
-
*
|
|
1579
|
+
* Synchronously kill all stdio MCP server child processes.
|
|
1580
|
+
* Must be called by the owner (e.g. transport/command layer) during shutdown.
|
|
1542
1581
|
*/
|
|
1543
|
-
|
|
1582
|
+
cleanupChildProcesses() {
|
|
1544
1583
|
for (const [serverName, client] of this.clients) try {
|
|
1545
1584
|
const childProcess = client["childProcess"];
|
|
1546
1585
|
if (childProcess && !childProcess.killed) {
|
|
@@ -1601,6 +1640,20 @@ var McpClientManagerService = class {
|
|
|
1601
1640
|
try {
|
|
1602
1641
|
await Promise.race([this.performConnection(mcpClient, config), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`Connection timeout after ${timeoutMs}ms`)), timeoutMs))]);
|
|
1603
1642
|
mcpClient.setConnected(true);
|
|
1643
|
+
if (config.transport === "http" || config.transport === "sse") mcpClient.setReconnectFn(async () => {
|
|
1644
|
+
try {
|
|
1645
|
+
const newClient = new __modelcontextprotocol_sdk_client_index_js.Client({
|
|
1646
|
+
name: "@agiflowai/one-mcp-client",
|
|
1647
|
+
version: "0.1.0"
|
|
1648
|
+
}, { capabilities: {} });
|
|
1649
|
+
const newMcpClient = new McpClient(serverName, config.transport, newClient, {});
|
|
1650
|
+
await this.performConnection(newMcpClient, config);
|
|
1651
|
+
return { client: newClient };
|
|
1652
|
+
} catch (error) {
|
|
1653
|
+
console.error(`Failed to reconnect to ${serverName}:`, error);
|
|
1654
|
+
throw error;
|
|
1655
|
+
}
|
|
1656
|
+
});
|
|
1604
1657
|
if (!mcpClient.serverInstruction) try {
|
|
1605
1658
|
const serverInstruction = mcpClient["client"].getInstructions();
|
|
1606
1659
|
if (serverInstruction) mcpClient.serverInstruction = serverInstruction;
|
|
@@ -2808,7 +2861,7 @@ IMPORTANT: Only use tools discovered from describe_tools with id="${this.serverI
|
|
|
2808
2861
|
|
|
2809
2862
|
//#endregion
|
|
2810
2863
|
//#region package.json
|
|
2811
|
-
var version = "0.3.
|
|
2864
|
+
var version = "0.3.16";
|
|
2812
2865
|
|
|
2813
2866
|
//#endregion
|
|
2814
2867
|
//#region src/server/index.ts
|
|
@@ -2819,6 +2872,7 @@ var version = "0.3.14";
|
|
|
2819
2872
|
* - Factory pattern for server creation
|
|
2820
2873
|
* - Tool registration pattern
|
|
2821
2874
|
* - Dependency injection for services
|
|
2875
|
+
* - Shared services pattern for multi-session HTTP transport
|
|
2822
2876
|
*
|
|
2823
2877
|
* CODING STANDARDS:
|
|
2824
2878
|
* - Register all tools, resources, and prompts here
|
|
@@ -2922,7 +2976,13 @@ function buildProxyInstructions(serverDefinitions, mode, includeSkillsTool) {
|
|
|
2922
2976
|
"Use describe_tools to inspect capabilities and use_tool to execute them."
|
|
2923
2977
|
].join("\n\n");
|
|
2924
2978
|
}
|
|
2925
|
-
|
|
2979
|
+
/**
|
|
2980
|
+
* Initialize shared services and tools once for use across multiple sessions.
|
|
2981
|
+
* Use with createSessionServer() for HTTP transport where multiple agents
|
|
2982
|
+
* connect concurrently. This avoids duplicating downstream connections,
|
|
2983
|
+
* file watchers, caches, and tool instances per session.
|
|
2984
|
+
*/
|
|
2985
|
+
async function initializeSharedServices(options) {
|
|
2926
2986
|
const clientManager = new McpClientManagerService();
|
|
2927
2987
|
let configSkills;
|
|
2928
2988
|
let configId;
|
|
@@ -2995,13 +3055,47 @@ async function createServer(options) {
|
|
|
2995
3055
|
definitionsCacheService = new DefinitionsCacheService(clientManager, skillService);
|
|
2996
3056
|
}
|
|
2997
3057
|
else definitionsCacheService = new DefinitionsCacheService(clientManager, skillService);
|
|
3058
|
+
const proxyMode = options?.proxyMode || "meta";
|
|
2998
3059
|
const describeTools = new DescribeToolsTool(clientManager, skillService, serverId, definitionsCacheService);
|
|
2999
|
-
const
|
|
3060
|
+
const useTool = new UseToolTool(clientManager, skillService, serverId, definitionsCacheService);
|
|
3000
3061
|
const searchListTools = new SearchListToolsTool(clientManager, definitionsCacheService);
|
|
3001
3062
|
toolsRef.describeTools = describeTools;
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3063
|
+
if (skillService) skillService.startWatching().catch((error) => {
|
|
3064
|
+
console.error(`[skill-watcher] File watcher failed (non-critical): ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3065
|
+
});
|
|
3066
|
+
if (!shouldStartFromCache && effectiveDefinitionsCachePath && options?.configFilePath) definitionsCacheService.collectForCache({
|
|
3067
|
+
configPath: options.configFilePath,
|
|
3068
|
+
configHash,
|
|
3069
|
+
oneMcpVersion: version,
|
|
3070
|
+
serverId
|
|
3071
|
+
}).then((definitionsCache) => DefinitionsCacheService.writeToFile(effectiveDefinitionsCachePath, definitionsCache)).then(() => {
|
|
3072
|
+
console.error(`[definitions-cache] Wrote ${effectiveDefinitionsCachePath}`);
|
|
3073
|
+
}).catch((error) => {
|
|
3074
|
+
console.error(`[definitions-cache] Failed to persist ${effectiveDefinitionsCachePath}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3075
|
+
});
|
|
3076
|
+
const dispose = async () => {
|
|
3077
|
+
await clientManager.disconnectAll();
|
|
3078
|
+
if (skillService) skillService.stopWatching();
|
|
3079
|
+
};
|
|
3080
|
+
return {
|
|
3081
|
+
clientManager,
|
|
3082
|
+
definitionsCacheService,
|
|
3083
|
+
skillService,
|
|
3084
|
+
describeTools,
|
|
3085
|
+
useTool,
|
|
3086
|
+
searchListTools,
|
|
3087
|
+
serverId,
|
|
3088
|
+
proxyMode,
|
|
3089
|
+
dispose
|
|
3090
|
+
};
|
|
3091
|
+
}
|
|
3092
|
+
/**
|
|
3093
|
+
* Create a lightweight per-session MCP Server instance that delegates
|
|
3094
|
+
* to shared services and tools. Use with initializeSharedServices()
|
|
3095
|
+
* for multi-session HTTP transport.
|
|
3096
|
+
*/
|
|
3097
|
+
async function createSessionServer(shared) {
|
|
3098
|
+
const { clientManager, definitionsCacheService, skillService, describeTools, useTool: useToolWithCache, searchListTools, serverId, proxyMode } = shared;
|
|
3005
3099
|
const server = new __modelcontextprotocol_sdk_server_index_js.Server({
|
|
3006
3100
|
name: "@agiflowai/one-mcp",
|
|
3007
3101
|
version: "0.1.0"
|
|
@@ -3011,10 +3105,7 @@ async function createServer(options) {
|
|
|
3011
3105
|
resources: {},
|
|
3012
3106
|
prompts: {}
|
|
3013
3107
|
},
|
|
3014
|
-
instructions: buildProxyInstructions(
|
|
3015
|
-
});
|
|
3016
|
-
if (skillService) skillService.startWatching().catch((error) => {
|
|
3017
|
-
console.error(`[skill-watcher] File watcher failed (non-critical): ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3108
|
+
instructions: buildProxyInstructions(await definitionsCacheService.getServerDefinitions(), proxyMode, await hasAnySkills(definitionsCacheService, skillService))
|
|
3018
3109
|
});
|
|
3019
3110
|
server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListToolsRequestSchema, async () => ({ tools: proxyMode === "flat" ? await (async () => {
|
|
3020
3111
|
const currentServerDefinitions = await definitionsCacheService.getServerDefinitions();
|
|
@@ -3051,14 +3142,14 @@ async function createServer(options) {
|
|
|
3051
3142
|
throw new Error(`Unknown tool: ${name}`);
|
|
3052
3143
|
});
|
|
3053
3144
|
server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListResourcesRequestSchema, async () => {
|
|
3054
|
-
const
|
|
3145
|
+
const currentServerDefinitions = await definitionsCacheService.getServerDefinitions();
|
|
3055
3146
|
const resourceToServers = /* @__PURE__ */ new Map();
|
|
3056
|
-
for (const serverDefinition of
|
|
3147
|
+
for (const serverDefinition of currentServerDefinitions) for (const resource of serverDefinition.resources) {
|
|
3057
3148
|
if (!resourceToServers.has(resource.uri)) resourceToServers.set(resource.uri, []);
|
|
3058
3149
|
resourceToServers.get(resource.uri)?.push(serverDefinition.serverName);
|
|
3059
3150
|
}
|
|
3060
3151
|
const resources = [];
|
|
3061
|
-
for (const serverDefinition of
|
|
3152
|
+
for (const serverDefinition of currentServerDefinitions) for (const resource of serverDefinition.resources) {
|
|
3062
3153
|
const hasClash = (resourceToServers.get(resource.uri) || []).length > 1;
|
|
3063
3154
|
resources.push({
|
|
3064
3155
|
...resource,
|
|
@@ -3077,10 +3168,10 @@ async function createServer(options) {
|
|
|
3077
3168
|
return await (await clientManager.ensureConnected(matchingServers[0])).readResource(actualUri);
|
|
3078
3169
|
});
|
|
3079
3170
|
server.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListPromptsRequestSchema, async () => {
|
|
3080
|
-
const
|
|
3171
|
+
const currentServerDefinitions = await definitionsCacheService.getServerDefinitions();
|
|
3081
3172
|
const promptToServers = /* @__PURE__ */ new Map();
|
|
3082
3173
|
const serverPromptsMap = /* @__PURE__ */ new Map();
|
|
3083
|
-
for (const serverDefinition of
|
|
3174
|
+
for (const serverDefinition of currentServerDefinitions) {
|
|
3084
3175
|
serverPromptsMap.set(serverDefinition.serverName, serverDefinition.prompts);
|
|
3085
3176
|
for (const prompt of serverDefinition.prompts) {
|
|
3086
3177
|
if (!promptToServers.has(prompt.name)) promptToServers.set(prompt.name, []);
|
|
@@ -3088,7 +3179,7 @@ async function createServer(options) {
|
|
|
3088
3179
|
}
|
|
3089
3180
|
}
|
|
3090
3181
|
const aggregatedPrompts = [];
|
|
3091
|
-
for (const serverDefinition of
|
|
3182
|
+
for (const serverDefinition of currentServerDefinitions) {
|
|
3092
3183
|
const prompts = serverPromptsMap.get(serverDefinition.serverName) || [];
|
|
3093
3184
|
for (const prompt of prompts) {
|
|
3094
3185
|
const hasClash = (promptToServers.get(prompt.name) || []).length > 1;
|
|
@@ -3103,29 +3194,26 @@ async function createServer(options) {
|
|
|
3103
3194
|
});
|
|
3104
3195
|
server.setRequestHandler(__modelcontextprotocol_sdk_types_js.GetPromptRequestSchema, async (request) => {
|
|
3105
3196
|
const { name, arguments: args } = request.params;
|
|
3106
|
-
const
|
|
3197
|
+
const currentServerDefinitions = await definitionsCacheService.getServerDefinitions();
|
|
3107
3198
|
const { serverName, actualToolName: actualPromptName } = parseToolName(name);
|
|
3108
3199
|
if (serverName) return await (await clientManager.ensureConnected(serverName)).getPrompt(actualPromptName, args);
|
|
3109
3200
|
const serversWithPrompt = [];
|
|
3110
|
-
for (const serverDefinition of
|
|
3201
|
+
for (const serverDefinition of currentServerDefinitions) if (serverDefinition.prompts.some((prompt) => prompt.name === name)) serversWithPrompt.push(serverDefinition.serverName);
|
|
3111
3202
|
if (serversWithPrompt.length === 0) throw new Error(`Prompt not found: ${name}`);
|
|
3112
3203
|
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.`);
|
|
3113
3204
|
const client = clientManager.getClient(serversWithPrompt[0]);
|
|
3114
3205
|
if (!client) return await (await clientManager.ensureConnected(serversWithPrompt[0])).getPrompt(name, args);
|
|
3115
3206
|
return await client.getPrompt(name, args);
|
|
3116
3207
|
});
|
|
3117
|
-
if (!shouldStartFromCache && effectiveDefinitionsCachePath && options?.configFilePath) definitionsCacheService.collectForCache({
|
|
3118
|
-
configPath: options.configFilePath,
|
|
3119
|
-
configHash,
|
|
3120
|
-
oneMcpVersion: version,
|
|
3121
|
-
serverId
|
|
3122
|
-
}).then((definitionsCache) => DefinitionsCacheService.writeToFile(effectiveDefinitionsCachePath, definitionsCache)).then(() => {
|
|
3123
|
-
console.error(`[definitions-cache] Wrote ${effectiveDefinitionsCachePath}`);
|
|
3124
|
-
}).catch((error) => {
|
|
3125
|
-
console.error(`[definitions-cache] Failed to persist ${effectiveDefinitionsCachePath}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3126
|
-
});
|
|
3127
3208
|
return server;
|
|
3128
3209
|
}
|
|
3210
|
+
/**
|
|
3211
|
+
* Create a single MCP server instance (backward-compatible wrapper).
|
|
3212
|
+
* For multi-session HTTP transport, use initializeSharedServices() + createSessionServer() instead.
|
|
3213
|
+
*/
|
|
3214
|
+
async function createServer(options) {
|
|
3215
|
+
return createSessionServer(await initializeSharedServices(options));
|
|
3216
|
+
}
|
|
3129
3217
|
|
|
3130
3218
|
//#endregion
|
|
3131
3219
|
//#region src/types/index.ts
|
|
@@ -4205,6 +4293,12 @@ Object.defineProperty(exports, 'createServer', {
|
|
|
4205
4293
|
return createServer;
|
|
4206
4294
|
}
|
|
4207
4295
|
});
|
|
4296
|
+
Object.defineProperty(exports, 'createSessionServer', {
|
|
4297
|
+
enumerable: true,
|
|
4298
|
+
get: function () {
|
|
4299
|
+
return createSessionServer;
|
|
4300
|
+
}
|
|
4301
|
+
});
|
|
4208
4302
|
Object.defineProperty(exports, 'findConfigFile', {
|
|
4209
4303
|
enumerable: true,
|
|
4210
4304
|
get: function () {
|
|
@@ -4217,6 +4311,12 @@ Object.defineProperty(exports, 'generateServerId', {
|
|
|
4217
4311
|
return generateServerId;
|
|
4218
4312
|
}
|
|
4219
4313
|
});
|
|
4314
|
+
Object.defineProperty(exports, 'initializeSharedServices', {
|
|
4315
|
+
enumerable: true,
|
|
4316
|
+
get: function () {
|
|
4317
|
+
return initializeSharedServices;
|
|
4318
|
+
}
|
|
4319
|
+
});
|
|
4220
4320
|
Object.defineProperty(exports, 'version', {
|
|
4221
4321
|
enumerable: true,
|
|
4222
4322
|
get: function () {
|