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

@@ -28,18 +28,25 @@ describe('loadConfig', () => {
});
it('loads config from file', () => {
saveConfig({ ...DEFAULT_CONFIG, daemonUrl: 'http://custom:5000' }, { configDir: tempDir });
saveConfig({ ...DEFAULT_CONFIG, mcplocalUrl: 'http://custom:5000' }, { configDir: tempDir });
const config = loadConfig({ configDir: tempDir });
expect(config.daemonUrl).toBe('http://custom:5000');
expect(config.mcplocalUrl).toBe('http://custom:5000');
});
it('applies defaults for missing fields', () => {
const { writeFileSync } = require('node:fs') as typeof import('node:fs');
writeFileSync(join(tempDir, 'config.json'), '{"daemonUrl":"http://x:1"}');
writeFileSync(join(tempDir, 'config.json'), '{"mcplocalUrl":"http://x:1"}');
const config = loadConfig({ configDir: tempDir });
expect(config.daemonUrl).toBe('http://x:1');
expect(config.mcplocalUrl).toBe('http://x:1');
expect(config.registries).toEqual(['official', 'glama', 'smithery']);
});
it('backward compat: daemonUrl maps to mcplocalUrl', () => {
const { writeFileSync } = require('node:fs') as typeof import('node:fs');
writeFileSync(join(tempDir, 'config.json'), '{"daemonUrl":"http://old:3000"}');
const config = loadConfig({ configDir: tempDir });
expect(config.mcplocalUrl).toBe('http://old:3000');
});
});
describe('saveConfig', () => {
@@ -57,7 +64,7 @@ describe('saveConfig', () => {
it('round-trips configuration', () => {
const custom = {
...DEFAULT_CONFIG,
daemonUrl: 'http://custom:9000',
mcplocalUrl: 'http://custom:9000',
registries: ['official' as const],
outputFormat: 'json' as const,
};
@@ -70,14 +77,14 @@ describe('saveConfig', () => {
describe('mergeConfig', () => {
it('merges overrides into existing config', () => {
saveConfig(DEFAULT_CONFIG, { configDir: tempDir });
const merged = mergeConfig({ daemonUrl: 'http://new:1234' }, { configDir: tempDir });
expect(merged.daemonUrl).toBe('http://new:1234');
const merged = mergeConfig({ mcplocalUrl: 'http://new:1234' }, { configDir: tempDir });
expect(merged.mcplocalUrl).toBe('http://new:1234');
expect(merged.registries).toEqual(DEFAULT_CONFIG.registries);
});
it('works when no config file exists', () => {
const merged = mergeConfig({ outputFormat: 'yaml' }, { configDir: tempDir });
expect(merged.outputFormat).toBe('yaml');
expect(merged.daemonUrl).toBe('http://localhost:3000');
expect(merged.mcplocalUrl).toBe('http://localhost:3200');
});
});