Start a single server and register its tools.
(name: string, config: MCPServerConfig)
| 102 | |
| 103 | /** Start a single server and register its tools. */ |
| 104 | async startOne(name: string, config: MCPServerConfig): Promise<void> { |
| 105 | // If already running, stop first |
| 106 | const existing = this.clients.get(name); |
| 107 | if (existing) await existing.stop(); |
| 108 | |
| 109 | // Expand ${ENV_VAR} references in env values, args, headers, and url so a |
| 110 | // config that stores `${GITHUB_PAT}` (not the literal secret) resolves at |
| 111 | // launch time from the process environment. Missing vars expand to '' and |
| 112 | // log a warning so the failure is diagnosable. |
| 113 | const resolved = expandEnvRefs(config, name); |
| 114 | |
| 115 | const client = new MCPClient(name, resolved); |
| 116 | this.clients.set(name, client); |
| 117 | |
| 118 | client.on('tools-changed', () => { |
| 119 | // Re-register tools when the server signals a change |
| 120 | this.registerTools(client, resolved.destructive ?? true); |
| 121 | }); |
| 122 | client.on('exit', () => { |
| 123 | // Server died — keep the registry tools but they'll fail with MCP_UNAVAILABLE |
| 124 | logger.warn(`MCP ${name} exited unexpectedly`); |
| 125 | }); |
| 126 | |
| 127 | await client.start(); |
| 128 | this.registerTools(client, resolved.destructive ?? true); |
| 129 | } |
| 130 | |
| 131 | /** (Re-)register all of a client's tools in the QodeX registry. Removes stale entries from previous tool lists. */ |
| 132 | private registerTools(client: MCPClient, destructive: boolean): void { |
no test coverage detected