mcp-coordinator 0.2.1 → 0.4.0

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.
Files changed (60) hide show
  1. package/README.md +846 -846
  2. package/dashboard/Dockerfile +19 -19
  3. package/dashboard/public/index.html +1178 -1178
  4. package/dist/cli/dashboard.js +9 -5
  5. package/dist/cli/server/backup.d.ts +7 -0
  6. package/dist/cli/server/backup.js +162 -0
  7. package/dist/cli/server/index.js +5 -0
  8. package/dist/cli/server/restore.d.ts +2 -0
  9. package/dist/cli/server/restore.js +117 -0
  10. package/dist/cli/server/start.js +24 -1
  11. package/dist/cli/server/status.js +16 -23
  12. package/dist/src/agent-activity.js +6 -6
  13. package/dist/src/agent-registry.js +6 -6
  14. package/dist/src/announce-workflow.d.ts +52 -0
  15. package/dist/src/announce-workflow.js +91 -0
  16. package/dist/src/consultation.d.ts +22 -0
  17. package/dist/src/consultation.js +118 -45
  18. package/dist/src/database.js +126 -126
  19. package/dist/src/db-adapter.d.ts +30 -0
  20. package/dist/src/db-adapter.js +32 -1
  21. package/dist/src/dependency-map.js +5 -5
  22. package/dist/src/file-tracker.d.ts +10 -0
  23. package/dist/src/file-tracker.js +40 -8
  24. package/dist/src/http/handle-health.d.ts +23 -0
  25. package/dist/src/http/handle-health.js +86 -0
  26. package/dist/src/http/handle-rest.d.ts +23 -0
  27. package/dist/src/http/handle-rest.js +374 -0
  28. package/dist/src/http/utils.d.ts +15 -0
  29. package/dist/src/http/utils.js +39 -0
  30. package/dist/src/impact-scorer.js +87 -50
  31. package/dist/src/introspection.js +1 -1
  32. package/dist/src/metrics.d.ts +83 -0
  33. package/dist/src/metrics.js +162 -0
  34. package/dist/src/mqtt-bridge.d.ts +21 -0
  35. package/dist/src/mqtt-bridge.js +55 -5
  36. package/dist/src/mqtt-broker.d.ts +16 -0
  37. package/dist/src/mqtt-broker.js +16 -1
  38. package/dist/src/path-guard.d.ts +14 -0
  39. package/dist/src/path-guard.js +44 -0
  40. package/dist/src/reset-guard.d.ts +16 -0
  41. package/dist/src/reset-guard.js +24 -0
  42. package/dist/src/serve-http.d.ts +31 -1
  43. package/dist/src/serve-http.js +189 -446
  44. package/dist/src/server-setup.d.ts +2 -0
  45. package/dist/src/server-setup.js +25 -366
  46. package/dist/src/sse-emitter.d.ts +6 -0
  47. package/dist/src/sse-emitter.js +50 -2
  48. package/dist/src/tools/agents-tools.d.ts +8 -0
  49. package/dist/src/tools/agents-tools.js +46 -0
  50. package/dist/src/tools/consultation-tools.d.ts +21 -0
  51. package/dist/src/tools/consultation-tools.js +170 -0
  52. package/dist/src/tools/dependencies-tools.d.ts +8 -0
  53. package/dist/src/tools/dependencies-tools.js +27 -0
  54. package/dist/src/tools/files-tools.d.ts +8 -0
  55. package/dist/src/tools/files-tools.js +28 -0
  56. package/dist/src/tools/mqtt-tools.d.ts +9 -0
  57. package/dist/src/tools/mqtt-tools.js +33 -0
  58. package/dist/src/tools/status-tools.d.ts +8 -0
  59. package/dist/src/tools/status-tools.js +63 -0
  60. package/package.json +83 -80
