diff --git a/apps/web/src/components/app/docs-sections/tools.tsx b/apps/web/src/components/app/docs-sections/tools.tsx
index a6380880..9b5f4768 100644
--- a/apps/web/src/components/app/docs-sections/tools.tsx
+++ b/apps/web/src/components/app/docs-sections/tools.tsx
@@ -50,8 +50,10 @@ export function ToolsContent() {
directly rather than through a shell, so pipes, globs, and{" "}
&& don't work — put anything shell-shaped in a
script and point command at that. A malformed entry
- aborts the whole manifest, so a typo in one tool makes every{" "}
- repo_ tool disappear.
+ aborts the whole manifest, and that failure takes the MCP request with
+ it — so a typo in one tool doesn't just hide the repo_{" "}
+ tools, it leaves the session with no Dispatch tools at all until the
+ file is fixed.
@@ -131,7 +133,10 @@ export function ToolsContent() {
scopes are "agent" (standard agents and persona
reviewers) and "job" (scheduled job runs). Useful for
job-only maintenance commands that shouldn't clutter a regular agent's
- toolset.
+ toolset. Anything Dispatch doesn't recognize is dropped from the
+ array, and a scope left with nothing recognizable is
+ treated as no scope at all — so a typo quietly re-exposes the tool
+ everywhere.
{`
{
diff --git a/docs/03-api-spec.md b/docs/03-api-spec.md
index d51a383c..dd088b12 100644
--- a/docs/03-api-spec.md
+++ b/docs/03-api-spec.md
@@ -694,7 +694,7 @@ These endpoints use the `/api/mcp` base path (not `/api/v1`).
| POST | `/api/mcp/:agentId` | Handle agent-scoped MCP requests with repo context |
| POST | `/api/mcp/jobs/:runId/:agentId` | Handle job-scoped MCP requests (adds job lifecycle tools) |
-Agent-scoped MCP loads repo tools from `.dispatch/tools.json` in the agent's working directory.
+Agent-scoped and job-scoped MCP both load repo tools from `.dispatch/tools.json` at the root of the agent's checkout — the worktree root when the agent has one, otherwise the repo root — resolved from `agent.cwd`. A tool's optional `scope` array decides which of the two routes exposes it (`agent` or `job`); the global `/api/mcp` route has no agent and loads none.
## Error Codes
diff --git a/plugins/dispatch/skills/repo-tools/SKILL.md b/plugins/dispatch/skills/repo-tools/SKILL.md
index 31b4ec4a..d4d0c7ad 100644
--- a/plugins/dispatch/skills/repo-tools/SKILL.md
+++ b/plugins/dispatch/skills/repo-tools/SKILL.md
@@ -50,18 +50,25 @@ it at the moment of use.
## Tool entries
-| Field | Required | Notes |
-| ------------- | -------- | --------------------------------------------------------------------------- |
-| `name` | yes | Exposed as `repo_`. Dots are stripped — MCP names cannot contain them |
-| `description` | yes | This is what makes the tool get used. See below |
-| `command` | yes | Argv array, run from the agent's checkout root |
-| `params` | no | Turned into CLI flags appended to `command` |
-| `scope` | no | Any of `agent`, `reviewer`, `job`. Omit to expose everywhere |
+| Field | Required | Notes |
+| ------------- | -------- | ------------------------------------------------------------------------------------------------------------ |
+| `name` | yes | Exposed as `repo_`. Dots are stripped — MCP names cannot contain them |
+| `description` | yes | This is what makes the tool get used. See below |
+| `command` | yes | Argv array, run from the agent's checkout root |
+| `params` | no | Turned into CLI flags appended to `command` |
+| `scope` | no | `agent` (standard agents and persona reviewers) and/or `job` (scheduled job runs). Omit to expose everywhere |
`repo_` prefixing is automatic and keeps repo tools in their own namespace, so a
repo tool can never shadow a built-in Dispatch tool like `create_pr` or
`dispatch_event`.
+Scope values Dispatch doesn't recognize are dropped from the array, and a `scope`
+left with nothing recognizable falls back to no scope at all — so a misspelled
+scope silently re-exposes a job-only tool to every agent. Older manifests
+sometimes carry `"reviewer"`; nothing is ever loaded under that scope, so a tool
+scoped to it alone is exposed to no one. Persona reviewers are covered by
+`agent`.
+
**Write the description for an agent that has never seen this repo.** It is the
only thing standing between the tool existing and the tool being used. Say what
the command does and when to reach for it — not just what it is named.
@@ -108,5 +115,7 @@ the server immediately, but a **newly added** tool usually will not be callable
by an already-running agent until it reconnects or a new session starts.
A malformed entry (missing `name`, `description`, or `command`) throws at load,
-which surfaces as the repo's tools being absent rather than as a parse error. If
-`repo_*` tools vanish, validate the JSON first.
+and that error escapes the MCP request handler rather than being reported as a
+parse error. The symptom is not "the `repo_*` tools are missing" — it is the
+whole Dispatch MCP server failing for that session, built-in tools included. If
+Dispatch's tools stop resolving, validate `.dispatch/tools.json` first.