feat: implement v2 3-tier architecture (mcpctl → mcplocal → mcpd)
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / typecheck (pull_request) Has been cancelled
CI / test (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / package (pull_request) Has been cancelled

- Rename local-proxy to mcplocal with HTTP server, LLM pipeline, mcpd discovery
- Add LLM pre-processing: token estimation, filter cache, metrics, Gemini CLI + DeepSeek providers
- Add mcpd auth (login/logout) and MCP proxy endpoints
- Update CLI: dual URLs (mcplocalUrl/mcpdUrl), auth commands, --direct flag
- Add tiered health monitoring, shell completions, e2e integration tests
- 57 test files, 597 tests passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michal
2026-02-22 11:42:06 +00:00
parent a4fe5fdbe2
commit b8c5cf718a
82 changed files with 5832 additions and 123 deletions

View File

@@ -2,16 +2,19 @@ import { Command } from 'commander';
import http from 'node:http';
import { loadConfig } from '../config/index.js';
import type { ConfigLoaderDeps } from '../config/index.js';
import { loadCredentials } from '../auth/index.js';
import type { CredentialsDeps } from '../auth/index.js';
import { formatJson, formatYaml } from '../formatters/index.js';
import { APP_VERSION } from '@mcpctl/shared';
export interface StatusCommandDeps {
configDeps: Partial<ConfigLoaderDeps>;
credentialsDeps: Partial<CredentialsDeps>;
log: (...args: string[]) => void;
checkDaemon: (url: string) => Promise<boolean>;
checkHealth: (url: string) => Promise<boolean>;
}
function defaultCheckDaemon(url: string): Promise<boolean> {
function defaultCheckHealth(url: string): Promise<boolean> {
return new Promise((resolve) => {
const req = http.get(`${url}/health`, { timeout: 3000 }, (res) => {
resolve(res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 400);
@@ -27,24 +30,33 @@ function defaultCheckDaemon(url: string): Promise<boolean> {
const defaultDeps: StatusCommandDeps = {
configDeps: {},
credentialsDeps: {},
log: (...args) => console.log(...args),
checkDaemon: defaultCheckDaemon,
checkHealth: defaultCheckHealth,
};
export function createStatusCommand(deps?: Partial<StatusCommandDeps>): Command {
const { configDeps, log, checkDaemon } = { ...defaultDeps, ...deps };
const { configDeps, credentialsDeps, log, checkHealth } = { ...defaultDeps, ...deps };
return new Command('status')
.description('Show mcpctl status and connectivity')
.option('-o, --output <format>', 'output format (table, json, yaml)', 'table')
.action(async (opts: { output: string }) => {
const config = loadConfig(configDeps);
const daemonReachable = await checkDaemon(config.daemonUrl);
const creds = loadCredentials(credentialsDeps);
const [mcplocalReachable, mcpdReachable] = await Promise.all([
checkHealth(config.mcplocalUrl),
checkHealth(config.mcpdUrl),
]);
const status = {
version: APP_VERSION,
daemonUrl: config.daemonUrl,
daemonReachable,
mcplocalUrl: config.mcplocalUrl,
mcplocalReachable,
mcpdUrl: config.mcpdUrl,
mcpdReachable,
auth: creds ? { user: creds.user } : null,
registries: config.registries,
outputFormat: config.outputFormat,
};
@@ -55,7 +67,9 @@ export function createStatusCommand(deps?: Partial<StatusCommandDeps>): Command
log(formatYaml(status));
} else {
log(`mcpctl v${status.version}`);
log(`Daemon: ${status.daemonUrl} (${daemonReachable ? 'connected' : 'unreachable'})`);
log(`mcplocal: ${status.mcplocalUrl} (${mcplocalReachable ? 'connected' : 'unreachable'})`);
log(`mcpd: ${status.mcpdUrl} (${mcpdReachable ? 'connected' : 'unreachable'})`);
log(`Auth: ${creds ? `logged in as ${creds.user}` : 'not logged in'}`);
log(`Registries: ${status.registries.join(', ')}`);
log(`Output: ${status.outputFormat}`);
}