@@ -0,0 +1,44 @@
1
+ import path from "path";
2
+ /**
3
+ * Resolve a request URL into a safe filesystem path within a known root.
4
+ *
5
+ * Defends against path traversal: a request like `/dashboard/../../etc/passwd`
6
+ * would otherwise escape the dashboard directory because `path.join` does not
7
+ * validate that the result stays under the root.
8
+ *
9
+ * Returns the resolved absolute path on success, or `null` if the path would
10
+ * escape the root, contains a null byte, or is otherwise invalid.
11
+ *
12
+ * `urlPath` should already have the route prefix stripped (e.g. for
13
+ * `/dashboard/app.js` pass `"app.js"`).
14
+ */
15
+ export function safeJoinUnderRoot(root, urlPath) {
16
+ // Reject null bytes (NUL injection that some libs/OS handle inconsistently).
17
+ if (urlPath.includes("\0"))
18
+ return null;
19
+ // Decode percent-encoding so "%2e%2e/foo" cannot bypass the literal ".." check.
20
+ // decodeURIComponent throws on malformed sequences — treat as invalid.
21
+ let decoded;
22
+ try {
23
+ decoded = decodeURIComponent(urlPath);
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ if (decoded.includes("\0"))
29
+ return null;
30
+ // Strip leading slashes so absolute-path injection ("//etc/passwd") becomes relative.
31
+ const trimmed = decoded.replace(/^[/\\]+/, "");
32
+ // Empty after strip → caller decides what default file to serve.
33
+ if (trimmed === "")
34
+ return null;
35
+ const rootResolved = path.resolve(root);
36
+ const candidate = path.resolve(rootResolved, trimmed);
37
+ // The resolved candidate MUST be either equal to the root or live below it.
38
+ // Append separator before comparison to avoid the "/var/data" vs "/var/data-evil" trap.
39
+ const rootWithSep = rootResolved.endsWith(path.sep) ? rootResolved : rootResolved + path.sep;
40
+ if (candidate !== rootResolved && !candidate.startsWith(rootWithSep)) {
41
+ return null;
42
+ }
43
+ return candidate;
44
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Guard for the destructive `/api/reset` endpoint.
3
+ *
4
+ * `/api/reset` wipes every coordination table. When `COORDINATOR_AUTH_ENABLED`
5
+ * is on, the upstream auth middleware enforces admin-role tokens for this route
6
+ * (see `auth.ts` `ADMIN_ONLY_ROUTES`). When auth is OFF (the default), we still
7
+ * need to prevent accidental data loss in production.
8
+ *
9
+ * Allowed when ANY of:
10
+ * - NODE_ENV === "test" (vitest sets this automatically)
11
+ * - COORDINATOR_ALLOW_RESET=true (explicit opt-in for dev/CI scripts)
12
+ * - authEnabled === true (handled by the auth middleware upstream)
13
+ *
14
+ * Otherwise rejected.
15
+ */
16
+ export declare function canResetDb(env: NodeJS.ProcessEnv, authEnabled: boolean): boolean;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Guard for the destructive `/api/reset` endpoint.
3
+ *
4
+ * `/api/reset` wipes every coordination table. When `COORDINATOR_AUTH_ENABLED`
5
+ * is on, the upstream auth middleware enforces admin-role tokens for this route
6
+ * (see `auth.ts` `ADMIN_ONLY_ROUTES`). When auth is OFF (the default), we still
7
+ * need to prevent accidental data loss in production.
8
+ *
9
+ * Allowed when ANY of:
10
+ * - NODE_ENV === "test" (vitest sets this automatically)
11
+ * - COORDINATOR_ALLOW_RESET=true (explicit opt-in for dev/CI scripts)
12
+ * - authEnabled === true (handled by the auth middleware upstream)
13
+ *
14
+ * Otherwise rejected.
15
+ */
16
+ export function canResetDb(env, authEnabled) {
17
+ if (authEnabled)
18
+ return true;
19
+ if (env.NODE_ENV === "test")
20
+ return true;
21
+ if (env.COORDINATOR_ALLOW_RESET === "true")
22
+ return true;
23
+ return false;
24
+ }
@@ -1,5 +1,35 @@
1
1
  export interface ServerOptions {
2
2
  port?: number;
3
3
  dataDir?: string;
4
+ /**
5
+ * MQTT TCP listener port. Defaults to COORDINATOR_MQTT_TCP_PORT env or 1883.
6
+ * Pass an OS-ephemeral free port (see net.createServer().listen(0)) to run
7
+ * multiple coordinators in the same process without collision.
8
+ */
9
+ mqttTcpPort?: number;
10
+ /**
11
+ * MQTT WebSocket path on the HTTP server. Defaults to COORDINATOR_MQTT_WS_PATH or "/mqtt".
12
+ */
13
+ mqttWsPath?: string;
14
+ /**
15
+ * If false, do NOT register process-level SIGTERM/SIGINT handlers. Default
16
+ * true. Embedders that manage their own signals (essaim's orchestrator runs
17
+ * many in-process coordinators per session) should pass false and call
18
+ * `handle.stop()` from their own teardown.
19
+ */
20
+ registerSignalHandlers?: boolean;
4
21
  }
5
- export declare function startServer(opts?: ServerOptions): Promise<void>;
22
+ /**
23
+ * Returned by startServer(). Lets callers shut down all owned resources
24
+ * (HTTP server, MQTT broker + bridge, SSE listeners, DB, quota timer) without
25
+ * waiting for process exit. Safe to call multiple times.
26
+ *
27
+ * Backward-compatible: previous callers used `await startServer({...})` and
28
+ * ignored the resolved value. They continue to work; the new return value is
29
+ * additive.
30
+ */
31
+ export interface ServerHandle {
32
+ port: number;
33
+ stop: () => Promise<void>;
34
+ }
35
+ export declare function startServer(opts?: ServerOptions): Promise<ServerHandle>;