@agimon-ai/mcp-proxy 0.7.3 → 0.8.0

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_src = require('./src-Dp2m9_I_.cjs');
2
+ const require_src = require("./src-dZuRf3Wt.cjs");
3
3
  let node_fs = require("node:fs");
4
4
  let node_fs_promises = require("node:fs/promises");
5
5
  let js_yaml = require("js-yaml");
@@ -10,17 +10,14 @@ node_path = require_src.__toESM(node_path);
10
10
  let node_child_process = require("node:child_process");
11
11
  let liquidjs = require("liquidjs");
12
12
  let commander = require("commander");
13
- let __agimon_ai_foundation_port_registry = require("@agimon-ai/foundation-port-registry");
14
- let __agimon_ai_foundation_process_registry = require("@agimon-ai/foundation-process-registry");
13
+ let _agimon_ai_foundation_port_registry = require("@agimon-ai/foundation-port-registry");
14
+ let _agimon_ai_foundation_process_registry = require("@agimon-ai/foundation-process-registry");
15
15
  let node_url = require("node:url");
16
-
17
16
  //#region src/templates/mcp-config.json?raw
18
17
  var mcp_config_default = "{\n \"_comment\": \"MCP Server Configuration - Use ${VAR_NAME} syntax for environment variable interpolation\",\n \"_instructions\": \"config.instruction: Server's default instruction | instruction: User override (takes precedence)\",\n \"mcpServers\": {\n \"example-server\": {\n \"command\": \"node\",\n \"args\": [\"/path/to/mcp-server/build/index.js\"],\n \"env\": {\n \"LOG_LEVEL\": \"info\",\n \"_comment\": \"You can use environment variable interpolation:\",\n \"_example_DATABASE_URL\": \"${DATABASE_URL}\",\n \"_example_API_KEY\": \"${MY_API_KEY}\"\n },\n \"config\": {\n \"instruction\": \"Use this server for...\"\n },\n \"_instruction_override\": \"Optional user override - takes precedence over config.instruction\"\n }\n }\n}\n";
19
-
20
18
  //#endregion
21
19
  //#region src/templates/mcp-config.yaml.liquid?raw
22
20
  var mcp_config_yaml_default = "# MCP Server Configuration\n# This file configures the MCP servers that mcp-proxy will connect to\n#\n# Environment Variable Interpolation:\n# Use ${VAR_NAME} syntax to reference environment variables\n# Example: ${HOME}, ${API_KEY}, ${DATABASE_URL}\n#\n# Instructions:\n# - config.instruction: Server's default instruction (from server documentation)\n# - instruction: User override (optional, takes precedence over config.instruction)\n# - config.toolBlacklist: Array of tool names to hide/block from this server\n# - config.omitToolDescription: Boolean to show only tool names without descriptions (saves tokens)\n\n# Remote Configuration Sources (OPTIONAL)\n# Fetch and merge configurations from remote URLs\n# Remote configs are merged with local configs based on merge strategy\n#\n# SECURITY: SSRF Protection is ENABLED by default\n# - Only HTTPS URLs are allowed (set security.enforceHttps: false to allow HTTP)\n# - Private IPs and localhost are blocked (set security.allowPrivateIPs: true for internal networks)\n# - Blocked ranges: 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16\nremoteConfigs:\n # Example 1: Basic remote config with default security\n # - url: ${AGIFLOW_URL}/api/v1/mcp-configs\n # headers:\n # Authorization: Bearer ${AGIFLOW_API_KEY}\n # mergeStrategy: local-priority # Options: local-priority (default), remote-priority, merge-deep\n #\n # Example 2: Remote config with custom security settings (for internal networks)\n # - url: ${INTERNAL_URL}/mcp-configs\n # headers:\n # Authorization: Bearer ${INTERNAL_TOKEN}\n # security:\n # allowPrivateIPs: true # Allow internal IPs (default: false)\n # enforceHttps: false # Allow HTTP (default: true, HTTPS only)\n # mergeStrategy: local-priority\n #\n # Example 3: Remote config with additional validation (OPTIONAL)\n # - url: ${AGIFLOW_URL}/api/v1/mcp-configs\n # headers:\n # Authorization: Bearer ${AGIFLOW_API_KEY}\n # X-API-Key: ${AGIFLOW_API_KEY}\n # security:\n # enforceHttps: true # Require HTTPS (default: true)\n # allowPrivateIPs: false # Block private IPs (default: false)\n # validation: # OPTIONAL: Additional regex validation on top of security checks\n # url: ^https://.*\\.agiflow\\.io/.* # OPTIONAL: Regex pattern to validate URL format\n # headers: # OPTIONAL: Regex patterns to validate header values\n # Authorization: ^Bearer [A-Za-z0-9_-]+$\n # X-API-Key: ^[A-Za-z0-9_-]{32,}$\n # mergeStrategy: local-priority\n\nmcpServers:\n{%- if mcpServers %}{% for server in mcpServers %}\n {{ server.name }}:\n command: {{ server.command }}\n args:{% for arg in server.args %}\n - '{{ arg }}'{% endfor %}\n # env:\n # LOG_LEVEL: info\n # # API_KEY: ${MY_API_KEY}\n # config:\n # instruction: Use this server for...\n # # toolBlacklist:\n # # - tool_to_block\n # # omitToolDescription: true\n{% endfor %}\n # Example MCP server using SSE transport\n # remote-server:\n # url: https://example.com/mcp\n # type: sse\n # headers:\n # Authorization: Bearer ${API_KEY}\n # config:\n # instruction: This server provides tools for...\n{% else %}\n # Example MCP server using stdio transport\n example-server:\n command: node\n args:\n - /path/to/mcp-server/build/index.js\n env:\n # Environment variables for the MCP server\n LOG_LEVEL: info\n # You can use environment variable interpolation:\n # DATABASE_URL: ${DATABASE_URL}\n # API_KEY: ${MY_API_KEY}\n config:\n # Server's default instruction (from server documentation)\n instruction: Use this server for...\n # Optional: Block specific tools from being listed or executed\n # toolBlacklist:\n # - dangerous_tool_name\n # - another_blocked_tool\n # Optional: Omit tool descriptions to save tokens (default: false)\n # omitToolDescription: true\n # instruction: Optional user override - takes precedence over config.instruction\n\n # Example MCP server using SSE transport with environment variables\n # remote-server:\n # url: https://example.com/mcp\n # type: sse\n # headers:\n # # Use ${VAR_NAME} to interpolate environment variables\n # Authorization: Bearer ${API_KEY}\n # config:\n # instruction: This server provides tools for...\n # # Optional: Block specific tools from being listed or executed\n # # toolBlacklist:\n # # - tool_to_block\n # # Optional: Omit tool descriptions to save tokens (default: false)\n # # omitToolDescription: true\n # # instruction: Optional user override\n{% endif %}\n";
