@heretyc/subagent-mcp 2.12.5 → 2.12.8
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 +52 -35
- package/dist/concurrency.js +1 -1
- package/dist/index.js +2 -3
- package/dist/init.js +1 -1
- package/dist/orchestration/marker.js +12 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,39 +5,56 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@heretyc/subagent-mcp)
|
|
6
6
|
[](https://github.com/Heretyc/subagent-mcp/actions/workflows/claude-routine.yml)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- **
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- **
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
8
|
+
## Core premise
|
|
9
|
+
|
|
10
|
+
subagent-mcp is an MCP (stdio) server that turns any AI coding assistant
|
|
11
|
+
(Claude Code, Codex, Gemini CLI) into a **manager/orchestrator of a team of
|
|
12
|
+
AI sub-agents** running on macOS, Linux, and Windows. It drives the locally
|
|
13
|
+
authenticated `claude` and `codex` CLIs you already signed into — **no direct
|
|
14
|
+
HTTP API calls and no API keys, ever** (an explicit, permanent non-goal). It
|
|
15
|
+
serves developers running big, long-horizon coding jobs who want to escape a
|
|
16
|
+
single conversation's context limits and vendor lock-in.
|
|
17
|
+
|
|
18
|
+
Its central promise: the orchestrator **monitors but never reads or writes
|
|
19
|
+
files itself** — every step is delegated to a fresh sub-agent, so the
|
|
20
|
+
orchestrator's context fills only with ≤100-line summaries. This extends
|
|
21
|
+
effective context "geometrically" instead of linearly, enabling marathon tasks
|
|
22
|
+
with little or no compaction. Guarantees/invariants it promises: a single
|
|
23
|
+
machine-global, provider-agnostic concurrency cap (default 20, min 10; rejects
|
|
24
|
+
at cap, never queues); fail-safe **ON** on hosts lacking hooks (unknown
|
|
25
|
+
orchestration state defaults to ON); orchestration state is authoritative only
|
|
26
|
+
via harness-verified `<subagent-mcp state="...">` hook tags, never inferred from
|
|
27
|
+
prose (guards against directive drift/hallucination); sub-agents run **gated by
|
|
28
|
+
default** (permission ceiling `auto`); and automatic model/provider/effort
|
|
29
|
+
routing per task category so the user never picks a model.
|
|
30
|
+
|
|
31
|
+
## Key problems it solves
|
|
32
|
+
|
|
33
|
+
- **Context exhaustion / compaction on long tasks** — delegate-only
|
|
34
|
+
orchestration keeps the manager's context holding summaries, not raw files,
|
|
35
|
+
so long jobs run with minimal compaction.
|
|
36
|
+
- **Single-vendor blind spots and lock-in** — mixed Claude + Codex (provider-
|
|
37
|
+
agnostic) operation means one vendor's weakness or outage doesn't blind or
|
|
38
|
+
block the whole job.
|
|
39
|
+
- **No API keys / no direct API calls** — drives locally signed-in vendor CLIs
|
|
40
|
+
instead of the Anthropic/OpenAI HTTP APIs, avoiding key management and cost of
|
|
41
|
+
a gateway.
|
|
42
|
+
- **Directive drift & hallucination over long runs** — operating rules are
|
|
43
|
+
re-injected redundantly (MCP `instructions`, INIT_BLOCK, per-turn hooks,
|
|
44
|
+
managed AGENTS.md/CLAUDE.md/GEMINI.md blocks) and made authoritative via
|
|
45
|
+
harness-verified state tags.
|
|
46
|
+
- **Model-selection burden** — a benchmark-derived routing table auto-picks
|
|
47
|
+
provider/model/effort from a plain-English prompt + task category.
|
|
48
|
+
- **Uncontrolled/unsafe sub-agent actions** — a shared permission engine gates
|
|
49
|
+
sub-agent operations (SAFE→allow, DANGER→deny, NEUTRAL→park for a decision)
|
|
50
|
+
with `auto`/`manual`/`yolo` ceilings and one-time `respond_permission`.
|
|
51
|
+
- **Runaway fan-out / resource contention** — one machine-wide concurrency cap
|
|
52
|
+
and worktree isolation (branch-per-task) with a first-line sub-agent
|
|
53
|
+
carve-out to prevent fork-bomb recursion.
|
|
54
|
+
- **Orchestrator observability** — a fixed set of tools (launch/poll/kill/
|
|
55
|
+
send_message/list/wait/respond_permission + orchestration & model modes) plus
|
|
56
|
+
a status lifecycle (processing/stalled/finished/errored/stopped/
|
|
57
|
+
zombie_killed/permission_requested) so a quiet agent isn't mistaken for dead.
|
|
41
58
|
|
|
42
59
|
## Install
|
|
43
60
|
|
|
@@ -167,7 +184,7 @@ keeps running either way. Full spec: [docs/spec/permissions.md](docs/spec/permis
|
|
|
167
184
|
- **"It won't start a new agent (cap reached)."** You've hit the concurrent
|
|
168
185
|
limit. Use `list_agents` to see what's running and `kill_agent` on anything
|
|
169
186
|
you no longer need — that frees a slot immediately. Raising the number in
|
|
170
|
-
`global-
|
|
187
|
+
`global-subagent-mcp-config.jsonc` also works.
|
|
171
188
|
- **"Where are the logs?"** Each agent's recent output is available any time via
|
|
172
189
|
`poll_agent`. The server's own diagnostics go to your host's normal MCP
|
|
173
190
|
server log (your Claude Code or Codex session logs) — all server logging goes
|
|
@@ -179,7 +196,7 @@ keeps running either way. Full spec: [docs/spec/permissions.md](docs/spec/permis
|
|
|
179
196
|
|---|---|
|
|
180
197
|
| [docs/spec/arch-rationale.md](docs/spec/arch-rationale.md) | Why it's built this way — the full design rationale |
|
|
181
198
|
| [docs/registration.md](docs/registration.md) | Per-platform setup: Claude Code, Codex, Gemini CLI, Claude Desktop |
|
|
182
|
-
| [docs/tools.md](docs/tools.md) | Full tool reference — all
|
|
199
|
+
| [docs/tools.md](docs/tools.md) | Full tool reference — all nine tools, parameters, return shapes |
|
|
183
200
|
| [docs/usage.md](docs/usage.md) | Model & effort matrix, ultracode mode, usage examples |
|
|
184
201
|
| [docs/SPEC.md](docs/SPEC.md) | Full technical specification |
|
|
185
202
|
| [docs/spec/permissions.md](docs/spec/permissions.md) | Permission system — ceiling modes, shared engine, threat model |
|
package/dist/concurrency.js
CHANGED
|
@@ -25,7 +25,7 @@ export function clampCap(raw) {
|
|
|
25
25
|
return v;
|
|
26
26
|
}
|
|
27
27
|
export function stripJsoncComments(text) {
|
|
28
|
-
return text.replace(/^\s*\/\/.*$/gm, "");
|
|
28
|
+
return text.replace(/^\uFEFF/, "").replace(/^\s*\/\/.*$/gm, "");
|
|
29
29
|
}
|
|
30
30
|
function parseJsonObject(text) {
|
|
31
31
|
const parsed = JSON.parse(stripJsoncComments(text));
|
package/dist/index.js
CHANGED
|
@@ -441,8 +441,7 @@ function handleCompletedStdoutLines(agent, lines, at) {
|
|
|
441
441
|
agent.status = "finished";
|
|
442
442
|
if (agent.exitedAt === null)
|
|
443
443
|
agent.exitedAt = at;
|
|
444
|
-
|
|
445
|
-
agent.slotPath = null;
|
|
444
|
+
updateSlotMetadata(agent, at);
|
|
446
445
|
}
|
|
447
446
|
}
|
|
448
447
|
}
|
|
@@ -516,7 +515,7 @@ const ORCHESTRATION_INSTRUCTIONS = "subagent-mcp - CANONICAL OPERATING MODEL (fu
|
|
|
516
515
|
const SUBAGENT_INSTRUCTIONS = "SUB-AGENT SESSION: you are a child process launched by subagent-mcp. Follow the parent prompt. Do not treat yourself as the orchestrator, do not re-trigger orchestration carryover, and do not launch further sub-agents unless the parent prompt explicitly assigns that.\n\nMODEL SELECTION MODE (parallel to orchestration-mode, set via the model-selection-mode tool). DEFAULT is \"smart\" and is used whenever unset: in smart, launch_agent REJECTS any call supplying provider/model/effort selectors and the server auto-picks the best model. \"user-approved-overrides\" opens a 30-MINUTE window where selectors are HONORED, enforced LAZILY (the mode reverts to smart on the next launch_agent call after 30 minutes) and re-enabling does NOT extend an active window. HONOR-BASED: you MUST NOT set \"user-approved-overrides\" without explicit interactive USER authorization via the structured-question tool (AskUserQuestion on Claude / request-user-input on Codex); never enable it on your own initiative.";
|
|
517
516
|
const server = new McpServer({
|
|
518
517
|
name: "subagent-mcp",
|
|
519
|
-
version: "2.12.
|
|
518
|
+
version: "2.12.8",
|
|
520
519
|
description: "Launches always-interactive local Claude and Codex sub-agent sessions and is the orchestrator's sole launch channel. Claude runs via the Claude Agent SDK over the local Claude Code executable; Codex via `codex app-server` over stdio. The server never calls Anthropic or OpenAI HTTP APIs directly.",
|
|
521
520
|
}, {
|
|
522
521
|
instructions: process.env.SUBAGENT_MCP_SUBAGENT === "1"
|
package/dist/init.js
CHANGED
|
@@ -21,7 +21,7 @@ export const INIT_BLOCK = [
|
|
|
21
21
|
"",
|
|
22
22
|
"ORCHESTRATION ON — you are the ORCHESTRATOR. Allowed tools: only the structured-question tool (AskUserQuestion on Claude / request-user-input on Codex), subagent-mcp, and the /workflows tool. There is no inline-by-right; every step runs in a sub-agent. If one atomic step truly cannot run in a sub-agent, ask the user via the structured-question tool for a one-time exception for that single step, perform only that step, then resume delegating. Sole channel: while subagent-mcp is connected, every sub-agent launch goes through `launch_agent`; never use harness-native sub-agent tools or shell-spawned agents.",
|
|
23
23
|
"",
|
|
24
|
-
"ORCHESTRATOR WORKTREE SETUP:
|
|
24
|
+
"ORCHESTRATOR WORKTREE SETUP: for mutating work, first place sub-agents in a compliant linked worktree/work branch; the main checkout cwd applies only to read-only work or already-isolated target-tree contexts (sub-agents no longer self-isolate into per-agent worktrees). Serialize any sub-agents that write the same files — never run concurrent writers over overlapping paths (no cwd-level lock exists).",
|
|
25
25
|
"",
|
|
26
26
|
"READ-ESCALATION LADDER (the orchestrator's only read channels, in order): (1) subagent-mcp `poll_agent` TAIL; (2) if the tail is insufficient, dispatch ONE sub-agent to return a single summary of <=100 lines, trusted as-is (no separate verification step); (3) anything larger: the USER reads the document directly. No reads or writes occur outside these channels. An empty or stalled tail means the agent is ALIVE, not dead — do NOT busy-loop poll_agent; learn completion via `wait`. Large inter-agent data: the orchestrator assigns scratch-file paths (%TEMP% on Windows, /tmp on POSIX) in prompts; the producing sub-agent writes, the consuming sub-agent reads; the orchestrator NEVER reads those files.",
|
|
27
27
|
"",
|
|
@@ -55,6 +55,9 @@ function cwdDisablePath(cwd) {
|
|
|
55
55
|
export function sessionPointerPath(cwd) {
|
|
56
56
|
return join(stateDir, `orch-session-${cwdHash(cwd)}.json`);
|
|
57
57
|
}
|
|
58
|
+
export function serverSessionPointerPath(cwd, serverKey = process.ppid) {
|
|
59
|
+
return join(stateDir, `orch-session-${cwdHash(cwd)}-${hashKey(String(serverKey))}.json`);
|
|
60
|
+
}
|
|
58
61
|
/**
|
|
59
62
|
* Enable orchestration for cwd. ALWAYS overwrites — re-enabling re-baselines by
|
|
60
63
|
* clearing owner_session/baseline_turn back to null so the next hook turn
|
|
@@ -128,9 +131,15 @@ export function writeDisableCwd(cwd) {
|
|
|
128
131
|
// Fail-safe: never throw to the caller.
|
|
129
132
|
}
|
|
130
133
|
}
|
|
131
|
-
export function writeCurrentSession(cwd, sessionKey) {
|
|
134
|
+
export function writeCurrentSession(cwd, sessionKey, serverKey = process.ppid) {
|
|
132
135
|
try {
|
|
133
136
|
mkdirSync(stateDir, { recursive: true, mode: 0o700 });
|
|
137
|
+
writeFileSync(serverSessionPointerPath(cwd, serverKey), JSON.stringify({ session_key: sessionKey }), {
|
|
138
|
+
encoding: "utf8",
|
|
139
|
+
mode: 0o600,
|
|
140
|
+
});
|
|
141
|
+
// Back-compat only: older consumers may still read the cwd-keyed pointer.
|
|
142
|
+
// New disable/query paths must read the server-scoped pointer instead.
|
|
134
143
|
writeFileSync(sessionPointerPath(cwd), JSON.stringify({ session_key: sessionKey }), {
|
|
135
144
|
encoding: "utf8",
|
|
136
145
|
mode: 0o600,
|
|
@@ -140,9 +149,9 @@ export function writeCurrentSession(cwd, sessionKey) {
|
|
|
140
149
|
// Fail-safe: never throw to the caller.
|
|
141
150
|
}
|
|
142
151
|
}
|
|
143
|
-
export function readCurrentSession(cwd) {
|
|
152
|
+
export function readCurrentSession(cwd, serverKey = process.ppid) {
|
|
144
153
|
try {
|
|
145
|
-
const raw = readFileSync(
|
|
154
|
+
const raw = readFileSync(serverSessionPointerPath(cwd, serverKey), "utf8");
|
|
146
155
|
const parsed = JSON.parse(raw);
|
|
147
156
|
return typeof parsed.session_key === "string" ? parsed.session_key : undefined;
|
|
148
157
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heretyc/subagent-mcp",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.8",
|
|
4
4
|
"description": "MCP server that launches and manages always-interactive Claude Code and Codex sub-agent sessions (no direct Anthropic/OpenAI API).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"postinstall": "node scripts/postinstall.mjs",
|
|
39
39
|
"prepare": "npm run build",
|
|
40
40
|
"prepublishOnly": "npm test",
|
|
41
|
-
"test": "npm run check:versions && node test/effort.test.mjs && node test/drivers.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/global-concurrency-cap.test.mjs && node test/update-check.test.mjs && node test/zombie.test.mjs && node test/zombie-reap-idle.test.mjs && node test/orchestration-marker.test.mjs && node test/orchestration-hook-core.test.mjs && node test/orchestration-adapters.test.mjs && node test/orchestration-pretool.test.mjs && node test/orchestration-directives.test.mjs && node test/no-five-call.test.mjs && node test/no-per-provider-cap.test.mjs && node test/rag-pointers.test.mjs && node test/check-worktree-subagent.test.mjs && node test/launch-agent-upsert.test.mjs && node test/claude-session-limit.test.mjs && node test/init-migration.test.mjs && node test/init-global.test.mjs && node test/mirror-fragments.test.mjs && node test/performance-tier-effort.test.mjs && node test/setup-repair.test.mjs && node test/setup-quoting.test.mjs && node test/setup-wire.test.mjs && node test/setup-cli-integration.test.mjs && node test/init.test.mjs && node test/model-selection-mode.test.mjs && node test/cli-args.test.mjs && node test/index-guard.test.mjs && node test/drivers-guard.test.mjs && node test/audit-next13-lb3.test.mjs && node test/zombie-guard.test.mjs && node test/concurrency-guard.test.mjs && node test/hook-core-guard.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"
|
|
41
|
+
"test": "npm run check:versions && node test/effort.test.mjs && node test/drivers.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/global-concurrency-cap.test.mjs && node test/update-check.test.mjs && node test/zombie.test.mjs && node test/zombie-reap-idle.test.mjs && node test/orchestration-marker.test.mjs && node test/orchestration-hook-core.test.mjs && node test/orchestration-adapters.test.mjs && node test/orchestration-pretool.test.mjs && node test/orchestration-directives.test.mjs && node test/no-five-call.test.mjs && node test/no-per-provider-cap.test.mjs && node test/rag-pointers.test.mjs && node test/check-worktree-subagent.test.mjs && node test/launch-agent-upsert.test.mjs && node test/claude-session-limit.test.mjs && node test/init-migration.test.mjs && node test/init-global.test.mjs && node test/mirror-fragments.test.mjs && node test/performance-tier-effort.test.mjs && node test/setup-repair.test.mjs && node test/setup-quoting.test.mjs && node test/setup-wire.test.mjs && node test/setup-cli-integration.test.mjs && node test/init.test.mjs && node test/model-selection-mode.test.mjs && node test/cli-args.test.mjs && node test/index-guard.test.mjs && node test/drivers-guard.test.mjs && node test/audit-next13-lb3.test.mjs && node test/zombie-guard.test.mjs && node test/concurrency-guard.test.mjs && node test/hook-core-guard.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/config-bom.test.mjs && node test/permission-system.test.mjs && node test/lifecycle-matrix.test.mjs && node test/output-hook-registration.test.mjs && node test/mcp-compliance.test.mjs"
|
|
42
42
|
},
|
|
43
43
|
"author": "Lexi Blackburn",
|
|
44
44
|
"license": "Apache-2.0",
|