<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary
Cloud-agent Linear MCP is now disabled by policy for every role, full stop. src/mcp-config.ts's buildMcpServers always returns servers: undefined — implementer, reviewer, addresser, spec-author, CI resolver, conflict resolver, Mercy, and retro concern-validity never receive a Linear (or other) MCP server, whether on an initial Agent.create turn, a warm agent.send re-drive, or a resumed Agent.resume turn — regardless of whether the legacy DRONES_LINEAR_MCP_URL / DRONES_LINEAR_MCP_API_KEY env vars are set.
Parent-side, trusted Linear API access is completely unchanged. LINEAR_API_KEY / src/linear-api.ts (dispatcher claims, ticket write-back, drones link) still talk to Linear directly from the host process, exactly as before. This PR is only about capabilities handed to a Cursor cloud agent.
## Why It's Needed
AI-208 shipped src/mcp-config.ts as the sole chokepoint for Agent.create / agent.send / Agent.resume MCP config, with an opt-in Linear HTTP server that every cloud-agent role shared under one credential. Several of those roles — reviewer, addresser, CI-fix, conflict resolver, Mercy, retro — exist specifically to read content the harness does not author (PR diffs, review-comment bodies, CI failure text). Handing any of them a write-capable Linear tool is a confused-deputy exposure that no amount of key scoping fixes: a successful prompt injection in a reviewed PR would otherwise inherit live Linear read/write access. AI-299 already hardens the input-fence half of this threat (spec-author's untrusted-ticket handling); this closes the capability half by removing the tool from every role that has no approved, concrete need for it.
## Changes
- src/mcp-config.ts — buildMcpServers never attaches a server any more; the SDK mcpServers option remains absent (never an empty map) at every call site. Legacy DRONES_LINEAR_MCP_URL / DRONES_LINEAR_MCP_API_KEY presence is detected and turned into a loud, credential-free deprecation issue (drones doctor WARN + once-per-process harness log) instead of authorizing attachment. Added a new typed McpCloudPolicy (currently only "disabled-by-default") surfaced on McpServerBuildResult.policy and McpReceiptProvenance.policy. assessMcpConfigForDoctor drops its old "ok" state (nothing is ever successfully attached any more) down to inert / warn. The three sanctioned wrappers (createCloudAgent / sendToAgent / resumeCloudAgent) and the untrusted-content disableMcp opt-out are unchanged structurally — they still re-derive from buildMcpServers on every call, which now always yields nothing.
- src/telemetry.ts — receipts now stamp mcp.policy alongside the existing mcp.servers / mcp.issues.
- src/doctor.ts — drops the now-unreachable "ok" MCP-config branch.
- src/spec-author.ts / src/cli/frame.ts / src/cli/farm.ts / src/farm.ts — removed the dead AI-208 degrade path that told the drones frame exploration agent "a Linear MCP tool is configured" based on DRONES_LINEAR_MCP_URL — that claim was already misleading once mcp-config.ts stopped attaching anything, since the harness's actual attachment mechanism is fully env-driven inside the central chokepoint, independent of this per-verb plumbing. buildSpecAuthorPrompt now unconditionally tells the agent no Linear MCP tool is configured. Also removed: validateSpecAuthorMcpUrl, DRONES_LINEAR_MCP_URL_ENV / DRONES_LINEAR_MCP_ALLOW_INSECURE_ENV, the "invalid-mcp-url" block reason, and the mcpLinearUrl / allowInsecureMcpUrl plumbing through authorSpec, drones frame, and drones farm's spec-authoring stage.
- src/ci-resolver.ts / src/eligibility-cloud.ts — updated stale docstrings that described the pre-AI-300 MCP-attachment behavior.
- Tests — src/mcp-config.test.ts rewritten around the new policy (including a dedicated AI-300 inventory block covering initial + warm/resumed turns); src/telemetry.test.ts, src/doctor.test.ts updated for the new receipt/doctor shape; nine per-role warm/resumed-turn tests (ci-watcher, addresser, browser-verify, runner, reviewer, conflict-resolver, retro-concern-validity, mercy-watcher, artifact-recovery) flipped from "legacy env ⇒ attached" to "legacy env ⇒ still absent"; spec-author test suites updated for the removed degrade path.
- Docs — .env.example, AGENTS.md, README.md, ARCHITECTURE.md, ROADMAP.md updated to state the pinned policy and stop instructing operators to configure a cloud-agent Linear key. Added docs/decisions/20260819T204111.516Z-ai-300-cloud-agent-linear-mcp-is-disabled-by-policy.md.
No test used a real Linear API key — all DRONES_LINEAR_MCP_API_KEY values in tests/fixtures are clearly-inert placeholders (e.g. lin_api_super_secret_value_12345), matching prior convention.
## Breaking Changes
- Operator-facing: the legacy DRONES_LINEAR_MCP_URL / DRONES_LINEAR_MCP_API_KEY env vars no longer have any effect on any cloud-agent role. If an operator had these set expecting a cloud agent to use Linear, that capability is now gone (this is the intended, pinned behavior change) — drones doctor and the harness's own logs surface a WARN naming exactly this.
- drones frame no longer reads DRONES_LINEAR_MCP_URL / DRONES_LINEAR_MCP_ALLOW_INSECURE at all, and its exploration prompt no longer varies based on them.
- API removals (all src/spec-author.ts exports): DRONES_LINEAR_MCP_URL_ENV, DRONES_LINEAR_MCP_ALLOW_INSECURE_ENV, validateSpecAuthorMcpUrl; SpecAuthorBlockReason no longer includes "invalid-mcp-url"; SpecAuthorAgentRunArgs, BuildSpecAuthorPromptArgs, and AuthorSpecInput no longer accept mcpLinearUrl / allowInsecureMcpUrl; FarmTickOptions no longer accepts specAuthorMcpLinearUrl / specAuthorAllowInsecureMcpUrl.
- Receipt shape: DroneRunRecord.mcp gains a new required-when-present policy field (additive; existing consumers reading .servers / .issues are unaffected).
- Parent-side LINEAR_API_KEY behavior is not changed.
## Test Plan
- pnpm typecheck — clean (tsc --noEmit, exit 0).
- pnpm test (vitest + Python unittest suites) — 4637/4637 vitest tests passed across 142 files; 621/621 Python tests passed (6 skipped, expected).
- Focused re-runs during development: src/mcp-config.test.ts, src/mcp-call-sites.test.ts, src/telemetry.test.ts, src/doctor.test.ts, and every per-role MCP-wiring test file (ci-watcher, addresser, browser-verify, runner, reviewer, conflict-resolver, retro-concern-validity, mercy-watcher, artifact-recovery, spec-author, spec-author-agent-runner, farm) — all green.
- pnpm build — clean (tsc, exit 0).
- Manually verified no test injects a real Linear credential; verified via grep that no raw key, fingerprint, query string, or secret-bearing endpoint is written into any receipt/doctor/log fixture or documentation example.
## Verification Artifact
$ pnpm typecheck> tsc --noEmit
(exit 0)
$ pnpm test
Test Files 142 passed (142)
Tests 4637 passed (4637)
...
Ran 621 tests in 60.951s
OK (skipped=6)
$ pnpm build
> tsc
(exit 0)
## Impact Estimate
Business value: Eliminates a confused-deputy capability from cloud agents that read attacker-influenceable repository and review content. A successful prompt injection no longer inherits an unnecessary workspace-wide Linear tool, while trusted parent-side dispatch/write-back remains fully available.
Actual effort: Touched the central MCP configuration/provenance contract (mcp-config.ts), its receipt/doctor consumers (telemetry.ts, doctor.ts), removed a second, independent (and now-misleading) MCP-adjacent code path in spec-author.ts plus its CLI/farm plumbing, and updated 13 test files plus 5 documentation files and the decisions log — consistent with the spec's 3-point pre-AI estimate for inventorying every cloud-agent/warm-turn MCP path, changing the typed contract, pinning no-capability behavior across security-sensitive tests, and updating operator documentation.
<!-- CURSOR_AGENT_PR_BODY_END -->
<div><a href="https://cursor.com/agents/bc-7ef9c939-1933-442b-8a09-69b0ec8aa26f?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-7ef9c939-1933-442b-8a09-69b0ec8aa26f&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div>