23
-
24
21
  //#endregion
25
22
  //#region src/utils/output.ts
26
23
  function writeLine(message = "") {
@@ -44,7 +41,6 @@ const print = {
44
41
  item: (message) => writeLine(`- ${message}`),
45
42
  indent: (message) => writeLine(` ${message}`)
46
43
  };
47
-
48
44
  //#endregion
49
45
  //#region src/commands/init.ts
50
46
  /**
@@ -114,7 +110,6 @@ const initCommand = new commander.Command("init").description("Initialize MCP co
114
110
  process.exit(1);
115
111
  }
116
112
  });
117
-
118
113
  //#endregion
119
114
  //#region src/commands/prestart-http.ts
120
115
  /**
@@ -142,7 +137,7 @@ function resolveWorkspaceRoot(startPath = process.env.PROJECT_PATH || process.cw
142
137
  }
143
138
  const PROCESS_REGISTRY_SERVICE_HTTP$1 = "mcp-proxy-http";
144
139
  async function findExistingHealthyRuntime(workspaceRoot) {
145
- const match = (await new __agimon_ai_foundation_process_registry.ProcessRegistryService(process.env.PROCESS_REGISTRY_PATH).listProcesses({
140
+ const match = (await new _agimon_ai_foundation_process_registry.ProcessRegistryService(process.env.PROCESS_REGISTRY_PATH).listProcesses({
146
141
  repositoryPath: workspaceRoot,
147
142
  serviceName: PROCESS_REGISTRY_SERVICE_HTTP$1
148
143
  }))[0];
@@ -163,14 +158,14 @@ async function findExistingHealthyRuntime(workspaceRoot) {
163
158
  return null;
164
159
  }
165
160
  function buildCliCandidates() {
166
- const __filename$1 = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
167
- const __dirname$1 = node_path.default.dirname(__filename$1);
161
+ const __filename = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
162
+ const __dirname = node_path.default.dirname(__filename);
168
163
  const distCandidates = [
169
- node_path.default.resolve(__dirname$1, "cli.mjs"),
170
- node_path.default.resolve(__dirname$1, "..", "dist", "cli.mjs"),
171
- node_path.default.resolve(__dirname$1, "..", "..", "dist", "cli.mjs")
164
+ node_path.default.resolve(__dirname, "cli.mjs"),
165
+ node_path.default.resolve(__dirname, "..", "dist", "cli.mjs"),
166
+ node_path.default.resolve(__dirname, "..", "..", "dist", "cli.mjs")
172
167
  ];
173
- const srcCandidates = [node_path.default.resolve(__dirname$1, "..", "cli.ts"), node_path.default.resolve(__dirname$1, "..", "..", "src", "cli.ts")];
168
+ const srcCandidates = [node_path.default.resolve(__dirname, "..", "cli.ts"), node_path.default.resolve(__dirname, "..", "..", "src", "cli.ts")];
174
169
  for (const candidate of distCandidates) if ((0, node_fs.existsSync)(candidate)) return {
175
170
  command: process.execPath,
176
171
  args: [candidate]
@@ -198,7 +193,7 @@ async function waitForFile(filePath, timeoutMs) {
198
193
  await (0, node_fs_promises.access)(filePath);
199
194
  return;
200
195
  } catch {}
201
- await new Promise((resolve$2) => setTimeout(resolve$2, POLL_INTERVAL_MS));
196
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
202
197
  }
203
198
  throw new Error(`Timed out waiting for runtime state file: ${filePath}`);
204
199
  }
@@ -220,7 +215,7 @@ async function waitForHealthyRuntime(serverId, timeoutMs) {
220
215
  }
221
216
  } catch {}
222
217
  }
223
- await new Promise((resolve$2) => setTimeout(resolve$2, POLL_INTERVAL_MS));
218
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
224
219
  }
225
220
  throw new Error(`Timed out waiting for HTTP runtime '${serverId}' to become healthy`);
226
221
  }
@@ -266,7 +261,7 @@ async function prestartHttpRuntime(options) {
266
261
  ...process.env,
267
262
  ...registryPath ? {
268
263
  PORT_REGISTRY_PATH: registryPath,
269
- PROCESS_REGISTRY_PATH: (0, __agimon_ai_foundation_process_registry.resolveSiblingRegistryPath)(registryPath, "processes.json")
264
+ PROCESS_REGISTRY_PATH: (0, _agimon_ai_foundation_process_registry.resolveSiblingRegistryPath)(registryPath, "processes.json")
270
265
  } : {}
271
266
  };
272
267
  const child = spawnBackgroundRuntime([
@@ -316,7 +311,6 @@ const prestartHttpCommand = new commander.Command("prestart-http").description("
316
311
  throw new Error(`Failed to prestart HTTP runtime '${options.id || "generated-server-id"}': ${error instanceof Error ? error.message : String(error)}`, { cause: error });
317
312
  }
318
313
  });
319
-
320
314
  //#endregion
321
315
  //#region src/commands/mcp-serve.ts
322
316
  /**
@@ -490,7 +484,7 @@ function createRuntimeRecord(serverId, config, port, shutdownToken, configPath)
490
484
  };
491
485
  }
492
486
  function createPortRegistryService() {
493
- return new __agimon_ai_foundation_port_registry.PortRegistryService(process.env.PORT_REGISTRY_PATH);
487
+ return new _agimon_ai_foundation_port_registry.PortRegistryService(process.env.PORT_REGISTRY_PATH);
494
488
  }
495
489
  function getRegistryEnvironment() {
496
490
  return process.env.NODE_ENV ?? "development";
@@ -498,7 +492,7 @@ function getRegistryEnvironment() {
498
492
  async function createPortRegistryLease(serviceName, host, preferredPort, serverId, transport, configPath, portRange = preferredPort !== void 0 ? {
499
493
  min: preferredPort,
500
494
  max: preferredPort
501
- } : __agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE) {
495
+ } : _agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE) {
502
496
  const portRegistry = createPortRegistryService();
503
497
  const result = await portRegistry.reservePort({
504
498
  repositoryPath: getRegistryRepositoryPath(),
@@ -630,14 +624,14 @@ async function createAndStartHttpRuntime(serverOptions, config, resolvedConfigPa
630
624
  const portRange = requestedPort !== void 0 ? {
631
625
  min: requestedPort,
632
626
  max: requestedPort
633
- } : __agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE;
627
+ } : _agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE;
634
628
  const portLease = await createPortRegistryLease(PORT_REGISTRY_SERVICE_HTTP, config.host ?? DEFAULT_HOST, requestedPort, runtimeServerId, TRANSPORT_TYPE_HTTP, resolvedConfigPath, portRange);
635
629
  const runtimePort = portLease.port;
636
630
  const runtimeConfig = {
637
631
  ...config,
638
632
  port: runtimePort
639
633
  };
640
- const processLease = await (0, __agimon_ai_foundation_process_registry.createProcessLease)({
634
+ const processLease = await (0, _agimon_ai_foundation_process_registry.createProcessLease)({
641
635
  repositoryPath: getRegistryRepositoryPath(),
642
636
  serviceName: PROCESS_REGISTRY_SERVICE_HTTP,
643
637
  serviceType: PROCESS_REGISTRY_SERVICE_TYPE,
@@ -707,7 +701,7 @@ async function startSseTransport(serverOptions, config) {
707
701
  const portRange = requestedPort !== void 0 ? {
708
702
  min: requestedPort,
709
703
  max: requestedPort
710
- } : __agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE;
704
+ } : _agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE;
711
705
  const portLease = await createPortRegistryLease("mcp-proxy-sse", config.host ?? DEFAULT_HOST, requestedPort, serverOptions.serverId ?? require_src.generateServerId(), TRANSPORT_TYPE_SSE, void 0, portRange);
712
706
  const resolvedConfig = {
713
707
  ...config,
@@ -830,7 +824,6 @@ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MC
830
824
  process.exit(1);
831
825
  }
832
826
  });
833
-
834
827
  //#endregion
835
828
  //#region src/commands/bootstrap.ts
836
829
  function toErrorMessage$8(error) {
@@ -920,7 +913,6 @@ async function withConnectedCommandContext(options, run) {
920
913
  if (config.proxy?.port) return await withProxiedContext(container, config, configFilePath, options, run);
921
914
  return await withDirectContext(container, config, configFilePath, options, run);
922
915
  }
923
-
924
916
  //#endregion
925
917
  //#region src/commands/list-tools.ts
926
918
  /**
@@ -991,7 +983,6 @@ const searchToolsCommand = new commander.Command("search-tools").description("Se
991
983
  process.exit(1);
992
984
  }
993
985
  });
994
-
995
986
  //#endregion
996
987
  //#region src/commands/describe-tools.ts
997
988
  /**
@@ -1132,7 +1123,6 @@ const describeToolsCommand = new commander.Command("describe-tools").description
1132
1123
  process.exit(1);
1133
1124
  }
1134
1125
  });
1135
-
1136
1126
  //#endregion
1137
1127
  //#region src/commands/use-tool.ts
1138
1128
  /**
@@ -1174,34 +1164,34 @@ const useToolCommand = new commander.Command("use-tool").description("Execute an
1174
1164
  await withConnectedCommandContext(options, async ({ container, config, clientManager }) => {
1175
1165
  const clients = clientManager.getAllClients();
1176
1166
  if (options.server) {
1177
- const client$1 = clientManager.getClient(options.server);
1178
- if (!client$1) throw new Error(`Server "${options.server}" not found`);
1167
+ const client = clientManager.getClient(options.server);
1168
+ if (!client) throw new Error(`Server "${options.server}" not found`);
1179
1169
  if (!options.json) console.error(`Executing ${toolName} on ${options.server}...`);
1180
- const requestOptions$1 = options.timeout ? { timeout: options.timeout } : void 0;
1181
- const result$1 = await client$1.callTool(toolName, toolArgs, requestOptions$1);
1182
- if (options.json) console.log(JSON.stringify(result$1, null, 2));
1170
+ const requestOptions = options.timeout ? { timeout: options.timeout } : void 0;
1171
+ const result = await client.callTool(toolName, toolArgs, requestOptions);
1172
+ if (options.json) console.log(JSON.stringify(result, null, 2));
1183
1173
  else {
1184
1174
  console.log("\nResult:");
1185
- if (result$1.content) for (const content of result$1.content) if (content.type === "text") console.log(content.text);
1175
+ if (result.content) for (const content of result.content) if (content.type === "text") console.log(content.text);
1186
1176
  else console.log(JSON.stringify(content, null, 2));
1187
- if (result$1.isError) {
1177
+ if (result.isError) {
1188
1178
  console.error("\n⚠️ Tool execution returned an error");
1189
1179
  process.exit(1);
1190
1180
  }
1191
1181
  }
1192
1182
  return;
1193
1183
  }
1194
- const searchResults = await Promise.all(clients.map(async (client$1) => {
1184
+ const searchResults = await Promise.all(clients.map(async (client) => {
1195
1185
  try {
1196
- const hasTool = (await client$1.listTools()).some((t) => t.name === toolName);
1186
+ const hasTool = (await client.listTools()).some((t) => t.name === toolName);
1197
1187
  return {
1198
- serverName: client$1.serverName,
1188
+ serverName: client.serverName,
1199
1189
  hasTool,
1200
1190
  error: null
1201
1191
  };
1202
1192
  } catch (error) {
1203
1193
  return {
1204
- serverName: client$1.serverName,
1194
+ serverName: client.serverName,
1205
1195
  hasTool: false,
1206
1196
  error
1207
1197
  };
@@ -1223,11 +1213,11 @@ const useToolCommand = new commander.Command("use-tool").description("Execute an
1223
1213
  const skillName = toolName.startsWith("skill__") ? toolName.slice(7) : toolName;
1224
1214
  const skill = await skillService.getSkill(skillName);
1225
1215
  if (skill) {
1226
- const result$1 = { content: [{
1216
+ const result = { content: [{
1227
1217
  type: "text",
1228
1218
  text: skill.content
1229
1219
  }] };
1230
- if (options.json) console.log(JSON.stringify(result$1, null, 2));
1220
+ if (options.json) console.log(JSON.stringify(result, null, 2));
1231
1221
  else {
1232
1222
  console.log("\nSkill content:");
1233
1223
  console.log(skill.content);
@@ -1262,7 +1252,6 @@ const useToolCommand = new commander.Command("use-tool").description("Execute an
1262
1252
  process.exit(1);
1263
1253
  }
1264
1254
  });
1265
-
1266
1255
  //#endregion
1267
1256
  //#region src/commands/list-resources.ts
1268
1257
  /**
@@ -1333,7 +1322,6 @@ const listResourcesCommand = new commander.Command("list-resources").description
1333
1322
  process.exit(1);
1334
1323
  }
1335
1324
  });
1336
-
1337
1325
  //#endregion
1338
1326
  //#region src/commands/read-resource.ts
1339
1327
  /**
@@ -1368,26 +1356,26 @@ const readResourceCommand = new commander.Command("read-resource").description("
1368
1356
  await withConnectedCommandContext(options, async ({ clientManager }) => {
1369
1357
  const clients = clientManager.getAllClients();
1370
1358
  if (options.server) {
1371
- const client$1 = clientManager.getClient(options.server);
1372
- if (!client$1) throw new Error(`Server "${options.server}" not found`);
1359
+ const client = clientManager.getClient(options.server);
1360
+ if (!client) throw new Error(`Server "${options.server}" not found`);
1373
1361
  if (!options.json) console.error(`Reading ${uri} from ${options.server}...`);
1374
- const result$1 = await client$1.readResource(uri);
1375
- if (options.json) console.log(JSON.stringify(result$1, null, 2));
1376
- else for (const content of result$1.contents) if ("text" in content) console.log(content.text);
1362
+ const result = await client.readResource(uri);
1363
+ if (options.json) console.log(JSON.stringify(result, null, 2));
1364
+ else for (const content of result.contents) if ("text" in content) console.log(content.text);
1377
1365
  else console.log(JSON.stringify(content, null, 2));
1378
1366
  return;
1379
1367
  }
1380
- const searchResults = await Promise.all(clients.map(async (client$1) => {
1368
+ const searchResults = await Promise.all(clients.map(async (client) => {
1381
1369
  try {
1382
- const hasResource = (await client$1.listResources()).some((r) => r.uri === uri);
1370
+ const hasResource = (await client.listResources()).some((r) => r.uri === uri);
1383
1371
  return {
1384
- serverName: client$1.serverName,
1372
+ serverName: client.serverName,
1385
1373
  hasResource,
1386
1374
  error: null
1387
1375
  };
1388
1376
  } catch (error) {
1389
1377
  return {
1390
- serverName: client$1.serverName,
1378
+ serverName: client.serverName,
1391
1379
  hasResource: false,
1392
1380
  error
1393
1381
  };
@@ -1417,7 +1405,6 @@ const readResourceCommand = new commander.Command("read-resource").description("
1417
1405
  process.exit(1);
1418
1406
  }
1419
1407
  });
1420
-
1421
1408
  //#endregion
1422
1409
  //#region src/commands/list-prompts.ts
1423
1410
  function toErrorMessage$2(error) {
@@ -1458,7 +1445,6 @@ const listPromptsCommand = new commander.Command("list-prompts").description("Li
1458
1445
  process.exit(1);
1459
1446
  }
1460
1447
  });
1461
-
1462
1448
  //#endregion
1463
1449
  //#region src/commands/get-prompt.ts
1464
1450
  function toErrorMessage$1(error) {
@@ -1475,11 +1461,11 @@ const getPromptCommand = new commander.Command("get-prompt").description("Get a
1475
1461
  await withConnectedCommandContext(options, async ({ clientManager }) => {
1476
1462
  const clients = clientManager.getAllClients();
1477
1463
  if (options.server) {
1478
- const client$1 = clientManager.getClient(options.server);
1479
- if (!client$1) throw new Error(`Server "${options.server}" not found`);
1480
- const prompt$1 = await client$1.getPrompt(promptName, promptArgs);
1481
- if (options.json) console.log(JSON.stringify(prompt$1, null, 2));
1482
- else for (const message of prompt$1.messages) {
1464
+ const client = clientManager.getClient(options.server);
1465
+ if (!client) throw new Error(`Server "${options.server}" not found`);
1466
+ const prompt = await client.getPrompt(promptName, promptArgs);
1467
+ if (options.json) console.log(JSON.stringify(prompt, null, 2));
1468
+ else for (const message of prompt.messages) {
1483
1469
  const content = message.content;
1484
1470
  if (typeof content === "object" && content && "text" in content) console.log(content.text);
1485
1471
  else console.log(JSON.stringify(message, null, 2));
@@ -1487,11 +1473,11 @@ const getPromptCommand = new commander.Command("get-prompt").description("Get a
1487
1473
  return;
1488
1474
  }
1489
1475
  const matchingServers = [];
1490
- await Promise.all(clients.map(async (client$1) => {
1476
+ await Promise.all(clients.map(async (client) => {
1491
1477
  try {
1492
- if ((await client$1.listPrompts()).some((prompt$1) => prompt$1.name === promptName)) matchingServers.push(client$1.serverName);
1478
+ if ((await client.listPrompts()).some((prompt) => prompt.name === promptName)) matchingServers.push(client.serverName);
1493
1479
  } catch (error) {
1494
- if (!options.json) console.error(`Failed to list prompts from ${client$1.serverName}: ${toErrorMessage$1(error)}`);
1480
+ if (!options.json) console.error(`Failed to list prompts from ${client.serverName}: ${toErrorMessage$1(error)}`);
1495
1481
  }
1496
1482
  }));
1497
1483
  if (matchingServers.length === 0) throw new Error(`Prompt "${promptName}" not found on any connected server`);
@@ -1511,7 +1497,6 @@ const getPromptCommand = new commander.Command("get-prompt").description("Get a
1511
1497
  process.exit(1);
1512
1498
  }
1513
1499
  });
1514
-
1515
1500
  //#endregion
1516
1501
  //#region src/commands/prefetch.ts
1517
1502
  /**
@@ -1638,7 +1623,6 @@ const prefetchCommand = new commander.Command("prefetch").description("Pre-downl
1638
1623
  process.exit(1);
1639
1624
  }
1640
1625
  });
1641
-
1642
1626
  //#endregion
1643
1627
  //#region src/commands/stop.ts
1644
1628
  /**
@@ -1684,7 +1668,6 @@ const stopCommand = new commander.Command("stop").description("Stop a running HT
1684
1668
  process.exit(1);
1685
1669
  }
1686
1670
  });
1687
-
1688
1671
  //#endregion
1689
1672
  //#region src/cli.ts
1690
1673
  /**
@@ -1734,5 +1717,4 @@ main().catch((error) => {
1734
1717
  console.error(`Fatal error: ${error instanceof Error ? error.message : error}`);
1735
1718
  process.exit(1);
1736
1719
  });
1737
-
1738
- //#endregion
1720
+ //#endregion
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { C as DefinitionsCacheService, D as version, T as findConfigFile, b as RuntimeStateService, d as StdioHttpTransportHandler, f as StdioTransportHandler, m as HttpTransportHandler, n as createServer, o as createProxyIoCContainer, p as SseTransportHandler, r as createSessionServer, t as TRANSPORT_MODE, u as initializeSharedServices, w as generateServerId, y as StopServerService } from "./src-Y-cyyxaw.mjs";
2
+ import { C as DefinitionsCacheService, D as version, T as findConfigFile, b as RuntimeStateService, d as StdioHttpTransportHandler, f as StdioTransportHandler, m as HttpTransportHandler, n as createServer, o as createProxyIoCContainer, p as SseTransportHandler, r as createSessionServer, t as TRANSPORT_MODE, u as initializeSharedServices, w as generateServerId, y as StopServerService } from "./src-Dorvm5bM.mjs";
3
3
  import { constants, existsSync, readFileSync } from "node:fs";
4
4
  import { access, writeFile } from "node:fs/promises";
5
5
  import yaml from "js-yaml";
@@ -11,14 +11,11 @@ import { Command } from "commander";
11
11
  import { DEFAULT_PORT_RANGE, PortRegistryService } from "@agimon-ai/foundation-port-registry";
12
12
  import { ProcessRegistryService, createProcessLease, resolveSiblingRegistryPath } from "@agimon-ai/foundation-process-registry";
13
13
  import { fileURLToPath } from "node:url";
14
-
15
14
  //#region src/templates/mcp-config.json?raw
16
15
  var mcp_config_default = "{\n \"_comment\": \"MCP Server Configuration - Use ${VAR_NAME} syntax for environment variable interpolation\",\n \"_instructions\": \"config.instruction: Server's default instruction | instruction: User override (takes precedence)\",\n \"mcpServers\": {\n \"example-server\": {\n \"command\": \"node\",\n \"args\": [\"/path/to/mcp-server/build/index.js\"],\n \"env\": {\n \"LOG_LEVEL\": \"info\",\n \"_comment\": \"You can use environment variable interpolation:\",\n \"_example_DATABASE_URL\": \"${DATABASE_URL}\",\n \"_example_API_KEY\": \"${MY_API_KEY}\"\n },\n \"config\": {\n \"instruction\": \"Use this server for...\"\n },\n \"_instruction_override\": \"Optional user override - takes precedence over config.instruction\"\n }\n }\n}\n";
17
-
18
16
  //#endregion
19
17
  //#region src/templates/mcp-config.yaml.liquid?raw
20
18
  var mcp_config_yaml_default = "# MCP Server Configuration\n# This file configures the MCP servers that mcp-proxy will connect to\n#\n# Environment Variable Interpolation:\n# Use ${VAR_NAME} syntax to reference environment variables\n# Example: ${HOME}, ${API_KEY}, ${DATABASE_URL}\n#\n# Instructions:\n# - config.instruction: Server's default instruction (from server documentation)\n# - instruction: User override (optional, takes precedence over config.instruction)\n# - config.toolBlacklist: Array of tool names to hide/block from this server\n# - config.omitToolDescription: Boolean to show only tool names without descriptions (saves tokens)\n\n# Remote Configuration Sources (OPTIONAL)\n# Fetch and merge configurations from remote URLs\n# Remote configs are merged with local configs based on merge strategy\n#\n# SECURITY: SSRF Protection is ENABLED by default\n# - Only HTTPS URLs are allowed (set security.enforceHttps: false to allow HTTP)\n# - Private IPs and localhost are blocked (set security.allowPrivateIPs: true for internal networks)\n# - Blocked ranges: 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16\nremoteConfigs:\n # Example 1: Basic remote config with default security\n # - url: ${AGIFLOW_URL}/api/v1/mcp-configs\n # headers:\n # Authorization: Bearer ${AGIFLOW_API_KEY}\n # mergeStrategy: local-priority # Options: local-priority (default), remote-priority, merge-deep\n #\n # Example 2: Remote config with custom security settings (for internal networks)\n # - url: ${INTERNAL_URL}/mcp-configs\n # headers:\n # Authorization: Bearer ${INTERNAL_TOKEN}\n # security:\n # allowPrivateIPs: true # Allow internal IPs (default: false)\n # enforceHttps: false # Allow HTTP (default: true, HTTPS only)\n # mergeStrategy: local-priority\n #\n # Example 3: Remote config with additional validation (OPTIONAL)\n # - url: ${AGIFLOW_URL}/api/v1/mcp-configs\n # headers:\n # Authorization: Bearer ${AGIFLOW_API_KEY}\n # X-API-Key: ${AGIFLOW_API_KEY}\n # security:\n # enforceHttps: true # Require HTTPS (default: true)\n # allowPrivateIPs: false # Block private IPs (default: false)\n # validation: # OPTIONAL: Additional regex validation on top of security checks\n # url: ^https://.*\\.agiflow\\.io/.* # OPTIONAL: Regex pattern to validate URL format\n # headers: # OPTIONAL: Regex patterns to validate header values\n # Authorization: ^Bearer [A-Za-z0-9_-]+$\n # X-API-Key: ^[A-Za-z0-9_-]{32,}$\n # mergeStrategy: local-priority\n\nmcpServers:\n{%- if mcpServers %}{% for server in mcpServers %}\n {{ server.name }}:\n command: {{ server.command }}\n args:{% for arg in server.args %}\n - '{{ arg }}'{% endfor %}\n # env:\n # LOG_LEVEL: info\n # # API_KEY: ${MY_API_KEY}\n # config:\n # instruction: Use this server for...\n # # toolBlacklist:\n # # - tool_to_block\n # # omitToolDescription: true\n{% endfor %}\n # Example MCP server using SSE transport\n # remote-server:\n # url: https://example.com/mcp\n # type: sse\n # headers:\n # Authorization: Bearer ${API_KEY}\n # config:\n # instruction: This server provides tools for...\n{% else %}\n # Example MCP server using stdio transport\n example-server:\n command: node\n args:\n - /path/to/mcp-server/build/index.js\n env:\n # Environment variables for the MCP server\n LOG_LEVEL: info\n # You can use environment variable interpolation:\n # DATABASE_URL: ${DATABASE_URL}\n # API_KEY: ${MY_API_KEY}\n config:\n # Server's default instruction (from server documentation)\n instruction: Use this server for...\n # Optional: Block specific tools from being listed or executed\n # toolBlacklist:\n # - dangerous_tool_name\n # - another_blocked_tool\n # Optional: Omit tool descriptions to save tokens (default: false)\n # omitToolDescription: true\n # instruction: Optional user override - takes precedence over config.instruction\n\n # Example MCP server using SSE transport with environment variables\n # remote-server:\n # url: https://example.com/mcp\n # type: sse\n # headers:\n # # Use ${VAR_NAME} to interpolate environment variables\n # Authorization: Bearer ${API_KEY}\n # config:\n # instruction: This server provides tools for...\n # # Optional: Block specific tools from being listed or executed\n # # toolBlacklist:\n # # - tool_to_block\n # # Optional: Omit tool descriptions to save tokens (default: false)\n # # omitToolDescription: true\n # # instruction: Optional user override\n{% endif %}\n";
21
-
22
19
  //#endregion
23
20
  //#region src/utils/output.ts
24
21
  function writeLine(message = "") {
@@ -42,7 +39,6 @@ const print = {
42
39
  item: (message) => writeLine(`- ${message}`),
43
40
  indent: (message) => writeLine(` ${message}`)
44
41
  };
45
-
46
42
  //#endregion
47
43
  //#region src/commands/init.ts
48
44
  /**
@@ -112,7 +108,6 @@ const initCommand = new Command("init").description("Initialize MCP configuratio
112
108
  process.exit(1);
113
109
  }
114
110
  });
115
-
116
111
  //#endregion
117
112
  //#region src/commands/prestart-http.ts
118
113
  /**
@@ -196,7 +191,7 @@ async function waitForFile(filePath, timeoutMs) {
196
191
  await access(filePath);
197
192
  return;
198
193
  } catch {}
199
- await new Promise((resolve$1) => setTimeout(resolve$1, POLL_INTERVAL_MS));
194
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
200
195
  }
201
196
  throw new Error(`Timed out waiting for runtime state file: ${filePath}`);
202
197
  }
@@ -218,7 +213,7 @@ async function waitForHealthyRuntime(serverId, timeoutMs) {
218
213
  }
219
214
  } catch {}
220
215
  }
221
- await new Promise((resolve$1) => setTimeout(resolve$1, POLL_INTERVAL_MS));
216
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
222
217
  }
223
218
  throw new Error(`Timed out waiting for HTTP runtime '${serverId}' to become healthy`);
224
219
  }
@@ -314,7 +309,6 @@ const prestartHttpCommand = new Command("prestart-http").description("Start an m
314
309
  throw new Error(`Failed to prestart HTTP runtime '${options.id || "generated-server-id"}': ${error instanceof Error ? error.message : String(error)}`, { cause: error });
315
310
  }
316
311
  });
317
-
318
312
  //#endregion
319
313
  //#region src/commands/mcp-serve.ts
320
314
  /**
@@ -828,7 +822,6 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
828
822
  process.exit(1);
829
823
  }
830
824
  });
831
-
832
825
  //#endregion
833
826
  //#region src/commands/bootstrap.ts
834
827
  function toErrorMessage$8(error) {
@@ -918,7 +911,6 @@ async function withConnectedCommandContext(options, run) {
918
911
  if (config.proxy?.port) return await withProxiedContext(container, config, configFilePath, options, run);
919
912
  return await withDirectContext(container, config, configFilePath, options, run);
920
913
  }
921
-
922
914
  //#endregion
923
915
  //#region src/commands/list-tools.ts
924
916
  /**
@@ -989,7 +981,6 @@ const searchToolsCommand = new Command("search-tools").description("Search proxi
989
981
  process.exit(1);
990
982
  }
991
983
  });
992
-
993
984
  //#endregion
994
985
  //#region src/commands/describe-tools.ts
995
986
  /**
@@ -1130,7 +1121,6 @@ const describeToolsCommand = new Command("describe-tools").description("Describe
1130
1121
  process.exit(1);
1131
1122
  }
1132
1123
  });
1133
-
1134
1124
  //#endregion
1135
1125
  //#region src/commands/use-tool.ts
1136
1126
  /**
@@ -1172,34 +1162,34 @@ const useToolCommand = new Command("use-tool").description("Execute an MCP tool
1172
1162
  await withConnectedCommandContext(options, async ({ container, config, clientManager }) => {
1173
1163
  const clients = clientManager.getAllClients();
1174
1164
  if (options.server) {
1175
- const client$1 = clientManager.getClient(options.server);
1176
- if (!client$1) throw new Error(`Server "${options.server}" not found`);
1165
+ const client = clientManager.getClient(options.server);
1166
+ if (!client) throw new Error(`Server "${options.server}" not found`);
1177
1167
  if (!options.json) console.error(`Executing ${toolName} on ${options.server}...`);
1178
- const requestOptions$1 = options.timeout ? { timeout: options.timeout } : void 0;
1179
- const result$1 = await client$1.callTool(toolName, toolArgs, requestOptions$1);
1180
- if (options.json) console.log(JSON.stringify(result$1, null, 2));
1168
+ const requestOptions = options.timeout ? { timeout: options.timeout } : void 0;
1169
+ const result = await client.callTool(toolName, toolArgs, requestOptions);
1170
+ if (options.json) console.log(JSON.stringify(result, null, 2));
1181
1171
  else {
1182
1172
  console.log("\nResult:");
1183
- if (result$1.content) for (const content of result$1.content) if (content.type === "text") console.log(content.text);
1173
+ if (result.content) for (const content of result.content) if (content.type === "text") console.log(content.text);
1184
1174
  else console.log(JSON.stringify(content, null, 2));
1185
- if (result$1.isError) {
1175
+ if (result.isError) {
1186
1176
  console.error("\n⚠️ Tool execution returned an error");
1187
1177
  process.exit(1);
1188
1178
  }
1189
1179
  }
1190
1180
  return;
1191
1181
  }
1192
- const searchResults = await Promise.all(clients.map(async (client$1) => {
1182
+ const searchResults = await Promise.all(clients.map(async (client) => {
1193
1183
  try {
1194
- const hasTool = (await client$1.listTools()).some((t) => t.name === toolName);
1184
+ const hasTool = (await client.listTools()).some((t) => t.name === toolName);
1195
1185
  return {
1196
- serverName: client$1.serverName,
1186
+ serverName: client.serverName,
1197
1187
  hasTool,
1198
1188
  error: null
1199
1189
  };
1200
1190
  } catch (error) {
1201
1191
  return {
1202
- serverName: client$1.serverName,
1192
+ serverName: client.serverName,
1203
1193
  hasTool: false,
1204
1194
  error
1205
1195
  };
@@ -1221,11 +1211,11 @@ const useToolCommand = new Command("use-tool").description("Execute an MCP tool
1221
1211
  const skillName = toolName.startsWith("skill__") ? toolName.slice(7) : toolName;
1222
1212
  const skill = await skillService.getSkill(skillName);
1223
1213
  if (skill) {
1224
- const result$1 = { content: [{
1214
+ const result = { content: [{
1225
1215
  type: "text",
1226
1216
  text: skill.content
1227
1217
  }] };
1228
- if (options.json) console.log(JSON.stringify(result$1, null, 2));
1218
+ if (options.json) console.log(JSON.stringify(result, null, 2));
1229
1219
  else {
1230
1220
  console.log("\nSkill content:");
1231
1221
  console.log(skill.content);
@@ -1260,7 +1250,6 @@ const useToolCommand = new Command("use-tool").description("Execute an MCP tool
1260
1250
  process.exit(1);
1261
1251
  }
1262
1252
  });
1263
-
1264
1253
  //#endregion
1265
1254
  //#region src/commands/list-resources.ts
1266
1255
  /**
@@ -1331,7 +1320,6 @@ const listResourcesCommand = new Command("list-resources").description("List all
1331
1320
  process.exit(1);
1332
1321
  }
1333
1322
  });
1334
-
1335
1323
  //#endregion
1336
1324
  //#region src/commands/read-resource.ts
1337
1325
  /**
@@ -1366,26 +1354,26 @@ const readResourceCommand = new Command("read-resource").description("Read a res
1366
1354
  await withConnectedCommandContext(options, async ({ clientManager }) => {
1367
1355
  const clients = clientManager.getAllClients();
1368
1356
  if (options.server) {
1369
- const client$1 = clientManager.getClient(options.server);
1370
- if (!client$1) throw new Error(`Server "${options.server}" not found`);
1357
+ const client = clientManager.getClient(options.server);
1358
+ if (!client) throw new Error(`Server "${options.server}" not found`);
1371
1359
  if (!options.json) console.error(`Reading ${uri} from ${options.server}...`);
1372
- const result$1 = await client$1.readResource(uri);
1373
- if (options.json) console.log(JSON.stringify(result$1, null, 2));
1374
- else for (const content of result$1.contents) if ("text" in content) console.log(content.text);
1360
+ const result = await client.readResource(uri);
1361
+ if (options.json) console.log(JSON.stringify(result, null, 2));
1362
+ else for (const content of result.contents) if ("text" in content) console.log(content.text);
1375
1363
  else console.log(JSON.stringify(content, null, 2));
1376
1364
  return;
1377
1365
  }
1378
- const searchResults = await Promise.all(clients.map(async (client$1) => {
1366
+ const searchResults = await Promise.all(clients.map(async (client) => {
1379
1367
  try {
1380
- const hasResource = (await client$1.listResources()).some((r) => r.uri === uri);
1368
+ const hasResource = (await client.listResources()).some((r) => r.uri === uri);
1381
1369
  return {
1382
- serverName: client$1.serverName,
1370
+ serverName: client.serverName,
1383
1371
  hasResource,
1384
1372
  error: null
1385
1373
  };
1386
1374
  } catch (error) {
1387
1375
  return {
1388
- serverName: client$1.serverName,
1376
+ serverName: client.serverName,
1389
1377
  hasResource: false,
1390
1378
  error
1391
1379
  };
@@ -1415,7 +1403,6 @@ const readResourceCommand = new Command("read-resource").description("Read a res
1415
1403
  process.exit(1);
1416
1404
  }
1417
1405
  });
1418
-
1419
1406
  //#endregion
1420
1407
  //#region src/commands/list-prompts.ts
1421
1408
  function toErrorMessage$2(error) {
@@ -1456,7 +1443,6 @@ const listPromptsCommand = new Command("list-prompts").description("List all ava
1456
1443
  process.exit(1);
1457
1444
  }
1458
1445
  });
1459
-
1460
1446
  //#endregion
1461
1447
  //#region src/commands/get-prompt.ts
1462
1448
  function toErrorMessage$1(error) {
@@ -1473,11 +1459,11 @@ const getPromptCommand = new Command("get-prompt").description("Get a prompt by
1473
1459
  await withConnectedCommandContext(options, async ({ clientManager }) => {
1474
1460
  const clients = clientManager.getAllClients();
1475
1461
  if (options.server) {
1476
- const client$1 = clientManager.getClient(options.server);
1477
- if (!client$1) throw new Error(`Server "${options.server}" not found`);
1478
- const prompt$1 = await client$1.getPrompt(promptName, promptArgs);
1479
- if (options.json) console.log(JSON.stringify(prompt$1, null, 2));
1480
- else for (const message of prompt$1.messages) {
1462
+ const client = clientManager.getClient(options.server);
1463
+ if (!client) throw new Error(`Server "${options.server}" not found`);
1464
+ const prompt = await client.getPrompt(promptName, promptArgs);
1465
+ if (options.json) console.log(JSON.stringify(prompt, null, 2));
1466
+ else for (const message of prompt.messages) {
1481
1467
  const content = message.content;
1482
1468
  if (typeof content === "object" && content && "text" in content) console.log(content.text);
1483
1469
  else console.log(JSON.stringify(message, null, 2));
@@ -1485,11 +1471,11 @@ const getPromptCommand = new Command("get-prompt").description("Get a prompt by
1485
1471
  return;
1486
1472
  }
1487
1473
  const matchingServers = [];
1488
- await Promise.all(clients.map(async (client$1) => {
1474
+ await Promise.all(clients.map(async (client) => {
1489
1475
  try {
1490
- if ((await client$1.listPrompts()).some((prompt$1) => prompt$1.name === promptName)) matchingServers.push(client$1.serverName);
1476
+ if ((await client.listPrompts()).some((prompt) => prompt.name === promptName)) matchingServers.push(client.serverName);
1491
1477
  } catch (error) {
1492
- if (!options.json) console.error(`Failed to list prompts from ${client$1.serverName}: ${toErrorMessage$1(error)}`);
1478
+ if (!options.json) console.error(`Failed to list prompts from ${client.serverName}: ${toErrorMessage$1(error)}`);
1493
1479
  }
1494
1480
  }));
1495
1481
  if (matchingServers.length === 0) throw new Error(`Prompt "${promptName}" not found on any connected server`);
@@ -1509,7 +1495,6 @@ const getPromptCommand = new Command("get-prompt").description("Get a prompt by
1509
1495
  process.exit(1);
1510
1496
  }
1511
1497
  });
1512
-
1513
1498
  //#endregion
1514
1499
  //#region src/commands/prefetch.ts
1515
1500
  /**
@@ -1636,7 +1621,6 @@ const prefetchCommand = new Command("prefetch").description("Pre-download packag
1636
1621
  process.exit(1);
1637
1622
  }
1638
1623
  });
1639
-
1640
1624
  //#endregion
1641
1625
  //#region src/commands/stop.ts
1642
1626
  /**
@@ -1682,7 +1666,6 @@ const stopCommand = new Command("stop").description("Stop a running HTTP mcp-pro
1682
1666
  process.exit(1);
1683
1667
  }
1684
1668
  });
1685
-
1686
1669
  //#endregion
1687
1670
  //#region src/cli.ts
1688
1671
  /**
@@ -1732,6 +1715,5 @@ main().catch((error) => {
1732
1715
  console.error(`Fatal error: ${error instanceof Error ? error.message : error}`);
1733
1716
  process.exit(1);
1734
1717
  });
1735
-
1736
1718
  //#endregion
1737
- export { };
1719
+ export {};