fix: preserve env sub-tables instead of flattening into phantom servers#3
Merged
Conversation
mcpsync had no model for a server's `env`, so syncing either:
• created a phantom transport-less server from Codex's nested
`[mcp_servers.NAME.env]` sub-table (read as a server literally named
"NAME.env") — which Codex then rejects with "invalid transport", and
• silently dropped env vars (API keys!) off any server that had them,
since the Server model never captured env on read or wrote it back.
Add real `env` support, mirroring `headers`:
• config.Server gains an `env` string-map; wired through dupe/free/eql
and the source-of-truth read (parseRegistry) + write (writeMcpServers).
• JSON targets: read `"env"` and write it back (reuses writeJsonHeadersField).
• TOML (Codex): readServersToml now routes `[mcp_servers.NAME.env]` into the
pending server's env (and also reads inline `env = { ... }`); it skips any
dotted `.env`/`.headers` section so no phantom server is ever emitted —
which also cleans up phantoms a previous mcpsync wrote. Writes env back as
an inline table.
Round-trip tested (TOML sub-table, inline TOML, JSON) and verified on real
configs: env preserved, no phantom, `diff` clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ozgurulukir
pushed a commit
to ozgurulukir/codedb
that referenced
this pull request
Jun 9, 2026
… from installer The mcpsync-based registration added in the Windsurf/Devin PR could corrupt a user's configs: mcpsync (≤0.0.4) flattened a server's nested env into a phantom transport-less server and dropped env vars. (Fixed upstream in justrach/mcpsync#3, but the installer auto-installs whatever mcpsync is live.) Windsurf and Devin both use a standard mcpServers JSON object, so register codedb the same way the other tools are — a direct, additive python write of just the codedb entry, guarded by the tool's presence. This: • can't drop a server's env/headers (only the codedb key is written), • can't create phantom servers, • needs no mcpsync (no extra download / network dependency), • preserves Devin's non-mcpServers peer keys. nuke.zig already deregisters both (unchanged). Verified in a sandbox: env- bearing servers and peer keys preserved, codedb added, ~/.mcpconfig.json never touched. install.sh is `bash -n` clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
mcpsync's
Servermodel had noenv, so a sync would:[mcp_servers.NAME.env]sub-table —readServersTomlread it as a server literally namedNAME.env, then wrote it back as[mcp_servers."NAME.env"]. Codex rejects that withinvalid configuration: invalid transport in mcp_servers.NAME.env.envon read, so it was gone on write.This was hit in the wild: a
codedbsync corrupted~/.codex/config.toml(node_repl.env) and created malformedgitagent.enventries in Windsurf/Devin/Gemini/OpenCode.The fix — real
envsupport (mirrorsheaders)config.Servergains anenvstring-map, wired throughdupe/free/eqland the source-of-truth read (parseRegistry) + write (writeMcpServers)."env"and write it back (reuseswriteJsonHeadersField).readServersTomlnow routes[mcp_servers.NAME.env]into the pending server's env (and also reads inlineenv = { ... }), and skips any dotted.env/.headerssection so a phantom server can never be emitted. This also cleans up phantoms a previous mcpsync wrote. env is written back as an inline table.Tested
targets.zig;zig build testgreen.mcpsync diffclean across all 7 tools.Behavior-preserving for servers without env; purely additive otherwise.