@heretyc/subagent-mcp 2.6.0 → 2.6.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.
@@ -1,2 +1,2 @@
1
1
  // GENERATED by scripts/gen-ruleset-scaffold.mjs from src/advanced-ruleset.py — DO NOT EDIT.
2
- export const RULESET_SCAFFOLD = "#!/usr/bin/env python3\r\n\"\"\"advanced-ruleset.py — final-authority model-routing override hook for subagent-mcp.\r\n\r\n(a) PERFORMANCE WARNING: this script runs synchronously inside EVERY launch_agent\r\n call. Slow rules slow every agent launch. Keep rules lean and low-latency —\r\n no network calls, no heavy imports at module top. This is YOUR responsibility;\r\n you have been warned.\r\n\r\n(b) OUTPUT CONTRACT (routing mode): print to stdout ONE JSON array — the modified\r\n candidate list (reorder / filter / replace allowed). Template:\r\n [\r\n {\"provider\": \"claude\", \"model\": \"sonnet\", \"effort\": \"high\", \"rank\": 1},\r\n {\"provider\": \"codex\", \"model\": \"gpt-5.5\", \"effort\": \"xhigh\", \"rank\": 2}\r\n ]\r\n Valid providers: claude, codex. Valid models: haiku, sonnet, opus, opus-4-8 (claude);\r\n gpt-5.5 (codex). Valid efforts: haiku -> \"none\" only; sonnet -> low|medium|high|xhigh|max;\r\n opus/opus-4-8 -> those plus ultracode; gpt-5.5 -> low|medium|high|xhigh.\r\n \"rank\" on output is ignored. An EMPTY array vetoes the launch. Anything else\r\n invalid fails the launch hard — the server validates strictly.\r\n\r\n(c) INPUT CONTRACT (routing mode, invoked as: <python> advanced-ruleset.py route):\r\n stdin receives one JSON object:\r\n { \"candidates\": [ {\"provider\",\"model\",\"effort\",\"rank\"} ... ], # rank 1..N best->worst\r\n \"context\": { \"task_category\": str, \"cwd\": str,\r\n \"selection_mode\": \"auto\"|\"provider\"|\"provider_model\"|\"explicit\",\r\n \"provider\": str|None, \"model\": str|None, \"effort\": str|None } }\r\n OS environment variables are visible natively (os.environ).\r\n\r\nENV-CHECK MODE (no arguments): prints {\"ready\": true|false, \"load-rules\": true|false}.\r\nRuns once per MCP server process. load-rules false => ruleset silently disabled\r\nfor the rest of the process. Set LOAD_RULES = True below to activate.\r\n\"\"\"\r\nimport json\r\nimport sys\r\n\r\nLOAD_RULES = False\r\n\r\n# --- Requirements stub (scaffold itself is stdlib-only) ----------------------\r\n# List third-party distributions your rules import, e.g.:\r\n# REQUIREMENTS = [\"requests\", \"pyyaml\"]\r\n# Install with: <python> -m pip install <name> ...\r\nREQUIREMENTS = []\r\n\r\ndef missing_requirements():\r\n \"\"\"pip-check helper: returns the REQUIREMENTS entries not importable here.\"\"\"\r\n import importlib.util\r\n return [r for r in REQUIREMENTS\r\n if importlib.util.find_spec(r.replace(\"-\", \"_\")) is None]\r\n\r\ndef env_check():\r\n missing = missing_requirements()\r\n json.dump({\"ready\": not missing, \"load-rules\": bool(LOAD_RULES)}, sys.stdout)\r\n\r\ndef apply_rules(candidates, context):\r\n \"\"\"YOUR RULES HERE. Default: passthrough (returns the list unchanged).\"\"\"\r\n return candidates\r\n\r\ndef route():\r\n payload = json.load(sys.stdin)\r\n out = apply_rules(payload.get(\"candidates\", []), payload.get(\"context\", {}))\r\n json.dump(out, sys.stdout)\r\n\r\nif __name__ == \"__main__\":\r\n if len(sys.argv) > 1 and sys.argv[1] == \"route\":\r\n route()\r\n else:\r\n env_check()\r\n";
2
+ export const RULESET_SCAFFOLD = "#!/usr/bin/env python3\n\"\"\"advanced-ruleset.py — final-authority model-routing override hook for subagent-mcp.\n\n(a) PERFORMANCE WARNING: this script runs synchronously inside EVERY launch_agent\n call. Slow rules slow every agent launch. Keep rules lean and low-latency —\n no network calls, no heavy imports at module top. This is YOUR responsibility;\n you have been warned.\n\n(b) OUTPUT CONTRACT (routing mode): print to stdout ONE JSON array — the modified\n candidate list (reorder / filter / replace allowed). Template:\n [\n {\"provider\": \"claude\", \"model\": \"sonnet\", \"effort\": \"high\", \"rank\": 1},\n {\"provider\": \"codex\", \"model\": \"gpt-5.5\", \"effort\": \"xhigh\", \"rank\": 2}\n ]\n Valid providers: claude, codex. Valid models: haiku, sonnet, opus, opus-4-8 (claude);\n gpt-5.5 (codex). Valid efforts: haiku -> \"none\" only; sonnet -> low|medium|high|xhigh|max;\n opus/opus-4-8 -> those plus ultracode; gpt-5.5 -> low|medium|high|xhigh.\n \"rank\" on output is ignored. An EMPTY array vetoes the launch. Anything else\n invalid fails the launch hard — the server validates strictly.\n\n(c) INPUT CONTRACT (routing mode, invoked as: <python> advanced-ruleset.py route):\n stdin receives one JSON object:\n { \"candidates\": [ {\"provider\",\"model\",\"effort\",\"rank\"} ... ], # rank 1..N best->worst\n \"context\": { \"task_category\": str, \"cwd\": str,\n \"selection_mode\": \"auto\"|\"provider\"|\"provider_model\"|\"explicit\",\n \"provider\": str|None, \"model\": str|None, \"effort\": str|None } }\n OS environment variables are visible natively (os.environ).\n\nENV-CHECK MODE (no arguments): prints {\"ready\": true|false, \"load-rules\": true|false}.\nRuns once per MCP server process. load-rules false => ruleset silently disabled\nfor the rest of the process. Set LOAD_RULES = True below to activate.\n\"\"\"\nimport json\nimport sys\n\nLOAD_RULES = False\n\n# --- Requirements stub (scaffold itself is stdlib-only) ----------------------\n# List third-party distributions your rules import, e.g.:\n# REQUIREMENTS = [\"requests\", \"pyyaml\"]\n# Install with: <python> -m pip install <name> ...\nREQUIREMENTS = []\n\ndef missing_requirements():\n \"\"\"pip-check helper: returns the REQUIREMENTS entries not importable here.\"\"\"\n import importlib.util\n return [r for r in REQUIREMENTS\n if importlib.util.find_spec(r.replace(\"-\", \"_\")) is None]\n\ndef env_check():\n missing = missing_requirements()\n json.dump({\"ready\": not missing, \"load-rules\": bool(LOAD_RULES)}, sys.stdout)\n\ndef apply_rules(candidates, context):\n \"\"\"YOUR RULES HERE. Default: passthrough (returns the list unchanged).\"\"\"\n return candidates\n\ndef route():\n payload = json.load(sys.stdin)\n out = apply_rules(payload.get(\"candidates\", []), payload.get(\"context\", {}))\n json.dump(out, sys.stdout)\n\nif __name__ == \"__main__\":\n if len(sys.argv) > 1 and sys.argv[1] == \"route\":\n route()\n else:\n env_check()\n";
package/package.json CHANGED
@@ -1,51 +1,51 @@
1
- {
2
- "name": "@heretyc/subagent-mcp",
3
- "version": "2.6.0",
4
- "description": "MCP server that launches and manages local Claude Code and Codex CLI sub-agents as child processes (no direct Anthropic/OpenAI API).",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "subagent-mcp": "dist/index.js"
9
- },
10
- "files": [
11
- "dist",
12
- "directives",
13
- "scripts/postinstall.mjs",
14
- "LICENSE",
15
- "NOTICE",
16
- "README.md"
17
- ],
18
- "scripts": {
19
- "build": "node scripts/gen-ruleset-scaffold.mjs && tsc && node scripts/copy-provider.mjs",
20
- "start": "node dist/index.js",
21
- "postinstall": "node scripts/postinstall.mjs",
22
- "prepare": "npm run build",
23
- "prepublishOnly": "npm test",
24
- "test": "node test/effort.test.mjs && node test/platform.test.mjs && node test/wait.test.mjs && node test/status.test.mjs && node test/output.test.mjs && node test/stream.test.mjs && node test/routing.test.mjs && node test/deadlock.test.mjs && node test/handler-validation.test.mjs && node test/index-handler.test.mjs && node test/ruleset.test.mjs && node test/ruleset-exec.test.mjs && node test/ruleset-handler.test.mjs && node test/failover.test.mjs && node test/orchestration-marker.test.mjs && node test/orchestration-hook-core.test.mjs && node test/orchestration-adapters.test.mjs && node test/orchestration-directives.test.mjs && node test/setup-repair.test.mjs && node scripts/validate_provider.mjs && node scripts/validate_seed_sites.mjs && node scripts/validate_routing_audit.mjs && node test/seed-sites.test.mjs && node test/mcp-compliance.test.mjs"
25
- },
26
- "author": "Lexi Blackburn",
27
- "license": "Apache-2.0",
28
- "repository": {
29
- "type": "git",
30
- "url": "git+https://github.com/Heretyc/subagent-mcp.git"
31
- },
32
- "homepage": "https://github.com/Heretyc/subagent-mcp#readme",
33
- "bugs": {
34
- "url": "https://github.com/Heretyc/subagent-mcp/issues"
35
- },
36
- "dependencies": {
37
- "@modelcontextprotocol/sdk": "^1.0.0",
38
- "zod": "^3.0.0"
39
- },
40
- "devDependencies": {
41
- "@types/node": "^20.0.0",
42
- "typescript": "^5.0.0"
43
- },
44
- "engines": {
45
- "node": ">=18"
46
- },
47
- "publishConfig": {
48
- "registry": "https://npm.pkg.github.com",
49
- "access": "public"
50
- }
51
- }
1
+ {
2
+ "name": "@heretyc/subagent-mcp",
3
+ "version": "2.6.1",
4
+ "description": "MCP server that launches and manages local Claude Code and Codex CLI sub-agents as child processes (no direct Anthropic/OpenAI API).",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "subagent-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "directives",
13
+ "scripts/postinstall.mjs",
14
+ "LICENSE",
15
+ "NOTICE",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "node scripts/gen-ruleset-scaffold.mjs && tsc && node scripts/copy-provider.mjs",
20
+ "start": "node dist/index.js",
21
+ "postinstall": "node scripts/postinstall.mjs",
22
+ "prepare": "npm run build",
23
+ "prepublishOnly": "npm test",
24
+ "test": "node test/effort.test.mjs && node test/platform.test.mjs && node test/wait.test.mjs && node test/status.test.mjs && node test/output.test.mjs && node test/stream.test.mjs && node test/routing.test.mjs && node test/deadlock.test.mjs && node test/handler-validation.test.mjs && node test/index-handler.test.mjs && node test/ruleset.test.mjs && node test/ruleset-exec.test.mjs && node test/ruleset-handler.test.mjs && node test/failover.test.mjs && node test/orchestration-marker.test.mjs && node test/orchestration-hook-core.test.mjs && node test/orchestration-adapters.test.mjs && node test/orchestration-directives.test.mjs && node test/setup-repair.test.mjs && node scripts/validate_provider.mjs && node scripts/validate_seed_sites.mjs && node scripts/validate_routing_audit.mjs && node test/seed-sites.test.mjs && node test/mcp-compliance.test.mjs"
25
+ },
26
+ "author": "Lexi Blackburn",
27
+ "license": "Apache-2.0",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/Heretyc/subagent-mcp.git"
31
+ },
32
+ "homepage": "https://github.com/Heretyc/subagent-mcp#readme",
33
+ "bugs": {
34
+ "url": "https://github.com/Heretyc/subagent-mcp/issues"
35
+ },
36
+ "dependencies": {
37
+ "@modelcontextprotocol/sdk": "^1.0.0",
38
+ "zod": "^3.0.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^20.0.0",
42
+ "typescript": "^5.0.0"
43
+ },
44
+ "engines": {
45
+ "node": ">=18"
46
+ },
47
+ "publishConfig": {
48
+ "registry": "https://npm.pkg.github.com",
49
+ "access": "public"
50
+ }
51
+ }
@@ -1,102 +1,102 @@
1
- #!/usr/bin/env node
2
- // Postinstall banner for subagent-mcp.
3
- //
4
- // `npm install -g @heretyc/subagent-mcp` ships only the MCP server + hook
5
- // assets; it does NOT wire them into Claude Code / Codex. Without feedback the
6
- // user has no idea an addon landed, let alone that a second step is required.
7
- // This prints a clear "what installed / what to run next / how to verify"
8
- // banner so the install is self-explanatory.
9
- //
10
- // Rules:
11
- // - NEVER fail the install. Any error is swallowed; always exit 0.
12
- // - Only speak for a real end-user install. In the dev checkout (src/ present)
13
- // stay silent so `npm install` during development isn't noisy.
14
- // - Print only — do not mutate vendor config. Wiring is the explicit,
15
- // reversible `subagent-mcp setup` step.
16
-
17
- import { existsSync, readFileSync } from "node:fs";
18
- import { homedir } from "node:os";
19
- import { join, dirname, resolve } from "node:path";
20
- import { fileURLToPath } from "node:url";
21
- import { execSync } from "node:child_process";
22
-
23
- try {
24
- // Install root: scripts/postinstall.mjs -> scripts/ -> <root>
25
- const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
26
-
27
- // Dev checkout? (src/ only exists in the repo, never in the shipped tarball.)
28
- // Stay silent there — the maintainer doesn't need the end-user banner.
29
- if (existsSync(join(ROOT, "src"))) process.exit(0);
30
-
31
- let version = "";
32
- try {
33
- version = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8")).version || "";
34
- } catch { /* version is cosmetic */ }
35
-
36
- // Best-effort vendor detection so the banner can say what WILL be wired.
37
- // Pure read-only; failures just fall back to "not detected".
38
- function has(cmd) {
39
- try {
40
- execSync(process.platform === "win32" ? `where ${cmd}` : `command -v ${cmd}`, {
41
- stdio: "ignore",
42
- });
43
- return true;
44
- } catch {
45
- return false;
46
- }
47
- }
48
- const hasClaude = has("claude");
49
- const hasCodex = has("codex") || existsSync(join(homedir(), ".codex"));
50
-
51
- const L = [];
52
- const line = (s = "") => L.push(s);
53
- const bar = "============================================================";
54
-
55
- line();
56
- line(bar);
57
- line(` subagent-mcp installed${version ? ` (v${version})` : ""}`);
58
- line(bar);
59
- line();
60
- line(" This is an MCP ADDON for Claude Code CLI and Codex CLI.");
61
- line(" It is NOT active yet — one command wires it in.");
62
- line();
63
- line(" FINISH SETUP (auto-detects vendors, wires all present):");
64
- line();
65
- line(" subagent-mcp setup");
66
- line();
67
- line(" That registers the MCP server AND installs the per-turn");
68
- line(" orchestration-mode hooks for every vendor it finds.");
69
- line();
70
-
71
- // Detected vendors — concrete, so the user knows what setup will touch.
72
- if (hasClaude || hasCodex) {
73
- line(" Detected on this machine:");
74
- if (hasClaude) line(" - Claude Code CLI (will get MCP server + UserPromptSubmit hook)");
75
- if (hasCodex) line(" - Codex CLI (will get MCP server + SessionStart/UserPromptSubmit hooks)");
76
- } else {
77
- line(" No Claude Code or Codex CLI detected yet. Install one,");
78
- line(" then run: subagent-mcp setup");
79
- }
80
- line();
81
-
82
- line(" AFTER setup — confirm it took effect:");
83
- if (hasClaude || !hasCodex) {
84
- line(" - Claude Code: restart the session, run /mcp");
85
- line(" -> 'subagent-mcp' shows Connected.");
86
- }
87
- if (hasCodex || !hasClaude) {
88
- line(" - Codex CLI: restart the session, run /hooks");
89
- line(" -> TRUST the new subagent-mcp hook.");
90
- }
91
- line();
92
- line(" Preview without changes: subagent-mcp setup --dry-run");
93
- line(" Health check any time: subagent-mcp doctor");
94
- line(" Docs: https://github.com/Heretyc/subagent-mcp#readme");
95
- line(bar);
96
- line();
97
-
98
- process.stdout.write(L.join("\n") + "\n");
99
- } catch {
100
- // Never let a banner failure break the install.
101
- }
102
- process.exit(0);
1
+ #!/usr/bin/env node
2
+ // Postinstall banner for subagent-mcp.
3
+ //
4
+ // `npm install -g @heretyc/subagent-mcp` ships only the MCP server + hook
5
+ // assets; it does NOT wire them into Claude Code / Codex. Without feedback the
6
+ // user has no idea an addon landed, let alone that a second step is required.
7
+ // This prints a clear "what installed / what to run next / how to verify"
8
+ // banner so the install is self-explanatory.
9
+ //
10
+ // Rules:
11
+ // - NEVER fail the install. Any error is swallowed; always exit 0.
12
+ // - Only speak for a real end-user install. In the dev checkout (src/ present)
13
+ // stay silent so `npm install` during development isn't noisy.
14
+ // - Print only — do not mutate vendor config. Wiring is the explicit,
15
+ // reversible `subagent-mcp setup` step.
16
+
17
+ import { existsSync, readFileSync } from "node:fs";
18
+ import { homedir } from "node:os";
19
+ import { join, dirname, resolve } from "node:path";
20
+ import { fileURLToPath } from "node:url";
21
+ import { execSync } from "node:child_process";
22
+
23
+ try {
24
+ // Install root: scripts/postinstall.mjs -> scripts/ -> <root>
25
+ const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
26
+
27
+ // Dev checkout? (src/ only exists in the repo, never in the shipped tarball.)
28
+ // Stay silent there — the maintainer doesn't need the end-user banner.
29
+ if (existsSync(join(ROOT, "src"))) process.exit(0);
30
+
31
+ let version = "";
32
+ try {
33
+ version = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8")).version || "";
34
+ } catch { /* version is cosmetic */ }
35
+
36
+ // Best-effort vendor detection so the banner can say what WILL be wired.
37
+ // Pure read-only; failures just fall back to "not detected".
38
+ function has(cmd) {
39
+ try {
40
+ execSync(process.platform === "win32" ? `where ${cmd}` : `command -v ${cmd}`, {
41
+ stdio: "ignore",
42
+ });
43
+ return true;
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+ const hasClaude = has("claude");
49
+ const hasCodex = has("codex") || existsSync(join(homedir(), ".codex"));
50
+
51
+ const L = [];
52
+ const line = (s = "") => L.push(s);
53
+ const bar = "============================================================";
54
+
55
+ line();
56
+ line(bar);
57
+ line(` subagent-mcp installed${version ? ` (v${version})` : ""}`);
58
+ line(bar);
59
+ line();
60
+ line(" This is an MCP ADDON for Claude Code CLI and Codex CLI.");
61
+ line(" It is NOT active yet — one command wires it in.");
62
+ line();
63
+ line(" FINISH SETUP (auto-detects vendors, wires all present):");
64
+ line();
65
+ line(" subagent-mcp setup");
66
+ line();
67
+ line(" That registers the MCP server AND installs the per-turn");
68
+ line(" orchestration-mode hooks for every vendor it finds.");
69
+ line();
70
+
71
+ // Detected vendors — concrete, so the user knows what setup will touch.
72
+ if (hasClaude || hasCodex) {
73
+ line(" Detected on this machine:");
74
+ if (hasClaude) line(" - Claude Code CLI (will get MCP server + UserPromptSubmit hook)");
75
+ if (hasCodex) line(" - Codex CLI (will get MCP server + SessionStart/UserPromptSubmit hooks)");
76
+ } else {
77
+ line(" No Claude Code or Codex CLI detected yet. Install one,");
78
+ line(" then run: subagent-mcp setup");
79
+ }
80
+ line();
81
+
82
+ line(" AFTER setup — confirm it took effect:");
83
+ if (hasClaude || !hasCodex) {
84
+ line(" - Claude Code: restart the session, run /mcp");
85
+ line(" -> 'subagent-mcp' shows Connected.");
86
+ }
87
+ if (hasCodex || !hasClaude) {
88
+ line(" - Codex CLI: restart the session, run /hooks");
89
+ line(" -> TRUST the new subagent-mcp hook.");
90
+ }
91
+ line();
92
+ line(" Preview without changes: subagent-mcp setup --dry-run");
93
+ line(" Health check any time: subagent-mcp doctor");
94
+ line(" Docs: https://github.com/Heretyc/subagent-mcp#readme");
95
+ line(bar);
96
+ line();
97
+
98
+ process.stdout.write(L.join("\n") + "\n");
99
+ } catch {
100
+ // Never let a banner failure break the install.
101
+ }
102
+ process.exit(0);