@mcp-z/cli 1.0.4 ā 1.0.5
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/cjs/commands/inspect.js +9 -2
- package/dist/cjs/commands/inspect.js.map +1 -1
- package/dist/cjs/commands/search.js +9 -2
- package/dist/cjs/commands/search.js.map +1 -1
- package/dist/cjs/commands/up.js +9 -2
- package/dist/cjs/commands/up.js.map +1 -1
- package/dist/cjs/lib/find-config-path.d.cts +23 -0
- package/dist/cjs/lib/find-config-path.d.ts +23 -0
- package/dist/cjs/lib/find-config-path.js +111 -0
- package/dist/cjs/lib/find-config-path.js.map +1 -0
- package/dist/cjs/lib/resolve-server-config.js +9 -2
- package/dist/cjs/lib/resolve-server-config.js.map +1 -1
- package/dist/esm/commands/inspect.js +4 -2
- package/dist/esm/commands/inspect.js.map +1 -1
- package/dist/esm/commands/search.js +4 -2
- package/dist/esm/commands/search.js.map +1 -1
- package/dist/esm/commands/up.js +4 -2
- package/dist/esm/commands/up.js.map +1 -1
- package/dist/esm/lib/find-config-path.d.ts +23 -0
- package/dist/esm/lib/find-config-path.js +58 -0
- package/dist/esm/lib/find-config-path.js.map +1 -0
- package/dist/esm/lib/resolve-server-config.js +4 -2
- package/dist/esm/lib/resolve-server-config.js.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/lib/find-config.d.cts +0 -14
- package/dist/cjs/lib/find-config.d.ts +0 -14
- package/dist/cjs/lib/find-config.js +0 -93
- package/dist/cjs/lib/find-config.js.map +0 -1
- package/dist/esm/lib/find-config.d.ts +0 -14
- package/dist/esm/lib/find-config.js +0 -42
- package/dist/esm/lib/find-config.js.map +0 -1
|
@@ -16,7 +16,7 @@ Object.defineProperty(exports, "inspectCommand", {
|
|
|
16
16
|
var _client = require("@mcp-z/client");
|
|
17
17
|
var _fs = /*#__PURE__*/ _interop_require_wildcard(require("fs"));
|
|
18
18
|
var _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
|
|
19
|
-
var
|
|
19
|
+
var _findconfigpathts = /*#__PURE__*/ _interop_require_default(require("../lib/find-config-path.js"));
|
|
20
20
|
var _typests = require("../types.js");
|
|
21
21
|
function _array_like_to_array(arr, len) {
|
|
22
22
|
if (len == null || len > arr.length) len = arr.length;
|
|
@@ -62,6 +62,11 @@ function _instanceof(left, right) {
|
|
|
62
62
|
return left instanceof right;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
function _interop_require_default(obj) {
|
|
66
|
+
return obj && obj.__esModule ? obj : {
|
|
67
|
+
default: obj
|
|
68
|
+
};
|
|
69
|
+
}
|
|
65
70
|
function _getRequireWildcardCache(nodeInterop) {
|
|
66
71
|
if (typeof WeakMap !== "function") return null;
|
|
67
72
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -257,7 +262,9 @@ function inspectCommand() {
|
|
|
257
262
|
10,
|
|
258
263
|
15
|
|
259
264
|
]);
|
|
260
|
-
configPath = (0,
|
|
265
|
+
configPath = (0, _findconfigpathts.default)({
|
|
266
|
+
config: opts.config
|
|
267
|
+
});
|
|
261
268
|
raw = JSON.parse(_fs.readFileSync(configPath, 'utf8'));
|
|
262
269
|
servers = (_ref = (_raw_mcpServers = raw.mcpServers) !== null && _raw_mcpServers !== void 0 ? _raw_mcpServers : raw.servers) !== null && _ref !== void 0 ? _ref : raw;
|
|
263
270
|
configDir = _path.dirname(configPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/commands/inspect.ts"],"sourcesContent":["/**\n * inspect.ts\n *\n * Inspect MCP servers: explore tools, resources, prompts, and health status.\n * Supports stdio (spawned) and http (remote) servers per MCP spec.\n */\n\nimport { createServerRegistry, type PromptArgument, type ServerRegistry, type ServersConfig } from '@mcp-z/client';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { findConfigPath } from '../lib/find-config.ts';\nimport { isHttpServer, type ServerConfig } from '../types.ts';\n\nconst MAX_DESCRIPTION = 100;\n\nexport interface InspectOptions {\n config?: string; // --config custom.json\n servers?: string; // --servers echo-server-1,echo-server-2 (comma-separated)\n tools?: boolean; // --tools\n resources?: boolean; // --resources\n prompts?: boolean; // --prompts\n health?: boolean; // --health\n json?: boolean; // --json\n verbose?: boolean; // --verbose\n attach?: boolean; // --attach (connect to running servers instead of spawning)\n}\n\ninterface ServerInfo {\n name: string;\n status: 'ready' | 'failed';\n startupTime: number | undefined;\n error: string | undefined;\n tools: ToolInfo[] | undefined;\n resources: ResourceInfo[] | undefined;\n prompts: PromptInfo[] | undefined;\n}\n\ninterface ToolInfo {\n name: string;\n description: string | undefined;\n inputSchema: unknown;\n}\n\ninterface ResourceInfo {\n uri: string;\n name: string;\n description: string | undefined;\n mimeType: string | undefined;\n}\n\ninterface PromptInfo {\n name: string;\n description: string | undefined;\n arguments: PromptArgument[] | undefined;\n}\n\n/**\n * Main inspect command implementation.\n *\n * @param opts - Inspect options from CLI flags\n *\n * @example\n * // Show summary of .mcp.json servers (spawns servers)\n * await inspectCommand({});\n *\n * @example\n * // Show all tools from echo server (spawns server)\n * await inspectCommand({ servers: 'echo', tools: true });\n *\n * @example\n * // Connect to running servers (attach mode)\n * await inspectCommand({ config: 'http-servers.json', attach: true, health: true });\n */\nexport async function inspectCommand(opts: InspectOptions = {}): Promise<void> {\n let registry: ServerRegistry | undefined;\n\n try {\n const configPath = findConfigPath(opts.config);\n const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));\n const servers = raw.mcpServers ?? raw.servers ?? raw;\n const configDir = path.dirname(configPath);\n const serverNames = Object.keys(servers || {});\n const serversToInspect = filterServers(serverNames, opts.servers);\n\n // Create registry (spawns stdio servers, registers HTTP servers)\n // In attach mode, don't spawn - just register for connection\n registry = createServerRegistry(servers, {\n cwd: configDir,\n dialects: opts.attach ? [] : ['servers', 'start'], // Empty dialects = no spawning\n });\n\n const serverInfos: ServerInfo[] = [];\n for (const serverName of serversToInspect) {\n const info = await inspectServer(serverName, servers, registry, opts);\n serverInfos.push(info);\n }\n\n // 5. Output results\n if (opts.json) {\n outputJSON(serverInfos);\n } else {\n outputPretty(serverInfos, opts);\n }\n } finally {\n // 6. Cleanup - registry.close() handles all clients and servers\n if (registry) {\n try {\n await registry.close();\n } catch (_) {\n // Ignore close errors\n }\n }\n }\n}\n\n/**\n * Filter servers based on --servers flag.\n */\nfunction filterServers(allServers: string[], serversFlag?: string): string[] {\n if (!serversFlag) {\n return allServers;\n }\n\n const requested = serversFlag.split(',').map((s) => s.trim());\n const missing = requested.filter((s) => !allServers.includes(s));\n\n if (missing.length > 0) {\n throw new Error(`Server(s) not found in config: ${missing.join(', ')}\\n\\nAvailable servers: ${allServers.join(', ')}`);\n }\n\n return requested;\n}\n\n/**\n * Inspect a single server: collect tools, resources, prompts, health.\n */\nasync function inspectServer(serverName: string, servers: ServersConfig, registry: ServerRegistry, opts: InspectOptions): Promise<ServerInfo> {\n const start = Date.now();\n\n try {\n // Connect to server via registry\n const serverConfig = servers?.[serverName];\n if (!serverConfig) {\n throw new Error(`Server ${serverName} not found in config`);\n }\n\n if (!isHttpServer(serverConfig as ServerConfig) && !serverConfig.command) {\n throw new Error(`Stdio server ${serverName} missing required \"command\" field`);\n }\n\n const client = await registry.connect(serverName);\n\n // Collect content based on flags\n const needsTools = opts.tools || shouldShowSummary(opts);\n const needsResources = opts.resources || shouldShowSummary(opts);\n const needsPrompts = opts.prompts || shouldShowSummary(opts);\n\n // Handle each capability independently - servers may not implement all methods\n const [toolsResult, resourcesResult, promptsResult] = await Promise.all([needsTools ? client.listTools().catch(() => null) : Promise.resolve(null), needsResources ? client.listResources().catch(() => null) : Promise.resolve(null), needsPrompts ? client.listPrompts().catch(() => null) : Promise.resolve(null)]);\n\n const startupTime = Date.now() - start;\n\n return {\n name: serverName,\n status: 'ready',\n startupTime,\n error: undefined,\n tools: toolsResult?.tools\n ? toolsResult.tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n }))\n : undefined,\n resources: resourcesResult?.resources\n ? resourcesResult.resources.map((r) => ({\n uri: r.uri,\n name: r.name,\n description: r.description,\n mimeType: r.mimeType,\n }))\n : undefined,\n prompts: promptsResult?.prompts\n ? promptsResult.prompts.map((p) => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments,\n }))\n : undefined,\n };\n } catch (error) {\n // Format error message with context\n let errorMessage = error instanceof Error ? error.message : String(error);\n\n // For fetch errors, dig into the cause for more details\n if (error instanceof Error && error.message === 'fetch failed' && 'cause' in error) {\n const cause = error.cause as { code?: string; message?: string } | undefined;\n if (cause?.code === 'ECONNREFUSED') {\n const serverConfig = servers?.[serverName];\n const url = serverConfig && 'url' in serverConfig ? serverConfig.url : undefined;\n errorMessage = url ? `Connection refused (server not running at ${url})` : 'Connection refused (server not running)';\n } else if (cause?.message) {\n errorMessage = `${error.message}: ${cause.message}`;\n }\n }\n\n return {\n name: serverName,\n status: 'failed',\n startupTime: undefined,\n error: errorMessage,\n tools: undefined,\n resources: undefined,\n prompts: undefined,\n };\n }\n}\n\n/**\n * Determine if we should show summary (no specific content flags).\n */\nfunction shouldShowSummary(opts: InspectOptions): boolean {\n return !opts.tools && !opts.resources && !opts.prompts && !opts.health;\n}\n\n/**\n * Truncate description to max length with ellipsis.\n */\nfunction truncateDescription(desc: string, _maxLength = MAX_DESCRIPTION): string {\n return desc;\n // if (!desc || desc.length <= maxLength) {\n // return desc;\n // }\n // return `${desc.slice(0, maxLength - 3)}...`;\n}\n\n/**\n * Render verbose details for a tool (parameters with types and descriptions)\n */\nfunction renderToolVerbose(tool: ToolInfo, indent: string): void {\n // Description is already shown inline, so skip it here\n const schema = tool.inputSchema as { properties?: Record<string, unknown>; required?: string[] } | undefined;\n if (!schema || !schema.properties) {\n return;\n }\n\n const properties = schema.properties;\n const required = schema.required || [];\n\n // Separate required and optional parameters\n const requiredParams: string[] = [];\n const optionalParams: string[] = [];\n\n for (const [name, _prop] of Object.entries(properties)) {\n if (required.includes(name)) {\n requiredParams.push(name);\n } else {\n optionalParams.push(name);\n }\n }\n\n // Show required parameters\n if (requiredParams.length > 0) {\n console.log(`${indent}Required Parameters:`);\n for (const name of requiredParams) {\n renderParameter(name, properties[name], `${indent} `);\n }\n console.log('');\n }\n\n // Show optional parameters\n if (optionalParams.length > 0) {\n console.log(`${indent}Optional Parameters:`);\n for (const name of optionalParams) {\n renderParameter(name, properties[name], `${indent} `);\n }\n console.log('');\n }\n}\n\n/**\n * Render verbose details for a resource\n */\nfunction renderResourceVerbose(resource: ResourceInfo, indent: string): void {\n // Description is already shown inline, so only show URI and MIME type\n if (resource.uri) {\n console.log(`${indent}URI: ${resource.uri}`);\n }\n if (resource.mimeType) {\n console.log(`${indent}MIME Type: ${resource.mimeType}`);\n }\n if (resource.uri || resource.mimeType) {\n console.log('');\n }\n}\n\n/**\n * Render verbose details for a prompt\n */\nfunction renderPromptVerbose(prompt: PromptInfo, indent: string): void {\n // Description is already shown inline, so only show arguments\n if (prompt.arguments && Array.isArray(prompt.arguments) && prompt.arguments.length > 0) {\n console.log(`${indent}Arguments:`);\n for (const arg of prompt.arguments) {\n const argObj = arg as { name?: string; description?: string; required?: boolean };\n const name = argObj.name || 'unknown';\n const description = argObj.description || '';\n const required = argObj.required ? ' (required)' : ' (optional)';\n const desc = description ? ` - ${description}` : '';\n console.log(`${indent} ${name}${required}${desc}`);\n }\n console.log('');\n }\n}\n\n/**\n * Render a single parameter with type and description\n */\nfunction renderParameter(name: string, prop: unknown, indent: string): void {\n const p = prop as { description?: string; enum?: unknown[] };\n const type = getParameterType(prop);\n const constraints = getParameterConstraints(prop);\n const typeInfo = constraints ? `(${type}) ${constraints}` : `(${type})`;\n const desc = p.description ? ` - ${p.description}` : '';\n\n console.log(`${indent}${name} ${typeInfo}${desc}`);\n\n // Show enum options on separate line if present\n if (p.enum && Array.isArray(p.enum)) {\n console.log(`${indent} Options: ${p.enum.join(', ')}`);\n }\n}\n\n/**\n * Get human-readable type from JSON Schema property\n */\nfunction getParameterType(prop: unknown): string {\n const p = prop as { type?: string | string[]; items?: { type?: string }; anyOf?: Array<{ type?: string }>; enum?: unknown[] };\n if (p.type) {\n if (Array.isArray(p.type)) {\n return p.type.join(' | ');\n }\n if (p.type === 'array' && p.items) {\n const itemType = p.items.type || 'any';\n return `array of ${itemType}`;\n }\n return p.type;\n }\n\n if (p.anyOf) {\n return p.anyOf.map((s) => s.type || 'any').join(' | ');\n }\n\n if (p.enum) {\n return 'enum';\n }\n\n return 'any';\n}\n\n/**\n * Get parameter constraints (default, min, max, etc.)\n */\nfunction getParameterConstraints(prop: unknown): string {\n const p = prop as {\n default?: unknown;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n minItems?: number;\n maxItems?: number;\n };\n const constraints: string[] = [];\n\n if (p.default !== undefined) {\n const defaultValue = typeof p.default === 'string' ? `\"${p.default}\"` : String(p.default);\n constraints.push(`default: ${defaultValue}`);\n }\n\n if (p.minimum !== undefined) {\n constraints.push(`min: ${p.minimum}`);\n }\n\n if (p.maximum !== undefined) {\n constraints.push(`max: ${p.maximum}`);\n }\n\n if (p.minLength !== undefined) {\n constraints.push(`minLength: ${p.minLength}`);\n }\n\n if (p.maxLength !== undefined) {\n constraints.push(`maxLength: ${p.maxLength}`);\n }\n\n if (p.minItems !== undefined) {\n constraints.push(`minItems: ${p.minItems}`);\n }\n\n if (p.maxItems !== undefined) {\n constraints.push(`maxItems: ${p.maxItems}`);\n }\n\n return constraints.length > 0 ? `[${constraints.join(', ')}]` : '';\n}\n\n/**\n * Output results as JSON.\n */\nfunction outputJSON(serverInfos: ServerInfo[]): void {\n const output = {\n servers: serverInfos.reduce(\n (acc, info) => {\n acc[info.name] = {\n status: info.status,\n startupTime: info.startupTime ? `${(info.startupTime / 1000).toFixed(1)}s` : undefined,\n error: info.error,\n tools: info.tools,\n resources: info.resources,\n prompts: info.prompts,\n };\n return acc;\n },\n {} as Record<string, unknown>\n ),\n };\n\n console.log(JSON.stringify(output, null, 2));\n}\n\n/**\n * Output results in human-readable format.\n */\nfunction outputPretty(serverInfos: ServerInfo[], opts: InspectOptions): void {\n const showSummary = shouldShowSummary(opts);\n\n for (const info of serverInfos) {\n // Summary mode\n if (showSummary) {\n if (info.status === 'ready') {\n const toolCount = info.tools?.length || 0;\n const resourceCount = info.resources?.length || 0;\n const promptCount = info.prompts?.length || 0;\n const time = info.startupTime ? `(${(info.startupTime / 1000).toFixed(1)}s)` : '';\n console.log(`š¦ ${info.name}: ${time}`);\n\n // Show detailed list of tools\n console.log(`tools: ${toolCount}`);\n if (info.tools && info.tools.length > 0) {\n for (let i = 0; i < info.tools.length; i++) {\n const tool = info.tools[i];\n if (!tool) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = tool.description ? ` - ${opts.verbose ? tool.description : truncateDescription(tool.description)}` : '';\n console.log(`${i + 1}. ${tool.name}${desc}`);\n if (opts.verbose) {\n renderToolVerbose(tool, ' ');\n }\n }\n }\n\n // Show detailed list of resources\n console.log(`resources: ${resourceCount}`);\n if (info.resources && info.resources.length > 0) {\n for (let i = 0; i < info.resources.length; i++) {\n const resource = info.resources[i];\n if (!resource) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = resource.description ? ` - ${opts.verbose ? resource.description : truncateDescription(resource.description)}` : '';\n console.log(`${i + 1}. ${resource.name}${desc}`);\n if (opts.verbose) {\n renderResourceVerbose(resource, ' ');\n }\n }\n }\n\n // Show detailed list of prompts\n console.log(`prompts: ${promptCount}`);\n if (info.prompts && info.prompts.length > 0) {\n for (let i = 0; i < info.prompts.length; i++) {\n const prompt = info.prompts[i];\n if (!prompt) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = prompt.description ? ` - ${opts.verbose ? prompt.description : truncateDescription(prompt.description)}` : '';\n console.log(`${i + 1}. ${prompt.name}${desc}`);\n if (opts.verbose) {\n renderPromptVerbose(prompt, ' ');\n }\n }\n }\n } else {\n console.log(`š¦ ${info.name}: ā failed - ${info.error}`);\n }\n continue;\n }\n\n // Health mode\n if (opts.health) {\n if (info.status === 'ready') {\n const time = info.startupTime ? `(${(info.startupTime / 1000).toFixed(1)}s)` : '';\n console.log(`ā ${info.name} - ready ${time}`);\n } else {\n console.log(`ā ${info.name} - failed`);\n console.log(` Error: ${info.error}`);\n }\n continue;\n }\n\n // Tools mode\n if (opts.tools) {\n console.log(`\\nš¦ ${info.name} (${info.tools?.length || 0} tools)`);\n if (info.tools && info.tools.length > 0) {\n for (let i = 0; i < info.tools.length; i++) {\n const tool = info.tools[i];\n if (!tool) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = tool.description ? ` - ${opts.verbose ? tool.description : truncateDescription(tool.description)}` : '';\n console.log(` ${i + 1}. ${tool.name}${desc}`);\n if (opts.verbose) {\n renderToolVerbose(tool, ' ');\n }\n }\n }\n }\n\n // Resources mode\n if (opts.resources) {\n console.log(`\\nš¦ ${info.name} (${info.resources?.length || 0} resources)`);\n if (info.resources && info.resources.length > 0) {\n for (let i = 0; i < info.resources.length; i++) {\n const resource = info.resources[i];\n if (!resource) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = resource.description ? ` - ${opts.verbose ? resource.description : truncateDescription(resource.description)}` : '';\n console.log(` ${i + 1}. ${resource.name}${desc}`);\n if (opts.verbose) {\n renderResourceVerbose(resource, ' ');\n }\n }\n }\n }\n\n // Prompts mode\n if (opts.prompts) {\n console.log(`\\nš¦ ${info.name} (${info.prompts?.length || 0} prompts)`);\n if (info.prompts && info.prompts.length > 0) {\n for (let i = 0; i < info.prompts.length; i++) {\n const prompt = info.prompts[i];\n if (!prompt) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = prompt.description ? ` - ${opts.verbose ? prompt.description : truncateDescription(prompt.description)}` : '';\n console.log(` ${i + 1}. ${prompt.name}${desc}`);\n if (opts.verbose) {\n renderPromptVerbose(prompt, ' ');\n }\n }\n }\n }\n }\n\n console.log('');\n}\n"],"names":["inspectCommand","MAX_DESCRIPTION","opts","registry","raw","configPath","servers","configDir","serverNames","serversToInspect","serverInfos","serverName","info","_","findConfigPath","config","JSON","parse","fs","readFileSync","mcpServers","path","dirname","Object","keys","filterServers","createServerRegistry","cwd","dialects","attach","inspectServer","push","json","outputJSON","outputPretty","close","allServers","serversFlag","requested","split","map","s","trim","missing","filter","includes","length","Error","join","start","serverConfig","client","needsTools","needsResources","needsPrompts","toolsResult","resourcesResult","promptsResult","startupTime","error","errorMessage","cause","url","Date","now","isHttpServer","command","connect","tools","shouldShowSummary","resources","prompts","Promise","all","listTools","catch","resolve","listResources","listPrompts","name","status","undefined","t","description","inputSchema","r","uri","mimeType","p","arguments","message","String","code","health","truncateDescription","desc","_maxLength","renderToolVerbose","tool","indent","schema","properties","required","requiredParams","optionalParams","entries","_prop","console","log","renderParameter","renderResourceVerbose","resource","renderPromptVerbose","prompt","Array","isArray","arg","argObj","prop","type","getParameterType","constraints","getParameterConstraints","typeInfo","enum","items","itemType","anyOf","default","defaultValue","minimum","maximum","minLength","maxLength","minItems","maxItems","output","reduce","acc","toFixed","stringify","showSummary","toolCount","resourceCount","promptCount","time","i","verbose"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/commands/inspect.ts"],"sourcesContent":["/**\n * inspect.ts\n *\n * Inspect MCP servers: explore tools, resources, prompts, and health status.\n * Supports stdio (spawned) and http (remote) servers per MCP spec.\n */\n\nimport { createServerRegistry, type PromptArgument, type ServerRegistry, type ServersConfig } from '@mcp-z/client';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport findConfigPath from '../lib/find-config-path.ts';\nimport { isHttpServer, type ServerConfig } from '../types.ts';\n\nconst MAX_DESCRIPTION = 100;\n\nexport interface InspectOptions {\n config?: string; // --config custom.json\n servers?: string; // --servers echo-server-1,echo-server-2 (comma-separated)\n tools?: boolean; // --tools\n resources?: boolean; // --resources\n prompts?: boolean; // --prompts\n health?: boolean; // --health\n json?: boolean; // --json\n verbose?: boolean; // --verbose\n attach?: boolean; // --attach (connect to running servers instead of spawning)\n}\n\ninterface ServerInfo {\n name: string;\n status: 'ready' | 'failed';\n startupTime: number | undefined;\n error: string | undefined;\n tools: ToolInfo[] | undefined;\n resources: ResourceInfo[] | undefined;\n prompts: PromptInfo[] | undefined;\n}\n\ninterface ToolInfo {\n name: string;\n description: string | undefined;\n inputSchema: unknown;\n}\n\ninterface ResourceInfo {\n uri: string;\n name: string;\n description: string | undefined;\n mimeType: string | undefined;\n}\n\ninterface PromptInfo {\n name: string;\n description: string | undefined;\n arguments: PromptArgument[] | undefined;\n}\n\n/**\n * Main inspect command implementation.\n *\n * @param opts - Inspect options from CLI flags\n *\n * @example\n * // Show summary of .mcp.json servers (spawns servers)\n * await inspectCommand({});\n *\n * @example\n * // Show all tools from echo server (spawns server)\n * await inspectCommand({ servers: 'echo', tools: true });\n *\n * @example\n * // Connect to running servers (attach mode)\n * await inspectCommand({ config: 'http-servers.json', attach: true, health: true });\n */\nexport async function inspectCommand(opts: InspectOptions = {}): Promise<void> {\n let registry: ServerRegistry | undefined;\n\n try {\n const configPath = findConfigPath({ config: opts.config });\n const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));\n const servers = raw.mcpServers ?? raw.servers ?? raw;\n const configDir = path.dirname(configPath);\n const serverNames = Object.keys(servers || {});\n const serversToInspect = filterServers(serverNames, opts.servers);\n\n // Create registry (spawns stdio servers, registers HTTP servers)\n // In attach mode, don't spawn - just register for connection\n registry = createServerRegistry(servers, {\n cwd: configDir,\n dialects: opts.attach ? [] : ['servers', 'start'], // Empty dialects = no spawning\n });\n\n const serverInfos: ServerInfo[] = [];\n for (const serverName of serversToInspect) {\n const info = await inspectServer(serverName, servers, registry, opts);\n serverInfos.push(info);\n }\n\n // 5. Output results\n if (opts.json) {\n outputJSON(serverInfos);\n } else {\n outputPretty(serverInfos, opts);\n }\n } finally {\n // 6. Cleanup - registry.close() handles all clients and servers\n if (registry) {\n try {\n await registry.close();\n } catch (_) {\n // Ignore close errors\n }\n }\n }\n}\n\n/**\n * Filter servers based on --servers flag.\n */\nfunction filterServers(allServers: string[], serversFlag?: string): string[] {\n if (!serversFlag) {\n return allServers;\n }\n\n const requested = serversFlag.split(',').map((s) => s.trim());\n const missing = requested.filter((s) => !allServers.includes(s));\n\n if (missing.length > 0) {\n throw new Error(`Server(s) not found in config: ${missing.join(', ')}\\n\\nAvailable servers: ${allServers.join(', ')}`);\n }\n\n return requested;\n}\n\n/**\n * Inspect a single server: collect tools, resources, prompts, health.\n */\nasync function inspectServer(serverName: string, servers: ServersConfig, registry: ServerRegistry, opts: InspectOptions): Promise<ServerInfo> {\n const start = Date.now();\n\n try {\n // Connect to server via registry\n const serverConfig = servers?.[serverName];\n if (!serverConfig) {\n throw new Error(`Server ${serverName} not found in config`);\n }\n\n if (!isHttpServer(serverConfig as ServerConfig) && !serverConfig.command) {\n throw new Error(`Stdio server ${serverName} missing required \"command\" field`);\n }\n\n const client = await registry.connect(serverName);\n\n // Collect content based on flags\n const needsTools = opts.tools || shouldShowSummary(opts);\n const needsResources = opts.resources || shouldShowSummary(opts);\n const needsPrompts = opts.prompts || shouldShowSummary(opts);\n\n // Handle each capability independently - servers may not implement all methods\n const [toolsResult, resourcesResult, promptsResult] = await Promise.all([needsTools ? client.listTools().catch(() => null) : Promise.resolve(null), needsResources ? client.listResources().catch(() => null) : Promise.resolve(null), needsPrompts ? client.listPrompts().catch(() => null) : Promise.resolve(null)]);\n\n const startupTime = Date.now() - start;\n\n return {\n name: serverName,\n status: 'ready',\n startupTime,\n error: undefined,\n tools: toolsResult?.tools\n ? toolsResult.tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n }))\n : undefined,\n resources: resourcesResult?.resources\n ? resourcesResult.resources.map((r) => ({\n uri: r.uri,\n name: r.name,\n description: r.description,\n mimeType: r.mimeType,\n }))\n : undefined,\n prompts: promptsResult?.prompts\n ? promptsResult.prompts.map((p) => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments,\n }))\n : undefined,\n };\n } catch (error) {\n // Format error message with context\n let errorMessage = error instanceof Error ? error.message : String(error);\n\n // For fetch errors, dig into the cause for more details\n if (error instanceof Error && error.message === 'fetch failed' && 'cause' in error) {\n const cause = error.cause as { code?: string; message?: string } | undefined;\n if (cause?.code === 'ECONNREFUSED') {\n const serverConfig = servers?.[serverName];\n const url = serverConfig && 'url' in serverConfig ? serverConfig.url : undefined;\n errorMessage = url ? `Connection refused (server not running at ${url})` : 'Connection refused (server not running)';\n } else if (cause?.message) {\n errorMessage = `${error.message}: ${cause.message}`;\n }\n }\n\n return {\n name: serverName,\n status: 'failed',\n startupTime: undefined,\n error: errorMessage,\n tools: undefined,\n resources: undefined,\n prompts: undefined,\n };\n }\n}\n\n/**\n * Determine if we should show summary (no specific content flags).\n */\nfunction shouldShowSummary(opts: InspectOptions): boolean {\n return !opts.tools && !opts.resources && !opts.prompts && !opts.health;\n}\n\n/**\n * Truncate description to max length with ellipsis.\n */\nfunction truncateDescription(desc: string, _maxLength = MAX_DESCRIPTION): string {\n return desc;\n // if (!desc || desc.length <= maxLength) {\n // return desc;\n // }\n // return `${desc.slice(0, maxLength - 3)}...`;\n}\n\n/**\n * Render verbose details for a tool (parameters with types and descriptions)\n */\nfunction renderToolVerbose(tool: ToolInfo, indent: string): void {\n // Description is already shown inline, so skip it here\n const schema = tool.inputSchema as { properties?: Record<string, unknown>; required?: string[] } | undefined;\n if (!schema || !schema.properties) {\n return;\n }\n\n const properties = schema.properties;\n const required = schema.required || [];\n\n // Separate required and optional parameters\n const requiredParams: string[] = [];\n const optionalParams: string[] = [];\n\n for (const [name, _prop] of Object.entries(properties)) {\n if (required.includes(name)) {\n requiredParams.push(name);\n } else {\n optionalParams.push(name);\n }\n }\n\n // Show required parameters\n if (requiredParams.length > 0) {\n console.log(`${indent}Required Parameters:`);\n for (const name of requiredParams) {\n renderParameter(name, properties[name], `${indent} `);\n }\n console.log('');\n }\n\n // Show optional parameters\n if (optionalParams.length > 0) {\n console.log(`${indent}Optional Parameters:`);\n for (const name of optionalParams) {\n renderParameter(name, properties[name], `${indent} `);\n }\n console.log('');\n }\n}\n\n/**\n * Render verbose details for a resource\n */\nfunction renderResourceVerbose(resource: ResourceInfo, indent: string): void {\n // Description is already shown inline, so only show URI and MIME type\n if (resource.uri) {\n console.log(`${indent}URI: ${resource.uri}`);\n }\n if (resource.mimeType) {\n console.log(`${indent}MIME Type: ${resource.mimeType}`);\n }\n if (resource.uri || resource.mimeType) {\n console.log('');\n }\n}\n\n/**\n * Render verbose details for a prompt\n */\nfunction renderPromptVerbose(prompt: PromptInfo, indent: string): void {\n // Description is already shown inline, so only show arguments\n if (prompt.arguments && Array.isArray(prompt.arguments) && prompt.arguments.length > 0) {\n console.log(`${indent}Arguments:`);\n for (const arg of prompt.arguments) {\n const argObj = arg as { name?: string; description?: string; required?: boolean };\n const name = argObj.name || 'unknown';\n const description = argObj.description || '';\n const required = argObj.required ? ' (required)' : ' (optional)';\n const desc = description ? ` - ${description}` : '';\n console.log(`${indent} ${name}${required}${desc}`);\n }\n console.log('');\n }\n}\n\n/**\n * Render a single parameter with type and description\n */\nfunction renderParameter(name: string, prop: unknown, indent: string): void {\n const p = prop as { description?: string; enum?: unknown[] };\n const type = getParameterType(prop);\n const constraints = getParameterConstraints(prop);\n const typeInfo = constraints ? `(${type}) ${constraints}` : `(${type})`;\n const desc = p.description ? ` - ${p.description}` : '';\n\n console.log(`${indent}${name} ${typeInfo}${desc}`);\n\n // Show enum options on separate line if present\n if (p.enum && Array.isArray(p.enum)) {\n console.log(`${indent} Options: ${p.enum.join(', ')}`);\n }\n}\n\n/**\n * Get human-readable type from JSON Schema property\n */\nfunction getParameterType(prop: unknown): string {\n const p = prop as { type?: string | string[]; items?: { type?: string }; anyOf?: Array<{ type?: string }>; enum?: unknown[] };\n if (p.type) {\n if (Array.isArray(p.type)) {\n return p.type.join(' | ');\n }\n if (p.type === 'array' && p.items) {\n const itemType = p.items.type || 'any';\n return `array of ${itemType}`;\n }\n return p.type;\n }\n\n if (p.anyOf) {\n return p.anyOf.map((s) => s.type || 'any').join(' | ');\n }\n\n if (p.enum) {\n return 'enum';\n }\n\n return 'any';\n}\n\n/**\n * Get parameter constraints (default, min, max, etc.)\n */\nfunction getParameterConstraints(prop: unknown): string {\n const p = prop as {\n default?: unknown;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n minItems?: number;\n maxItems?: number;\n };\n const constraints: string[] = [];\n\n if (p.default !== undefined) {\n const defaultValue = typeof p.default === 'string' ? `\"${p.default}\"` : String(p.default);\n constraints.push(`default: ${defaultValue}`);\n }\n\n if (p.minimum !== undefined) {\n constraints.push(`min: ${p.minimum}`);\n }\n\n if (p.maximum !== undefined) {\n constraints.push(`max: ${p.maximum}`);\n }\n\n if (p.minLength !== undefined) {\n constraints.push(`minLength: ${p.minLength}`);\n }\n\n if (p.maxLength !== undefined) {\n constraints.push(`maxLength: ${p.maxLength}`);\n }\n\n if (p.minItems !== undefined) {\n constraints.push(`minItems: ${p.minItems}`);\n }\n\n if (p.maxItems !== undefined) {\n constraints.push(`maxItems: ${p.maxItems}`);\n }\n\n return constraints.length > 0 ? `[${constraints.join(', ')}]` : '';\n}\n\n/**\n * Output results as JSON.\n */\nfunction outputJSON(serverInfos: ServerInfo[]): void {\n const output = {\n servers: serverInfos.reduce(\n (acc, info) => {\n acc[info.name] = {\n status: info.status,\n startupTime: info.startupTime ? `${(info.startupTime / 1000).toFixed(1)}s` : undefined,\n error: info.error,\n tools: info.tools,\n resources: info.resources,\n prompts: info.prompts,\n };\n return acc;\n },\n {} as Record<string, unknown>\n ),\n };\n\n console.log(JSON.stringify(output, null, 2));\n}\n\n/**\n * Output results in human-readable format.\n */\nfunction outputPretty(serverInfos: ServerInfo[], opts: InspectOptions): void {\n const showSummary = shouldShowSummary(opts);\n\n for (const info of serverInfos) {\n // Summary mode\n if (showSummary) {\n if (info.status === 'ready') {\n const toolCount = info.tools?.length || 0;\n const resourceCount = info.resources?.length || 0;\n const promptCount = info.prompts?.length || 0;\n const time = info.startupTime ? `(${(info.startupTime / 1000).toFixed(1)}s)` : '';\n console.log(`š¦ ${info.name}: ${time}`);\n\n // Show detailed list of tools\n console.log(`tools: ${toolCount}`);\n if (info.tools && info.tools.length > 0) {\n for (let i = 0; i < info.tools.length; i++) {\n const tool = info.tools[i];\n if (!tool) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = tool.description ? ` - ${opts.verbose ? tool.description : truncateDescription(tool.description)}` : '';\n console.log(`${i + 1}. ${tool.name}${desc}`);\n if (opts.verbose) {\n renderToolVerbose(tool, ' ');\n }\n }\n }\n\n // Show detailed list of resources\n console.log(`resources: ${resourceCount}`);\n if (info.resources && info.resources.length > 0) {\n for (let i = 0; i < info.resources.length; i++) {\n const resource = info.resources[i];\n if (!resource) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = resource.description ? ` - ${opts.verbose ? resource.description : truncateDescription(resource.description)}` : '';\n console.log(`${i + 1}. ${resource.name}${desc}`);\n if (opts.verbose) {\n renderResourceVerbose(resource, ' ');\n }\n }\n }\n\n // Show detailed list of prompts\n console.log(`prompts: ${promptCount}`);\n if (info.prompts && info.prompts.length > 0) {\n for (let i = 0; i < info.prompts.length; i++) {\n const prompt = info.prompts[i];\n if (!prompt) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = prompt.description ? ` - ${opts.verbose ? prompt.description : truncateDescription(prompt.description)}` : '';\n console.log(`${i + 1}. ${prompt.name}${desc}`);\n if (opts.verbose) {\n renderPromptVerbose(prompt, ' ');\n }\n }\n }\n } else {\n console.log(`š¦ ${info.name}: ā failed - ${info.error}`);\n }\n continue;\n }\n\n // Health mode\n if (opts.health) {\n if (info.status === 'ready') {\n const time = info.startupTime ? `(${(info.startupTime / 1000).toFixed(1)}s)` : '';\n console.log(`ā ${info.name} - ready ${time}`);\n } else {\n console.log(`ā ${info.name} - failed`);\n console.log(` Error: ${info.error}`);\n }\n continue;\n }\n\n // Tools mode\n if (opts.tools) {\n console.log(`\\nš¦ ${info.name} (${info.tools?.length || 0} tools)`);\n if (info.tools && info.tools.length > 0) {\n for (let i = 0; i < info.tools.length; i++) {\n const tool = info.tools[i];\n if (!tool) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = tool.description ? ` - ${opts.verbose ? tool.description : truncateDescription(tool.description)}` : '';\n console.log(` ${i + 1}. ${tool.name}${desc}`);\n if (opts.verbose) {\n renderToolVerbose(tool, ' ');\n }\n }\n }\n }\n\n // Resources mode\n if (opts.resources) {\n console.log(`\\nš¦ ${info.name} (${info.resources?.length || 0} resources)`);\n if (info.resources && info.resources.length > 0) {\n for (let i = 0; i < info.resources.length; i++) {\n const resource = info.resources[i];\n if (!resource) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = resource.description ? ` - ${opts.verbose ? resource.description : truncateDescription(resource.description)}` : '';\n console.log(` ${i + 1}. ${resource.name}${desc}`);\n if (opts.verbose) {\n renderResourceVerbose(resource, ' ');\n }\n }\n }\n }\n\n // Prompts mode\n if (opts.prompts) {\n console.log(`\\nš¦ ${info.name} (${info.prompts?.length || 0} prompts)`);\n if (info.prompts && info.prompts.length > 0) {\n for (let i = 0; i < info.prompts.length; i++) {\n const prompt = info.prompts[i];\n if (!prompt) continue; // Array indexing can return undefined with noUncheckedIndexedAccess\n const desc = prompt.description ? ` - ${opts.verbose ? prompt.description : truncateDescription(prompt.description)}` : '';\n console.log(` ${i + 1}. ${prompt.name}${desc}`);\n if (opts.verbose) {\n renderPromptVerbose(prompt, ' ');\n }\n }\n }\n }\n }\n\n console.log('');\n}\n"],"names":["inspectCommand","MAX_DESCRIPTION","opts","registry","raw","configPath","servers","configDir","serverNames","serversToInspect","serverInfos","serverName","info","_","findConfigPath","config","JSON","parse","fs","readFileSync","mcpServers","path","dirname","Object","keys","filterServers","createServerRegistry","cwd","dialects","attach","inspectServer","push","json","outputJSON","outputPretty","close","allServers","serversFlag","requested","split","map","s","trim","missing","filter","includes","length","Error","join","start","serverConfig","client","needsTools","needsResources","needsPrompts","toolsResult","resourcesResult","promptsResult","startupTime","error","errorMessage","cause","url","Date","now","isHttpServer","command","connect","tools","shouldShowSummary","resources","prompts","Promise","all","listTools","catch","resolve","listResources","listPrompts","name","status","undefined","t","description","inputSchema","r","uri","mimeType","p","arguments","message","String","code","health","truncateDescription","desc","_maxLength","renderToolVerbose","tool","indent","schema","properties","required","requiredParams","optionalParams","entries","_prop","console","log","renderParameter","renderResourceVerbose","resource","renderPromptVerbose","prompt","Array","isArray","arg","argObj","prop","type","getParameterType","constraints","getParameterConstraints","typeInfo","enum","items","itemType","anyOf","default","defaultValue","minimum","maximum","minLength","maxLength","minItems","maxItems","output","reduce","acc","toFixed","stringify","showSummary","toolCount","resourceCount","promptCount","time","i","verbose"],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ Object.defineProperty(exports, "searchCommand", {
|
|
|
16
16
|
var _client = require("@mcp-z/client");
|
|
17
17
|
var _fs = /*#__PURE__*/ _interop_require_wildcard(require("fs"));
|
|
18
18
|
var _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
|
|
19
|
-
var
|
|
19
|
+
var _findconfigpathts = /*#__PURE__*/ _interop_require_default(require("../lib/find-config-path.js"));
|
|
20
20
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
21
21
|
try {
|
|
22
22
|
var info = gen[key](arg);
|
|
@@ -53,6 +53,11 @@ function _instanceof(left, right) {
|
|
|
53
53
|
return left instanceof right;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
function _interop_require_default(obj) {
|
|
57
|
+
return obj && obj.__esModule ? obj : {
|
|
58
|
+
default: obj
|
|
59
|
+
};
|
|
60
|
+
}
|
|
56
61
|
function _getRequireWildcardCache(nodeInterop) {
|
|
57
62
|
if (typeof WeakMap !== "function") return null;
|
|
58
63
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -209,7 +214,9 @@ function searchCommand(_0) {
|
|
|
209
214
|
13,
|
|
210
215
|
18
|
|
211
216
|
]);
|
|
212
|
-
configPath = (0,
|
|
217
|
+
configPath = (0, _findconfigpathts.default)({
|
|
218
|
+
config: opts.config
|
|
219
|
+
});
|
|
213
220
|
raw = JSON.parse(_fs.readFileSync(configPath, 'utf8'));
|
|
214
221
|
servers = (_ref = (_raw_mcpServers = raw.mcpServers) !== null && _raw_mcpServers !== void 0 ? _raw_mcpServers : raw.servers) !== null && _ref !== void 0 ? _ref : raw;
|
|
215
222
|
configDir = _path.dirname(configPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/commands/search.ts"],"sourcesContent":["/**\n * search.ts\n *\n * Search MCP server capabilities (tools, prompts, resources) without loading full schemas.\n * Designed for agent discovery workflows.\n */\n\nimport { type CapabilityType, createServerRegistry, type SearchField, type SearchOptions, type SearchResponse, type ServerRegistry } from '@mcp-z/client';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { findConfigPath } from '../lib/find-config.ts';\n\nexport interface SearchCommandOptions {\n config?: string;\n servers?: string;\n types?: string;\n fields?: string;\n limit?: number;\n threshold?: number;\n json?: boolean;\n attach?: boolean;\n}\n\n/**\n * Main search command implementation.\n *\n * @param query - The search query string\n * @param opts - Search options from CLI flags\n *\n * @example\n * // Search for email-related capabilities\n * await searchCommand('send email', {});\n *\n * @example\n * // Search only tools in specific servers\n * await searchCommand('spreadsheet', { types: 'tool', servers: 'sheets,drive' });\n */\nexport async function searchCommand(query: string, opts: SearchCommandOptions = {}): Promise<void> {\n let registry: ServerRegistry | undefined;\n\n try {\n const configPath = findConfigPath(opts.config);\n const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));\n const servers = raw.mcpServers ?? raw.servers ?? raw;\n const configDir = path.dirname(configPath);\n\n // Parse options\n const searchOptions: SearchOptions = {\n types: parseTypes(opts.types),\n servers: parseServers(opts.servers),\n searchFields: parseFields(opts.fields),\n limit: opts.limit ?? 20,\n threshold: opts.threshold ?? 0,\n };\n\n // Create registry (spawns stdio servers, registers HTTP servers)\n // In attach mode, don't spawn - just register for connection\n registry = createServerRegistry(servers, {\n cwd: configDir,\n dialects: opts.attach ? [] : ['servers', 'start'], // Empty dialects = no spawning\n });\n\n // Connect to all servers (or filtered subset)\n const serverNames = searchOptions.servers ?? Object.keys(servers || {});\n\n for (const serverName of serverNames) {\n try {\n await registry.connect(serverName);\n } catch (error) {\n // Log connection errors but continue with other servers\n if (!opts.json) {\n console.error(`ā Failed to connect to ${serverName}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n }\n\n // Search across connected clients\n const response = await registry.searchCapabilities(query, searchOptions);\n\n // Output results\n if (opts.json) {\n outputJSON(response);\n } else {\n outputPretty(response);\n }\n } finally {\n // Cleanup - registry.close() handles all clients and servers\n if (registry) {\n try {\n await registry.close();\n } catch (_) {\n // Ignore close errors\n }\n }\n }\n}\n\n/**\n * Parse comma-separated types into CapabilityType array\n */\nfunction parseTypes(typesStr?: string): CapabilityType[] | undefined {\n if (!typesStr) return undefined;\n\n const validTypes: CapabilityType[] = ['tool', 'prompt', 'resource'];\n const parsed = typesStr.split(',').map((t) => t.trim().toLowerCase()) as CapabilityType[];\n\n const invalid = parsed.filter((t) => !validTypes.includes(t));\n if (invalid.length > 0) {\n throw new Error(`Invalid types: ${invalid.join(', ')}. Valid types: ${validTypes.join(', ')}`);\n }\n\n return parsed;\n}\n\n/**\n * Parse comma-separated server names\n */\nfunction parseServers(serversStr?: string): string[] | undefined {\n if (!serversStr) return undefined;\n return serversStr.split(',').map((s) => s.trim());\n}\n\n/**\n * Parse comma-separated search fields\n */\nfunction parseFields(fieldsStr?: string): SearchField[] | undefined {\n if (!fieldsStr) return undefined;\n\n const validFields: SearchField[] = ['name', 'description', 'schema', 'server'];\n const parsed = fieldsStr.split(',').map((f) => f.trim().toLowerCase()) as SearchField[];\n\n const invalid = parsed.filter((f) => !validFields.includes(f));\n if (invalid.length > 0) {\n throw new Error(`Invalid fields: ${invalid.join(', ')}. Valid fields: ${validFields.join(', ')}`);\n }\n\n return parsed;\n}\n\n/**\n * Output results as JSON\n */\nfunction outputJSON(response: SearchResponse): void {\n console.log(JSON.stringify(response, null, 2));\n}\n\n/**\n * Output results in human-readable format\n */\nfunction outputPretty(response: SearchResponse): void {\n if (response.results.length === 0) {\n console.log(`No results found for \"${response.query}\"`);\n return;\n }\n\n console.log(`Found ${response.total} result${response.total !== 1 ? 's' : ''} for \"${response.query}\"${response.total > response.results.length ? ` (showing ${response.results.length})` : ''}:\\n`);\n\n for (const result of response.results) {\n const typeIcon = result.type === 'tool' ? 'š§' : result.type === 'prompt' ? 'š¬' : 'š';\n const score = (result.score * 100).toFixed(0);\n\n console.log(`${typeIcon} ${result.name} [${result.type}] (${score}%)`);\n console.log(` Server: ${result.server}`);\n\n if (result.description) {\n const desc = result.description.length > 100 ? `${result.description.slice(0, 97)}...` : result.description;\n console.log(` ${desc}`);\n }\n\n if (result.matchedOn.length > 0) {\n console.log(` Matched: ${result.matchedOn.join(', ')}`);\n }\n\n console.log('');\n }\n}\n"],"names":["searchCommand","query","opts","registry","raw","searchOptions","configPath","servers","configDir","serverNames","serverName","error","response","_","findConfigPath","config","JSON","parse","fs","readFileSync","mcpServers","path","dirname","types","parseTypes","parseServers","searchFields","parseFields","fields","limit","threshold","createServerRegistry","cwd","dialects","attach","Object","keys","connect","json","console","Error","message","String","searchCapabilities","outputJSON","outputPretty","close","typesStr","undefined","validTypes","parsed","split","map","t","trim","toLowerCase","invalid","filter","includes","length","join","serversStr","s","fieldsStr","validFields","f","log","stringify","results","total","result","typeIcon","type","score","toFixed","name","server","description","desc","slice","matchedOn"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/commands/search.ts"],"sourcesContent":["/**\n * search.ts\n *\n * Search MCP server capabilities (tools, prompts, resources) without loading full schemas.\n * Designed for agent discovery workflows.\n */\n\nimport { type CapabilityType, createServerRegistry, type SearchField, type SearchOptions, type SearchResponse, type ServerRegistry } from '@mcp-z/client';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport findConfigPath from '../lib/find-config-path.ts';\n\nexport interface SearchCommandOptions {\n config?: string;\n servers?: string;\n types?: string;\n fields?: string;\n limit?: number;\n threshold?: number;\n json?: boolean;\n attach?: boolean;\n}\n\n/**\n * Main search command implementation.\n *\n * @param query - The search query string\n * @param opts - Search options from CLI flags\n *\n * @example\n * // Search for email-related capabilities\n * await searchCommand('send email', {});\n *\n * @example\n * // Search only tools in specific servers\n * await searchCommand('spreadsheet', { types: 'tool', servers: 'sheets,drive' });\n */\nexport async function searchCommand(query: string, opts: SearchCommandOptions = {}): Promise<void> {\n let registry: ServerRegistry | undefined;\n\n try {\n const configPath = findConfigPath({ config: opts.config });\n const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));\n const servers = raw.mcpServers ?? raw.servers ?? raw;\n const configDir = path.dirname(configPath);\n\n // Parse options\n const searchOptions: SearchOptions = {\n types: parseTypes(opts.types),\n servers: parseServers(opts.servers),\n searchFields: parseFields(opts.fields),\n limit: opts.limit ?? 20,\n threshold: opts.threshold ?? 0,\n };\n\n // Create registry (spawns stdio servers, registers HTTP servers)\n // In attach mode, don't spawn - just register for connection\n registry = createServerRegistry(servers, {\n cwd: configDir,\n dialects: opts.attach ? [] : ['servers', 'start'], // Empty dialects = no spawning\n });\n\n // Connect to all servers (or filtered subset)\n const serverNames = searchOptions.servers ?? Object.keys(servers || {});\n\n for (const serverName of serverNames) {\n try {\n await registry.connect(serverName);\n } catch (error) {\n // Log connection errors but continue with other servers\n if (!opts.json) {\n console.error(`ā Failed to connect to ${serverName}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n }\n\n // Search across connected clients\n const response = await registry.searchCapabilities(query, searchOptions);\n\n // Output results\n if (opts.json) {\n outputJSON(response);\n } else {\n outputPretty(response);\n }\n } finally {\n // Cleanup - registry.close() handles all clients and servers\n if (registry) {\n try {\n await registry.close();\n } catch (_) {\n // Ignore close errors\n }\n }\n }\n}\n\n/**\n * Parse comma-separated types into CapabilityType array\n */\nfunction parseTypes(typesStr?: string): CapabilityType[] | undefined {\n if (!typesStr) return undefined;\n\n const validTypes: CapabilityType[] = ['tool', 'prompt', 'resource'];\n const parsed = typesStr.split(',').map((t) => t.trim().toLowerCase()) as CapabilityType[];\n\n const invalid = parsed.filter((t) => !validTypes.includes(t));\n if (invalid.length > 0) {\n throw new Error(`Invalid types: ${invalid.join(', ')}. Valid types: ${validTypes.join(', ')}`);\n }\n\n return parsed;\n}\n\n/**\n * Parse comma-separated server names\n */\nfunction parseServers(serversStr?: string): string[] | undefined {\n if (!serversStr) return undefined;\n return serversStr.split(',').map((s) => s.trim());\n}\n\n/**\n * Parse comma-separated search fields\n */\nfunction parseFields(fieldsStr?: string): SearchField[] | undefined {\n if (!fieldsStr) return undefined;\n\n const validFields: SearchField[] = ['name', 'description', 'schema', 'server'];\n const parsed = fieldsStr.split(',').map((f) => f.trim().toLowerCase()) as SearchField[];\n\n const invalid = parsed.filter((f) => !validFields.includes(f));\n if (invalid.length > 0) {\n throw new Error(`Invalid fields: ${invalid.join(', ')}. Valid fields: ${validFields.join(', ')}`);\n }\n\n return parsed;\n}\n\n/**\n * Output results as JSON\n */\nfunction outputJSON(response: SearchResponse): void {\n console.log(JSON.stringify(response, null, 2));\n}\n\n/**\n * Output results in human-readable format\n */\nfunction outputPretty(response: SearchResponse): void {\n if (response.results.length === 0) {\n console.log(`No results found for \"${response.query}\"`);\n return;\n }\n\n console.log(`Found ${response.total} result${response.total !== 1 ? 's' : ''} for \"${response.query}\"${response.total > response.results.length ? ` (showing ${response.results.length})` : ''}:\\n`);\n\n for (const result of response.results) {\n const typeIcon = result.type === 'tool' ? 'š§' : result.type === 'prompt' ? 'š¬' : 'š';\n const score = (result.score * 100).toFixed(0);\n\n console.log(`${typeIcon} ${result.name} [${result.type}] (${score}%)`);\n console.log(` Server: ${result.server}`);\n\n if (result.description) {\n const desc = result.description.length > 100 ? `${result.description.slice(0, 97)}...` : result.description;\n console.log(` ${desc}`);\n }\n\n if (result.matchedOn.length > 0) {\n console.log(` Matched: ${result.matchedOn.join(', ')}`);\n }\n\n console.log('');\n }\n}\n"],"names":["searchCommand","query","opts","registry","raw","searchOptions","configPath","servers","configDir","serverNames","serverName","error","response","_","findConfigPath","config","JSON","parse","fs","readFileSync","mcpServers","path","dirname","types","parseTypes","parseServers","searchFields","parseFields","fields","limit","threshold","createServerRegistry","cwd","dialects","attach","Object","keys","connect","json","console","Error","message","String","searchCapabilities","outputJSON","outputPretty","close","typesStr","undefined","validTypes","parsed","split","map","t","trim","toLowerCase","invalid","filter","includes","length","join","serversStr","s","fieldsStr","validFields","f","log","stringify","results","total","result","typeIcon","type","score","toFixed","name","server","description","desc","slice","matchedOn"],"mappings":"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"}
|
package/dist/cjs/commands/up.js
CHANGED
|
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "upCommand", {
|
|
|
11
11
|
var _client = require("@mcp-z/client");
|
|
12
12
|
var _fs = /*#__PURE__*/ _interop_require_wildcard(require("fs"));
|
|
13
13
|
var _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
|
|
14
|
-
var
|
|
14
|
+
var _findconfigpathts = /*#__PURE__*/ _interop_require_default(require("../lib/find-config-path.js"));
|
|
15
15
|
var _typests = require("../types.js");
|
|
16
16
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
17
17
|
try {
|
|
@@ -42,6 +42,11 @@ function _async_to_generator(fn) {
|
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
|
+
function _interop_require_default(obj) {
|
|
46
|
+
return obj && obj.__esModule ? obj : {
|
|
47
|
+
default: obj
|
|
48
|
+
};
|
|
49
|
+
}
|
|
45
50
|
function _getRequireWildcardCache(nodeInterop) {
|
|
46
51
|
if (typeof WeakMap !== "function") return null;
|
|
47
52
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -188,7 +193,9 @@ function upCommand() {
|
|
|
188
193
|
var _arguments = arguments;
|
|
189
194
|
return _ts_generator(this, function(_state) {
|
|
190
195
|
opts = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {};
|
|
191
|
-
configPath = (0,
|
|
196
|
+
configPath = (0, _findconfigpathts.default)({
|
|
197
|
+
config: opts.config
|
|
198
|
+
});
|
|
192
199
|
raw = JSON.parse(_fs.readFileSync(configPath, 'utf8'));
|
|
193
200
|
servers = (_ref = (_raw_mcpServers = raw.mcpServers) !== null && _raw_mcpServers !== void 0 ? _raw_mcpServers : raw.servers) !== null && _ref !== void 0 ? _ref : raw;
|
|
194
201
|
configDir = _path.dirname(configPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/commands/up.ts"],"sourcesContent":["import { createServerRegistry, type Dialect, type ServerRegistry } from '@mcp-z/client';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/commands/up.ts"],"sourcesContent":["import { createServerRegistry, type Dialect, type ServerRegistry } from '@mcp-z/client';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport findConfigPath from '../lib/find-config-path.ts';\nimport { hasStartBlock, type ServerConfig } from '../types.ts';\n\n/**\n * Configuration options for the upCommand function\n * @public\n */\nexport interface UpOptions {\n /** Optional path to custom .mcp.json configuration file */\n config?: string;\n /** Start only stdio servers (Claude Code compatible mode) */\n stdioOnly?: boolean;\n /** Start only HTTP servers with start blocks (for Claude Code Desktop) */\n httpOnly?: boolean;\n}\n\n/**\n * MCP server configuration entry per MCP specification.\n *\n * Supports two transport types:\n * - stdio (default if no type): spawned process with stdin/stdout\n * - http: remote HTTP server\n *\n * Transport can be inferred from URL protocol:\n * - http:// or https:// ā http\n *\n * @see https://modelcontextprotocol.io/specification/2025-06-18/basic/transports\n */\n\n/**\n * Start a cluster of MCP servers from a configuration file or object.\n *\n * @param opts - Configuration options\n * @param opts.config - Optional path to custom .mcp.json file\n * @returns ServerRegistry with servers map, config, connect method, and close function\n *\n * @example\n * // Auto-discover .mcp.json in current directory\n * const registry = await upCommand();\n *\n * @example\n * // Load from specific config\n * const registry = await upCommand({ config: '/path/to/.mcp.json' });\n *\n * @example\n * // Use in-memory config\n * const registry = await upCommand({\n * mcpServers: {\n * 'echo-stdio': { command: 'node', args: ['test/lib/servers/echo-stdio.ts'] }\n * }\n * });\n */\nexport async function upCommand(opts: UpOptions = {}): Promise<ServerRegistry> {\n const configPath = findConfigPath({ config: opts.config });\n const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));\n const servers = raw.mcpServers ?? raw.servers ?? raw;\n const configDir = path.dirname(configPath);\n\n // Determine dialects based on flags\n // Default is ['servers', 'start'] (spawns everything)\n let dialects: Dialect[] = ['servers', 'start'];\n if (opts.stdioOnly) {\n dialects = ['servers'];\n } else if (opts.httpOnly) {\n dialects = ['start'];\n // In http-only mode, check if there are any servers with start blocks\n const hasStartBlocks = Object.values(servers || {}).some((entry) => entry && hasStartBlock(entry as ServerConfig));\n if (!hasStartBlocks) {\n console.log(' No HTTP servers found with start configuration');\n console.log(' (stdio servers are spawned automatically by Claude Code)');\n // Return empty registry\n return createServerRegistry({}, { cwd: configDir });\n }\n }\n\n return createServerRegistry(servers, {\n cwd: configDir,\n dialects,\n });\n}\n"],"names":["upCommand","opts","raw","configPath","servers","configDir","dialects","hasStartBlocks","findConfigPath","config","JSON","parse","fs","readFileSync","mcpServers","path","dirname","stdioOnly","httpOnly","Object","values","some","entry","hasStartBlock","console","log","createServerRegistry","cwd"],"mappings":";;;;+BAuDsBA;;;eAAAA;;;sBAvDkD;0DACpD;4DACE;uEACK;uBACsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmD1C,SAAeA;;YAAUC,MAGdC,MAAAA,iBAFVC,YACAD,KACAE,SACAC,WAIFC,UAMIC;;;YAdsBN,OAAAA,oEAAkB,CAAC;YAC3CE,aAAaK,IAAAA,yBAAc,EAAC;gBAAEC,QAAQR,KAAKQ,MAAM;YAAC;YAClDP,MAAMQ,KAAKC,KAAK,CAACC,IAAGC,YAAY,CAACV,YAAY;YAC7CC,WAAUF,QAAAA,kBAAAA,IAAIY,UAAU,cAAdZ,6BAAAA,kBAAkBA,IAAIE,OAAO,cAA7BF,kBAAAA,OAAiCA;YAC3CG,YAAYU,MAAKC,OAAO,CAACb;YAE/B,oCAAoC;YACpC,sDAAsD;YAClDG;gBAAuB;gBAAW;;YACtC,IAAIL,KAAKgB,SAAS,EAAE;gBAClBX;oBAAY;;YACd,OAAO,IAAIL,KAAKiB,QAAQ,EAAE;gBACxBZ;oBAAY;;gBACZ,sEAAsE;gBAChEC,iBAAiBY,OAAOC,MAAM,CAAChB,WAAW,CAAC,GAAGiB,IAAI,CAAC,SAACC;2BAAUA,SAASC,IAAAA,sBAAa,EAACD;;gBAC3F,IAAI,CAACf,gBAAgB;oBACnBiB,QAAQC,GAAG,CAAC;oBACZD,QAAQC,GAAG,CAAC;oBACZ,wBAAwB;oBACxB;;wBAAOC,IAAAA,4BAAoB,EAAC,CAAC,GAAG;4BAAEC,KAAKtB;wBAAU;;gBACnD;YACF;YAEA;;gBAAOqB,IAAAA,4BAAoB,EAACtB,SAAS;oBACnCuB,KAAKtB;oBACLC,UAAAA;gBACF;;;IACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find-config-path.ts
|
|
3
|
+
*
|
|
4
|
+
* Find config file by searching up the directory tree.
|
|
5
|
+
* Searches from cwd up to stopDir (default: home directory).
|
|
6
|
+
*/
|
|
7
|
+
export interface FindConfigOptions {
|
|
8
|
+
/** Config filename or path (default: ".mcp.json") */
|
|
9
|
+
config?: string;
|
|
10
|
+
/** Directory to start searching from (default: process.cwd()) */
|
|
11
|
+
cwd?: string;
|
|
12
|
+
/** Directory to stop searching at, inclusive (default: os.homedir()) */
|
|
13
|
+
stopDir?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Find a config file by searching up directory tree from cwd to stopDir.
|
|
17
|
+
*
|
|
18
|
+
* If config includes a path separator or is absolute, it is treated as a path.
|
|
19
|
+
* Otherwise it is treated as a filename and searched upwards.
|
|
20
|
+
*
|
|
21
|
+
* @throws Error if config file not found
|
|
22
|
+
*/
|
|
23
|
+
export default function findConfigPath(options?: FindConfigOptions): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find-config-path.ts
|
|
3
|
+
*
|
|
4
|
+
* Find config file by searching up the directory tree.
|
|
5
|
+
* Searches from cwd up to stopDir (default: home directory).
|
|
6
|
+
*/
|
|
7
|
+
export interface FindConfigOptions {
|
|
8
|
+
/** Config filename or path (default: ".mcp.json") */
|
|
9
|
+
config?: string;
|
|
10
|
+
/** Directory to start searching from (default: process.cwd()) */
|
|
11
|
+
cwd?: string;
|
|
12
|
+
/** Directory to stop searching at, inclusive (default: os.homedir()) */
|
|
13
|
+
stopDir?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Find a config file by searching up directory tree from cwd to stopDir.
|
|
17
|
+
*
|
|
18
|
+
* If config includes a path separator or is absolute, it is treated as a path.
|
|
19
|
+
* Otherwise it is treated as a filename and searched upwards.
|
|
20
|
+
*
|
|
21
|
+
* @throws Error if config file not found
|
|
22
|
+
*/
|
|
23
|
+
export default function findConfigPath(options?: FindConfigOptions): string;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* find-config-path.ts
|
|
3
|
+
*
|
|
4
|
+
* Find config file by searching up the directory tree.
|
|
5
|
+
* Searches from cwd up to stopDir (default: home directory).
|
|
6
|
+
*/ "use strict";
|
|
7
|
+
Object.defineProperty(exports, "__esModule", {
|
|
8
|
+
value: true
|
|
9
|
+
});
|
|
10
|
+
Object.defineProperty(exports, /**
|
|
11
|
+
* Find a config file by searching up directory tree from cwd to stopDir.
|
|
12
|
+
*
|
|
13
|
+
* If config includes a path separator or is absolute, it is treated as a path.
|
|
14
|
+
* Otherwise it is treated as a filename and searched upwards.
|
|
15
|
+
*
|
|
16
|
+
* @throws Error if config file not found
|
|
17
|
+
*/ "default", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: function() {
|
|
20
|
+
return findConfigPath;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
var _fs = /*#__PURE__*/ _interop_require_wildcard(require("fs"));
|
|
24
|
+
var _os = /*#__PURE__*/ _interop_require_wildcard(require("os"));
|
|
25
|
+
var _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
|
|
26
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
27
|
+
if (typeof WeakMap !== "function") return null;
|
|
28
|
+
var cacheBabelInterop = new WeakMap();
|
|
29
|
+
var cacheNodeInterop = new WeakMap();
|
|
30
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
31
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
32
|
+
})(nodeInterop);
|
|
33
|
+
}
|
|
34
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
35
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
36
|
+
return obj;
|
|
37
|
+
}
|
|
38
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
39
|
+
return {
|
|
40
|
+
default: obj
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
44
|
+
if (cache && cache.has(obj)) {
|
|
45
|
+
return cache.get(obj);
|
|
46
|
+
}
|
|
47
|
+
var newObj = {
|
|
48
|
+
__proto__: null
|
|
49
|
+
};
|
|
50
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
51
|
+
for(var key in obj){
|
|
52
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
53
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
54
|
+
if (desc && (desc.get || desc.set)) {
|
|
55
|
+
Object.defineProperty(newObj, key, desc);
|
|
56
|
+
} else {
|
|
57
|
+
newObj[key] = obj[key];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
newObj.default = obj;
|
|
62
|
+
if (cache) {
|
|
63
|
+
cache.set(obj, newObj);
|
|
64
|
+
}
|
|
65
|
+
return newObj;
|
|
66
|
+
}
|
|
67
|
+
function findConfigPath() {
|
|
68
|
+
var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
69
|
+
var _options_config, _options_cwd, _options_stopDir;
|
|
70
|
+
var config = (_options_config = options.config) !== null && _options_config !== void 0 ? _options_config : '.mcp.json';
|
|
71
|
+
var cwd = (_options_cwd = options.cwd) !== null && _options_cwd !== void 0 ? _options_cwd : process.cwd();
|
|
72
|
+
var stopDir = (_options_stopDir = options.stopDir) !== null && _options_stopDir !== void 0 ? _options_stopDir : _os.homedir();
|
|
73
|
+
if (isPathLike(config)) {
|
|
74
|
+
var resolved = _path.isAbsolute(config) ? config : _path.resolve(cwd, config);
|
|
75
|
+
if (!_fs.existsSync(resolved)) {
|
|
76
|
+
throw new Error("Config file not found: ".concat(resolved));
|
|
77
|
+
}
|
|
78
|
+
var stat = _fs.statSync(resolved);
|
|
79
|
+
if (stat.isDirectory()) {
|
|
80
|
+
var candidate = _path.join(resolved, '.mcp.json');
|
|
81
|
+
if (!_fs.existsSync(candidate)) {
|
|
82
|
+
throw new Error("Config file not found: ".concat(candidate));
|
|
83
|
+
}
|
|
84
|
+
return candidate;
|
|
85
|
+
}
|
|
86
|
+
return resolved;
|
|
87
|
+
}
|
|
88
|
+
var root = _path.parse(cwd).root;
|
|
89
|
+
var dir = cwd;
|
|
90
|
+
while(true){
|
|
91
|
+
var candidate1 = _path.join(dir, config);
|
|
92
|
+
if (_fs.existsSync(candidate1)) return candidate1;
|
|
93
|
+
if (dir === root) break;
|
|
94
|
+
if (isSamePath(dir, stopDir)) break;
|
|
95
|
+
// Stop after checking stopDir if it's an ancestor.
|
|
96
|
+
if (!isWithin(dir, stopDir)) break;
|
|
97
|
+
dir = _path.dirname(dir);
|
|
98
|
+
}
|
|
99
|
+
throw new Error("Config file not found: ".concat(config, "\n\nSearched from ").concat(cwd, " up to ").concat(stopDir));
|
|
100
|
+
}
|
|
101
|
+
function isPathLike(value) {
|
|
102
|
+
return _path.isAbsolute(value) || /[\\/]/.test(value);
|
|
103
|
+
}
|
|
104
|
+
function isWithin(child, parent) {
|
|
105
|
+
var rel = _path.relative(parent, child);
|
|
106
|
+
return rel === '' || !rel.startsWith('..') && !_path.isAbsolute(rel);
|
|
107
|
+
}
|
|
108
|
+
function isSamePath(a, b) {
|
|
109
|
+
return _path.resolve(a) === _path.resolve(b);
|
|
110
|
+
}
|
|
111
|
+
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/lib/find-config-path.ts"],"sourcesContent":["/**\n * find-config-path.ts\n *\n * Find config file by searching up the directory tree.\n * Searches from cwd up to stopDir (default: home directory).\n */\n\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nexport interface FindConfigOptions {\n /** Config filename or path (default: \".mcp.json\") */\n config?: string;\n /** Directory to start searching from (default: process.cwd()) */\n cwd?: string;\n /** Directory to stop searching at, inclusive (default: os.homedir()) */\n stopDir?: string;\n}\n\n/**\n * Find a config file by searching up directory tree from cwd to stopDir.\n *\n * If config includes a path separator or is absolute, it is treated as a path.\n * Otherwise it is treated as a filename and searched upwards.\n *\n * @throws Error if config file not found\n */\nexport default function findConfigPath(options: FindConfigOptions = {}): string {\n const config = options.config ?? '.mcp.json';\n const cwd = options.cwd ?? process.cwd();\n const stopDir = options.stopDir ?? os.homedir();\n\n if (isPathLike(config)) {\n const resolved = path.isAbsolute(config) ? config : path.resolve(cwd, config);\n if (!fs.existsSync(resolved)) {\n throw new Error(`Config file not found: ${resolved}`);\n }\n const stat = fs.statSync(resolved);\n if (stat.isDirectory()) {\n const candidate = path.join(resolved, '.mcp.json');\n if (!fs.existsSync(candidate)) {\n throw new Error(`Config file not found: ${candidate}`);\n }\n return candidate;\n }\n return resolved;\n }\n\n const root = path.parse(cwd).root;\n let dir = cwd;\n\n while (true) {\n const candidate = path.join(dir, config);\n if (fs.existsSync(candidate)) return candidate;\n\n if (dir === root) break;\n if (isSamePath(dir, stopDir)) break;\n\n // Stop after checking stopDir if it's an ancestor.\n if (!isWithin(dir, stopDir)) break;\n\n dir = path.dirname(dir);\n }\n\n throw new Error(`Config file not found: ${config}\\n\\nSearched from ${cwd} up to ${stopDir}`);\n}\n\nfunction isPathLike(value: string): boolean {\n return path.isAbsolute(value) || /[\\\\/]/.test(value);\n}\n\nfunction isWithin(child: string, parent: string): boolean {\n const rel = path.relative(parent, child);\n return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));\n}\n\nfunction isSamePath(a: string, b: string): boolean {\n return path.resolve(a) === path.resolve(b);\n}\n"],"names":["findConfigPath","options","config","cwd","process","stopDir","os","homedir","isPathLike","resolved","path","isAbsolute","resolve","fs","existsSync","Error","stat","statSync","isDirectory","candidate","join","root","parse","dir","isSamePath","isWithin","dirname","value","test","child","parent","rel","relative","startsWith","a","b"],"mappings":"AAAA;;;;;CAKC;;;;+BAeD;;;;;;;CAOC,GACD;;;eAAwBA;;;0DArBJ;0DACA;4DACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBP,SAASA;QAAeC,UAAAA,iEAA6B,CAAC;QACpDA,iBACHA,cACIA;IAFhB,IAAMC,UAASD,kBAAAA,QAAQC,MAAM,cAAdD,6BAAAA,kBAAkB;IACjC,IAAME,OAAMF,eAAAA,QAAQE,GAAG,cAAXF,0BAAAA,eAAeG,QAAQD,GAAG;IACtC,IAAME,WAAUJ,mBAAAA,QAAQI,OAAO,cAAfJ,8BAAAA,mBAAmBK,IAAGC,OAAO;IAE7C,IAAIC,WAAWN,SAAS;QACtB,IAAMO,WAAWC,MAAKC,UAAU,CAACT,UAAUA,SAASQ,MAAKE,OAAO,CAACT,KAAKD;QACtE,IAAI,CAACW,IAAGC,UAAU,CAACL,WAAW;YAC5B,MAAM,IAAIM,MAAM,AAAC,0BAAkC,OAATN;QAC5C;QACA,IAAMO,OAAOH,IAAGI,QAAQ,CAACR;QACzB,IAAIO,KAAKE,WAAW,IAAI;YACtB,IAAMC,YAAYT,MAAKU,IAAI,CAACX,UAAU;YACtC,IAAI,CAACI,IAAGC,UAAU,CAACK,YAAY;gBAC7B,MAAM,IAAIJ,MAAM,AAAC,0BAAmC,OAAVI;YAC5C;YACA,OAAOA;QACT;QACA,OAAOV;IACT;IAEA,IAAMY,OAAOX,MAAKY,KAAK,CAACnB,KAAKkB,IAAI;IACjC,IAAIE,MAAMpB;IAEV,MAAO,KAAM;QACX,IAAMgB,aAAYT,MAAKU,IAAI,CAACG,KAAKrB;QACjC,IAAIW,IAAGC,UAAU,CAACK,aAAY,OAAOA;QAErC,IAAII,QAAQF,MAAM;QAClB,IAAIG,WAAWD,KAAKlB,UAAU;QAE9B,mDAAmD;QACnD,IAAI,CAACoB,SAASF,KAAKlB,UAAU;QAE7BkB,MAAMb,MAAKgB,OAAO,CAACH;IACrB;IAEA,MAAM,IAAIR,MAAM,AAAC,0BAAoDZ,OAA3BD,QAAO,sBAAiCG,OAAbF,KAAI,WAAiB,OAARE;AACpF;AAEA,SAASG,WAAWmB,KAAa;IAC/B,OAAOjB,MAAKC,UAAU,CAACgB,UAAU,QAAQC,IAAI,CAACD;AAChD;AAEA,SAASF,SAASI,KAAa,EAAEC,MAAc;IAC7C,IAAMC,MAAMrB,MAAKsB,QAAQ,CAACF,QAAQD;IAClC,OAAOE,QAAQ,MAAO,CAACA,IAAIE,UAAU,CAAC,SAAS,CAACvB,MAAKC,UAAU,CAACoB;AAClE;AAEA,SAASP,WAAWU,CAAS,EAAEC,CAAS;IACtC,OAAOzB,MAAKE,OAAO,CAACsB,OAAOxB,MAAKE,OAAO,CAACuB;AAC1C"}
|
|
@@ -16,7 +16,7 @@ Object.defineProperty(exports, "resolveServerConfig", {
|
|
|
16
16
|
var _client = require("@mcp-z/client");
|
|
17
17
|
var _fs = /*#__PURE__*/ _interop_require_wildcard(require("fs"));
|
|
18
18
|
var _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
|
|
19
|
-
var
|
|
19
|
+
var _findconfigpathts = /*#__PURE__*/ _interop_require_default(require("./find-config-path.js"));
|
|
20
20
|
function _define_property(obj, key, value) {
|
|
21
21
|
if (key in obj) {
|
|
22
22
|
Object.defineProperty(obj, key, {
|
|
@@ -37,6 +37,11 @@ function _instanceof(left, right) {
|
|
|
37
37
|
return left instanceof right;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
+
function _interop_require_default(obj) {
|
|
41
|
+
return obj && obj.__esModule ? obj : {
|
|
42
|
+
default: obj
|
|
43
|
+
};
|
|
44
|
+
}
|
|
40
45
|
function _getRequireWildcardCache(nodeInterop) {
|
|
41
46
|
if (typeof WeakMap !== "function") return null;
|
|
42
47
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -141,7 +146,9 @@ function resolveServerConfig(opts) {
|
|
|
141
146
|
if (!opts.server) {
|
|
142
147
|
throw new Error('Server name is required when using config file');
|
|
143
148
|
}
|
|
144
|
-
var cfgPath = (0,
|
|
149
|
+
var cfgPath = (0, _findconfigpathts.default)({
|
|
150
|
+
config: opts.config
|
|
151
|
+
});
|
|
145
152
|
var raw = JSON.parse(_fs.readFileSync(cfgPath, 'utf8'));
|
|
146
153
|
var servers = (_ref = (_raw_mcpServers = raw.mcpServers) !== null && _raw_mcpServers !== void 0 ? _raw_mcpServers : raw.servers) !== null && _ref !== void 0 ? _ref : raw;
|
|
147
154
|
var serverNames = Object.keys(servers || {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/lib/resolve-server-config.ts"],"sourcesContent":["/**\n * resolve-server-config.ts\n *\n * Shared config resolution for CLI commands.\n * Supports both config file-based and inline server configurations.\n */\n\nimport type { McpServerEntry, ServersConfig } from '@mcp-z/client';\nimport { validateServers } from '@mcp-z/client';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { ServerConfig } from '../types.ts';\nimport { findConfigPath } from './find-config.ts';\n\n/**\n * Options for inline server configuration.\n */\nexport interface InlineConfigOptions {\n /** Server name (optional when inline config provided) */\n server?: string;\n /** Config file path (mutually exclusive with inline options) */\n config?: string;\n /** Stdio run command string (e.g., \"npx -y @echo/server\") */\n run?: string;\n /** HTTP server URL */\n url?: string;\n /** Full server config as JSON string */\n serverConfig?: string;\n}\n\n/**\n * Resolved server configuration.\n */\nexport interface ResolvedServerConfig {\n /** Server name for display purposes */\n serverName: string;\n /** The server configuration object */\n serverConfig: ServerConfig;\n /** Working directory for the server (cwd for inline, config dir for file) */\n configDir: string;\n /** Full servers config (for HTTP auth flow that needs full config) */\n fullConfig: ServersConfig;\n}\n\n/**\n * Resolve server configuration from CLI options.\n *\n * Supports three modes:\n * 1. Config file: --config path + server positional\n * 2. Inline stdio: --run \"npx server\"\n * 3. Inline HTTP: --url \"https://...\"\n * 4. Full JSON: --server '{\"command\":\"npx\",...}'\n *\n * @param opts - CLI options for config resolution\n * @returns Resolved server configuration\n * @throws Error if configuration is invalid\n */\nexport function resolveServerConfig(opts: InlineConfigOptions): ResolvedServerConfig {\n // Validate mutual exclusivity of inline options\n const inlineOptions = [opts.run, opts.url, opts.serverConfig].filter(Boolean);\n if (inlineOptions.length > 1) {\n throw new Error('Cannot use multiple inline config options. Use only one of: --run, --url, or --server');\n }\n\n const hasInlineConfig = inlineOptions.length > 0;\n\n // Validate mutual exclusivity with config file\n if (hasInlineConfig && opts.config) {\n throw new Error('Cannot use --config with inline config options (--run, --url, --server)');\n }\n\n // Handle inline configuration\n if (hasInlineConfig) {\n return resolveInlineConfig(opts);\n }\n\n // Handle config file-based configuration\n return resolveFileConfig(opts);\n}\n\n/**\n * Resolve inline server configuration.\n */\nfunction resolveInlineConfig(opts: InlineConfigOptions): ResolvedServerConfig {\n const serverName = opts.server || 'inline';\n const configDir = process.cwd();\n let serverConfig: ServerConfig;\n\n if (opts.run) {\n // Parse run string into command + args (simple helper, no schema validation needed)\n serverConfig = parseRunString(opts.run);\n } else if (opts.url) {\n // Create HTTP server config (simple helper, no schema validation needed)\n serverConfig = {\n type: 'http',\n url: opts.url,\n };\n } else if (opts.serverConfig) {\n // Parse full JSON config with schema validation\n serverConfig = parseServerConfigJson(opts.serverConfig, serverName);\n } else {\n throw new Error('No inline config provided');\n }\n\n // Create a minimal servers config for the resolved server\n const fullConfig: ServersConfig = {\n [serverName]: serverConfig,\n };\n\n return {\n serverName,\n serverConfig,\n configDir,\n fullConfig,\n };\n}\n\n/**\n * Resolve config file-based server configuration.\n */\nfunction resolveFileConfig(opts: InlineConfigOptions): ResolvedServerConfig {\n if (!opts.server) {\n throw new Error('Server name is required when using config file');\n }\n\n const cfgPath = findConfigPath(opts.config);\n const raw = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));\n const servers: ServersConfig = raw.mcpServers ?? raw.servers ?? raw;\n\n const serverNames = Object.keys(servers || {});\n if (!serverNames.includes(opts.server)) {\n throw new Error(`Server '${opts.server}' not found in config\\n\\nAvailable servers: ${serverNames.join(', ')}`);\n }\n\n const serverConfig = servers[opts.server];\n if (!serverConfig) {\n throw new Error(`Server ${opts.server} not found in config`);\n }\n\n return {\n serverName: opts.server,\n serverConfig: serverConfig as ServerConfig,\n configDir: path.dirname(cfgPath),\n fullConfig: servers,\n };\n}\n\n/**\n * Parse a run string into a ServerConfigStdio.\n *\n * @example\n * parseRunString(\"npx -y @echo/server\")\n * // => { command: \"npx\", args: [\"-y\", \"@echo/server\"] }\n */\nfunction parseRunString(runStr: string): ServerConfig {\n const parts = runStr.trim().split(/\\s+/);\n if (parts.length === 0 || !parts[0]) {\n throw new Error('Run string cannot be empty');\n }\n\n return {\n command: parts[0],\n args: parts.slice(1),\n };\n}\n\n/**\n * Parse and validate a full server config JSON string against the MCP schema.\n *\n * @example\n * parseServerConfigJson('{\"command\":\"npx\",\"args\":[\"-y\",\"@echo/server\"]}')\n * parseServerConfigJson('{\"url\":\"https://example.com/mcp\",\"type\":\"http\"}')\n */\nfunction parseServerConfigJson(jsonStr: string, serverName: string): ServerConfig {\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonStr);\n } catch (error) {\n throw new Error(`Failed to parse server config JSON: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n if (typeof parsed !== 'object' || parsed === null) {\n throw new Error('Server config must be a JSON object');\n }\n\n const config = parsed as McpServerEntry;\n\n // Validate: must have either 'command' (stdio) or 'url' (http)\n if (!config.command && !config.url) {\n throw new Error('Server config must have either \"command\" (for stdio) or \"url\" (for http)');\n }\n\n // Normalize: if url is present without explicit type, set type to 'http'\n if (config.url && !config.type) {\n config.type = 'http';\n }\n\n // Validate against the MCP servers schema\n const serversMap = { [serverName]: config };\n const validation = validateServers(serversMap);\n if (!validation.valid) {\n const errorDetails = validation.errors?.join('\\n ') || 'Unknown validation error';\n throw new Error(`Invalid server config:\\n ${errorDetails}`);\n }\n\n // Return as ServerConfig (compatible with McpServerEntry)\n return config as ServerConfig;\n}\n"],"names":["resolveServerConfig","opts","inlineOptions","run","url","serverConfig","filter","Boolean","length","Error","hasInlineConfig","config","resolveInlineConfig","resolveFileConfig","serverName","server","configDir","process","cwd","parseRunString","type","parseServerConfigJson","fullConfig","raw","cfgPath","findConfigPath","JSON","parse","fs","readFileSync","servers","mcpServers","serverNames","Object","keys","includes","join","path","dirname","runStr","parts","trim","split","command","args","slice","jsonStr","parsed","error","message","String","serversMap","validation","validateServers","valid","errorDetails","errors"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/cli/src/lib/resolve-server-config.ts"],"sourcesContent":["/**\n * resolve-server-config.ts\n *\n * Shared config resolution for CLI commands.\n * Supports both config file-based and inline server configurations.\n */\n\nimport type { McpServerEntry, ServersConfig } from '@mcp-z/client';\nimport { validateServers } from '@mcp-z/client';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { ServerConfig } from '../types.ts';\nimport findConfigPath from './find-config-path.ts';\n\n/**\n * Options for inline server configuration.\n */\nexport interface InlineConfigOptions {\n /** Server name (optional when inline config provided) */\n server?: string;\n /** Config file path (mutually exclusive with inline options) */\n config?: string;\n /** Stdio run command string (e.g., \"npx -y @echo/server\") */\n run?: string;\n /** HTTP server URL */\n url?: string;\n /** Full server config as JSON string */\n serverConfig?: string;\n}\n\n/**\n * Resolved server configuration.\n */\nexport interface ResolvedServerConfig {\n /** Server name for display purposes */\n serverName: string;\n /** The server configuration object */\n serverConfig: ServerConfig;\n /** Working directory for the server (cwd for inline, config dir for file) */\n configDir: string;\n /** Full servers config (for HTTP auth flow that needs full config) */\n fullConfig: ServersConfig;\n}\n\n/**\n * Resolve server configuration from CLI options.\n *\n * Supports three modes:\n * 1. Config file: --config path + server positional\n * 2. Inline stdio: --run \"npx server\"\n * 3. Inline HTTP: --url \"https://...\"\n * 4. Full JSON: --server '{\"command\":\"npx\",...}'\n *\n * @param opts - CLI options for config resolution\n * @returns Resolved server configuration\n * @throws Error if configuration is invalid\n */\nexport function resolveServerConfig(opts: InlineConfigOptions): ResolvedServerConfig {\n // Validate mutual exclusivity of inline options\n const inlineOptions = [opts.run, opts.url, opts.serverConfig].filter(Boolean);\n if (inlineOptions.length > 1) {\n throw new Error('Cannot use multiple inline config options. Use only one of: --run, --url, or --server');\n }\n\n const hasInlineConfig = inlineOptions.length > 0;\n\n // Validate mutual exclusivity with config file\n if (hasInlineConfig && opts.config) {\n throw new Error('Cannot use --config with inline config options (--run, --url, --server)');\n }\n\n // Handle inline configuration\n if (hasInlineConfig) {\n return resolveInlineConfig(opts);\n }\n\n // Handle config file-based configuration\n return resolveFileConfig(opts);\n}\n\n/**\n * Resolve inline server configuration.\n */\nfunction resolveInlineConfig(opts: InlineConfigOptions): ResolvedServerConfig {\n const serverName = opts.server || 'inline';\n const configDir = process.cwd();\n let serverConfig: ServerConfig;\n\n if (opts.run) {\n // Parse run string into command + args (simple helper, no schema validation needed)\n serverConfig = parseRunString(opts.run);\n } else if (opts.url) {\n // Create HTTP server config (simple helper, no schema validation needed)\n serverConfig = {\n type: 'http',\n url: opts.url,\n };\n } else if (opts.serverConfig) {\n // Parse full JSON config with schema validation\n serverConfig = parseServerConfigJson(opts.serverConfig, serverName);\n } else {\n throw new Error('No inline config provided');\n }\n\n // Create a minimal servers config for the resolved server\n const fullConfig: ServersConfig = {\n [serverName]: serverConfig,\n };\n\n return {\n serverName,\n serverConfig,\n configDir,\n fullConfig,\n };\n}\n\n/**\n * Resolve config file-based server configuration.\n */\nfunction resolveFileConfig(opts: InlineConfigOptions): ResolvedServerConfig {\n if (!opts.server) {\n throw new Error('Server name is required when using config file');\n }\n\n const cfgPath = findConfigPath({ config: opts.config });\n const raw = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));\n const servers: ServersConfig = raw.mcpServers ?? raw.servers ?? raw;\n\n const serverNames = Object.keys(servers || {});\n if (!serverNames.includes(opts.server)) {\n throw new Error(`Server '${opts.server}' not found in config\\n\\nAvailable servers: ${serverNames.join(', ')}`);\n }\n\n const serverConfig = servers[opts.server];\n if (!serverConfig) {\n throw new Error(`Server ${opts.server} not found in config`);\n }\n\n return {\n serverName: opts.server,\n serverConfig: serverConfig as ServerConfig,\n configDir: path.dirname(cfgPath),\n fullConfig: servers,\n };\n}\n\n/**\n * Parse a run string into a ServerConfigStdio.\n *\n * @example\n * parseRunString(\"npx -y @echo/server\")\n * // => { command: \"npx\", args: [\"-y\", \"@echo/server\"] }\n */\nfunction parseRunString(runStr: string): ServerConfig {\n const parts = runStr.trim().split(/\\s+/);\n if (parts.length === 0 || !parts[0]) {\n throw new Error('Run string cannot be empty');\n }\n\n return {\n command: parts[0],\n args: parts.slice(1),\n };\n}\n\n/**\n * Parse and validate a full server config JSON string against the MCP schema.\n *\n * @example\n * parseServerConfigJson('{\"command\":\"npx\",\"args\":[\"-y\",\"@echo/server\"]}')\n * parseServerConfigJson('{\"url\":\"https://example.com/mcp\",\"type\":\"http\"}')\n */\nfunction parseServerConfigJson(jsonStr: string, serverName: string): ServerConfig {\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonStr);\n } catch (error) {\n throw new Error(`Failed to parse server config JSON: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n if (typeof parsed !== 'object' || parsed === null) {\n throw new Error('Server config must be a JSON object');\n }\n\n const config = parsed as McpServerEntry;\n\n // Validate: must have either 'command' (stdio) or 'url' (http)\n if (!config.command && !config.url) {\n throw new Error('Server config must have either \"command\" (for stdio) or \"url\" (for http)');\n }\n\n // Normalize: if url is present without explicit type, set type to 'http'\n if (config.url && !config.type) {\n config.type = 'http';\n }\n\n // Validate against the MCP servers schema\n const serversMap = { [serverName]: config };\n const validation = validateServers(serversMap);\n if (!validation.valid) {\n const errorDetails = validation.errors?.join('\\n ') || 'Unknown validation error';\n throw new Error(`Invalid server config:\\n ${errorDetails}`);\n }\n\n // Return as ServerConfig (compatible with McpServerEntry)\n return config as ServerConfig;\n}\n"],"names":["resolveServerConfig","opts","inlineOptions","run","url","serverConfig","filter","Boolean","length","Error","hasInlineConfig","config","resolveInlineConfig","resolveFileConfig","serverName","server","configDir","process","cwd","parseRunString","type","parseServerConfigJson","fullConfig","raw","cfgPath","findConfigPath","JSON","parse","fs","readFileSync","servers","mcpServers","serverNames","Object","keys","includes","join","path","dirname","runStr","parts","trim","split","command","args","slice","jsonStr","parsed","error","message","String","serversMap","validation","validateServers","valid","errorDetails","errors"],"mappings":"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"}
|