@agiflowai/one-mcp 0.2.1 → 0.2.2
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 -12
- package/dist/cli.mjs +15 -12
- package/dist/{http-23nhycE8.cjs → http-3v8zyDO3.cjs} +182 -148
- package/dist/{http-CkWO35l-.mjs → http-CzQfsUEI.mjs} +168 -140
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_http = require('./http-
|
|
2
|
+
const require_http = require('./http-3v8zyDO3.cjs');
|
|
3
3
|
let node_fs_promises = require("node:fs/promises");
|
|
4
4
|
let node_path = require("node:path");
|
|
5
5
|
let commander = require("commander");
|
|
@@ -63,7 +63,7 @@ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MC
|
|
|
63
63
|
try {
|
|
64
64
|
const transportType = options.type.toLowerCase();
|
|
65
65
|
const serverOptions = {
|
|
66
|
-
configFilePath: options.config,
|
|
66
|
+
configFilePath: options.config || require_http.findConfigFile(),
|
|
67
67
|
noCache: options.cache === false
|
|
68
68
|
};
|
|
69
69
|
if (transportType === "stdio") await startServer(new require_http.StdioTransportHandler(await require_http.createServer(serverOptions)));
|
|
@@ -115,11 +115,12 @@ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MC
|
|
|
115
115
|
*/
|
|
116
116
|
const listToolsCommand = new commander.Command("list-tools").description("List all available tools from connected MCP servers").option("-c, --config <path>", "Path to MCP server configuration file").option("-s, --server <name>", "Filter by server name").option("-j, --json", "Output as JSON", false).action(async (options) => {
|
|
117
117
|
try {
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
const configFilePath = options.config || require_http.findConfigFile();
|
|
119
|
+
if (!configFilePath) {
|
|
120
|
+
console.error("Error: No config file found. Use --config or create mcp-config.yaml");
|
|
120
121
|
process.exit(1);
|
|
121
122
|
}
|
|
122
|
-
const config = await new require_http.ConfigFetcherService({ configFilePath
|
|
123
|
+
const config = await new require_http.ConfigFetcherService({ configFilePath }).fetchConfiguration();
|
|
123
124
|
const clientManager = new require_http.McpClientManagerService();
|
|
124
125
|
const connectionPromises = Object.entries(config.mcpServers).map(async ([serverName, serverConfig]) => {
|
|
125
126
|
try {
|
|
@@ -190,11 +191,12 @@ const listToolsCommand = new commander.Command("list-tools").description("List a
|
|
|
190
191
|
*/
|
|
191
192
|
const describeToolsCommand = new commander.Command("describe-tools").description("Describe specific MCP tools").argument("<toolNames...>", "Tool names to describe").option("-c, --config <path>", "Path to MCP server configuration file").option("-s, --server <name>", "Filter by server name").option("-j, --json", "Output as JSON", false).action(async (toolNames, options) => {
|
|
192
193
|
try {
|
|
193
|
-
|
|
194
|
-
|
|
194
|
+
const configFilePath = options.config || require_http.findConfigFile();
|
|
195
|
+
if (!configFilePath) {
|
|
196
|
+
console.error("Error: No config file found. Use --config or create mcp-config.yaml");
|
|
195
197
|
process.exit(1);
|
|
196
198
|
}
|
|
197
|
-
const config = await new require_http.ConfigFetcherService({ configFilePath
|
|
199
|
+
const config = await new require_http.ConfigFetcherService({ configFilePath }).fetchConfiguration();
|
|
198
200
|
const clientManager = new require_http.McpClientManagerService();
|
|
199
201
|
const connectionPromises = Object.entries(config.mcpServers).map(async ([serverName, serverConfig]) => {
|
|
200
202
|
try {
|
|
@@ -290,8 +292,9 @@ const describeToolsCommand = new commander.Command("describe-tools").description
|
|
|
290
292
|
*/
|
|
291
293
|
const useToolCommand = new commander.Command("use-tool").description("Execute an MCP tool with arguments").argument("<toolName>", "Tool name to execute").option("-c, --config <path>", "Path to MCP server configuration file").option("-s, --server <name>", "Server name (required if tool exists on multiple servers)").option("-a, --args <json>", "Tool arguments as JSON string", "{}").option("-j, --json", "Output as JSON", false).action(async (toolName, options) => {
|
|
292
294
|
try {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
+
const configFilePath = options.config || require_http.findConfigFile();
|
|
296
|
+
if (!configFilePath) {
|
|
297
|
+
console.error("Error: No config file found. Use --config or create mcp-config.yaml");
|
|
295
298
|
process.exit(1);
|
|
296
299
|
}
|
|
297
300
|
let toolArgs = {};
|
|
@@ -301,7 +304,7 @@ const useToolCommand = new commander.Command("use-tool").description("Execute an
|
|
|
301
304
|
console.error("Error: Invalid JSON in --args");
|
|
302
305
|
process.exit(1);
|
|
303
306
|
}
|
|
304
|
-
const config = await new require_http.ConfigFetcherService({ configFilePath
|
|
307
|
+
const config = await new require_http.ConfigFetcherService({ configFilePath }).fetchConfiguration();
|
|
305
308
|
const clientManager = new require_http.McpClientManagerService();
|
|
306
309
|
const connectionPromises = Object.entries(config.mcpServers).map(async ([serverName, serverConfig]) => {
|
|
307
310
|
try {
|
|
@@ -457,7 +460,7 @@ const initCommand = new commander.Command("init").description("Initialize MCP co
|
|
|
457
460
|
|
|
458
461
|
//#endregion
|
|
459
462
|
//#region package.json
|
|
460
|
-
var version = "0.2.
|
|
463
|
+
var version = "0.2.2";
|
|
461
464
|
|
|
462
465
|
//#endregion
|
|
463
466
|
//#region src/cli.ts
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as findConfigFile, i as createServer, n as SseTransportHandler, o as McpClientManagerService, r as StdioTransportHandler, s as ConfigFetcherService, t as HttpTransportHandler } from "./http-CzQfsUEI.mjs";
|
|
3
3
|
import { writeFile } from "node:fs/promises";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import { Command } from "commander";
|
|
@@ -63,7 +63,7 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
|
|
|
63
63
|
try {
|
|
64
64
|
const transportType = options.type.toLowerCase();
|
|
65
65
|
const serverOptions = {
|
|
66
|
-
configFilePath: options.config,
|
|
66
|
+
configFilePath: options.config || findConfigFile(),
|
|
67
67
|
noCache: options.cache === false
|
|
68
68
|
};
|
|
69
69
|
if (transportType === "stdio") await startServer(new StdioTransportHandler(await createServer(serverOptions)));
|
|
@@ -115,11 +115,12 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
|
|
|
115
115
|
*/
|
|
116
116
|
const listToolsCommand = new Command("list-tools").description("List all available tools from connected MCP servers").option("-c, --config <path>", "Path to MCP server configuration file").option("-s, --server <name>", "Filter by server name").option("-j, --json", "Output as JSON", false).action(async (options) => {
|
|
117
117
|
try {
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
const configFilePath = options.config || findConfigFile();
|
|
119
|
+
if (!configFilePath) {
|
|
120
|
+
console.error("Error: No config file found. Use --config or create mcp-config.yaml");
|
|
120
121
|
process.exit(1);
|
|
121
122
|
}
|
|
122
|
-
const config = await new ConfigFetcherService({ configFilePath
|
|
123
|
+
const config = await new ConfigFetcherService({ configFilePath }).fetchConfiguration();
|
|
123
124
|
const clientManager = new McpClientManagerService();
|
|
124
125
|
const connectionPromises = Object.entries(config.mcpServers).map(async ([serverName, serverConfig]) => {
|
|
125
126
|
try {
|
|
@@ -190,11 +191,12 @@ const listToolsCommand = new Command("list-tools").description("List all availab
|
|
|
190
191
|
*/
|
|
191
192
|
const describeToolsCommand = new Command("describe-tools").description("Describe specific MCP tools").argument("<toolNames...>", "Tool names to describe").option("-c, --config <path>", "Path to MCP server configuration file").option("-s, --server <name>", "Filter by server name").option("-j, --json", "Output as JSON", false).action(async (toolNames, options) => {
|
|
192
193
|
try {
|
|
193
|
-
|
|
194
|
-
|
|
194
|
+
const configFilePath = options.config || findConfigFile();
|
|
195
|
+
if (!configFilePath) {
|
|
196
|
+
console.error("Error: No config file found. Use --config or create mcp-config.yaml");
|
|
195
197
|
process.exit(1);
|
|
196
198
|
}
|
|
197
|
-
const config = await new ConfigFetcherService({ configFilePath
|
|
199
|
+
const config = await new ConfigFetcherService({ configFilePath }).fetchConfiguration();
|
|
198
200
|
const clientManager = new McpClientManagerService();
|
|
199
201
|
const connectionPromises = Object.entries(config.mcpServers).map(async ([serverName, serverConfig]) => {
|
|
200
202
|
try {
|
|
@@ -290,8 +292,9 @@ const describeToolsCommand = new Command("describe-tools").description("Describe
|
|
|
290
292
|
*/
|
|
291
293
|
const useToolCommand = new Command("use-tool").description("Execute an MCP tool with arguments").argument("<toolName>", "Tool name to execute").option("-c, --config <path>", "Path to MCP server configuration file").option("-s, --server <name>", "Server name (required if tool exists on multiple servers)").option("-a, --args <json>", "Tool arguments as JSON string", "{}").option("-j, --json", "Output as JSON", false).action(async (toolName, options) => {
|
|
292
294
|
try {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
+
const configFilePath = options.config || findConfigFile();
|
|
296
|
+
if (!configFilePath) {
|
|
297
|
+
console.error("Error: No config file found. Use --config or create mcp-config.yaml");
|
|
295
298
|
process.exit(1);
|
|
296
299
|
}
|
|
297
300
|
let toolArgs = {};
|
|
@@ -301,7 +304,7 @@ const useToolCommand = new Command("use-tool").description("Execute an MCP tool
|
|
|
301
304
|
console.error("Error: Invalid JSON in --args");
|
|
302
305
|
process.exit(1);
|
|
303
306
|
}
|
|
304
|
-
const config = await new ConfigFetcherService({ configFilePath
|
|
307
|
+
const config = await new ConfigFetcherService({ configFilePath }).fetchConfiguration();
|
|
305
308
|
const clientManager = new McpClientManagerService();
|
|
306
309
|
const connectionPromises = Object.entries(config.mcpServers).map(async ([serverName, serverConfig]) => {
|
|
307
310
|
try {
|
|
@@ -457,7 +460,7 @@ const initCommand = new Command("init").description("Initialize MCP configuratio
|
|
|
457
460
|
|
|
458
461
|
//#endregion
|
|
459
462
|
//#region package.json
|
|
460
|
-
var version = "0.2.
|
|
463
|
+
var version = "0.2.2";
|
|
461
464
|
|
|
462
465
|
//#endregion
|
|
463
466
|
//#region src/cli.ts
|
|
@@ -976,6 +976,75 @@ var McpClientManagerService = class {
|
|
|
976
976
|
}
|
|
977
977
|
};
|
|
978
978
|
|
|
979
|
+
//#endregion
|
|
980
|
+
//#region src/utils/findConfigFile.ts
|
|
981
|
+
/**
|
|
982
|
+
* Config File Finder Utility
|
|
983
|
+
*
|
|
984
|
+
* DESIGN PATTERNS:
|
|
985
|
+
* - Utility function pattern for reusable logic
|
|
986
|
+
* - Fail-fast pattern with early returns
|
|
987
|
+
* - Environment variable configuration pattern
|
|
988
|
+
*
|
|
989
|
+
* CODING STANDARDS:
|
|
990
|
+
* - Use sync filesystem operations for config discovery (performance)
|
|
991
|
+
* - Check PROJECT_PATH environment variable first
|
|
992
|
+
* - Fall back to current working directory
|
|
993
|
+
* - Support both .yaml and .json extensions
|
|
994
|
+
* - Return null if no config file is found
|
|
995
|
+
*
|
|
996
|
+
* AVOID:
|
|
997
|
+
* - Throwing errors (return null instead for optional config)
|
|
998
|
+
* - Hardcoded file names without extension variants
|
|
999
|
+
* - Ignoring environment variables
|
|
1000
|
+
*/
|
|
1001
|
+
/**
|
|
1002
|
+
* Find MCP configuration file by checking PROJECT_PATH first, then cwd
|
|
1003
|
+
* Looks for both mcp-config.yaml and mcp-config.json
|
|
1004
|
+
*
|
|
1005
|
+
* @returns Absolute path to config file, or null if not found
|
|
1006
|
+
*/
|
|
1007
|
+
function findConfigFile() {
|
|
1008
|
+
const configFileNames = [
|
|
1009
|
+
"mcp-config.yaml",
|
|
1010
|
+
"mcp-config.yml",
|
|
1011
|
+
"mcp-config.json"
|
|
1012
|
+
];
|
|
1013
|
+
const projectPath = process.env.PROJECT_PATH;
|
|
1014
|
+
if (projectPath) for (const fileName of configFileNames) {
|
|
1015
|
+
const configPath = (0, node_path.resolve)(projectPath, fileName);
|
|
1016
|
+
if ((0, node_fs.existsSync)(configPath)) return configPath;
|
|
1017
|
+
}
|
|
1018
|
+
const cwd = process.cwd();
|
|
1019
|
+
for (const fileName of configFileNames) {
|
|
1020
|
+
const configPath = (0, node_path.join)(cwd, fileName);
|
|
1021
|
+
if ((0, node_fs.existsSync)(configPath)) return configPath;
|
|
1022
|
+
}
|
|
1023
|
+
return null;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
//#endregion
|
|
1027
|
+
//#region src/utils/parseToolName.ts
|
|
1028
|
+
/**
|
|
1029
|
+
* Parse tool name to extract server and actual tool name
|
|
1030
|
+
* Supports both plain tool names and prefixed format: {serverName}__{toolName}
|
|
1031
|
+
*
|
|
1032
|
+
* @param toolName - The tool name to parse (e.g., "my_tool" or "server__my_tool")
|
|
1033
|
+
* @returns Parsed result with optional serverName and actualToolName
|
|
1034
|
+
*
|
|
1035
|
+
* @example
|
|
1036
|
+
* parseToolName("my_tool") // { actualToolName: "my_tool" }
|
|
1037
|
+
* parseToolName("server__my_tool") // { serverName: "server", actualToolName: "my_tool" }
|
|
1038
|
+
*/
|
|
1039
|
+
function parseToolName(toolName) {
|
|
1040
|
+
const separatorIndex = toolName.indexOf("__");
|
|
1041
|
+
if (separatorIndex > 0) return {
|
|
1042
|
+
serverName: toolName.substring(0, separatorIndex),
|
|
1043
|
+
actualToolName: toolName.substring(separatorIndex + 2)
|
|
1044
|
+
};
|
|
1045
|
+
return { actualToolName: toolName };
|
|
1046
|
+
}
|
|
1047
|
+
|
|
979
1048
|
//#endregion
|
|
980
1049
|
//#region src/tools/DescribeToolsTool.ts
|
|
981
1050
|
var DescribeToolsTool = class DescribeToolsTool {
|
|
@@ -986,46 +1055,50 @@ var DescribeToolsTool = class DescribeToolsTool {
|
|
|
986
1055
|
}
|
|
987
1056
|
async getDefinition() {
|
|
988
1057
|
const clients = this.clientManager.getAllClients();
|
|
989
|
-
const
|
|
1058
|
+
const toolToServers = /* @__PURE__ */ new Map();
|
|
1059
|
+
const serverToolsMap = /* @__PURE__ */ new Map();
|
|
1060
|
+
await Promise.all(clients.map(async (client) => {
|
|
990
1061
|
try {
|
|
991
1062
|
const tools = await client.listTools();
|
|
992
1063
|
const blacklist = new Set(client.toolBlacklist || []);
|
|
993
1064
|
const filteredTools = tools.filter((t) => !blacklist.has(t.name));
|
|
994
|
-
|
|
995
|
-
const
|
|
996
|
-
|
|
1065
|
+
serverToolsMap.set(client.serverName, filteredTools);
|
|
1066
|
+
for (const tool of filteredTools) {
|
|
1067
|
+
if (!toolToServers.has(tool.name)) toolToServers.set(tool.name, []);
|
|
1068
|
+
toolToServers.get(tool.name).push(client.serverName);
|
|
1069
|
+
}
|
|
997
1070
|
} catch (error) {
|
|
998
1071
|
console.error(`Failed to list tools from ${client.serverName}:`, error);
|
|
999
|
-
|
|
1000
|
-
return `\n\n**Server: ${client.serverName}**${instructionLine}\n`;
|
|
1072
|
+
serverToolsMap.set(client.serverName, []);
|
|
1001
1073
|
}
|
|
1002
1074
|
}));
|
|
1075
|
+
const serverDescriptions = clients.map((client) => {
|
|
1076
|
+
const tools = serverToolsMap.get(client.serverName) || [];
|
|
1077
|
+
const formatToolName = (toolName) => {
|
|
1078
|
+
return (toolToServers.get(toolName) || []).length > 1 ? `${client.serverName}__${toolName}` : toolName;
|
|
1079
|
+
};
|
|
1080
|
+
const toolList = client.omitToolDescription ? tools.map((t) => formatToolName(t.name)).join(", ") : tools.map((t) => `${formatToolName(t.name)}: """${t.description || "No description"}"""`).join("\n");
|
|
1081
|
+
const instructionLine = client.serverInstruction ? `\n"""${client.serverInstruction}"""` : "";
|
|
1082
|
+
return `\n\n### Server: ${client.serverName}${instructionLine}\n\n- Available tools:\n${toolList || "No tools available"}`;
|
|
1083
|
+
});
|
|
1003
1084
|
return {
|
|
1004
1085
|
name: DescribeToolsTool.TOOL_NAME,
|
|
1005
|
-
description:
|
|
1006
|
-
|
|
1007
|
-
## Available MCP Servers:${serverDescriptions.join("")}
|
|
1086
|
+
description: `## Available MCP Servers:${serverDescriptions.join("")}
|
|
1008
1087
|
|
|
1009
1088
|
## Usage:
|
|
1010
|
-
|
|
1089
|
+
Before you use any tools above, you MUST call this tool with a list of tool names to learn how to use them properly before use_tool; this includes:
|
|
1011
1090
|
- Arguments schema needed to pass to the tool use
|
|
1012
1091
|
- Description about each tool
|
|
1013
1092
|
|
|
1014
1093
|
This tool is optimized for batch queries - you can request multiple tools at once for better performance.`,
|
|
1015
1094
|
inputSchema: {
|
|
1016
1095
|
type: "object",
|
|
1017
|
-
properties: {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
},
|
|
1024
|
-
serverName: {
|
|
1025
|
-
type: "string",
|
|
1026
|
-
description: "Optional server name to search within. If not specified, searches all servers."
|
|
1027
|
-
}
|
|
1028
|
-
},
|
|
1096
|
+
properties: { toolNames: {
|
|
1097
|
+
type: "array",
|
|
1098
|
+
items: { type: "string" },
|
|
1099
|
+
description: "List of tool names to get detailed information about",
|
|
1100
|
+
minItems: 1
|
|
1101
|
+
} },
|
|
1029
1102
|
required: ["toolNames"],
|
|
1030
1103
|
additionalProperties: false
|
|
1031
1104
|
}
|
|
@@ -1033,7 +1106,7 @@ This tool is optimized for batch queries - you can request multiple tools at onc
|
|
|
1033
1106
|
}
|
|
1034
1107
|
async execute(input) {
|
|
1035
1108
|
try {
|
|
1036
|
-
const { toolNames
|
|
1109
|
+
const { toolNames } = input;
|
|
1037
1110
|
const clients = this.clientManager.getAllClients();
|
|
1038
1111
|
if (!toolNames || toolNames.length === 0) return {
|
|
1039
1112
|
content: [{
|
|
@@ -1042,127 +1115,85 @@ This tool is optimized for batch queries - you can request multiple tools at onc
|
|
|
1042
1115
|
}],
|
|
1043
1116
|
isError: true
|
|
1044
1117
|
};
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
content: [{
|
|
1049
|
-
type: "text",
|
|
1050
|
-
text: `Server "${serverName}" not found. Available servers: ${clients.map((c) => c.serverName).join(", ")}`
|
|
1051
|
-
}],
|
|
1052
|
-
isError: true
|
|
1053
|
-
};
|
|
1054
|
-
const tools = await client.listTools();
|
|
1055
|
-
const blacklist = new Set(client.toolBlacklist || []);
|
|
1056
|
-
const filteredTools = tools.filter((t) => !blacklist.has(t.name));
|
|
1057
|
-
const foundTools$1 = [];
|
|
1058
|
-
const notFoundTools$1 = [];
|
|
1059
|
-
for (const toolName of toolNames) {
|
|
1060
|
-
if (blacklist.has(toolName)) {
|
|
1061
|
-
notFoundTools$1.push(toolName);
|
|
1062
|
-
continue;
|
|
1063
|
-
}
|
|
1064
|
-
const tool = filteredTools.find((t) => t.name === toolName);
|
|
1065
|
-
if (tool) foundTools$1.push({
|
|
1066
|
-
server: serverName,
|
|
1067
|
-
tool: {
|
|
1068
|
-
name: tool.name,
|
|
1069
|
-
description: tool.description,
|
|
1070
|
-
inputSchema: tool.inputSchema
|
|
1071
|
-
}
|
|
1072
|
-
});
|
|
1073
|
-
else notFoundTools$1.push(toolName);
|
|
1074
|
-
}
|
|
1075
|
-
if (foundTools$1.length === 0) return {
|
|
1076
|
-
content: [{
|
|
1077
|
-
type: "text",
|
|
1078
|
-
text: `None of the requested tools found on server "${serverName}".\nRequested: ${toolNames.join(", ")}\nAvailable tools: ${tools.map((t) => t.name).join(", ")}`
|
|
1079
|
-
}],
|
|
1080
|
-
isError: true
|
|
1081
|
-
};
|
|
1082
|
-
const result$1 = { tools: foundTools$1 };
|
|
1083
|
-
if (notFoundTools$1.length > 0) {
|
|
1084
|
-
result$1.notFound = notFoundTools$1;
|
|
1085
|
-
result$1.warning = `Some tools were not found on server "${serverName}": ${notFoundTools$1.join(", ")}`;
|
|
1086
|
-
}
|
|
1087
|
-
return { content: [{
|
|
1088
|
-
type: "text",
|
|
1089
|
-
text: JSON.stringify(result$1, null, 2)
|
|
1090
|
-
}] };
|
|
1091
|
-
}
|
|
1092
|
-
const foundTools = [];
|
|
1093
|
-
const notFoundTools = [...toolNames];
|
|
1094
|
-
const toolMatches = /* @__PURE__ */ new Map();
|
|
1095
|
-
const results = await Promise.all(clients.map(async (client) => {
|
|
1118
|
+
const serverToolsMap = /* @__PURE__ */ new Map();
|
|
1119
|
+
const toolToServers = /* @__PURE__ */ new Map();
|
|
1120
|
+
await Promise.all(clients.map(async (client) => {
|
|
1096
1121
|
try {
|
|
1097
1122
|
const tools = await client.listTools();
|
|
1098
1123
|
const blacklist = new Set(client.toolBlacklist || []);
|
|
1099
1124
|
const filteredTools = tools.filter((t) => !blacklist.has(t.name));
|
|
1100
|
-
|
|
1101
|
-
for (const
|
|
1102
|
-
if (
|
|
1103
|
-
|
|
1104
|
-
if (tool) matches.push({
|
|
1105
|
-
toolName,
|
|
1106
|
-
server: client.serverName,
|
|
1107
|
-
tool
|
|
1108
|
-
});
|
|
1125
|
+
serverToolsMap.set(client.serverName, filteredTools);
|
|
1126
|
+
for (const tool of filteredTools) {
|
|
1127
|
+
if (!toolToServers.has(tool.name)) toolToServers.set(tool.name, []);
|
|
1128
|
+
toolToServers.get(tool.name).push(client.serverName);
|
|
1109
1129
|
}
|
|
1110
|
-
return matches;
|
|
1111
1130
|
} catch (error) {
|
|
1112
1131
|
console.error(`Failed to list tools from ${client.serverName}:`, error);
|
|
1113
|
-
|
|
1132
|
+
serverToolsMap.set(client.serverName, []);
|
|
1114
1133
|
}
|
|
1115
1134
|
}));
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
foundTools.push({
|
|
1130
|
-
server: match.server,
|
|
1135
|
+
const foundTools = [];
|
|
1136
|
+
const notFoundTools = [];
|
|
1137
|
+
for (const requestedToolName of toolNames) {
|
|
1138
|
+
const { serverName, actualToolName } = parseToolName(requestedToolName);
|
|
1139
|
+
if (serverName) {
|
|
1140
|
+
const serverTools = serverToolsMap.get(serverName);
|
|
1141
|
+
if (!serverTools) {
|
|
1142
|
+
notFoundTools.push(requestedToolName);
|
|
1143
|
+
continue;
|
|
1144
|
+
}
|
|
1145
|
+
const tool = serverTools.find((t) => t.name === actualToolName);
|
|
1146
|
+
if (tool) foundTools.push({
|
|
1147
|
+
server: serverName,
|
|
1131
1148
|
tool: {
|
|
1132
|
-
name:
|
|
1133
|
-
description:
|
|
1134
|
-
inputSchema:
|
|
1149
|
+
name: tool.name,
|
|
1150
|
+
description: tool.description,
|
|
1151
|
+
inputSchema: tool.inputSchema
|
|
1135
1152
|
}
|
|
1136
1153
|
});
|
|
1137
|
-
|
|
1138
|
-
if (idx > -1) notFoundTools.splice(idx, 1);
|
|
1154
|
+
else notFoundTools.push(requestedToolName);
|
|
1139
1155
|
} else {
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
if (
|
|
1156
|
+
const servers = toolToServers.get(actualToolName);
|
|
1157
|
+
if (!servers || servers.length === 0) {
|
|
1158
|
+
notFoundTools.push(requestedToolName);
|
|
1159
|
+
continue;
|
|
1160
|
+
}
|
|
1161
|
+
if (servers.length === 1) {
|
|
1162
|
+
const server = servers[0];
|
|
1163
|
+
const tool = serverToolsMap.get(server).find((t) => t.name === actualToolName);
|
|
1164
|
+
foundTools.push({
|
|
1165
|
+
server,
|
|
1166
|
+
tool: {
|
|
1167
|
+
name: tool.name,
|
|
1168
|
+
description: tool.description,
|
|
1169
|
+
inputSchema: tool.inputSchema
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
} else for (const server of servers) {
|
|
1173
|
+
const tool = serverToolsMap.get(server).find((t) => t.name === actualToolName);
|
|
1174
|
+
foundTools.push({
|
|
1175
|
+
server,
|
|
1176
|
+
tool: {
|
|
1177
|
+
name: tool.name,
|
|
1178
|
+
description: tool.description,
|
|
1179
|
+
inputSchema: tool.inputSchema
|
|
1180
|
+
}
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1146
1183
|
}
|
|
1147
1184
|
}
|
|
1148
|
-
if (foundTools.length === 0
|
|
1185
|
+
if (foundTools.length === 0) return {
|
|
1149
1186
|
content: [{
|
|
1150
1187
|
type: "text",
|
|
1151
|
-
text: `None of the requested tools found on any connected server.\nRequested: ${toolNames.join(", ")}\nUse describe_tools
|
|
1188
|
+
text: `None of the requested tools found on any connected server.\nRequested: ${toolNames.join(", ")}\nUse describe_tools to see available tools.`
|
|
1152
1189
|
}],
|
|
1153
1190
|
isError: true
|
|
1154
1191
|
};
|
|
1155
1192
|
const result = { tools: foundTools };
|
|
1156
|
-
if (notFoundTools.length > 0)
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
message: `Tool "${item.toolName}" found on multiple servers: ${item.servers.join(", ")}. Please specify serverName to disambiguate.`
|
|
1161
|
-
}));
|
|
1162
|
-
const warnings = [];
|
|
1163
|
-
if (notFoundTools.length > 0) warnings.push(`Tools not found: ${notFoundTools.join(", ")}`);
|
|
1164
|
-
if (ambiguousTools.length > 0) warnings.push(`Ambiguous tools (specify serverName): ${ambiguousTools.map((t) => t.toolName).join(", ")}`);
|
|
1165
|
-
if (warnings.length > 0) result.warnings = warnings;
|
|
1193
|
+
if (notFoundTools.length > 0) {
|
|
1194
|
+
result.notFound = notFoundTools;
|
|
1195
|
+
result.warnings = [`Tools not found: ${notFoundTools.join(", ")}`];
|
|
1196
|
+
}
|
|
1166
1197
|
return { content: [{
|
|
1167
1198
|
type: "text",
|
|
1168
1199
|
text: JSON.stringify(result, null, 2)
|
|
@@ -1204,10 +1235,6 @@ var UseToolTool = class UseToolTool {
|
|
|
1204
1235
|
toolArgs: {
|
|
1205
1236
|
type: "object",
|
|
1206
1237
|
description: "Arguments to pass to the tool, as discovered from describe_tools"
|
|
1207
|
-
},
|
|
1208
|
-
serverName: {
|
|
1209
|
-
type: "string",
|
|
1210
|
-
description: "Optional server name to disambiguate when multiple servers have the same tool"
|
|
1211
1238
|
}
|
|
1212
1239
|
},
|
|
1213
1240
|
required: ["toolName"],
|
|
@@ -1217,8 +1244,9 @@ var UseToolTool = class UseToolTool {
|
|
|
1217
1244
|
}
|
|
1218
1245
|
async execute(input) {
|
|
1219
1246
|
try {
|
|
1220
|
-
const { toolName, toolArgs = {}
|
|
1247
|
+
const { toolName: inputToolName, toolArgs = {} } = input;
|
|
1221
1248
|
const clients = this.clientManager.getAllClients();
|
|
1249
|
+
const { serverName, actualToolName } = parseToolName(inputToolName);
|
|
1222
1250
|
if (serverName) {
|
|
1223
1251
|
const client$1 = this.clientManager.getClient(serverName);
|
|
1224
1252
|
if (!client$1) return {
|
|
@@ -1228,20 +1256,20 @@ var UseToolTool = class UseToolTool {
|
|
|
1228
1256
|
}],
|
|
1229
1257
|
isError: true
|
|
1230
1258
|
};
|
|
1231
|
-
if (client$1.toolBlacklist && client$1.toolBlacklist.includes(
|
|
1259
|
+
if (client$1.toolBlacklist && client$1.toolBlacklist.includes(actualToolName)) return {
|
|
1232
1260
|
content: [{
|
|
1233
1261
|
type: "text",
|
|
1234
|
-
text: `Tool "${
|
|
1262
|
+
text: `Tool "${actualToolName}" is blacklisted on server "${serverName}" and cannot be executed.`
|
|
1235
1263
|
}],
|
|
1236
1264
|
isError: true
|
|
1237
1265
|
};
|
|
1238
1266
|
try {
|
|
1239
|
-
return await client$1.callTool(
|
|
1267
|
+
return await client$1.callTool(actualToolName, toolArgs);
|
|
1240
1268
|
} catch (error) {
|
|
1241
1269
|
return {
|
|
1242
1270
|
content: [{
|
|
1243
1271
|
type: "text",
|
|
1244
|
-
text: `Failed to call tool "${
|
|
1272
|
+
text: `Failed to call tool "${actualToolName}" on server "${serverName}": ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1245
1273
|
}],
|
|
1246
1274
|
isError: true
|
|
1247
1275
|
};
|
|
@@ -1250,8 +1278,8 @@ var UseToolTool = class UseToolTool {
|
|
|
1250
1278
|
const matchingServers = [];
|
|
1251
1279
|
const results = await Promise.all(clients.map(async (client$1) => {
|
|
1252
1280
|
try {
|
|
1253
|
-
if (client$1.toolBlacklist && client$1.toolBlacklist.includes(
|
|
1254
|
-
if ((await client$1.listTools()).some((t) => t.name ===
|
|
1281
|
+
if (client$1.toolBlacklist && client$1.toolBlacklist.includes(actualToolName)) return null;
|
|
1282
|
+
if ((await client$1.listTools()).some((t) => t.name === actualToolName)) return client$1.serverName;
|
|
1255
1283
|
} catch (error) {
|
|
1256
1284
|
console.error(`Failed to list tools from ${client$1.serverName}:`, error);
|
|
1257
1285
|
}
|
|
@@ -1261,14 +1289,14 @@ var UseToolTool = class UseToolTool {
|
|
|
1261
1289
|
if (matchingServers.length === 0) return {
|
|
1262
1290
|
content: [{
|
|
1263
1291
|
type: "text",
|
|
1264
|
-
text: `Tool "${
|
|
1292
|
+
text: `Tool "${actualToolName}" not found on any connected server. Use describe_tools to see available tools.`
|
|
1265
1293
|
}],
|
|
1266
1294
|
isError: true
|
|
1267
1295
|
};
|
|
1268
1296
|
if (matchingServers.length > 1) return {
|
|
1269
1297
|
content: [{
|
|
1270
1298
|
type: "text",
|
|
1271
|
-
text: `
|
|
1299
|
+
text: `Tool "${actualToolName}" found on multiple servers. Use prefixed format to specify: ${matchingServers.map((s) => `${s}__${actualToolName}`).join(", ")}`
|
|
1272
1300
|
}],
|
|
1273
1301
|
isError: true
|
|
1274
1302
|
};
|
|
@@ -1282,12 +1310,12 @@ var UseToolTool = class UseToolTool {
|
|
|
1282
1310
|
isError: true
|
|
1283
1311
|
};
|
|
1284
1312
|
try {
|
|
1285
|
-
return await client.callTool(
|
|
1313
|
+
return await client.callTool(actualToolName, toolArgs);
|
|
1286
1314
|
} catch (error) {
|
|
1287
1315
|
return {
|
|
1288
1316
|
content: [{
|
|
1289
1317
|
type: "text",
|
|
1290
|
-
text: `Failed to call tool "${
|
|
1318
|
+
text: `Failed to call tool "${actualToolName}": ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1291
1319
|
}],
|
|
1292
1320
|
isError: true
|
|
1293
1321
|
};
|
|
@@ -1482,14 +1510,14 @@ var SseTransportHandler = class {
|
|
|
1482
1510
|
}
|
|
1483
1511
|
}
|
|
1484
1512
|
async start() {
|
|
1485
|
-
return new Promise((resolve, reject) => {
|
|
1513
|
+
return new Promise((resolve$1, reject) => {
|
|
1486
1514
|
try {
|
|
1487
1515
|
this.server = this.app.listen(this.config.port, this.config.host, () => {
|
|
1488
1516
|
console.error(`@agiflowai/one-mcp MCP server started with SSE transport on http://${this.config.host}:${this.config.port}`);
|
|
1489
1517
|
console.error(`SSE endpoint: http://${this.config.host}:${this.config.port}/sse`);
|
|
1490
1518
|
console.error(`Messages endpoint: http://${this.config.host}:${this.config.port}/messages`);
|
|
1491
1519
|
console.error(`Health check: http://${this.config.host}:${this.config.port}/health`);
|
|
1492
|
-
resolve();
|
|
1520
|
+
resolve$1();
|
|
1493
1521
|
});
|
|
1494
1522
|
this.server.on("error", (error) => {
|
|
1495
1523
|
reject(error);
|
|
@@ -1500,17 +1528,17 @@ var SseTransportHandler = class {
|
|
|
1500
1528
|
});
|
|
1501
1529
|
}
|
|
1502
1530
|
async stop() {
|
|
1503
|
-
return new Promise((resolve, reject) => {
|
|
1531
|
+
return new Promise((resolve$1, reject) => {
|
|
1504
1532
|
if (this.server) {
|
|
1505
1533
|
this.sessionManager.clear();
|
|
1506
1534
|
this.server.close((err) => {
|
|
1507
1535
|
if (err) reject(err);
|
|
1508
1536
|
else {
|
|
1509
1537
|
this.server = null;
|
|
1510
|
-
resolve();
|
|
1538
|
+
resolve$1();
|
|
1511
1539
|
}
|
|
1512
1540
|
});
|
|
1513
|
-
} else resolve();
|
|
1541
|
+
} else resolve$1();
|
|
1514
1542
|
});
|
|
1515
1543
|
}
|
|
1516
1544
|
getPort() {
|
|
@@ -1662,12 +1690,12 @@ var HttpTransportHandler = class {
|
|
|
1662
1690
|
this.sessionManager.deleteSession(sessionId);
|
|
1663
1691
|
}
|
|
1664
1692
|
async start() {
|
|
1665
|
-
return new Promise((resolve, reject) => {
|
|
1693
|
+
return new Promise((resolve$1, reject) => {
|
|
1666
1694
|
try {
|
|
1667
1695
|
this.server = this.app.listen(this.config.port, this.config.host, () => {
|
|
1668
1696
|
console.error(`@agiflowai/one-mcp MCP server started on http://${this.config.host}:${this.config.port}/mcp`);
|
|
1669
1697
|
console.error(`Health check: http://${this.config.host}:${this.config.port}/health`);
|
|
1670
|
-
resolve();
|
|
1698
|
+
resolve$1();
|
|
1671
1699
|
});
|
|
1672
1700
|
this.server.on("error", (error) => {
|
|
1673
1701
|
reject(error);
|
|
@@ -1678,17 +1706,17 @@ var HttpTransportHandler = class {
|
|
|
1678
1706
|
});
|
|
1679
1707
|
}
|
|
1680
1708
|
async stop() {
|
|
1681
|
-
return new Promise((resolve, reject) => {
|
|
1709
|
+
return new Promise((resolve$1, reject) => {
|
|
1682
1710
|
if (this.server) {
|
|
1683
1711
|
this.sessionManager.clear();
|
|
1684
1712
|
this.server.close((err) => {
|
|
1685
1713
|
if (err) reject(err);
|
|
1686
1714
|
else {
|
|
1687
1715
|
this.server = null;
|
|
1688
|
-
resolve();
|
|
1716
|
+
resolve$1();
|
|
1689
1717
|
}
|
|
1690
1718
|
});
|
|
1691
|
-
} else resolve();
|
|
1719
|
+
} else resolve$1();
|
|
1692
1720
|
});
|
|
1693
1721
|
}
|
|
1694
1722
|
getPort() {
|
|
@@ -1741,4 +1769,10 @@ Object.defineProperty(exports, 'createServer', {
|
|
|
1741
1769
|
get: function () {
|
|
1742
1770
|
return createServer;
|
|
1743
1771
|
}
|
|
1772
|
+
});
|
|
1773
|
+
Object.defineProperty(exports, 'findConfigFile', {
|
|
1774
|
+
enumerable: true,
|
|
1775
|
+
get: function () {
|
|
1776
|
+
return findConfigFile;
|
|
1777
|
+
}
|
|
1744
1778
|
});
|
|
@@ -5,7 +5,7 @@ import { existsSync } from "node:fs";
|
|
|
5
5
|
import yaml from "js-yaml";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
8
|
-
import { join } from "node:path";
|
|
8
|
+
import { join, resolve } from "node:path";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
11
11
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
@@ -951,6 +951,75 @@ var McpClientManagerService = class {
|
|
|
951
951
|
}
|
|
952
952
|
};
|
|
953
953
|
|
|
954
|
+
//#endregion
|
|
955
|
+
//#region src/utils/findConfigFile.ts
|
|
956
|
+
/**
|
|
957
|
+
* Config File Finder Utility
|
|
958
|
+
*
|
|
959
|
+
* DESIGN PATTERNS:
|
|
960
|
+
* - Utility function pattern for reusable logic
|
|
961
|
+
* - Fail-fast pattern with early returns
|
|
962
|
+
* - Environment variable configuration pattern
|
|
963
|
+
*
|
|
964
|
+
* CODING STANDARDS:
|
|
965
|
+
* - Use sync filesystem operations for config discovery (performance)
|
|
966
|
+
* - Check PROJECT_PATH environment variable first
|
|
967
|
+
* - Fall back to current working directory
|
|
968
|
+
* - Support both .yaml and .json extensions
|
|
969
|
+
* - Return null if no config file is found
|
|
970
|
+
*
|
|
971
|
+
* AVOID:
|
|
972
|
+
* - Throwing errors (return null instead for optional config)
|
|
973
|
+
* - Hardcoded file names without extension variants
|
|
974
|
+
* - Ignoring environment variables
|
|
975
|
+
*/
|
|
976
|
+
/**
|
|
977
|
+
* Find MCP configuration file by checking PROJECT_PATH first, then cwd
|
|
978
|
+
* Looks for both mcp-config.yaml and mcp-config.json
|
|
979
|
+
*
|
|
980
|
+
* @returns Absolute path to config file, or null if not found
|
|
981
|
+
*/
|
|
982
|
+
function findConfigFile() {
|
|
983
|
+
const configFileNames = [
|
|
984
|
+
"mcp-config.yaml",
|
|
985
|
+
"mcp-config.yml",
|
|
986
|
+
"mcp-config.json"
|
|
987
|
+
];
|
|
988
|
+
const projectPath = process.env.PROJECT_PATH;
|
|
989
|
+
if (projectPath) for (const fileName of configFileNames) {
|
|
990
|
+
const configPath = resolve(projectPath, fileName);
|
|
991
|
+
if (existsSync(configPath)) return configPath;
|
|
992
|
+
}
|
|
993
|
+
const cwd = process.cwd();
|
|
994
|
+
for (const fileName of configFileNames) {
|
|
995
|
+
const configPath = join(cwd, fileName);
|
|
996
|
+
if (existsSync(configPath)) return configPath;
|
|
997
|
+
}
|
|
998
|
+
return null;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
//#endregion
|
|
1002
|
+
//#region src/utils/parseToolName.ts
|
|
1003
|
+
/**
|
|
1004
|
+
* Parse tool name to extract server and actual tool name
|
|
1005
|
+
* Supports both plain tool names and prefixed format: {serverName}__{toolName}
|
|
1006
|
+
*
|
|
1007
|
+
* @param toolName - The tool name to parse (e.g., "my_tool" or "server__my_tool")
|
|
1008
|
+
* @returns Parsed result with optional serverName and actualToolName
|
|
1009
|
+
*
|
|
1010
|
+
* @example
|
|
1011
|
+
* parseToolName("my_tool") // { actualToolName: "my_tool" }
|
|
1012
|
+
* parseToolName("server__my_tool") // { serverName: "server", actualToolName: "my_tool" }
|
|
1013
|
+
*/
|
|
1014
|
+
function parseToolName(toolName) {
|
|
1015
|
+
const separatorIndex = toolName.indexOf("__");
|
|
1016
|
+
if (separatorIndex > 0) return {
|
|
1017
|
+
serverName: toolName.substring(0, separatorIndex),
|
|
1018
|
+
actualToolName: toolName.substring(separatorIndex + 2)
|
|
1019
|
+
};
|
|
1020
|
+
return { actualToolName: toolName };
|
|
1021
|
+
}
|
|
1022
|
+
|
|
954
1023
|
//#endregion
|
|
955
1024
|
//#region src/tools/DescribeToolsTool.ts
|
|
956
1025
|
var DescribeToolsTool = class DescribeToolsTool {
|
|
@@ -961,46 +1030,50 @@ var DescribeToolsTool = class DescribeToolsTool {
|
|
|
961
1030
|
}
|
|
962
1031
|
async getDefinition() {
|
|
963
1032
|
const clients = this.clientManager.getAllClients();
|
|
964
|
-
const
|
|
1033
|
+
const toolToServers = /* @__PURE__ */ new Map();
|
|
1034
|
+
const serverToolsMap = /* @__PURE__ */ new Map();
|
|
1035
|
+
await Promise.all(clients.map(async (client) => {
|
|
965
1036
|
try {
|
|
966
1037
|
const tools = await client.listTools();
|
|
967
1038
|
const blacklist = new Set(client.toolBlacklist || []);
|
|
968
1039
|
const filteredTools = tools.filter((t) => !blacklist.has(t.name));
|
|
969
|
-
|
|
970
|
-
const
|
|
971
|
-
|
|
1040
|
+
serverToolsMap.set(client.serverName, filteredTools);
|
|
1041
|
+
for (const tool of filteredTools) {
|
|
1042
|
+
if (!toolToServers.has(tool.name)) toolToServers.set(tool.name, []);
|
|
1043
|
+
toolToServers.get(tool.name).push(client.serverName);
|
|
1044
|
+
}
|
|
972
1045
|
} catch (error) {
|
|
973
1046
|
console.error(`Failed to list tools from ${client.serverName}:`, error);
|
|
974
|
-
|
|
975
|
-
return `\n\n**Server: ${client.serverName}**${instructionLine}\n`;
|
|
1047
|
+
serverToolsMap.set(client.serverName, []);
|
|
976
1048
|
}
|
|
977
1049
|
}));
|
|
1050
|
+
const serverDescriptions = clients.map((client) => {
|
|
1051
|
+
const tools = serverToolsMap.get(client.serverName) || [];
|
|
1052
|
+
const formatToolName = (toolName) => {
|
|
1053
|
+
return (toolToServers.get(toolName) || []).length > 1 ? `${client.serverName}__${toolName}` : toolName;
|
|
1054
|
+
};
|
|
1055
|
+
const toolList = client.omitToolDescription ? tools.map((t) => formatToolName(t.name)).join(", ") : tools.map((t) => `${formatToolName(t.name)}: """${t.description || "No description"}"""`).join("\n");
|
|
1056
|
+
const instructionLine = client.serverInstruction ? `\n"""${client.serverInstruction}"""` : "";
|
|
1057
|
+
return `\n\n### Server: ${client.serverName}${instructionLine}\n\n- Available tools:\n${toolList || "No tools available"}`;
|
|
1058
|
+
});
|
|
978
1059
|
return {
|
|
979
1060
|
name: DescribeToolsTool.TOOL_NAME,
|
|
980
|
-
description:
|
|
981
|
-
|
|
982
|
-
## Available MCP Servers:${serverDescriptions.join("")}
|
|
1061
|
+
description: `## Available MCP Servers:${serverDescriptions.join("")}
|
|
983
1062
|
|
|
984
1063
|
## Usage:
|
|
985
|
-
|
|
1064
|
+
Before you use any tools above, you MUST call this tool with a list of tool names to learn how to use them properly before use_tool; this includes:
|
|
986
1065
|
- Arguments schema needed to pass to the tool use
|
|
987
1066
|
- Description about each tool
|
|
988
1067
|
|
|
989
1068
|
This tool is optimized for batch queries - you can request multiple tools at once for better performance.`,
|
|
990
1069
|
inputSchema: {
|
|
991
1070
|
type: "object",
|
|
992
|
-
properties: {
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
},
|
|
999
|
-
serverName: {
|
|
1000
|
-
type: "string",
|
|
1001
|
-
description: "Optional server name to search within. If not specified, searches all servers."
|
|
1002
|
-
}
|
|
1003
|
-
},
|
|
1071
|
+
properties: { toolNames: {
|
|
1072
|
+
type: "array",
|
|
1073
|
+
items: { type: "string" },
|
|
1074
|
+
description: "List of tool names to get detailed information about",
|
|
1075
|
+
minItems: 1
|
|
1076
|
+
} },
|
|
1004
1077
|
required: ["toolNames"],
|
|
1005
1078
|
additionalProperties: false
|
|
1006
1079
|
}
|
|
@@ -1008,7 +1081,7 @@ This tool is optimized for batch queries - you can request multiple tools at onc
|
|
|
1008
1081
|
}
|
|
1009
1082
|
async execute(input) {
|
|
1010
1083
|
try {
|
|
1011
|
-
const { toolNames
|
|
1084
|
+
const { toolNames } = input;
|
|
1012
1085
|
const clients = this.clientManager.getAllClients();
|
|
1013
1086
|
if (!toolNames || toolNames.length === 0) return {
|
|
1014
1087
|
content: [{
|
|
@@ -1017,127 +1090,85 @@ This tool is optimized for batch queries - you can request multiple tools at onc
|
|
|
1017
1090
|
}],
|
|
1018
1091
|
isError: true
|
|
1019
1092
|
};
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
content: [{
|
|
1024
|
-
type: "text",
|
|
1025
|
-
text: `Server "${serverName}" not found. Available servers: ${clients.map((c) => c.serverName).join(", ")}`
|
|
1026
|
-
}],
|
|
1027
|
-
isError: true
|
|
1028
|
-
};
|
|
1029
|
-
const tools = await client.listTools();
|
|
1030
|
-
const blacklist = new Set(client.toolBlacklist || []);
|
|
1031
|
-
const filteredTools = tools.filter((t) => !blacklist.has(t.name));
|
|
1032
|
-
const foundTools$1 = [];
|
|
1033
|
-
const notFoundTools$1 = [];
|
|
1034
|
-
for (const toolName of toolNames) {
|
|
1035
|
-
if (blacklist.has(toolName)) {
|
|
1036
|
-
notFoundTools$1.push(toolName);
|
|
1037
|
-
continue;
|
|
1038
|
-
}
|
|
1039
|
-
const tool = filteredTools.find((t) => t.name === toolName);
|
|
1040
|
-
if (tool) foundTools$1.push({
|
|
1041
|
-
server: serverName,
|
|
1042
|
-
tool: {
|
|
1043
|
-
name: tool.name,
|
|
1044
|
-
description: tool.description,
|
|
1045
|
-
inputSchema: tool.inputSchema
|
|
1046
|
-
}
|
|
1047
|
-
});
|
|
1048
|
-
else notFoundTools$1.push(toolName);
|
|
1049
|
-
}
|
|
1050
|
-
if (foundTools$1.length === 0) return {
|
|
1051
|
-
content: [{
|
|
1052
|
-
type: "text",
|
|
1053
|
-
text: `None of the requested tools found on server "${serverName}".\nRequested: ${toolNames.join(", ")}\nAvailable tools: ${tools.map((t) => t.name).join(", ")}`
|
|
1054
|
-
}],
|
|
1055
|
-
isError: true
|
|
1056
|
-
};
|
|
1057
|
-
const result$1 = { tools: foundTools$1 };
|
|
1058
|
-
if (notFoundTools$1.length > 0) {
|
|
1059
|
-
result$1.notFound = notFoundTools$1;
|
|
1060
|
-
result$1.warning = `Some tools were not found on server "${serverName}": ${notFoundTools$1.join(", ")}`;
|
|
1061
|
-
}
|
|
1062
|
-
return { content: [{
|
|
1063
|
-
type: "text",
|
|
1064
|
-
text: JSON.stringify(result$1, null, 2)
|
|
1065
|
-
}] };
|
|
1066
|
-
}
|
|
1067
|
-
const foundTools = [];
|
|
1068
|
-
const notFoundTools = [...toolNames];
|
|
1069
|
-
const toolMatches = /* @__PURE__ */ new Map();
|
|
1070
|
-
const results = await Promise.all(clients.map(async (client) => {
|
|
1093
|
+
const serverToolsMap = /* @__PURE__ */ new Map();
|
|
1094
|
+
const toolToServers = /* @__PURE__ */ new Map();
|
|
1095
|
+
await Promise.all(clients.map(async (client) => {
|
|
1071
1096
|
try {
|
|
1072
1097
|
const tools = await client.listTools();
|
|
1073
1098
|
const blacklist = new Set(client.toolBlacklist || []);
|
|
1074
1099
|
const filteredTools = tools.filter((t) => !blacklist.has(t.name));
|
|
1075
|
-
|
|
1076
|
-
for (const
|
|
1077
|
-
if (
|
|
1078
|
-
|
|
1079
|
-
if (tool) matches.push({
|
|
1080
|
-
toolName,
|
|
1081
|
-
server: client.serverName,
|
|
1082
|
-
tool
|
|
1083
|
-
});
|
|
1100
|
+
serverToolsMap.set(client.serverName, filteredTools);
|
|
1101
|
+
for (const tool of filteredTools) {
|
|
1102
|
+
if (!toolToServers.has(tool.name)) toolToServers.set(tool.name, []);
|
|
1103
|
+
toolToServers.get(tool.name).push(client.serverName);
|
|
1084
1104
|
}
|
|
1085
|
-
return matches;
|
|
1086
1105
|
} catch (error) {
|
|
1087
1106
|
console.error(`Failed to list tools from ${client.serverName}:`, error);
|
|
1088
|
-
|
|
1107
|
+
serverToolsMap.set(client.serverName, []);
|
|
1089
1108
|
}
|
|
1090
1109
|
}));
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
foundTools.push({
|
|
1105
|
-
server: match.server,
|
|
1110
|
+
const foundTools = [];
|
|
1111
|
+
const notFoundTools = [];
|
|
1112
|
+
for (const requestedToolName of toolNames) {
|
|
1113
|
+
const { serverName, actualToolName } = parseToolName(requestedToolName);
|
|
1114
|
+
if (serverName) {
|
|
1115
|
+
const serverTools = serverToolsMap.get(serverName);
|
|
1116
|
+
if (!serverTools) {
|
|
1117
|
+
notFoundTools.push(requestedToolName);
|
|
1118
|
+
continue;
|
|
1119
|
+
}
|
|
1120
|
+
const tool = serverTools.find((t) => t.name === actualToolName);
|
|
1121
|
+
if (tool) foundTools.push({
|
|
1122
|
+
server: serverName,
|
|
1106
1123
|
tool: {
|
|
1107
|
-
name:
|
|
1108
|
-
description:
|
|
1109
|
-
inputSchema:
|
|
1124
|
+
name: tool.name,
|
|
1125
|
+
description: tool.description,
|
|
1126
|
+
inputSchema: tool.inputSchema
|
|
1110
1127
|
}
|
|
1111
1128
|
});
|
|
1112
|
-
|
|
1113
|
-
if (idx > -1) notFoundTools.splice(idx, 1);
|
|
1129
|
+
else notFoundTools.push(requestedToolName);
|
|
1114
1130
|
} else {
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
if (
|
|
1131
|
+
const servers = toolToServers.get(actualToolName);
|
|
1132
|
+
if (!servers || servers.length === 0) {
|
|
1133
|
+
notFoundTools.push(requestedToolName);
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
if (servers.length === 1) {
|
|
1137
|
+
const server = servers[0];
|
|
1138
|
+
const tool = serverToolsMap.get(server).find((t) => t.name === actualToolName);
|
|
1139
|
+
foundTools.push({
|
|
1140
|
+
server,
|
|
1141
|
+
tool: {
|
|
1142
|
+
name: tool.name,
|
|
1143
|
+
description: tool.description,
|
|
1144
|
+
inputSchema: tool.inputSchema
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
} else for (const server of servers) {
|
|
1148
|
+
const tool = serverToolsMap.get(server).find((t) => t.name === actualToolName);
|
|
1149
|
+
foundTools.push({
|
|
1150
|
+
server,
|
|
1151
|
+
tool: {
|
|
1152
|
+
name: tool.name,
|
|
1153
|
+
description: tool.description,
|
|
1154
|
+
inputSchema: tool.inputSchema
|
|
1155
|
+
}
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1121
1158
|
}
|
|
1122
1159
|
}
|
|
1123
|
-
if (foundTools.length === 0
|
|
1160
|
+
if (foundTools.length === 0) return {
|
|
1124
1161
|
content: [{
|
|
1125
1162
|
type: "text",
|
|
1126
|
-
text: `None of the requested tools found on any connected server.\nRequested: ${toolNames.join(", ")}\nUse describe_tools
|
|
1163
|
+
text: `None of the requested tools found on any connected server.\nRequested: ${toolNames.join(", ")}\nUse describe_tools to see available tools.`
|
|
1127
1164
|
}],
|
|
1128
1165
|
isError: true
|
|
1129
1166
|
};
|
|
1130
1167
|
const result = { tools: foundTools };
|
|
1131
|
-
if (notFoundTools.length > 0)
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
message: `Tool "${item.toolName}" found on multiple servers: ${item.servers.join(", ")}. Please specify serverName to disambiguate.`
|
|
1136
|
-
}));
|
|
1137
|
-
const warnings = [];
|
|
1138
|
-
if (notFoundTools.length > 0) warnings.push(`Tools not found: ${notFoundTools.join(", ")}`);
|
|
1139
|
-
if (ambiguousTools.length > 0) warnings.push(`Ambiguous tools (specify serverName): ${ambiguousTools.map((t) => t.toolName).join(", ")}`);
|
|
1140
|
-
if (warnings.length > 0) result.warnings = warnings;
|
|
1168
|
+
if (notFoundTools.length > 0) {
|
|
1169
|
+
result.notFound = notFoundTools;
|
|
1170
|
+
result.warnings = [`Tools not found: ${notFoundTools.join(", ")}`];
|
|
1171
|
+
}
|
|
1141
1172
|
return { content: [{
|
|
1142
1173
|
type: "text",
|
|
1143
1174
|
text: JSON.stringify(result, null, 2)
|
|
@@ -1179,10 +1210,6 @@ var UseToolTool = class UseToolTool {
|
|
|
1179
1210
|
toolArgs: {
|
|
1180
1211
|
type: "object",
|
|
1181
1212
|
description: "Arguments to pass to the tool, as discovered from describe_tools"
|
|
1182
|
-
},
|
|
1183
|
-
serverName: {
|
|
1184
|
-
type: "string",
|
|
1185
|
-
description: "Optional server name to disambiguate when multiple servers have the same tool"
|
|
1186
1213
|
}
|
|
1187
1214
|
},
|
|
1188
1215
|
required: ["toolName"],
|
|
@@ -1192,8 +1219,9 @@ var UseToolTool = class UseToolTool {
|
|
|
1192
1219
|
}
|
|
1193
1220
|
async execute(input) {
|
|
1194
1221
|
try {
|
|
1195
|
-
const { toolName, toolArgs = {}
|
|
1222
|
+
const { toolName: inputToolName, toolArgs = {} } = input;
|
|
1196
1223
|
const clients = this.clientManager.getAllClients();
|
|
1224
|
+
const { serverName, actualToolName } = parseToolName(inputToolName);
|
|
1197
1225
|
if (serverName) {
|
|
1198
1226
|
const client$1 = this.clientManager.getClient(serverName);
|
|
1199
1227
|
if (!client$1) return {
|
|
@@ -1203,20 +1231,20 @@ var UseToolTool = class UseToolTool {
|
|
|
1203
1231
|
}],
|
|
1204
1232
|
isError: true
|
|
1205
1233
|
};
|
|
1206
|
-
if (client$1.toolBlacklist && client$1.toolBlacklist.includes(
|
|
1234
|
+
if (client$1.toolBlacklist && client$1.toolBlacklist.includes(actualToolName)) return {
|
|
1207
1235
|
content: [{
|
|
1208
1236
|
type: "text",
|
|
1209
|
-
text: `Tool "${
|
|
1237
|
+
text: `Tool "${actualToolName}" is blacklisted on server "${serverName}" and cannot be executed.`
|
|
1210
1238
|
}],
|
|
1211
1239
|
isError: true
|
|
1212
1240
|
};
|
|
1213
1241
|
try {
|
|
1214
|
-
return await client$1.callTool(
|
|
1242
|
+
return await client$1.callTool(actualToolName, toolArgs);
|
|
1215
1243
|
} catch (error) {
|
|
1216
1244
|
return {
|
|
1217
1245
|
content: [{
|
|
1218
1246
|
type: "text",
|
|
1219
|
-
text: `Failed to call tool "${
|
|
1247
|
+
text: `Failed to call tool "${actualToolName}" on server "${serverName}": ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1220
1248
|
}],
|
|
1221
1249
|
isError: true
|
|
1222
1250
|
};
|
|
@@ -1225,8 +1253,8 @@ var UseToolTool = class UseToolTool {
|
|
|
1225
1253
|
const matchingServers = [];
|
|
1226
1254
|
const results = await Promise.all(clients.map(async (client$1) => {
|
|
1227
1255
|
try {
|
|
1228
|
-
if (client$1.toolBlacklist && client$1.toolBlacklist.includes(
|
|
1229
|
-
if ((await client$1.listTools()).some((t) => t.name ===
|
|
1256
|
+
if (client$1.toolBlacklist && client$1.toolBlacklist.includes(actualToolName)) return null;
|
|
1257
|
+
if ((await client$1.listTools()).some((t) => t.name === actualToolName)) return client$1.serverName;
|
|
1230
1258
|
} catch (error) {
|
|
1231
1259
|
console.error(`Failed to list tools from ${client$1.serverName}:`, error);
|
|
1232
1260
|
}
|
|
@@ -1236,14 +1264,14 @@ var UseToolTool = class UseToolTool {
|
|
|
1236
1264
|
if (matchingServers.length === 0) return {
|
|
1237
1265
|
content: [{
|
|
1238
1266
|
type: "text",
|
|
1239
|
-
text: `Tool "${
|
|
1267
|
+
text: `Tool "${actualToolName}" not found on any connected server. Use describe_tools to see available tools.`
|
|
1240
1268
|
}],
|
|
1241
1269
|
isError: true
|
|
1242
1270
|
};
|
|
1243
1271
|
if (matchingServers.length > 1) return {
|
|
1244
1272
|
content: [{
|
|
1245
1273
|
type: "text",
|
|
1246
|
-
text: `
|
|
1274
|
+
text: `Tool "${actualToolName}" found on multiple servers. Use prefixed format to specify: ${matchingServers.map((s) => `${s}__${actualToolName}`).join(", ")}`
|
|
1247
1275
|
}],
|
|
1248
1276
|
isError: true
|
|
1249
1277
|
};
|
|
@@ -1257,12 +1285,12 @@ var UseToolTool = class UseToolTool {
|
|
|
1257
1285
|
isError: true
|
|
1258
1286
|
};
|
|
1259
1287
|
try {
|
|
1260
|
-
return await client.callTool(
|
|
1288
|
+
return await client.callTool(actualToolName, toolArgs);
|
|
1261
1289
|
} catch (error) {
|
|
1262
1290
|
return {
|
|
1263
1291
|
content: [{
|
|
1264
1292
|
type: "text",
|
|
1265
|
-
text: `Failed to call tool "${
|
|
1293
|
+
text: `Failed to call tool "${actualToolName}": ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1266
1294
|
}],
|
|
1267
1295
|
isError: true
|
|
1268
1296
|
};
|
|
@@ -1675,4 +1703,4 @@ var HttpTransportHandler = class {
|
|
|
1675
1703
|
};
|
|
1676
1704
|
|
|
1677
1705
|
//#endregion
|
|
1678
|
-
export {
|
|
1706
|
+
export { findConfigFile as a, createServer as i, SseTransportHandler as n, McpClientManagerService as o, StdioTransportHandler as r, ConfigFetcherService as s, HttpTransportHandler as t };
|
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as createServer, n as SseTransportHandler, r as StdioTransportHandler, t as HttpTransportHandler } from "./http-
|
|
1
|
+
import { i as createServer, n as SseTransportHandler, r as StdioTransportHandler, t as HttpTransportHandler } from "./http-CzQfsUEI.mjs";
|
|
2
2
|
|
|
3
3
|
export { HttpTransportHandler, SseTransportHandler, StdioTransportHandler, createServer };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agiflowai/one-mcp",
|
|
3
3
|
"description": "One MCP server package",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"express": "^4.21.2",
|
|
26
26
|
"js-yaml": "^4.1.0",
|
|
27
27
|
"zod": "^3.24.1",
|
|
28
|
-
"@agiflowai/aicode-utils": "1.0.
|
|
28
|
+
"@agiflowai/aicode-utils": "1.0.4"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/express": "^5.0.0",
|