Skip to content

feat(execenv): pass the managed MCP config to agy as a per-task plugin (CHE-1821) - #287

Merged
congvc-dev merged 5 commits into
mainfrom
agent/x99-claude-sonnet/1a332b572a95
Oct 17, 2026
Merged

congvc-dev merged 5 commits into
mainfrom
agent/x99-claude-sonnet/1a332b572a95

Conversation

@congvc-bot-x99

@congvc-bot-x99 congvc-bot-x99 Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Status: Independent verification: PASS on X99. Reviewer: x99-codex-sol, OpenAI gpt-6.1-sol, independent of Anthropic author x99-claude-sonnet. Current head: 2fc88de53f07606b58e994d93760f3c9740ba558. Current base: 2b135399996d8072c5a99deb88ef55edb62f49b4. Fresh OCR delegation and OER-1 receipt validation pass for this pair. CI: 13 successful checks, 7 skipped, 0 failed/pending. PR #290 (CHE-1824) repaired the baseline migration failure. Signed verdict on CHE-1821: 01a1476c-3951-7343-9481-1e6ef10a5b3b. Merge stays with Cheese.

Conditions:

  • agy has no per-run MCP flag or env var, and overriding HOME drops the provider settings. The only per-run location agy loads is <cwd>/.agents/plugins/<name>/mcp_config.json.
  • agy walks up from its cwd to the repo root when it discovers .agents. A plugin is therefore visible to every run started below the directory that holds it. It is safe only in a workdir that belongs to one task.
  • The plugin is additive. agy still loads the global servers, so an explicitly empty mcpServers does not switch the global servers off.
  • A server of type sse is not supported by agy. Streamable HTTP (url plus headers) and stdio work.

Change:

  • Add server/internal/daemon/execenv/antigravity_mcp.go. When the agent has a managed mcp_config and the provider is antigravity, Prepare and Reuse write .agents/plugins/multica-mcp/plugin.json and mcp_config.json (mode 0600, directory 0700) into the task workdir. The config is written verbatim.
  • Isolation: before any write, every existing path component under the workdir (.agents, .agents/plugins, multica-mcp) must be a plain directory. A tracked symlink is refused, so credentials cannot leave the private tree. A managed env and a per-task local worktree are allowed. An in-place local_directory fails closed with an error, because humans and unmanaged runs share that tree.
  • Cleanup: the files and directories are recorded in the sidecar manifest. The existing teardown (CleanupSidecars) removes only those. A pre-existing multica-mcp path is refused, never overwritten. Reuse rolls back the prior plugin first, so a changed or removed config does not leave a stale plugin.
  • Secrets: error text names paths only. Prepare does not log the config.
  • No change to server/pkg/agent. The workdir is owned by execenv, as for omp and cursor.

Evidence:

  • Review round 1 (x99-codex-sol): P1 symlink escape and P2 filepathJoin lint. Fixed tests-first. Commit 48349d19dac562610118a7d52e663dbd0021a673 is tests only. Against its parent, 4 new symlink tests fail (.agents, .agents/plugins, plugin dir, and Reuse) and the dangling-link control passes. It also replaces the 3 slash-joined filepath.Join calls. Commit 829555f70ed079f320fc0541f8fb6f6223f6d646 adds the guard and makes them pass. golangci-lint run --new-from-rev=1b238338d ./internal/daemon/execenv/... reports 0 issues.
  • Tests-first, first round. Commit 4a23818aa is tests only. Against its parent, 5 of 7 new tests fail on behavior (plugin missing, in-place run not refused, pre-existing plugin overwritten). The 2 control tests (no config, other provider) pass on the parent, as intended. Commit 50b8fe5ab makes all 7 pass.
  • OCR: fresh delegation for head 2fc88de53f07606b58e994d93760f3c9740ba558 and base 2b135399996d8072c5a99deb88ef55edb62f49b4. Independent reviewer: x99-codex-sol, OpenAI gpt-6.1-sol. Status: delegation-complete. No remaining P0/P1 finding. Receipt attachment on CHE-1821: 01a1476c-35d0-7ea1-9bf0-bc2c93b319eb (ocr-receipt-2fc88de.json). The official validate_receipt() passes at cheese-work/multica-dotfiles@75fed83dcdf007d2524bcdd44fc740a098aaa96f, blob 465398e360c7b706034518161c7aabea5f050bdf. The old head's receipt remains historical, not evidence for this pair.
  • Baseline: the duplicate migration prefix 627 failure was repaired on main by PR fix(migrations): renumber agent_task_queue_context to clear duplicate prefix 627 (CHE-1824) #290 (CHE-1824). This PR merged that main with a merge commit, no rebase, and changed no migration. go test ./internal/migrations passes on the merged head.
  • Real agy, binary ~/.local/share/agy/1.3.5/agy, sha256 e14253aa79d4e910cbf8bcb40b68e80f9e85476725e130ed085122c98face92b. The directory says 1.3.5 and --version prints 1.3.6. The file mtime is 16 Oct 2026 01:05 ICT, after the directory was created, so the binary was likely replaced in place by a later release (inference, not verified). All probe results apply to this hash only.
  • HTTP: with url plus headers (also with type: http), the fixture server saw the header on every request, including tools/call.
  • Concurrency (6 runs at once): the run in the managed dir got its server. A sibling plain dir got none. A second managed dir with a different server got only its own and could not call the first one's tool. Two runs in the same dir both got it, so a shared dir cannot isolate.
  • Ancestors: in a non-git dir, a child dir did not get the parent's plugin. In a git repo, a plugin at the root or in a subdirectory was found from every descendant and not from the parent. This is why an in-place local_directory is refused.
  • Same-name collision: a plugin server named hindsight-org was spawned and called while the global hindsight-org exists.
  • Cleanup: after a real agy run was killed with SIGTERM, CleanupSidecars restored the workdir to empty, an agent-added sibling plugin survived, and no fixture process was left.
  • go test ./internal/daemon/execenv fails the same 7 tests with and without this change (openclaw and hermes tests, host related). With the default TMPDIR, 3 cursor tests also fail because /tmp/.git and /tmp/.cursor/mcp.json exist on this host. go test ./internal/daemon passes. go test ./pkg/agent passed once and failed once in TestPiExecuteTurnErrorActivityAndRetryRecoveryCancelTimer, a timer test that passes 3 of 3 when run alone (flaky, not touched by this PR). The backend CI job also fails TestMigrationNumericPrefixesAreUnique (duplicate migration 627) on the parent, not caused by this PR. go vet is clean.
  • Not run: the daemon end to end under the real service, because no deploy or daemon restart is in scope.
  • After merge, update the X99 daemon by the CHE-1730 procedure. Then give each agy agent its own hindsight-org mcp_config and remove the global entry.

