Skip to content

fix(settings): grant create_session, the fan-out primitive the fleet procedure requires - #454

Merged
wenzowski merged 1 commit into
mainfrom
claude/milestone-issue-grooming-y21mib
Aug 14, 2026
Merged

wenzowski merged 1 commit into
mainfrom
claude/milestone-issue-grooming-y21mib

Conversation

@wenzowski

Copy link
Copy Markdown
Contributor

.claude/settings.json allowed get_session and list_sessions but never create_session, so /plan-fleet and mem:workflow/agent-fanout — both built on it — required a tool the allowlist did not grant. Every dispatch prompted.

Measured 2026-08-14. Five consecutive create_session calls returned MCP tool call requires approval while the operator reported approving each one. Two independent causes, both necessary; this PR fixes the second:

  1. The CLOUD-178 name flip. The connector attached as mcp__<uuid>__*, so no rule in this file matched any tool the session exposed. That half cannot be fixed in a tracked file — the UUID is account-specific (non-negotiable rule 1) — and CLOUD-191 is its durable answer.
  2. create_session was never allowlisted under any name. Independent of the flip, and what this PR closes.

set_session_title/set_session_tags come along because a dispatcher that can create a session but cannot label it cannot keep the board legible.

The trigger denies are untouched. AGENTS.md's ban on heartbeats stands. Worth stating because mem:connector-allowlist-recovery's recovery step 2 recommends allowing the bare mcp__<uuid>__* prefix, and doing that would silently un-deny send_later and create_trigger — the deny rules name the readable alias and match nothing under the UUID form. A user-level grant must mirror the denies; that correction is recorded on CLOUD-178.

Verification. mise run mcp-allow-check passes: every allow rule names a tool it can match, and every enabled server has a grant. Note the gate cannot catch cause 1 — mem:connector-allowlist-recovery records that it "passed throughout the session where writes were denied, because it was checking a name nothing was using." Only the injected config can answer which name is live.

DO-NOT-CLOSE — CLOUD-178 stays open for the name flip, which this does not address.

Refs: CLOUD-178

@linear-code

linear-code Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
CLOUD-178 claude.ai connector tools flip between readable and UUID names, silently breaking the permission allowlist

Split out of CLOUD-177, which is Done on its own scope. Evidence thread: the comments on CLOUD-177, in particular the final correction establishing verdict (a).

Ready

A claude.ai connector MCP server is exposed to a session under two different names over its lifetime, and a permission allow rule can only name one of them.

At session start the Linear connector appears as mcp__Linear__*. On a mid-session disconnect/re-register it comes back as mcp__4db58e41-cd4e-4818-8922-46cf616593f4__*, and the readable tools vanish from the listing entirely. .claude/settings.json allows "mcp__Linear", a prefix match, which matches nothing under the UUID name. Every Linear call then prompts for approval, with no signal that anything changed.

This hits the board-in-lockstep rule directly: moving a CLOUD-* issue between states is a save_issue call, so the workflow AGENTS.md mandates starts requiring a human tap per transition, mid-session, without warning.

Measured, across two containers

d38efda7 047c8272
At session start readable readable
After reconnect UUID UUID
Linear UUID 4db58e41-cd4e-4818-8922-46cf616593f4 same
Gmail UUID d648a34b-ef40-4201-b1af-9123d05d7a1e same
Xero UUID 0c388dc8-630a-4020-96c7-ff71ce1af383 same

Verdict: the UUID is stable and equal across containers. It is a durable identity for the connector; what varies is which of the two names is live at a given moment. This was initially mis-called as "unstable per boot" from a session that had not yet reconnected — absence of a reconnect is not evidence of naming stability, and any future measurement here needs to span at least one reconnect to say anything.

Confirmed load-bearing, not cosmetic: a save_issue under mcp__4db58e41-…__save_issue prompted, while a Linear write under the readable name moments earlier did not. (Both prompt-or-not observations are human-reported — an agent cannot observe its own approval prompts, and asserting otherwise is what made this take four passes to get right.)

Note this is a second, independent defect from the one that originally masked it: an org-level ask control on the Linear connector was overriding allow rules entirely, per Organization controls on connector tools. That control has been cleared and verified. Clearing it is what made this defect visible.

Ready predicate

A session survives a connector reconnect with Linear calls still auto-approved — no prompt on a save_issue issued under either the readable or the UUID name.

Done (proposed)

  • ~/.claude/settings.json allows both names:
"mcp__Linear",
"mcp__4db58e41-cd4e-4818-8922-46cf616593f4"
  • User-level, not the repo. A connector UUID is an account-specific identifier: meaningless to any other contributor or fork, and silently rotting if the connector is re-authorized. Repo rule 1 keeps those out of committed config. .claude/settings.json keeps "mcp__Linear" alone — correct and portable for anyone cloning batten — and the UUID lives in the personal scope where account facts belong.
  • Verified by observation across a reconnect, human-reported, not inferred from a session with no reconnect in it.

Open questions

  • Does the UUID survive re-authorization of the connector? Stable across two containers is not stable across an OAuth re-grant. If it rotates there, the user-level entry needs re-deriving and the failure mode returns silently. Worth knowing before treating this as closed.
  • Gmail and Xero have the same exposure and are not covered by any allow rule today. Not in scope here, but the same two-name fix applies if either is ever allowlisted.
  • No gate is possible for this one. Repo rule 2 wants a rule to ship with a runnable mechanism, and there is none available: the failure lives in a settings file outside the repo, keyed to an identifier the repo must not contain, and triggered by a remote-host event. Worth stating explicitly rather than leaving as an unmet obligation — this is a documented limitation, and the compensating control is that the failure is loud to the human (a prompt) even though it is silent to the agent.

Why the repo cannot fix this itself

In Claude Code on the web, connectors are "provisioned by the remote host and arrive as explicit --mcp-config entries" (MCP docs), which is also why they appear as mcp__Linear__* rather than the documented mcp__claude_ai_<server>__<tool> form. The naming is chosen per registration episode by the host, not by anything under this repo's control. The durable upstream fix would be a stable server name across re-registration, or permission matching on server identity rather than exposed tool-name prefix; until then, allowlisting both names is the available mitigation.


Generated by Claude Code

Review in Linear

…t procedure requires

`.claude/settings.json` allowed `get_session` and `list_sessions` but never
`create_session`, so `/plan-fleet` and `mem:workflow/agent-fanout` — both built
on it — required a tool the allowlist did not grant. Every dispatch prompted.

Measured 2026-08-14: five consecutive `create_session` calls returned
`MCP tool call requires approval` while the user reported approving each one.
Two independent causes, both necessary; this commit fixes the second.

The first is CLOUD-178's name flip: the connector attached as
`mcp__<uuid>__*`, so no rule here matched any tool the session exposed. That
half cannot be fixed in a tracked file — the UUID is account-specific (rule 1)
— and CLOUD-191 is its durable answer. Detail and the measurement series are on
CLOUD-178.

`set_session_title`/`set_session_tags` come along because a dispatcher that can
create a session but not label it cannot keep the board legible. The trigger
denies are untouched: AGENTS.md's ban on heartbeats stands.

Refs: CLOUD-178
@wenzowski
wenzowski marked this pull request as ready for review August 14, 2026 18:35
@wenzowski
wenzowski force-pushed the claude/milestone-issue-grooming-y21mib branch from c9ec8fb to 121de48 Compare August 14, 2026 18:35
@sonarqubecloud

Copy link
Copy Markdown

@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant