@agimon-ai/mcp-proxy 0.7.3 → 0.9.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 +73 -85
- package/dist/cli.mjs +64 -76
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +5 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +2 -3
- package/dist/{src-Y-cyyxaw.mjs → src-DA5H3rpr.mjs} +201 -313
- package/dist/{src-Dp2m9_I_.cjs → src-DJJH7z8i.cjs} +389 -506
- package/package.json +18 -18
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_src = require(
|
|
2
|
+
const require_src = require("./src-DJJH7z8i.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
|
|
14
|
-
let
|
|
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
|
/**
|
|
@@ -141,36 +136,35 @@ function resolveWorkspaceRoot(startPath = process.env.PROJECT_PATH || process.cw
|
|
|
141
136
|
}
|
|
142
137
|
}
|
|
143
138
|
const PROCESS_REGISTRY_SERVICE_HTTP$1 = "mcp-proxy-http";
|
|
144
|
-
async function
|
|
145
|
-
const match = (await new
|
|
139
|
+
async function findExistingRuntime(workspaceRoot) {
|
|
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];
|
|
149
144
|
if (!match?.host || !match?.port) return null;
|
|
145
|
+
const metadata = match.metadata;
|
|
146
|
+
return {
|
|
147
|
+
host: match.host,
|
|
148
|
+
port: match.port,
|
|
149
|
+
serverId: metadata?.serverId ?? "unknown"
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
async function isRuntimeHealthy(host, port) {
|
|
150
153
|
try {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
host: match.host,
|
|
156
|
-
port: match.port,
|
|
157
|
-
serverId: metadata?.serverId ?? "unknown",
|
|
158
|
-
workspaceRoot,
|
|
159
|
-
reusedExistingRuntime: true
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
} catch {}
|
|
163
|
-
return null;
|
|
154
|
+
return (await fetch(`http://${host}:${port}/health`)).ok;
|
|
155
|
+
} catch {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
164
158
|
}
|
|
165
159
|
function buildCliCandidates() {
|
|
166
|
-
const
|
|
167
|
-
const
|
|
160
|
+
const currentFile = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
|
|
161
|
+
const currentDir = node_path.default.dirname(currentFile);
|
|
168
162
|
const distCandidates = [
|
|
169
|
-
node_path.default.resolve(
|
|
170
|
-
node_path.default.resolve(
|
|
171
|
-
node_path.default.resolve(
|
|
163
|
+
node_path.default.resolve(currentDir, "cli.mjs"),
|
|
164
|
+
node_path.default.resolve(currentDir, "..", "dist", "cli.mjs"),
|
|
165
|
+
node_path.default.resolve(currentDir, "..", "..", "dist", "cli.mjs")
|
|
172
166
|
];
|
|
173
|
-
const srcCandidates = [node_path.default.resolve(
|
|
167
|
+
const srcCandidates = [node_path.default.resolve(currentDir, "..", "cli.ts"), node_path.default.resolve(currentDir, "..", "..", "src", "cli.ts")];
|
|
174
168
|
for (const candidate of distCandidates) if ((0, node_fs.existsSync)(candidate)) return {
|
|
175
169
|
command: process.execPath,
|
|
176
170
|
args: [candidate]
|
|
@@ -198,7 +192,7 @@ async function waitForFile(filePath, timeoutMs) {
|
|
|
198
192
|
await (0, node_fs_promises.access)(filePath);
|
|
199
193
|
return;
|
|
200
194
|
} catch {}
|
|
201
|
-
await new Promise((resolve
|
|
195
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
202
196
|
}
|
|
203
197
|
throw new Error(`Timed out waiting for runtime state file: ${filePath}`);
|
|
204
198
|
}
|
|
@@ -220,7 +214,7 @@ async function waitForHealthyRuntime(serverId, timeoutMs) {
|
|
|
220
214
|
}
|
|
221
215
|
} catch {}
|
|
222
216
|
}
|
|
223
|
-
await new Promise((resolve
|
|
217
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
224
218
|
}
|
|
225
219
|
throw new Error(`Timed out waiting for HTTP runtime '${serverId}' to become healthy`);
|
|
226
220
|
}
|
|
@@ -259,14 +253,21 @@ async function prestartHttpRuntime(options) {
|
|
|
259
253
|
const timeoutMs = parseTimeoutMs(options.timeoutMs);
|
|
260
254
|
const registryPath = options.registryPath || options.registryDir;
|
|
261
255
|
const workspaceRoot = resolveWorkspaceRoot();
|
|
262
|
-
const existing = await
|
|
263
|
-
if (existing) return
|
|
264
|
-
|
|
256
|
+
const existing = await findExistingRuntime(workspaceRoot);
|
|
257
|
+
if (existing && await isRuntimeHealthy(existing.host, existing.port)) return {
|
|
258
|
+
host: existing.host,
|
|
259
|
+
port: existing.port,
|
|
260
|
+
serverId: existing.serverId,
|
|
261
|
+
workspaceRoot,
|
|
262
|
+
reusedExistingRuntime: true
|
|
263
|
+
};
|
|
264
|
+
const targetPort = options.port ?? existing?.port;
|
|
265
|
+
await stopExistingRuntime(new require_src.RuntimeStateService(), options.id, options.host, targetPort);
|
|
265
266
|
const childEnv = {
|
|
266
267
|
...process.env,
|
|
267
268
|
...registryPath ? {
|
|
268
269
|
PORT_REGISTRY_PATH: registryPath,
|
|
269
|
-
PROCESS_REGISTRY_PATH: (0,
|
|
270
|
+
PROCESS_REGISTRY_PATH: (0, _agimon_ai_foundation_process_registry.resolveSiblingRegistryPath)(registryPath, "processes.json")
|
|
270
271
|
} : {}
|
|
271
272
|
};
|
|
272
273
|
const child = spawnBackgroundRuntime([
|
|
@@ -277,7 +278,7 @@ async function prestartHttpRuntime(options) {
|
|
|
277
278
|
serverId,
|
|
278
279
|
"--host",
|
|
279
280
|
options.host || DEFAULT_HOST$1,
|
|
280
|
-
...
|
|
281
|
+
...targetPort !== void 0 ? ["--port", String(targetPort)] : [],
|
|
281
282
|
...options.config ? ["--config", options.config] : [],
|
|
282
283
|
...options.cache === false ? ["--no-cache"] : [],
|
|
283
284
|
...options.definitionsCache ? ["--definitions-cache", options.definitionsCache] : [],
|
|
@@ -316,7 +317,6 @@ const prestartHttpCommand = new commander.Command("prestart-http").description("
|
|
|
316
317
|
throw new Error(`Failed to prestart HTTP runtime '${options.id || "generated-server-id"}': ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
317
318
|
}
|
|
318
319
|
});
|
|
319
|
-
|
|
320
320
|
//#endregion
|
|
321
321
|
//#region src/commands/mcp-serve.ts
|
|
322
322
|
/**
|
|
@@ -490,7 +490,7 @@ function createRuntimeRecord(serverId, config, port, shutdownToken, configPath)
|
|
|
490
490
|
};
|
|
491
491
|
}
|
|
492
492
|
function createPortRegistryService() {
|
|
493
|
-
return new
|
|
493
|
+
return new _agimon_ai_foundation_port_registry.PortRegistryService(process.env.PORT_REGISTRY_PATH);
|
|
494
494
|
}
|
|
495
495
|
function getRegistryEnvironment() {
|
|
496
496
|
return process.env.NODE_ENV ?? "development";
|
|
@@ -498,7 +498,7 @@ function getRegistryEnvironment() {
|
|
|
498
498
|
async function createPortRegistryLease(serviceName, host, preferredPort, serverId, transport, configPath, portRange = preferredPort !== void 0 ? {
|
|
499
499
|
min: preferredPort,
|
|
500
500
|
max: preferredPort
|
|
501
|
-
} :
|
|
501
|
+
} : _agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE) {
|
|
502
502
|
const portRegistry = createPortRegistryService();
|
|
503
503
|
const result = await portRegistry.reservePort({
|
|
504
504
|
repositoryPath: getRegistryRepositoryPath(),
|
|
@@ -630,14 +630,14 @@ async function createAndStartHttpRuntime(serverOptions, config, resolvedConfigPa
|
|
|
630
630
|
const portRange = requestedPort !== void 0 ? {
|
|
631
631
|
min: requestedPort,
|
|
632
632
|
max: requestedPort
|
|
633
|
-
} :
|
|
633
|
+
} : _agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE;
|
|
634
634
|
const portLease = await createPortRegistryLease(PORT_REGISTRY_SERVICE_HTTP, config.host ?? DEFAULT_HOST, requestedPort, runtimeServerId, TRANSPORT_TYPE_HTTP, resolvedConfigPath, portRange);
|
|
635
635
|
const runtimePort = portLease.port;
|
|
636
636
|
const runtimeConfig = {
|
|
637
637
|
...config,
|
|
638
638
|
port: runtimePort
|
|
639
639
|
};
|
|
640
|
-
const processLease = await (0,
|
|
640
|
+
const processLease = await (0, _agimon_ai_foundation_process_registry.createProcessLease)({
|
|
641
641
|
repositoryPath: getRegistryRepositoryPath(),
|
|
642
642
|
serviceName: PROCESS_REGISTRY_SERVICE_HTTP,
|
|
643
643
|
serviceType: PROCESS_REGISTRY_SERVICE_TYPE,
|
|
@@ -707,7 +707,7 @@ async function startSseTransport(serverOptions, config) {
|
|
|
707
707
|
const portRange = requestedPort !== void 0 ? {
|
|
708
708
|
min: requestedPort,
|
|
709
709
|
max: requestedPort
|
|
710
|
-
} :
|
|
710
|
+
} : _agimon_ai_foundation_port_registry.DEFAULT_PORT_RANGE;
|
|
711
711
|
const portLease = await createPortRegistryLease("mcp-proxy-sse", config.host ?? DEFAULT_HOST, requestedPort, serverOptions.serverId ?? require_src.generateServerId(), TRANSPORT_TYPE_SSE, void 0, portRange);
|
|
712
712
|
const resolvedConfig = {
|
|
713
713
|
...config,
|
|
@@ -830,7 +830,6 @@ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MC
|
|
|
830
830
|
process.exit(1);
|
|
831
831
|
}
|
|
832
832
|
});
|
|
833
|
-
|
|
834
833
|
//#endregion
|
|
835
834
|
//#region src/commands/bootstrap.ts
|
|
836
835
|
function toErrorMessage$8(error) {
|
|
@@ -920,7 +919,6 @@ async function withConnectedCommandContext(options, run) {
|
|
|
920
919
|
if (config.proxy?.port) return await withProxiedContext(container, config, configFilePath, options, run);
|
|
921
920
|
return await withDirectContext(container, config, configFilePath, options, run);
|
|
922
921
|
}
|
|
923
|
-
|
|
924
922
|
//#endregion
|
|
925
923
|
//#region src/commands/list-tools.ts
|
|
926
924
|
/**
|
|
@@ -991,7 +989,6 @@ const searchToolsCommand = new commander.Command("search-tools").description("Se
|
|
|
991
989
|
process.exit(1);
|
|
992
990
|
}
|
|
993
991
|
});
|
|
994
|
-
|
|
995
992
|
//#endregion
|
|
996
993
|
//#region src/commands/describe-tools.ts
|
|
997
994
|
/**
|
|
@@ -1132,7 +1129,6 @@ const describeToolsCommand = new commander.Command("describe-tools").description
|
|
|
1132
1129
|
process.exit(1);
|
|
1133
1130
|
}
|
|
1134
1131
|
});
|
|
1135
|
-
|
|
1136
1132
|
//#endregion
|
|
1137
1133
|
//#region src/commands/use-tool.ts
|
|
1138
1134
|
/**
|
|
@@ -1174,34 +1170,34 @@ const useToolCommand = new commander.Command("use-tool").description("Execute an
|
|
|
1174
1170
|
await withConnectedCommandContext(options, async ({ container, config, clientManager }) => {
|
|
1175
1171
|
const clients = clientManager.getAllClients();
|
|
1176
1172
|
if (options.server) {
|
|
1177
|
-
const client
|
|
1178
|
-
if (!client
|
|
1173
|
+
const client = clientManager.getClient(options.server);
|
|
1174
|
+
if (!client) throw new Error(`Server "${options.server}" not found`);
|
|
1179
1175
|
if (!options.json) console.error(`Executing ${toolName} on ${options.server}...`);
|
|
1180
|
-
const requestOptions
|
|
1181
|
-
const result
|
|
1182
|
-
if (options.json) console.log(JSON.stringify(result
|
|
1176
|
+
const requestOptions = options.timeout ? { timeout: options.timeout } : void 0;
|
|
1177
|
+
const result = await client.callTool(toolName, toolArgs, requestOptions);
|
|
1178
|
+
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
1183
1179
|
else {
|
|
1184
1180
|
console.log("\nResult:");
|
|
1185
|
-
if (result
|
|
1181
|
+
if (result.content) for (const content of result.content) if (content.type === "text") console.log(content.text);
|
|
1186
1182
|
else console.log(JSON.stringify(content, null, 2));
|
|
1187
|
-
if (result
|
|
1183
|
+
if (result.isError) {
|
|
1188
1184
|
console.error("\n⚠️ Tool execution returned an error");
|
|
1189
1185
|
process.exit(1);
|
|
1190
1186
|
}
|
|
1191
1187
|
}
|
|
1192
1188
|
return;
|
|
1193
1189
|
}
|
|
1194
|
-
const searchResults = await Promise.all(clients.map(async (client
|
|
1190
|
+
const searchResults = await Promise.all(clients.map(async (client) => {
|
|
1195
1191
|
try {
|
|
1196
|
-
const hasTool = (await client
|
|
1192
|
+
const hasTool = (await client.listTools()).some((t) => t.name === toolName);
|
|
1197
1193
|
return {
|
|
1198
|
-
serverName: client
|
|
1194
|
+
serverName: client.serverName,
|
|
1199
1195
|
hasTool,
|
|
1200
1196
|
error: null
|
|
1201
1197
|
};
|
|
1202
1198
|
} catch (error) {
|
|
1203
1199
|
return {
|
|
1204
|
-
serverName: client
|
|
1200
|
+
serverName: client.serverName,
|
|
1205
1201
|
hasTool: false,
|
|
1206
1202
|
error
|
|
1207
1203
|
};
|
|
@@ -1223,11 +1219,11 @@ const useToolCommand = new commander.Command("use-tool").description("Execute an
|
|
|
1223
1219
|
const skillName = toolName.startsWith("skill__") ? toolName.slice(7) : toolName;
|
|
1224
1220
|
const skill = await skillService.getSkill(skillName);
|
|
1225
1221
|
if (skill) {
|
|
1226
|
-
const result
|
|
1222
|
+
const result = { content: [{
|
|
1227
1223
|
type: "text",
|
|
1228
1224
|
text: skill.content
|
|
1229
1225
|
}] };
|
|
1230
|
-
if (options.json) console.log(JSON.stringify(result
|
|
1226
|
+
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
1231
1227
|
else {
|
|
1232
1228
|
console.log("\nSkill content:");
|
|
1233
1229
|
console.log(skill.content);
|
|
@@ -1262,7 +1258,6 @@ const useToolCommand = new commander.Command("use-tool").description("Execute an
|
|
|
1262
1258
|
process.exit(1);
|
|
1263
1259
|
}
|
|
1264
1260
|
});
|
|
1265
|
-
|
|
1266
1261
|
//#endregion
|
|
1267
1262
|
//#region src/commands/list-resources.ts
|
|
1268
1263
|
/**
|
|
@@ -1333,7 +1328,6 @@ const listResourcesCommand = new commander.Command("list-resources").description
|
|
|
1333
1328
|
process.exit(1);
|
|
1334
1329
|
}
|
|
1335
1330
|
});
|
|
1336
|
-
|
|
1337
1331
|
//#endregion
|
|
1338
1332
|
//#region src/commands/read-resource.ts
|
|
1339
1333
|
/**
|
|
@@ -1368,26 +1362,26 @@ const readResourceCommand = new commander.Command("read-resource").description("
|
|
|
1368
1362
|
await withConnectedCommandContext(options, async ({ clientManager }) => {
|
|
1369
1363
|
const clients = clientManager.getAllClients();
|
|
1370
1364
|
if (options.server) {
|
|
1371
|
-
const client
|
|
1372
|
-
if (!client
|
|
1365
|
+
const client = clientManager.getClient(options.server);
|
|
1366
|
+
if (!client) throw new Error(`Server "${options.server}" not found`);
|
|
1373
1367
|
if (!options.json) console.error(`Reading ${uri} from ${options.server}...`);
|
|
1374
|
-
const result
|
|
1375
|
-
if (options.json) console.log(JSON.stringify(result
|
|
1376
|
-
else for (const content of result
|
|
1368
|
+
const result = await client.readResource(uri);
|
|
1369
|
+
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
1370
|
+
else for (const content of result.contents) if ("text" in content) console.log(content.text);
|
|
1377
1371
|
else console.log(JSON.stringify(content, null, 2));
|
|
1378
1372
|
return;
|
|
1379
1373
|
}
|
|
1380
|
-
const searchResults = await Promise.all(clients.map(async (client
|
|
1374
|
+
const searchResults = await Promise.all(clients.map(async (client) => {
|
|
1381
1375
|
try {
|
|
1382
|
-
const hasResource = (await client
|
|
1376
|
+
const hasResource = (await client.listResources()).some((r) => r.uri === uri);
|
|
1383
1377
|
return {
|
|
1384
|
-
serverName: client
|
|
1378
|
+
serverName: client.serverName,
|
|
1385
1379
|
hasResource,
|
|
1386
1380
|
error: null
|
|
1387
1381
|
};
|
|
1388
1382
|
} catch (error) {
|
|
1389
1383
|
return {
|
|
1390
|
-
serverName: client
|
|
1384
|
+
serverName: client.serverName,
|
|
1391
1385
|
hasResource: false,
|
|
1392
1386
|
error
|
|
1393
1387
|
};
|
|
@@ -1417,7 +1411,6 @@ const readResourceCommand = new commander.Command("read-resource").description("
|
|
|
1417
1411
|
process.exit(1);
|
|
1418
1412
|
}
|
|
1419
1413
|
});
|
|
1420
|
-
|
|
1421
1414
|
//#endregion
|
|
1422
1415
|
//#region src/commands/list-prompts.ts
|
|
1423
1416
|
function toErrorMessage$2(error) {
|
|
@@ -1458,7 +1451,6 @@ const listPromptsCommand = new commander.Command("list-prompts").description("Li
|
|
|
1458
1451
|
process.exit(1);
|
|
1459
1452
|
}
|
|
1460
1453
|
});
|
|
1461
|
-
|
|
1462
1454
|
//#endregion
|
|
1463
1455
|
//#region src/commands/get-prompt.ts
|
|
1464
1456
|
function toErrorMessage$1(error) {
|
|
@@ -1475,11 +1467,11 @@ const getPromptCommand = new commander.Command("get-prompt").description("Get a
|
|
|
1475
1467
|
await withConnectedCommandContext(options, async ({ clientManager }) => {
|
|
1476
1468
|
const clients = clientManager.getAllClients();
|
|
1477
1469
|
if (options.server) {
|
|
1478
|
-
const client
|
|
1479
|
-
if (!client
|
|
1480
|
-
const prompt
|
|
1481
|
-
if (options.json) console.log(JSON.stringify(prompt
|
|
1482
|
-
else for (const message of prompt
|
|
1470
|
+
const client = clientManager.getClient(options.server);
|
|
1471
|
+
if (!client) throw new Error(`Server "${options.server}" not found`);
|
|
1472
|
+
const prompt = await client.getPrompt(promptName, promptArgs);
|
|
1473
|
+
if (options.json) console.log(JSON.stringify(prompt, null, 2));
|
|
1474
|
+
else for (const message of prompt.messages) {
|
|
1483
1475
|
const content = message.content;
|
|
1484
1476
|
if (typeof content === "object" && content && "text" in content) console.log(content.text);
|
|
1485
1477
|
else console.log(JSON.stringify(message, null, 2));
|
|
@@ -1487,11 +1479,11 @@ const getPromptCommand = new commander.Command("get-prompt").description("Get a
|
|
|
1487
1479
|
return;
|
|
1488
1480
|
}
|
|
1489
1481
|
const matchingServers = [];
|
|
1490
|
-
await Promise.all(clients.map(async (client
|
|
1482
|
+
await Promise.all(clients.map(async (client) => {
|
|
1491
1483
|
try {
|
|
1492
|
-
if ((await client
|
|
1484
|
+
if ((await client.listPrompts()).some((prompt) => prompt.name === promptName)) matchingServers.push(client.serverName);
|
|
1493
1485
|
} catch (error) {
|
|
1494
|
-
if (!options.json) console.error(`Failed to list prompts from ${client
|
|
1486
|
+
if (!options.json) console.error(`Failed to list prompts from ${client.serverName}: ${toErrorMessage$1(error)}`);
|
|
1495
1487
|
}
|
|
1496
1488
|
}));
|
|
1497
1489
|
if (matchingServers.length === 0) throw new Error(`Prompt "${promptName}" not found on any connected server`);
|
|
@@ -1511,7 +1503,6 @@ const getPromptCommand = new commander.Command("get-prompt").description("Get a
|
|
|
1511
1503
|
process.exit(1);
|
|
1512
1504
|
}
|
|
1513
1505
|
});
|
|
1514
|
-
|
|
1515
1506
|
//#endregion
|
|
1516
1507
|
//#region src/commands/prefetch.ts
|
|
1517
1508
|
/**
|
|
@@ -1638,7 +1629,6 @@ const prefetchCommand = new commander.Command("prefetch").description("Pre-downl
|
|
|
1638
1629
|
process.exit(1);
|
|
1639
1630
|
}
|
|
1640
1631
|
});
|
|
1641
|
-
|
|
1642
1632
|
//#endregion
|
|
1643
1633
|
//#region src/commands/stop.ts
|
|
1644
1634
|
/**
|
|
@@ -1684,7 +1674,6 @@ const stopCommand = new commander.Command("stop").description("Stop a running HT
|
|
|
1684
1674
|
process.exit(1);
|
|
1685
1675
|
}
|
|
1686
1676
|
});
|
|
1687
|
-
|
|
1688
1677
|
//#endregion
|
|
1689
1678
|
//#region src/cli.ts
|
|
1690
1679
|
/**
|
|
@@ -1734,5 +1723,4 @@ main().catch((error) => {
|
|
|
1734
1723
|
console.error(`Fatal error: ${error instanceof Error ? error.message : error}`);
|
|
1735
1724
|
process.exit(1);
|
|
1736
1725
|
});
|
|
1737
|
-
|
|
1738
|
-
//#endregion
|
|
1726
|
+
//#endregion
|