Red output (Test-First Gate)

Round 1. Contemporaneous output of the tests-only commit 4a23818aa4ce9b14cbefbc9c6fd57739235d2933 run on 16 Oct 2026 at 12:29 ICT, saved to a file at that time. The parent is 1b238338dda4c5d1b5637c5f6ec54a0a5b07852f. Command: go test ./internal/daemon/execenv/ -run 'Antigravity|OtherProviderWritesNoAntigravity' -count=1. The two control tests pass and are not listed.

--- FAIL: TestPrepareAntigravityManagedMcpFailsClosedInPlace (0.01s)
    antigravity_mcp_test.go:129: Prepare succeeded; a managed agy mcp_config in a shared local directory cannot be isolated
--- FAIL: TestPrepareAntigravityManagedMcpWritesPrivatePlugin (0.01s)
    antigravity_mcp_test.go:50: managed mcp_config was not written for agy: open <tmp>/001/workspace-wsagymcp/task-555566667777/workdir/.agents/plugins/multica-mcp/mcp_config.json: no such file or directory
--- FAIL: TestReuseAntigravityRefreshesAndDropsManagedMcp (0.01s)
    antigravity_mcp_test.go:237: after Reuse mcp_config = "" (err open <tmp>/001/workspace-wsagymcp/task-555566667777/workdir/.agents/plugins/multica-mcp/mcp_config.json: no such file or directory), want the refreshed config
--- FAIL: TestAntigravityManagedMcpWorktreeCleanupKeepsExistingCustomizations (0.10s)
    antigravity_mcp_test.go:174: plugin missing in worktree: stat <tmp>/002/workspace-wsagymcp/task-555566667777/worktree/.agents/plugins/multica-mcp/mcp_config.json: no such file or directory
--- FAIL: TestAntigravityManagedMcpWorktreeRefusesExistingPluginName (0.10s)
    antigravity_mcp_test.go:203: Prepare succeeded; it would have overwritten the repo's own plugin
FAIL
FAIL	github.com/multica-ai/multica/server/internal/daemon/execenv	0.128s
FAIL

Round 2. Tests-only commit 48349d19dac562610118a7d52e663dbd0021a673, parent 50b8fe5abf0c4ff006caf6801cf7fa846fab9bf4. The author kept only the test names from the run at 13:03 ICT, not the messages. The text below is a re-run of the same commit and command, captured later on 16 Oct 2026 for this body. It is not the original run. The dangling-link subtest and the earlier tests pass.

--- FAIL: TestReuseAntigravityRefusesSymlinkEscape (0.01s)
    antigravity_mcp_test.go:331: Reuse accepted a symlinked .agents
--- FAIL: TestAntigravityManagedMcpWorktreeRefusesSymlinkEscape (0.00s)
    --- FAIL: TestAntigravityManagedMcpWorktreeRefusesSymlinkEscape/agents_dir (0.23s)
        antigravity_mcp_test.go:281: Prepare accepted a tracked symlink that escapes the task-private worktree
    --- FAIL: TestAntigravityManagedMcpWorktreeRefusesSymlinkEscape/plugins_dir (0.23s)
        antigravity_mcp_test.go:281: Prepare accepted a tracked symlink that escapes the task-private worktree
    --- FAIL: TestAntigravityManagedMcpWorktreeRefusesSymlinkEscape/plugin_dir (0.23s)
        antigravity_mcp_test.go:281: Prepare accepted a tracked symlink that escapes the task-private worktree
FAIL
FAIL	github.com/multica-ai/multica/server/internal/daemon/execenv	0.275s
FAIL

Writing receipt: meaning check OK. Of 16 advisory warnings, 15 are true positives (13 passive phrases, 2 long sentences). The synonym warning is a false positive because it refers to different changes.

Changelog: Antigravity agents now receive the MCP servers saved on their agent.

Refs CHE-1821

@congvc-bot-x99
congvc-bot-x99 Bot marked this pull request as ready for review October 17, 2026 01:15
@congvc-dev
congvc-dev merged commit dbf4adb into main Oct 17, 2026
21 checks passed
@congvc-dev
congvc-dev deleted the agent/x99-claude-sonnet/1a332b572a95 branch October 17, 2026 01:44
congvc-bot-x99 Bot pushed a commit that referenced this pull request Oct 17, 2026
Bring in #287 (CHE-1821) and #276 (CHE-1793), merged after the sync base 2b13539.

# Conflicts:
#	server/pkg/db/generated/inbox.sql.go
#	server/pkg/db/queries/inbox.sql
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