@darkiceinteractive/mcp-conductor 2.0.0-alpha.1 → 3.0.0-beta.2
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/README.md +35 -5
- package/dist/bin/cli.d.ts +20 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +260 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bridge/http-server.d.ts +35 -0
- package/dist/bridge/http-server.d.ts.map +1 -1
- package/dist/bridge/http-server.js +51 -2
- package/dist/bridge/http-server.js.map +1 -1
- package/dist/bridge/index.d.ts +1 -0
- package/dist/bridge/index.d.ts.map +1 -1
- package/dist/bridge/index.js +1 -0
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/pool.d.ts +95 -0
- package/dist/bridge/pool.d.ts.map +1 -0
- package/dist/bridge/pool.js +384 -0
- package/dist/bridge/pool.js.map +1 -0
- package/dist/cache/cache.d.ts +64 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +209 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/cache/delta.d.ts +32 -0
- package/dist/cache/delta.d.ts.map +1 -0
- package/dist/cache/delta.js +131 -0
- package/dist/cache/delta.js.map +1 -0
- package/dist/cache/disk.d.ts +65 -0
- package/dist/cache/disk.d.ts.map +1 -0
- package/dist/cache/disk.js +238 -0
- package/dist/cache/disk.js.map +1 -0
- package/dist/cache/index.d.ts +53 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +12 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/key.d.ts +44 -0
- package/dist/cache/key.d.ts.map +1 -0
- package/dist/cache/key.js +83 -0
- package/dist/cache/key.js.map +1 -0
- package/dist/cache/lru.d.ts +57 -0
- package/dist/cache/lru.d.ts.map +1 -0
- package/dist/cache/lru.js +112 -0
- package/dist/cache/lru.js.map +1 -0
- package/dist/cache/policy.d.ts +34 -0
- package/dist/cache/policy.d.ts.map +1 -0
- package/dist/cache/policy.js +95 -0
- package/dist/cache/policy.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +33 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +135 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/export-servers.d.ts +22 -0
- package/dist/cli/commands/export-servers.d.ts.map +1 -0
- package/dist/cli/commands/export-servers.js +45 -0
- package/dist/cli/commands/export-servers.js.map +1 -0
- package/dist/cli/commands/import-servers.d.ts +57 -0
- package/dist/cli/commands/import-servers.d.ts.map +1 -0
- package/dist/cli/commands/import-servers.js +137 -0
- package/dist/cli/commands/import-servers.js.map +1 -0
- package/dist/cli/commands/routing.d.ts +34 -0
- package/dist/cli/commands/routing.d.ts.map +1 -0
- package/dist/cli/commands/routing.js +60 -0
- package/dist/cli/commands/routing.js.map +1 -0
- package/dist/cli/commands/test-server.d.ts +34 -0
- package/dist/cli/commands/test-server.d.ts.map +1 -0
- package/dist/cli/commands/test-server.js +86 -0
- package/dist/cli/commands/test-server.js.map +1 -0
- package/dist/cli/daemon.d.ts +60 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +244 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/replay.d.ts +16 -0
- package/dist/cli/replay.d.ts.map +1 -0
- package/dist/cli/replay.js +89 -0
- package/dist/cli/replay.js.map +1 -0
- package/dist/cli/wizard/setup.d.ts +12 -0
- package/dist/cli/wizard/setup.d.ts.map +1 -0
- package/dist/cli/wizard/setup.js +71 -0
- package/dist/cli/wizard/setup.js.map +1 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +4 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/schema.d.ts +34 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/daemon/client.d.ts +99 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +292 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/discovery.d.ts +50 -0
- package/dist/daemon/discovery.d.ts.map +1 -0
- package/dist/daemon/discovery.js +104 -0
- package/dist/daemon/discovery.js.map +1 -0
- package/dist/daemon/index.d.ts +16 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +11 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/sandbox-api.d.ts +45 -0
- package/dist/daemon/sandbox-api.d.ts.map +1 -0
- package/dist/daemon/sandbox-api.js +74 -0
- package/dist/daemon/sandbox-api.js.map +1 -0
- package/dist/daemon/server.d.ts +65 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +373 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/daemon/shared-kv.d.ts +81 -0
- package/dist/daemon/shared-kv.d.ts.map +1 -0
- package/dist/daemon/shared-kv.js +215 -0
- package/dist/daemon/shared-kv.js.map +1 -0
- package/dist/daemon/shared-lock.d.ts +71 -0
- package/dist/daemon/shared-lock.d.ts.map +1 -0
- package/dist/daemon/shared-lock.js +119 -0
- package/dist/daemon/shared-lock.js.map +1 -0
- package/dist/hub/mcp-hub.d.ts +23 -0
- package/dist/hub/mcp-hub.d.ts.map +1 -1
- package/dist/hub/mcp-hub.js +34 -1
- package/dist/hub/mcp-hub.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/observability/anomaly.d.ts +67 -0
- package/dist/observability/anomaly.d.ts.map +1 -0
- package/dist/observability/anomaly.js +141 -0
- package/dist/observability/anomaly.js.map +1 -0
- package/dist/observability/cost-predictor.d.ts +49 -0
- package/dist/observability/cost-predictor.d.ts.map +1 -0
- package/dist/observability/cost-predictor.js +145 -0
- package/dist/observability/cost-predictor.js.map +1 -0
- package/dist/observability/hot-path.d.ts +49 -0
- package/dist/observability/hot-path.d.ts.map +1 -0
- package/dist/observability/hot-path.js +125 -0
- package/dist/observability/hot-path.js.map +1 -0
- package/dist/observability/index.d.ts +10 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +10 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/replay.d.ts +104 -0
- package/dist/observability/replay.d.ts.map +1 -0
- package/dist/observability/replay.js +239 -0
- package/dist/observability/replay.js.map +1 -0
- package/dist/registry/built-in-recommendations.d.ts +54 -0
- package/dist/registry/built-in-recommendations.d.ts.map +1 -0
- package/dist/registry/built-in-recommendations.js +65 -0
- package/dist/registry/built-in-recommendations.js.map +1 -0
- package/dist/registry/events.d.ts +26 -0
- package/dist/registry/events.d.ts.map +1 -0
- package/dist/registry/events.js +22 -0
- package/dist/registry/events.js.map +1 -0
- package/dist/registry/index.d.ts +159 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +12 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/registry.d.ts +87 -0
- package/dist/registry/registry.d.ts.map +1 -0
- package/dist/registry/registry.js +294 -0
- package/dist/registry/registry.js.map +1 -0
- package/dist/registry/snapshot.d.ts +42 -0
- package/dist/registry/snapshot.d.ts.map +1 -0
- package/dist/registry/snapshot.js +71 -0
- package/dist/registry/snapshot.js.map +1 -0
- package/dist/registry/typegen.d.ts +48 -0
- package/dist/registry/typegen.d.ts.map +1 -0
- package/dist/registry/typegen.js +200 -0
- package/dist/registry/typegen.js.map +1 -0
- package/dist/registry/validator.d.ts +23 -0
- package/dist/registry/validator.d.ts.map +1 -0
- package/dist/registry/validator.js +50 -0
- package/dist/registry/validator.js.map +1 -0
- package/dist/reliability/breaker.d.ts +57 -0
- package/dist/reliability/breaker.d.ts.map +1 -0
- package/dist/reliability/breaker.js +130 -0
- package/dist/reliability/breaker.js.map +1 -0
- package/dist/reliability/errors.d.ts +78 -0
- package/dist/reliability/errors.d.ts.map +1 -0
- package/dist/reliability/errors.js +160 -0
- package/dist/reliability/errors.js.map +1 -0
- package/dist/reliability/gateway.d.ts +88 -0
- package/dist/reliability/gateway.d.ts.map +1 -0
- package/dist/reliability/gateway.js +180 -0
- package/dist/reliability/gateway.js.map +1 -0
- package/dist/reliability/index.d.ts +20 -0
- package/dist/reliability/index.d.ts.map +1 -0
- package/dist/reliability/index.js +16 -0
- package/dist/reliability/index.js.map +1 -0
- package/dist/reliability/profile.d.ts +49 -0
- package/dist/reliability/profile.d.ts.map +1 -0
- package/dist/reliability/profile.js +58 -0
- package/dist/reliability/profile.js.map +1 -0
- package/dist/reliability/retry.d.ts +39 -0
- package/dist/reliability/retry.d.ts.map +1 -0
- package/dist/reliability/retry.js +51 -0
- package/dist/reliability/retry.js.map +1 -0
- package/dist/reliability/timeout.d.ts +34 -0
- package/dist/reliability/timeout.d.ts.map +1 -0
- package/dist/reliability/timeout.js +53 -0
- package/dist/reliability/timeout.js.map +1 -0
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +122 -14
- package/dist/runtime/executor.js.map +1 -1
- package/dist/runtime/findtool/embed.d.ts +28 -0
- package/dist/runtime/findtool/embed.d.ts.map +1 -0
- package/dist/runtime/findtool/embed.js +85 -0
- package/dist/runtime/findtool/embed.js.map +1 -0
- package/dist/runtime/findtool/index.d.ts +52 -0
- package/dist/runtime/findtool/index.d.ts.map +1 -0
- package/dist/runtime/findtool/index.js +78 -0
- package/dist/runtime/findtool/index.js.map +1 -0
- package/dist/runtime/findtool/vector-index.d.ts +53 -0
- package/dist/runtime/findtool/vector-index.d.ts.map +1 -0
- package/dist/runtime/findtool/vector-index.js +71 -0
- package/dist/runtime/findtool/vector-index.js.map +1 -0
- package/dist/runtime/helpers/budget.d.ts +27 -0
- package/dist/runtime/helpers/budget.d.ts.map +1 -0
- package/dist/runtime/helpers/budget.js +103 -0
- package/dist/runtime/helpers/budget.js.map +1 -0
- package/dist/runtime/helpers/compact.d.ts +32 -0
- package/dist/runtime/helpers/compact.d.ts.map +1 -0
- package/dist/runtime/helpers/compact.js +93 -0
- package/dist/runtime/helpers/compact.js.map +1 -0
- package/dist/runtime/helpers/delta.d.ts +45 -0
- package/dist/runtime/helpers/delta.d.ts.map +1 -0
- package/dist/runtime/helpers/delta.js +116 -0
- package/dist/runtime/helpers/delta.js.map +1 -0
- package/dist/runtime/helpers/index.d.ts +16 -0
- package/dist/runtime/helpers/index.d.ts.map +1 -0
- package/dist/runtime/helpers/index.js +13 -0
- package/dist/runtime/helpers/index.js.map +1 -0
- package/dist/runtime/helpers/summarize.d.ts +24 -0
- package/dist/runtime/helpers/summarize.d.ts.map +1 -0
- package/dist/runtime/helpers/summarize.js +124 -0
- package/dist/runtime/helpers/summarize.js.map +1 -0
- package/dist/runtime/helpers/worker-preload.d.ts +25 -0
- package/dist/runtime/helpers/worker-preload.d.ts.map +1 -0
- package/dist/runtime/helpers/worker-preload.js +223 -0
- package/dist/runtime/helpers/worker-preload.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/pool/index.d.ts +11 -0
- package/dist/runtime/pool/index.d.ts.map +1 -0
- package/dist/runtime/pool/index.js +8 -0
- package/dist/runtime/pool/index.js.map +1 -0
- package/dist/runtime/pool/recycle.d.ts +44 -0
- package/dist/runtime/pool/recycle.d.ts.map +1 -0
- package/dist/runtime/pool/recycle.js +50 -0
- package/dist/runtime/pool/recycle.js.map +1 -0
- package/dist/runtime/pool/worker-pool.d.ts +77 -0
- package/dist/runtime/pool/worker-pool.d.ts.map +1 -0
- package/dist/runtime/pool/worker-pool.js +216 -0
- package/dist/runtime/pool/worker-pool.js.map +1 -0
- package/dist/runtime/pool/worker.d.ts +80 -0
- package/dist/runtime/pool/worker.d.ts.map +1 -0
- package/dist/runtime/pool/worker.js +324 -0
- package/dist/runtime/pool/worker.js.map +1 -0
- package/dist/server/mcp-server.d.ts +3 -0
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +457 -3
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/passthrough-registrar.d.ts +123 -0
- package/dist/server/passthrough-registrar.d.ts.map +1 -0
- package/dist/server/passthrough-registrar.js +199 -0
- package/dist/server/passthrough-registrar.js.map +1 -0
- package/dist/skills/skills-engine.d.ts +9 -1
- package/dist/skills/skills-engine.d.ts.map +1 -1
- package/dist/skills/skills-engine.js +20 -3
- package/dist/skills/skills-engine.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/tokenize.d.ts +55 -0
- package/dist/utils/tokenize.d.ts.map +1 -0
- package/dist/utils/tokenize.js +205 -0
- package/dist/utils/tokenize.js.map +1 -0
- package/dist/version.d.ts +3 -3
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +3 -3
- package/dist/version.js.map +1 -1
- package/package.json +13 -3
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Conductor Daemon Server.
|
|
3
|
+
*
|
|
4
|
+
* Listens on a Unix domain socket (primary) and optionally a TCP port (for
|
|
5
|
+
* Tailscale-mesh clients). Enforces HMAC-SHA256 auth on every connection using
|
|
6
|
+
* the shared secret loaded from `~/.mcp-conductor/daemon-auth.json`.
|
|
7
|
+
*
|
|
8
|
+
* Protocol (newline-delimited JSON):
|
|
9
|
+
* Client → Server: { id, method, params }
|
|
10
|
+
* Server → Client: { id, result } | { id, error }
|
|
11
|
+
*
|
|
12
|
+
* The daemon owns a SharedKV, SharedLock, and in-process pub/sub bus that all
|
|
13
|
+
* connected clients share.
|
|
14
|
+
*
|
|
15
|
+
* @module daemon/server
|
|
16
|
+
*/
|
|
17
|
+
import { createServer } from 'node:net';
|
|
18
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, chmodSync, unlinkSync, } from 'node:fs';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { homedir } from 'node:os';
|
|
21
|
+
import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
22
|
+
import { EventEmitter } from 'node:events';
|
|
23
|
+
import { logger } from '../utils/logger.js';
|
|
24
|
+
import { SharedKV } from './shared-kv.js';
|
|
25
|
+
import { SharedLock } from './shared-lock.js';
|
|
26
|
+
const DEFAULT_AUTH_PATH = join(homedir(), '.mcp-conductor', 'daemon-auth.json');
|
|
27
|
+
const DEFAULT_SOCKET_PATH = join(homedir(), '.mcp-conductor', 'daemon.sock');
|
|
28
|
+
const CONDUCTOR_DIR = join(homedir(), '.mcp-conductor');
|
|
29
|
+
function loadOrCreateSecret(authPath) {
|
|
30
|
+
if (existsSync(authPath)) {
|
|
31
|
+
const raw = readFileSync(authPath, 'utf-8');
|
|
32
|
+
return JSON.parse(raw).sharedSecret;
|
|
33
|
+
}
|
|
34
|
+
mkdirSync(CONDUCTOR_DIR, { recursive: true });
|
|
35
|
+
const secret = randomBytes(32).toString('hex');
|
|
36
|
+
const content = { sharedSecret: secret };
|
|
37
|
+
// Pass mode: 0o600 atomically so the file is never world-readable (CRIT-4).
|
|
38
|
+
writeFileSync(authPath, JSON.stringify(content, null, 2), { mode: 0o600, encoding: 'utf-8' });
|
|
39
|
+
logger.info('DaemonServer: generated new shared secret', { authPath });
|
|
40
|
+
return secret;
|
|
41
|
+
}
|
|
42
|
+
function hmacToken(secret, nonce) {
|
|
43
|
+
return createHmac('sha256', secret).update(nonce).digest('hex');
|
|
44
|
+
}
|
|
45
|
+
class PubSubBus {
|
|
46
|
+
emitter = new EventEmitter();
|
|
47
|
+
subscribe(channel, handler) {
|
|
48
|
+
this.emitter.on(channel, handler);
|
|
49
|
+
return { unsubscribe: () => this.emitter.off(channel, handler) };
|
|
50
|
+
}
|
|
51
|
+
broadcast(channel, message) {
|
|
52
|
+
this.emitter.emit(channel, message);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// DaemonServer
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
export class DaemonServer {
|
|
59
|
+
socketPath;
|
|
60
|
+
tcpPort;
|
|
61
|
+
sharedSecret;
|
|
62
|
+
kv;
|
|
63
|
+
lock;
|
|
64
|
+
bus = new PubSubBus();
|
|
65
|
+
unixServer;
|
|
66
|
+
tcpServer;
|
|
67
|
+
/** Map from socket to per-client state (including lock handles). */
|
|
68
|
+
clients = new Map();
|
|
69
|
+
startTime = Date.now();
|
|
70
|
+
requestsHandled = 0;
|
|
71
|
+
running = false;
|
|
72
|
+
constructor(options = {}) {
|
|
73
|
+
this.socketPath = options.socketPath ?? DEFAULT_SOCKET_PATH;
|
|
74
|
+
this.tcpPort = options.tcpPort;
|
|
75
|
+
const authPath = options.auth?.sharedSecretPath ?? DEFAULT_AUTH_PATH;
|
|
76
|
+
this.sharedSecret = options.auth?.sharedSecret ?? loadOrCreateSecret(authPath);
|
|
77
|
+
this.kv = new SharedKV(options.kvOptions);
|
|
78
|
+
this.lock = new SharedLock();
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Lifecycle
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
async start() {
|
|
84
|
+
if (this.running)
|
|
85
|
+
throw new Error('DaemonServer is already running');
|
|
86
|
+
this.running = true;
|
|
87
|
+
mkdirSync(CONDUCTOR_DIR, { recursive: true });
|
|
88
|
+
if (existsSync(this.socketPath)) {
|
|
89
|
+
unlinkSync(this.socketPath);
|
|
90
|
+
}
|
|
91
|
+
await this.startUnixServer();
|
|
92
|
+
if (this.tcpPort !== undefined) {
|
|
93
|
+
await this.startTcpServer();
|
|
94
|
+
}
|
|
95
|
+
logger.info('DaemonServer: started', {
|
|
96
|
+
socketPath: this.socketPath,
|
|
97
|
+
tcpPort: this.tcpPort,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async shutdown() {
|
|
101
|
+
this.running = false;
|
|
102
|
+
const closePromises = [];
|
|
103
|
+
for (const [socket] of this.clients) {
|
|
104
|
+
closePromises.push(new Promise((resolve) => {
|
|
105
|
+
socket.once('close', resolve);
|
|
106
|
+
socket.end();
|
|
107
|
+
setTimeout(() => { socket.destroy(); resolve(); }, 2000);
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
await Promise.all(closePromises);
|
|
111
|
+
this.clients.clear();
|
|
112
|
+
await Promise.all([
|
|
113
|
+
this.closeServer(this.unixServer),
|
|
114
|
+
this.closeServer(this.tcpServer),
|
|
115
|
+
]);
|
|
116
|
+
if (existsSync(this.socketPath)) {
|
|
117
|
+
try {
|
|
118
|
+
unlinkSync(this.socketPath);
|
|
119
|
+
}
|
|
120
|
+
catch { /* ignore */ }
|
|
121
|
+
}
|
|
122
|
+
await this.kv.shutdown();
|
|
123
|
+
logger.info('DaemonServer: shutdown complete');
|
|
124
|
+
}
|
|
125
|
+
stats() {
|
|
126
|
+
return {
|
|
127
|
+
uptime: Date.now() - this.startTime,
|
|
128
|
+
connectedClients: this.clients.size,
|
|
129
|
+
kvKeys: this.kv.size,
|
|
130
|
+
activeLocks: this.lock.hasActiveLocks,
|
|
131
|
+
requestsHandled: this.requestsHandled,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Server startup helpers
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
startUnixServer() {
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
const server = createServer((socket) => this.handleConnection(socket));
|
|
140
|
+
this.unixServer = server;
|
|
141
|
+
server.once('error', reject);
|
|
142
|
+
server.listen(this.socketPath, () => {
|
|
143
|
+
try {
|
|
144
|
+
chmodSync(this.socketPath, 0o600);
|
|
145
|
+
}
|
|
146
|
+
catch { /* ignore */ }
|
|
147
|
+
server.removeListener('error', reject);
|
|
148
|
+
server.on('error', (err) => {
|
|
149
|
+
logger.error('DaemonServer Unix socket error', { error: String(err) });
|
|
150
|
+
});
|
|
151
|
+
resolve();
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
startTcpServer() {
|
|
156
|
+
return new Promise((resolve, reject) => {
|
|
157
|
+
const server = createServer((socket) => this.handleConnection(socket));
|
|
158
|
+
this.tcpServer = server;
|
|
159
|
+
server.once('error', reject);
|
|
160
|
+
server.listen(this.tcpPort, '127.0.0.1', () => {
|
|
161
|
+
server.removeListener('error', reject);
|
|
162
|
+
server.on('error', (err) => {
|
|
163
|
+
logger.error('DaemonServer TCP error', { error: String(err) });
|
|
164
|
+
});
|
|
165
|
+
logger.info('DaemonServer: TCP listening', { port: this.tcpPort });
|
|
166
|
+
resolve();
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
closeServer(server) {
|
|
171
|
+
if (!server)
|
|
172
|
+
return Promise.resolve();
|
|
173
|
+
return new Promise((resolve) => {
|
|
174
|
+
server.close(() => resolve());
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Connection handling
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
handleConnection(socket) {
|
|
181
|
+
const state = { socket, lockHandles: new Map() };
|
|
182
|
+
this.clients.set(socket, state);
|
|
183
|
+
logger.debug('DaemonServer: client connected', { clients: this.clients.size });
|
|
184
|
+
let authenticated = false;
|
|
185
|
+
let buffer = '';
|
|
186
|
+
const nonce = randomBytes(16).toString('hex');
|
|
187
|
+
this.sendRaw(socket, { id: '__auth_challenge__', result: { nonce } });
|
|
188
|
+
// CRIT-3: close sockets that never complete auth within 10 s → prevents FD exhaustion.
|
|
189
|
+
const authDeadline = setTimeout(() => {
|
|
190
|
+
if (!authenticated) {
|
|
191
|
+
logger.warn('DaemonServer: auth timeout, destroying socket', { remote: socket.remoteAddress });
|
|
192
|
+
socket.destroy();
|
|
193
|
+
}
|
|
194
|
+
}, 10_000);
|
|
195
|
+
authDeadline.unref();
|
|
196
|
+
socket.setEncoding('utf-8');
|
|
197
|
+
socket.on('data', (chunk) => {
|
|
198
|
+
buffer += chunk;
|
|
199
|
+
const lines = buffer.split('\n');
|
|
200
|
+
buffer = lines.pop() ?? '';
|
|
201
|
+
for (const line of lines) {
|
|
202
|
+
const trimmed = line.trim();
|
|
203
|
+
if (!trimmed)
|
|
204
|
+
continue;
|
|
205
|
+
try {
|
|
206
|
+
const msg = JSON.parse(trimmed);
|
|
207
|
+
if (!authenticated) {
|
|
208
|
+
this.handleAuth(socket, msg, nonce, (ok) => {
|
|
209
|
+
authenticated = ok;
|
|
210
|
+
if (ok) {
|
|
211
|
+
clearTimeout(authDeadline); // CRIT-3: auth succeeded; cancel deadline
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
socket.destroy();
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
// Handle requests without blocking the data handler.
|
|
220
|
+
this.handleRequest(socket, state, msg).catch((err) => {
|
|
221
|
+
logger.error('DaemonServer: request handler error', { error: String(err) });
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
logger.warn('DaemonServer: malformed JSON from client');
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
socket.on('close', () => {
|
|
230
|
+
clearTimeout(authDeadline);
|
|
231
|
+
// Release all locks held by this client on disconnect.
|
|
232
|
+
for (const [key, handle] of state.lockHandles) {
|
|
233
|
+
handle.release().catch(() => { });
|
|
234
|
+
logger.debug('DaemonServer: auto-released lock on disconnect', { key });
|
|
235
|
+
}
|
|
236
|
+
state.lockHandles.clear();
|
|
237
|
+
this.clients.delete(socket);
|
|
238
|
+
logger.debug('DaemonServer: client disconnected', { clients: this.clients.size });
|
|
239
|
+
});
|
|
240
|
+
socket.on('error', (err) => {
|
|
241
|
+
logger.debug('DaemonServer: client socket error', { error: String(err) });
|
|
242
|
+
this.clients.delete(socket);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
handleAuth(socket, msg, nonce, callback) {
|
|
246
|
+
const params = msg.params;
|
|
247
|
+
const token = params?.token;
|
|
248
|
+
if (!token) {
|
|
249
|
+
this.sendRaw(socket, { id: msg.id, error: { code: 401, message: 'Missing auth token' } });
|
|
250
|
+
callback(false);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const expected = hmacToken(this.sharedSecret, nonce);
|
|
254
|
+
const expectedBuf = Buffer.from(expected, 'utf-8');
|
|
255
|
+
const providedBuf = Buffer.from(token, 'utf-8');
|
|
256
|
+
const ok = expectedBuf.length === providedBuf.length &&
|
|
257
|
+
timingSafeEqual(expectedBuf, providedBuf);
|
|
258
|
+
if (ok) {
|
|
259
|
+
this.sendRaw(socket, { id: msg.id, result: { authenticated: true } });
|
|
260
|
+
callback(true);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
this.sendRaw(socket, { id: msg.id, error: { code: 401, message: 'Invalid auth token' } });
|
|
264
|
+
callback(false);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async handleRequest(socket, state, msg) {
|
|
268
|
+
this.requestsHandled++;
|
|
269
|
+
try {
|
|
270
|
+
const result = await this.dispatch(msg.method, msg.params, socket, state);
|
|
271
|
+
this.sendRaw(socket, { id: msg.id, result });
|
|
272
|
+
}
|
|
273
|
+
catch (err) {
|
|
274
|
+
this.sendRaw(socket, {
|
|
275
|
+
id: msg.id,
|
|
276
|
+
error: { code: 500, message: String(err) },
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
async dispatch(method, params, socket, state) {
|
|
281
|
+
const p = params;
|
|
282
|
+
switch (method) {
|
|
283
|
+
// KV
|
|
284
|
+
case 'kv.get':
|
|
285
|
+
return this.kv.get(p?.key);
|
|
286
|
+
case 'kv.set':
|
|
287
|
+
this.kv.set(p?.key, p?.value, p?.options);
|
|
288
|
+
return null;
|
|
289
|
+
case 'kv.delete':
|
|
290
|
+
this.kv.delete(p?.key);
|
|
291
|
+
return null;
|
|
292
|
+
case 'kv.list':
|
|
293
|
+
return this.kv.list(p?.prefix);
|
|
294
|
+
// Locks
|
|
295
|
+
case 'lock.acquire': {
|
|
296
|
+
const key = p?.key;
|
|
297
|
+
const timeoutMs = p?.timeoutMs;
|
|
298
|
+
// HIGH-2: Reject if this client already holds the lock for this key.
|
|
299
|
+
// Silently overwriting the handle would orphan the old handle and
|
|
300
|
+
// permanently deadlock the key for all clients.
|
|
301
|
+
if (state.lockHandles.has(key)) {
|
|
302
|
+
throw new Error(`ALREADY_HOLDS_LOCK: Already holding lock for key '${key}'`);
|
|
303
|
+
}
|
|
304
|
+
// Acquire the lock — this awaits until the lock is free.
|
|
305
|
+
// Node.js is async; concurrent awaits on different sockets yield to
|
|
306
|
+
// the event loop, so release RPCs from other clients can proceed.
|
|
307
|
+
const handle = await this.lock.acquire(key, { timeoutMs });
|
|
308
|
+
// Persist the handle so lock.release can find and call it.
|
|
309
|
+
state.lockHandles.set(key, handle);
|
|
310
|
+
return { acquired: true, key };
|
|
311
|
+
}
|
|
312
|
+
case 'lock.release': {
|
|
313
|
+
const key = p?.key;
|
|
314
|
+
const handle = state.lockHandles.get(key);
|
|
315
|
+
if (handle) {
|
|
316
|
+
state.lockHandles.delete(key);
|
|
317
|
+
await handle.release();
|
|
318
|
+
return { released: true };
|
|
319
|
+
}
|
|
320
|
+
return { released: false, reason: 'no handle found for key' };
|
|
321
|
+
}
|
|
322
|
+
// Pub/sub
|
|
323
|
+
case 'broadcast': {
|
|
324
|
+
const channel = p?.channel;
|
|
325
|
+
const message = p?.message;
|
|
326
|
+
this.bus.broadcast(channel, message);
|
|
327
|
+
// HIGH-3: wrap in a dedicated envelope so clients cannot confuse a
|
|
328
|
+
// broadcast with an RPC response (e.g. a malicious {id:42,result:{}}
|
|
329
|
+
// broadcast would not be routed to pending RPC id 42).
|
|
330
|
+
// Note: sender is included so self-subscribing clients receive their
|
|
331
|
+
// own broadcasts (the envelope protection prevents injection regardless).
|
|
332
|
+
const envelope = JSON.stringify({ __broadcast__: true, channel, message }) + '\n';
|
|
333
|
+
for (const [client] of this.clients) {
|
|
334
|
+
if (!client.destroyed) {
|
|
335
|
+
client.write(envelope);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
case 'subscribe':
|
|
341
|
+
return { subscribed: true };
|
|
342
|
+
// Meta
|
|
343
|
+
case 'ping':
|
|
344
|
+
return { pong: true };
|
|
345
|
+
case 'stats':
|
|
346
|
+
return this.stats();
|
|
347
|
+
case 'tool.call':
|
|
348
|
+
// Placeholder — actual tool dispatch handled by the MCP server layer.
|
|
349
|
+
throw new Error('tool.call not implemented in daemon v3.0 (agents use direct mode)');
|
|
350
|
+
default:
|
|
351
|
+
throw new Error(`Unknown method: ${method}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// Wire helpers
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
sendRaw(socket, msg) {
|
|
358
|
+
if (!socket.destroyed) {
|
|
359
|
+
try {
|
|
360
|
+
socket.write(JSON.stringify(msg) + '\n');
|
|
361
|
+
}
|
|
362
|
+
catch (err) {
|
|
363
|
+
logger.debug('DaemonServer: failed to write to client', { error: String(err) });
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// ---------------------------------------------------------------------------
|
|
368
|
+
// Expose internals for integration tests
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
get kvStore() { return this.kv; }
|
|
371
|
+
get lockRegistry() { return this.lock; }
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Key-Value Store for MCP Conductor Daemon.
|
|
3
|
+
*
|
|
4
|
+
* Provides in-memory storage with optional disk persistence and TTL support.
|
|
5
|
+
* Each KV entry can carry an expiry timestamp; a background sweep runs every
|
|
6
|
+
* 30 s to evict stale entries and sync the on-disk snapshot.
|
|
7
|
+
*
|
|
8
|
+
* @module daemon/shared-kv
|
|
9
|
+
*/
|
|
10
|
+
/** Options accepted by {@link SharedKV.set}. */
|
|
11
|
+
export interface KVSetOptions {
|
|
12
|
+
/** Time-to-live in milliseconds. Entry is deleted after this duration. */
|
|
13
|
+
ttl?: number;
|
|
14
|
+
}
|
|
15
|
+
/** Options for constructing a {@link SharedKV} instance. */
|
|
16
|
+
export interface SharedKVOptions {
|
|
17
|
+
/** Directory for disk persistence. Defaults to `~/.mcp-conductor/kv/`. */
|
|
18
|
+
persistDir?: string;
|
|
19
|
+
/** Sweep interval for TTL expiry, in milliseconds. Defaults to 30 000. */
|
|
20
|
+
sweepIntervalMs?: number;
|
|
21
|
+
/** Namespace / shard name used for the snapshot file. Defaults to `default`. */
|
|
22
|
+
namespace?: string;
|
|
23
|
+
/** Whether to skip loading from disk on construction. Useful in tests. */
|
|
24
|
+
skipLoad?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Shared key-value store with TTL expiry and disk persistence.
|
|
28
|
+
*
|
|
29
|
+
* Thread-safety note: Node.js is single-threaded; all mutations are
|
|
30
|
+
* synchronous operations on the in-memory Map, so no locking is required
|
|
31
|
+
* within a single process. Cross-process sharing is handled by the daemon
|
|
32
|
+
* server, which owns a single SharedKV instance.
|
|
33
|
+
*/
|
|
34
|
+
export declare class SharedKV {
|
|
35
|
+
private readonly store;
|
|
36
|
+
private readonly persistDir;
|
|
37
|
+
private readonly snapshotPath;
|
|
38
|
+
private readonly sweepIntervalMs;
|
|
39
|
+
private sweepTimer;
|
|
40
|
+
private dirty;
|
|
41
|
+
constructor(options?: SharedKVOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Retrieve a value by key.
|
|
44
|
+
* Returns `null` if the key does not exist or has expired.
|
|
45
|
+
*/
|
|
46
|
+
get<T>(key: string): T | null;
|
|
47
|
+
/**
|
|
48
|
+
* Store a value, with an optional TTL.
|
|
49
|
+
*/
|
|
50
|
+
set<T>(key: string, value: T, options?: KVSetOptions): void;
|
|
51
|
+
/**
|
|
52
|
+
* Delete a key. No-op if the key does not exist.
|
|
53
|
+
*/
|
|
54
|
+
delete(key: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* List all non-expired keys, optionally filtered by a string prefix.
|
|
57
|
+
*/
|
|
58
|
+
list(prefix?: string): string[];
|
|
59
|
+
/**
|
|
60
|
+
* Remove all entries (optionally matching a prefix).
|
|
61
|
+
*/
|
|
62
|
+
clear(prefix?: string): void;
|
|
63
|
+
/** Total number of (potentially expired) entries currently held in memory. */
|
|
64
|
+
get size(): number;
|
|
65
|
+
/**
|
|
66
|
+
* Flush the in-memory state to disk and stop the sweep timer.
|
|
67
|
+
* Call this before process exit or daemon shutdown.
|
|
68
|
+
*/
|
|
69
|
+
shutdown(): Promise<void>;
|
|
70
|
+
private loadFromDisk;
|
|
71
|
+
/** Write the current (non-expired) state to disk. */
|
|
72
|
+
flushToDisk(): void;
|
|
73
|
+
private startSweep;
|
|
74
|
+
private evictExpired;
|
|
75
|
+
/**
|
|
76
|
+
* Delete all snapshot files under `persistDir`.
|
|
77
|
+
* Used in tests for clean-up between runs.
|
|
78
|
+
*/
|
|
79
|
+
static clearAllSnapshots(persistDir: string): void;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=shared-kv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-kv.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-kv.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,gDAAgD;AAChD,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAeD,4DAA4D;AAC5D,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8B;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,KAAK,CAAS;gBAEV,OAAO,GAAE,eAAoB;IAgBzC;;;OAGG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAa7B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAS3D;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMzB;;OAEG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAY/B;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAW5B,8EAA8E;IAC9E,IAAI,IAAI,IAAI,MAAM,CAEjB;IAMD;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAa/B,OAAO,CAAC,YAAY;IA2BpB,qDAAqD;IACrD,WAAW,IAAI,IAAI;IAqBnB,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,YAAY;IAUpB;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAQnD"}
|