@darkiceinteractive/mcp-conductor 1.1.0 → 3.0.0-beta.1
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 +65 -1
- package/dist/bridge/http-server.d.ts.map +1 -1
- package/dist/bridge/http-server.js +192 -7
- 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/bridge/session-registry.d.ts +64 -0
- package/dist/bridge/session-registry.d.ts.map +1 -0
- package/dist/bridge/session-registry.js +124 -0
- package/dist/bridge/session-registry.js.map +1 -0
- package/dist/cache/cache.d.ts +43 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +167 -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 +10 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +14 -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 +97 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +279 -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 +351 -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 +19 -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 +12 -0
- package/dist/runtime/executor.d.ts.map +1 -1
- package/dist/runtime/executor.js +148 -16
- 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 +6 -0
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +610 -45
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/passthrough-registrar.d.ts +73 -0
- package/dist/server/passthrough-registrar.d.ts.map +1 -0
- package/dist/server/passthrough-registrar.js +110 -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 +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +5 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/orphan-watch.d.ts +34 -0
- package/dist/utils/orphan-watch.d.ts.map +1 -0
- package/dist/utils/orphan-watch.js +54 -0
- package/dist/utils/orphan-watch.js.map +1 -0
- package/dist/utils/redact.d.ts +15 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +48 -0
- package/dist/utils/redact.js.map +1 -0
- 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
package/dist/config/defaults.js
CHANGED
|
@@ -29,7 +29,10 @@ export const DEFAULT_CONFIG = {
|
|
|
29
29
|
sandbox: {
|
|
30
30
|
maxMemoryMb: 128,
|
|
31
31
|
allowedNetHosts: ['localhost'],
|
|
32
|
-
|
|
32
|
+
// Bumped from 5 → 8 in v2.0.0-alpha.2 (X3 cleanup) per IBKR-side analysis
|
|
33
|
+
// finding #5. PRD Phase 4's worker pool further parameterises this with
|
|
34
|
+
// per-server overrides and warm-pool sizing.
|
|
35
|
+
maxConcurrentProcesses: 8,
|
|
33
36
|
maxOutputBytes: 10 * 1024 * 1024, // 10MB
|
|
34
37
|
},
|
|
35
38
|
skills: {
|
|
@@ -95,6 +98,8 @@ export const DEFAULT_CONDUCTOR_CONFIG = {
|
|
|
95
98
|
* - `STREAM_STUCK_TTL_MS` — `StreamManager` cleanup for hung running streams
|
|
96
99
|
* - `STREAM_CLEANUP_INTERVAL_MS` — `StreamManager` tick rate for the sweep
|
|
97
100
|
* - `MEMORY_LOG_INTERVAL_MS` — periodic heap/RSS log from the main entry point
|
|
101
|
+
* - `BRIDGE_SESSION_TTL_MS` — HTTP bridge session idle expiry (Mcp-Session-Id)
|
|
102
|
+
* - `BRIDGE_SESSION_CLEANUP_INTERVAL_MS` — sweep cadence for expired sessions
|
|
98
103
|
*/
|
|
99
104
|
export const LIFECYCLE_TIMEOUTS = {
|
|
100
105
|
SHUTDOWN_TIMEOUT_MS: 10_000,
|
|
@@ -104,5 +109,13 @@ export const LIFECYCLE_TIMEOUTS = {
|
|
|
104
109
|
STREAM_STUCK_TTL_MS: 15 * 60_000,
|
|
105
110
|
STREAM_CLEANUP_INTERVAL_MS: 60_000,
|
|
106
111
|
MEMORY_LOG_INTERVAL_MS: 60_000,
|
|
112
|
+
BRIDGE_SESSION_TTL_MS: 30 * 60_000,
|
|
113
|
+
BRIDGE_SESSION_CLEANUP_INTERVAL_MS: 5 * 60_000,
|
|
114
|
+
ORPHAN_CHECK_INTERVAL_MS: 10_000,
|
|
107
115
|
};
|
|
116
|
+
/**
|
|
117
|
+
* Cap on simultaneously tracked bridge sessions. Bounded to prevent the
|
|
118
|
+
* session registry from growing unbounded if a client keeps rotating IDs.
|
|
119
|
+
*/
|
|
120
|
+
export const MAX_BRIDGE_SESSIONS = 1000;
|
|
108
121
|
//# sourceMappingURL=defaults.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,EAAE,2DAA2D;QACpE,IAAI,EAAE,WAAW;KAClB;IACD,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,gBAAgB,EAAE,KAAK;QACvB,YAAY,EAAE,MAAM;QACpB,gBAAgB,EAAE,IAAI;KACvB;IACD,OAAO,EAAE;QACP,WAAW,EAAE,GAAG;QAChB,eAAe,EAAE,CAAC,WAAW,CAAC;QAC9B,sBAAsB,EAAE,CAAC;QACzB,cAAc,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO;KAC1C;IACD,MAAM,EAAE;QACN,IAAI,EAAE,IAAI;QACV,eAAe,EAAE,IAAI;KACtB;IACD,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,GAAG;KAChB;IACD,OAAO,EAAE;QACP,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,IAAI;KACd;IACD,OAAO,EAAE;QACP,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,QAAQ,EAAE,EAAE;KACb;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,sBAAsB;IAC/B,WAAW,EAAE,0BAA0B;IACvC,SAAS,EAAE,wBAAwB;IACnC,MAAM,EAAE,qBAAqB;IAC7B,aAAa,EAAE,4BAA4B;IAC3C,gBAAgB,EAAE,sBAAsB;IACxC,WAAW,EAAE,0BAA0B;IACvC,YAAY,EAAE,2BAA2B;IACzC,YAAY,EAAE,2BAA2B;IACzC,cAAc,EAAE,6BAA6B;IAC7C,eAAe,EAAE,8BAA8B;IAC/C,aAAa,EAAE,4BAA4B;CACnC,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,MAAM,EAAE;QACN,IAAI,EAAE,CAAC,EAAE,2DAA2D;QACpE,IAAI,EAAE,WAAW;KAClB;IACD,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,gBAAgB,EAAE,KAAK;QACvB,YAAY,EAAE,MAAM;QACpB,gBAAgB,EAAE,IAAI;KACvB;IACD,OAAO,EAAE;QACP,WAAW,EAAE,GAAG;QAChB,eAAe,EAAE,CAAC,WAAW,CAAC;QAC9B,0EAA0E;QAC1E,wEAAwE;QACxE,6CAA6C;QAC7C,sBAAsB,EAAE,CAAC;QACzB,cAAc,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO;KAC1C;IACD,MAAM,EAAE;QACN,IAAI,EAAE,IAAI;QACV,eAAe,EAAE,IAAI;KACtB;IACD,SAAS,EAAE;QACT,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,GAAG;KAChB;IACD,OAAO,EAAE;QACP,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,IAAI;KACd;IACD,OAAO,EAAE;QACP,SAAS,EAAE,CAAC,GAAG,CAAC;QAChB,QAAQ,EAAE,EAAE;KACb;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,mBAAmB;IACzB,OAAO,EAAE,sBAAsB;IAC/B,WAAW,EAAE,0BAA0B;IACvC,SAAS,EAAE,wBAAwB;IACnC,MAAM,EAAE,qBAAqB;IAC7B,aAAa,EAAE,4BAA4B;IAC3C,gBAAgB,EAAE,sBAAsB;IACxC,WAAW,EAAE,0BAA0B;IACvC,YAAY,EAAE,2BAA2B;IACzC,YAAY,EAAE,2BAA2B;IACzC,cAAc,EAAE,6BAA6B;IAC7C,eAAe,EAAE,8BAA8B;IAC/C,aAAa,EAAE,4BAA4B;CACnC,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,mBAAmB,EAAE,MAAM;IAC3B,qBAAqB,EAAE,KAAK;IAC5B,mBAAmB,EAAE,CAAC,GAAG,MAAM;IAC/B,uBAAuB,EAAE,EAAE,GAAG,MAAM;IACpC,mBAAmB,EAAE,EAAE,GAAG,MAAM;IAChC,0BAA0B,EAAE,MAAM;IAClC,sBAAsB,EAAE,MAAM;IAC9B,qBAAqB,EAAE,EAAE,GAAG,MAAM;IAClC,kCAAkC,EAAE,CAAC,GAAG,MAAM;IAC9C,wBAAwB,EAAE,MAAM;CACxB,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC"}
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -92,4 +92,38 @@ export interface ConductorConfig {
|
|
|
92
92
|
/** MCP servers that conductor will connect to internally */
|
|
93
93
|
servers: Record<string, ConductorServerConfig>;
|
|
94
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Connection pool configuration for persistent stdio connections to MCP
|
|
97
|
+
* backend servers. Reduces cold-start latency by keeping connections alive
|
|
98
|
+
* and multiplexing JSON-RPC requests over the same stdio channel.
|
|
99
|
+
*/
|
|
100
|
+
export interface ConnectionPoolConfig {
|
|
101
|
+
/** Minimum idle connections to keep per server (default: 1) */
|
|
102
|
+
minConnectionsPerServer?: number;
|
|
103
|
+
/** Maximum simultaneous connections per server (default: 4) */
|
|
104
|
+
maxConnectionsPerServer?: number;
|
|
105
|
+
/** Idle connection shutdown timeout in ms (default: 300000 = 5 min) */
|
|
106
|
+
idleTimeoutMs?: number;
|
|
107
|
+
/** Timeout for acquiring a connection from the pool (default: 5000) */
|
|
108
|
+
acquireTimeoutMs?: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Warm Deno worker pool configuration. Workers are pre-spawned at startup
|
|
112
|
+
* so the first execute_code call hits an already-warm sandbox.
|
|
113
|
+
*/
|
|
114
|
+
export interface WorkerPoolConfig {
|
|
115
|
+
/** Number of warm workers to maintain (default: 4) */
|
|
116
|
+
size?: number;
|
|
117
|
+
/** Recycle a worker after this many jobs (default: 100) */
|
|
118
|
+
maxJobsPerWorker?: number;
|
|
119
|
+
/** Recycle a worker after this many ms since spawn (default: 600000 = 10 min) */
|
|
120
|
+
maxAgeMs?: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Phase 4 runtime pool configuration block (nested under `runtime` in conductor config).
|
|
124
|
+
*/
|
|
125
|
+
export interface RuntimePoolConfig {
|
|
126
|
+
workerPool?: WorkerPoolConfig;
|
|
127
|
+
connectionPool?: ConnectionPoolConfig;
|
|
128
|
+
}
|
|
95
129
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAC1B,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC9B,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,kDAAkD;IAClD,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;CAChD"}
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Conductor Daemon Client.
|
|
3
|
+
*
|
|
4
|
+
* Thin agent-side bridge that connects to a running DaemonServer over a Unix
|
|
5
|
+
* socket or TCP and exposes a `callTool` interface compatible with the direct
|
|
6
|
+
* execution path. Authentication uses HMAC-SHA256 with the shared secret read
|
|
7
|
+
* from `~/.mcp-conductor/daemon-auth.json`.
|
|
8
|
+
*
|
|
9
|
+
* The sandbox `mcp.shared.*` API is built on top of this client.
|
|
10
|
+
*
|
|
11
|
+
* @module daemon/client
|
|
12
|
+
*/
|
|
13
|
+
import type { KVSetOptions } from './shared-kv.js';
|
|
14
|
+
export interface DaemonClientOptions {
|
|
15
|
+
/** Unix socket path. Defaults to `~/.mcp-conductor/daemon.sock`. */
|
|
16
|
+
socketPath?: string;
|
|
17
|
+
/**
|
|
18
|
+
* TCP address of the daemon when connecting over Tailscale.
|
|
19
|
+
* Format: `"host:port"` e.g. `"100.64.0.1:9876"`.
|
|
20
|
+
*/
|
|
21
|
+
tailscaleAddress?: string;
|
|
22
|
+
/** Auth configuration. */
|
|
23
|
+
auth?: {
|
|
24
|
+
sharedSecretPath?: string;
|
|
25
|
+
sharedSecret?: string;
|
|
26
|
+
};
|
|
27
|
+
/** Connection timeout in ms. Defaults to 5 000. */
|
|
28
|
+
connectTimeoutMs?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Client-side bridge to the daemon.
|
|
32
|
+
*
|
|
33
|
+
* Usage:
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const client = new DaemonClient();
|
|
36
|
+
* await client.connect();
|
|
37
|
+
* const result = await client.callTool('list_tools', {});
|
|
38
|
+
* await client.disconnect();
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare class DaemonClient {
|
|
42
|
+
private readonly socketPath;
|
|
43
|
+
private readonly tailscaleAddress?;
|
|
44
|
+
private readonly sharedSecret;
|
|
45
|
+
private readonly connectTimeoutMs;
|
|
46
|
+
private socket;
|
|
47
|
+
private connected;
|
|
48
|
+
private readonly pending;
|
|
49
|
+
private buffer;
|
|
50
|
+
private nextId;
|
|
51
|
+
constructor(options?: DaemonClientOptions);
|
|
52
|
+
/**
|
|
53
|
+
* Connect to the daemon and complete the auth handshake.
|
|
54
|
+
*/
|
|
55
|
+
connect(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Gracefully disconnect.
|
|
58
|
+
*/
|
|
59
|
+
disconnect(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Call an MCP tool via the daemon.
|
|
62
|
+
*/
|
|
63
|
+
callTool(name: string, args: unknown): Promise<unknown>;
|
|
64
|
+
/**
|
|
65
|
+
* Ping the daemon. Useful for health-checks.
|
|
66
|
+
*/
|
|
67
|
+
ping(): Promise<void>;
|
|
68
|
+
/** Retrieve daemon statistics. */
|
|
69
|
+
stats(): Promise<unknown>;
|
|
70
|
+
kvGet<T>(key: string): Promise<T | null>;
|
|
71
|
+
kvSet<T>(key: string, value: T, options?: KVSetOptions): Promise<void>;
|
|
72
|
+
kvDelete(key: string): Promise<void>;
|
|
73
|
+
kvList(prefix?: string): Promise<string[]>;
|
|
74
|
+
lockAcquire(key: string, options?: {
|
|
75
|
+
timeoutMs?: number;
|
|
76
|
+
}): Promise<{
|
|
77
|
+
release: () => Promise<void>;
|
|
78
|
+
}>;
|
|
79
|
+
broadcast(channel: string, message: unknown): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Subscribe to a channel. The handler is invoked for each push event
|
|
82
|
+
* received from the daemon. Returns an object with `unsubscribe()`.
|
|
83
|
+
*/
|
|
84
|
+
subscribe(channel: string, handler: (msg: unknown) => void): {
|
|
85
|
+
unsubscribe: () => void;
|
|
86
|
+
};
|
|
87
|
+
private readonly pushListeners;
|
|
88
|
+
private loadSecret;
|
|
89
|
+
private openSocket;
|
|
90
|
+
private authenticate;
|
|
91
|
+
private waitForMessage;
|
|
92
|
+
private rpc;
|
|
93
|
+
private onData;
|
|
94
|
+
private handleResponse;
|
|
95
|
+
private rejectAllPending;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/daemon/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAkCnD,MAAM,WAAW,mBAAmB;IAClC,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0BAA0B;IAC1B,IAAI,CAAC,EAAE;QACL,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,GAAE,mBAAwB;IAiB7C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBjC;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,kCAAkC;IAC5B,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAQzB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAIxC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ1C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IAarG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG;QAAE,WAAW,EAAE,MAAM,IAAI,CAAA;KAAE;IAiBxF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IAMnE,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,UAAU;YA4BJ,YAAY;IAU1B,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,GAAG;IAoBX,OAAO,CAAC,MAAM;IAiBd,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,gBAAgB;CAMzB"}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Conductor Daemon Client.
|
|
3
|
+
*
|
|
4
|
+
* Thin agent-side bridge that connects to a running DaemonServer over a Unix
|
|
5
|
+
* socket or TCP and exposes a `callTool` interface compatible with the direct
|
|
6
|
+
* execution path. Authentication uses HMAC-SHA256 with the shared secret read
|
|
7
|
+
* from `~/.mcp-conductor/daemon-auth.json`.
|
|
8
|
+
*
|
|
9
|
+
* The sandbox `mcp.shared.*` API is built on top of this client.
|
|
10
|
+
*
|
|
11
|
+
* @module daemon/client
|
|
12
|
+
*/
|
|
13
|
+
import { createConnection } from 'node:net';
|
|
14
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { homedir } from 'node:os';
|
|
17
|
+
import { createHmac } from 'node:crypto';
|
|
18
|
+
import { logger } from '../utils/logger.js';
|
|
19
|
+
const DEFAULT_SOCKET_PATH = join(homedir(), '.mcp-conductor', 'daemon.sock');
|
|
20
|
+
const DEFAULT_AUTH_PATH = join(homedir(), '.mcp-conductor', 'daemon-auth.json');
|
|
21
|
+
/**
|
|
22
|
+
* Client-side bridge to the daemon.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const client = new DaemonClient();
|
|
27
|
+
* await client.connect();
|
|
28
|
+
* const result = await client.callTool('list_tools', {});
|
|
29
|
+
* await client.disconnect();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export class DaemonClient {
|
|
33
|
+
socketPath;
|
|
34
|
+
tailscaleAddress;
|
|
35
|
+
sharedSecret;
|
|
36
|
+
connectTimeoutMs;
|
|
37
|
+
socket = null;
|
|
38
|
+
connected = false;
|
|
39
|
+
pending = new Map();
|
|
40
|
+
buffer = '';
|
|
41
|
+
nextId = 1;
|
|
42
|
+
constructor(options = {}) {
|
|
43
|
+
this.socketPath = options.socketPath ?? DEFAULT_SOCKET_PATH;
|
|
44
|
+
this.tailscaleAddress = options.tailscaleAddress;
|
|
45
|
+
this.connectTimeoutMs = options.connectTimeoutMs ?? 5_000;
|
|
46
|
+
const authPath = options.auth?.sharedSecretPath ?? DEFAULT_AUTH_PATH;
|
|
47
|
+
if (options.auth?.sharedSecret) {
|
|
48
|
+
this.sharedSecret = options.auth.sharedSecret;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.sharedSecret = this.loadSecret(authPath);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Lifecycle
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Connect to the daemon and complete the auth handshake.
|
|
59
|
+
*/
|
|
60
|
+
async connect() {
|
|
61
|
+
if (this.connected)
|
|
62
|
+
return;
|
|
63
|
+
const socket = await this.openSocket();
|
|
64
|
+
this.socket = socket;
|
|
65
|
+
socket.setEncoding('utf-8');
|
|
66
|
+
socket.on('data', (chunk) => this.onData(chunk));
|
|
67
|
+
socket.on('close', () => {
|
|
68
|
+
this.connected = false;
|
|
69
|
+
this.rejectAllPending(new Error('DaemonClient: connection closed'));
|
|
70
|
+
});
|
|
71
|
+
socket.on('error', (err) => {
|
|
72
|
+
logger.debug('DaemonClient: socket error', { error: String(err) });
|
|
73
|
+
this.rejectAllPending(err);
|
|
74
|
+
});
|
|
75
|
+
// Complete challenge-response auth.
|
|
76
|
+
await this.authenticate();
|
|
77
|
+
this.connected = true;
|
|
78
|
+
logger.debug('DaemonClient: connected and authenticated');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Gracefully disconnect.
|
|
82
|
+
*/
|
|
83
|
+
async disconnect() {
|
|
84
|
+
this.connected = false;
|
|
85
|
+
if (this.socket && !this.socket.destroyed) {
|
|
86
|
+
this.socket.end();
|
|
87
|
+
await new Promise((resolve) => {
|
|
88
|
+
this.socket.once('close', resolve);
|
|
89
|
+
setTimeout(resolve, 1000);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
this.socket = null;
|
|
93
|
+
logger.debug('DaemonClient: disconnected');
|
|
94
|
+
}
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Public RPC surface
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
/**
|
|
99
|
+
* Call an MCP tool via the daemon.
|
|
100
|
+
*/
|
|
101
|
+
async callTool(name, args) {
|
|
102
|
+
return this.rpc('tool.call', { name, args });
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Ping the daemon. Useful for health-checks.
|
|
106
|
+
*/
|
|
107
|
+
async ping() {
|
|
108
|
+
await this.rpc('ping', {});
|
|
109
|
+
}
|
|
110
|
+
/** Retrieve daemon statistics. */
|
|
111
|
+
async stats() {
|
|
112
|
+
return this.rpc('stats', {});
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Shared KV API
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
async kvGet(key) {
|
|
118
|
+
return this.rpc('kv.get', { key });
|
|
119
|
+
}
|
|
120
|
+
async kvSet(key, value, options) {
|
|
121
|
+
await this.rpc('kv.set', { key, value, options });
|
|
122
|
+
}
|
|
123
|
+
async kvDelete(key) {
|
|
124
|
+
await this.rpc('kv.delete', { key });
|
|
125
|
+
}
|
|
126
|
+
async kvList(prefix) {
|
|
127
|
+
return this.rpc('kv.list', { prefix });
|
|
128
|
+
}
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
// Shared lock API
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
async lockAcquire(key, options) {
|
|
133
|
+
await this.rpc('lock.acquire', { key, timeoutMs: options?.timeoutMs });
|
|
134
|
+
return {
|
|
135
|
+
release: async () => {
|
|
136
|
+
await this.rpc('lock.release', { key });
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
// Pub/sub API
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
async broadcast(channel, message) {
|
|
144
|
+
await this.rpc('broadcast', { channel, message });
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Subscribe to a channel. The handler is invoked for each push event
|
|
148
|
+
* received from the daemon. Returns an object with `unsubscribe()`.
|
|
149
|
+
*/
|
|
150
|
+
subscribe(channel, handler) {
|
|
151
|
+
const listener = (msg) => {
|
|
152
|
+
const push = msg;
|
|
153
|
+
if (push.channel === channel) {
|
|
154
|
+
handler(push.message);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
this.pushListeners.add(listener);
|
|
158
|
+
// Best-effort fire-and-forget notification to the server.
|
|
159
|
+
this.rpc('subscribe', { channel }).catch(() => { });
|
|
160
|
+
return {
|
|
161
|
+
unsubscribe: () => {
|
|
162
|
+
this.pushListeners.delete(listener);
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
pushListeners = new Set();
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Private helpers
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
loadSecret(authPath) {
|
|
171
|
+
if (!existsSync(authPath)) {
|
|
172
|
+
throw new Error(`DaemonClient: auth file not found at ${authPath}. ` +
|
|
173
|
+
'Start the daemon first with `mcp-conductor-cli daemon start`.');
|
|
174
|
+
}
|
|
175
|
+
const raw = readFileSync(authPath, 'utf-8');
|
|
176
|
+
return JSON.parse(raw).sharedSecret;
|
|
177
|
+
}
|
|
178
|
+
openSocket() {
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
let socket;
|
|
181
|
+
const timer = setTimeout(() => {
|
|
182
|
+
socket?.destroy();
|
|
183
|
+
reject(new Error(`DaemonClient: connection timed out after ${this.connectTimeoutMs}ms`));
|
|
184
|
+
}, this.connectTimeoutMs);
|
|
185
|
+
if (this.tailscaleAddress) {
|
|
186
|
+
const [host, portStr] = this.tailscaleAddress.split(':');
|
|
187
|
+
const port = parseInt(portStr ?? '9876', 10);
|
|
188
|
+
socket = createConnection({ host, port });
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
socket = createConnection({ path: this.socketPath });
|
|
192
|
+
}
|
|
193
|
+
socket.once('connect', () => {
|
|
194
|
+
clearTimeout(timer);
|
|
195
|
+
resolve(socket);
|
|
196
|
+
});
|
|
197
|
+
socket.once('error', (err) => {
|
|
198
|
+
clearTimeout(timer);
|
|
199
|
+
reject(err);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
async authenticate() {
|
|
204
|
+
// Wait for the challenge from the server.
|
|
205
|
+
const challenge = await this.waitForMessage('__auth_challenge__');
|
|
206
|
+
const nonce = challenge.nonce;
|
|
207
|
+
// Compute HMAC token and send auth response.
|
|
208
|
+
const token = createHmac('sha256', this.sharedSecret).update(nonce).digest('hex');
|
|
209
|
+
await this.rpc('__auth__', { token });
|
|
210
|
+
}
|
|
211
|
+
waitForMessage(id) {
|
|
212
|
+
return new Promise((resolve, reject) => {
|
|
213
|
+
this.pending.set(id, { resolve, reject });
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
rpc(method, params) {
|
|
217
|
+
return new Promise((resolve, reject) => {
|
|
218
|
+
if (!this.socket || this.socket.destroyed) {
|
|
219
|
+
reject(new Error('DaemonClient: not connected'));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const id = String(this.nextId++);
|
|
223
|
+
this.pending.set(id, { resolve, reject });
|
|
224
|
+
const msg = { id, method, params };
|
|
225
|
+
try {
|
|
226
|
+
this.socket.write(JSON.stringify(msg) + '\n');
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
this.pending.delete(id);
|
|
230
|
+
reject(err);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
onData(chunk) {
|
|
235
|
+
this.buffer += chunk;
|
|
236
|
+
const lines = this.buffer.split('\n');
|
|
237
|
+
this.buffer = lines.pop() ?? '';
|
|
238
|
+
for (const line of lines) {
|
|
239
|
+
const trimmed = line.trim();
|
|
240
|
+
if (!trimmed)
|
|
241
|
+
continue;
|
|
242
|
+
try {
|
|
243
|
+
const msg = JSON.parse(trimmed);
|
|
244
|
+
this.handleResponse(msg);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
logger.warn('DaemonClient: malformed JSON from server');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
handleResponse(msg) {
|
|
252
|
+
// Push events (id === '__push__') are delivered to pub/sub listeners.
|
|
253
|
+
if (msg.id === '__push__') {
|
|
254
|
+
for (const listener of this.pushListeners) {
|
|
255
|
+
listener(msg.result);
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const call = this.pending.get(msg.id);
|
|
260
|
+
if (!call) {
|
|
261
|
+
logger.warn('DaemonClient: received response for unknown id', { id: msg.id });
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
this.pending.delete(msg.id);
|
|
265
|
+
if (msg.error) {
|
|
266
|
+
call.reject(new Error(`RPC error ${msg.error.code}: ${msg.error.message}`));
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
call.resolve(msg.result);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
rejectAllPending(err) {
|
|
273
|
+
for (const [id, call] of this.pending) {
|
|
274
|
+
this.pending.delete(id);
|
|
275
|
+
call.reject(err);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/daemon/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tailscale Peer Discovery for MCP Conductor Daemon.
|
|
3
|
+
*
|
|
4
|
+
* Provides helpers to resolve a daemon's address on the Tailscale mesh by
|
|
5
|
+
* hostname. The implementation queries the local Tailscale CLI (`tailscale
|
|
6
|
+
* status --json`) which must already be authenticated. No additional Tailscale
|
|
7
|
+
* API token is required — this works entirely through the local socket that
|
|
8
|
+
* the Tailscale daemon exposes.
|
|
9
|
+
*
|
|
10
|
+
* Cross-daemon mesh locking is deferred to v3.1; this module's v3.0 role is:
|
|
11
|
+
* 1. Resolve a Tailscale hostname → IP so DaemonClient can connect via TCP.
|
|
12
|
+
* 2. Detect whether Tailscale is available at all (graceful fallback to Unix
|
|
13
|
+
* socket when Tailscale is absent).
|
|
14
|
+
*
|
|
15
|
+
* @module daemon/discovery
|
|
16
|
+
*/
|
|
17
|
+
export interface TailscalePeer {
|
|
18
|
+
hostname: string;
|
|
19
|
+
tailscaleIp: string;
|
|
20
|
+
online: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface TailscaleStatus {
|
|
23
|
+
available: boolean;
|
|
24
|
+
selfHostname?: string;
|
|
25
|
+
selfIp?: string;
|
|
26
|
+
peers: TailscalePeer[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolves daemon addresses on the Tailscale mesh by querying the local
|
|
30
|
+
* Tailscale CLI.
|
|
31
|
+
*/
|
|
32
|
+
export declare class TailscaleDiscovery {
|
|
33
|
+
private readonly tailscaleBin;
|
|
34
|
+
private readonly cacheTtlMs;
|
|
35
|
+
private cache;
|
|
36
|
+
/**
|
|
37
|
+
* Internal CLI runner — override in tests via `vi.spyOn(instance, '_runCli')`.
|
|
38
|
+
*/
|
|
39
|
+
_runCli: (bin: string) => Promise<string>;
|
|
40
|
+
constructor(options?: {
|
|
41
|
+
tailscaleBin?: string;
|
|
42
|
+
cacheTtlMs?: number;
|
|
43
|
+
});
|
|
44
|
+
status(): Promise<TailscaleStatus>;
|
|
45
|
+
resolve(hostname: string): Promise<string | null>;
|
|
46
|
+
isAvailable(): Promise<boolean>;
|
|
47
|
+
invalidateCache(): void;
|
|
48
|
+
private queryTailscaleCli;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/daemon/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AA4BD;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,KAAK,CAA+D;IAE5E;;OAEG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE9B,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO;IAMlE,MAAM,IAAI,OAAO,CAAC,eAAe,CAAC;IAUlC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAcjD,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAKrC,eAAe,IAAI,IAAI;YAIT,iBAAiB;CA4BhC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tailscale Peer Discovery for MCP Conductor Daemon.
|
|
3
|
+
*
|
|
4
|
+
* Provides helpers to resolve a daemon's address on the Tailscale mesh by
|
|
5
|
+
* hostname. The implementation queries the local Tailscale CLI (`tailscale
|
|
6
|
+
* status --json`) which must already be authenticated. No additional Tailscale
|
|
7
|
+
* API token is required — this works entirely through the local socket that
|
|
8
|
+
* the Tailscale daemon exposes.
|
|
9
|
+
*
|
|
10
|
+
* Cross-daemon mesh locking is deferred to v3.1; this module's v3.0 role is:
|
|
11
|
+
* 1. Resolve a Tailscale hostname → IP so DaemonClient can connect via TCP.
|
|
12
|
+
* 2. Detect whether Tailscale is available at all (graceful fallback to Unix
|
|
13
|
+
* socket when Tailscale is absent).
|
|
14
|
+
*
|
|
15
|
+
* @module daemon/discovery
|
|
16
|
+
*/
|
|
17
|
+
import { execFile } from 'node:child_process';
|
|
18
|
+
import { logger } from '../utils/logger.js';
|
|
19
|
+
/**
|
|
20
|
+
* Runs the Tailscale CLI and returns its JSON output.
|
|
21
|
+
* Extracted so tests can override via `vi.spyOn(discovery, '_runCli')`.
|
|
22
|
+
*/
|
|
23
|
+
async function runTailscaleCli(bin) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
execFile(bin, ['status', '--json'], { timeout: 5000 }, (err, stdout) => {
|
|
26
|
+
if (err)
|
|
27
|
+
reject(err);
|
|
28
|
+
else
|
|
29
|
+
resolve(stdout);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolves daemon addresses on the Tailscale mesh by querying the local
|
|
35
|
+
* Tailscale CLI.
|
|
36
|
+
*/
|
|
37
|
+
export class TailscaleDiscovery {
|
|
38
|
+
tailscaleBin;
|
|
39
|
+
cacheTtlMs;
|
|
40
|
+
cache = null;
|
|
41
|
+
/**
|
|
42
|
+
* Internal CLI runner — override in tests via `vi.spyOn(instance, '_runCli')`.
|
|
43
|
+
*/
|
|
44
|
+
_runCli;
|
|
45
|
+
constructor(options = {}) {
|
|
46
|
+
this.tailscaleBin = options.tailscaleBin ?? 'tailscale';
|
|
47
|
+
this.cacheTtlMs = options.cacheTtlMs ?? 10_000;
|
|
48
|
+
this._runCli = runTailscaleCli;
|
|
49
|
+
}
|
|
50
|
+
async status() {
|
|
51
|
+
if (this.cache && Date.now() < this.cache.expiresAt) {
|
|
52
|
+
return this.cache.status;
|
|
53
|
+
}
|
|
54
|
+
const result = await this.queryTailscaleCli();
|
|
55
|
+
this.cache = { expiresAt: Date.now() + this.cacheTtlMs, status: result };
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
async resolve(hostname) {
|
|
59
|
+
const st = await this.status();
|
|
60
|
+
if (!st.available)
|
|
61
|
+
return null;
|
|
62
|
+
if (st.selfHostname?.toLowerCase() === hostname.toLowerCase()) {
|
|
63
|
+
return st.selfIp ?? null;
|
|
64
|
+
}
|
|
65
|
+
const peer = st.peers.find((p) => p.hostname.toLowerCase() === hostname.toLowerCase());
|
|
66
|
+
return peer?.tailscaleIp ?? null;
|
|
67
|
+
}
|
|
68
|
+
async isAvailable() {
|
|
69
|
+
const st = await this.status();
|
|
70
|
+
return st.available;
|
|
71
|
+
}
|
|
72
|
+
invalidateCache() {
|
|
73
|
+
this.cache = null;
|
|
74
|
+
}
|
|
75
|
+
async queryTailscaleCli() {
|
|
76
|
+
try {
|
|
77
|
+
const stdout = await this._runCli(this.tailscaleBin);
|
|
78
|
+
const raw = JSON.parse(stdout);
|
|
79
|
+
const self = raw.Self;
|
|
80
|
+
const peers = [];
|
|
81
|
+
for (const peer of Object.values(raw.Peer ?? {})) {
|
|
82
|
+
const ip = peer.TailscaleIPs?.[0];
|
|
83
|
+
if (!ip || !peer.HostName)
|
|
84
|
+
continue;
|
|
85
|
+
peers.push({
|
|
86
|
+
hostname: peer.HostName,
|
|
87
|
+
tailscaleIp: ip,
|
|
88
|
+
online: peer.Online ?? false,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
available: true,
|
|
93
|
+
selfHostname: self?.HostName,
|
|
94
|
+
selfIp: self?.TailscaleIPs?.[0],
|
|
95
|
+
peers,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
logger.debug('TailscaleDiscovery: Tailscale CLI unavailable', { error: String(err) });
|
|
100
|
+
return { available: false, peers: [] };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/daemon/discovery.ts"],"names":[],"mappings":"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"}
|