fix: Codex no longer fails to load its config after uLoopMCP rewrites a codex mcp add entry - #1930
Merged
Merged
Conversation
Older uLoopMCP versions wrote both an inline env line and a legacy [mcp_servers.uLoopMCP.env] child table under [mcp_servers.uLoopMCP]. SectionRegex only matches up to the next top-level "[", so it never covers this child table, leaving it behind after AutoConfigure, UpdateDevelopmentSettings, or DeleteConfiguration. The result is a config.toml with a duplicate "env" key, which Codex fails to parse. Add LegacyEnvTableRegex plus a pure RemoveLegacyEnvTable helper and apply it on every write/delete path. AutoConfigure's content-building logic is extracted into BuildAutoConfiguredContent so the write flow can be tested at the string level. IsUpdateNeeded's legacy check is placed after the server-path guard so environments without the TypeScript server bundle still return false instead of reaching AutoConfigure's throw. Values are not migrated, only removed: the legacy table only ever held values uLoopMCP itself regenerates on every write. Co-authored-by: rougebleu <69626187+rougebleu@users.noreply.github.com>
Contributor
📝 WalkthroughWalkthroughCodex TOML detection and write paths now remove the legacy ChangesCodex environment table cleanup
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The moved AnyMcpServerRegex match handling used var, which this repository's coding style disallows for variable declarations.
git log -S 'mcp_servers.uLoopMCP.env' shows no prior uLoopMCP version ever wrote the table-style [mcp_servers.uLoopMCP.env] section; the initial Codex implementation (#292) already used the inline env form exclusively. Reword the comments to not attribute the table to older uLoopMCP versions, and state the real reason values are dropped rather than migrated (a duplicate env definition breaks Codex's TOML parser, and AutoConfigure / UpdateDevelopmentSettings regenerate the values uLoopMCP manages).
codex mcp add entry
…le removal The legacy-table strip added to DeleteConfiguration and UpdateDevelopmentSettings had no test, because both paths mixed file I/O with the string transformation and could only be exercised by writing to the real project config. Extract the pure content-building step of each path, mirroring how BuildAutoConfiguredContent was extracted for the write flow, and test both against strings. - Extract BuildDeletedContent, keeping the "nothing removed" short-circuit so a config without uLoopMCP entries still leaves its blank lines untouched. - Extract BuildDevelopmentSettingsContent and report whether the section exists, which collapses the two consecutive AutoConfigure retries into a single one. Co-authored-by: rougebleu <rye0126@gmail.com>
hatayama
force-pushed
the
fix/codex-legacy-env-table-removal
branch
from
July 27, 2026 16:00
0daf28a to
c9f5f52
Compare
This was referenced Jul 27, 2026
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.
Summary
envdefinition when a table-style[mcp_servers.uLoopMCP.env]section coexists with uLoopMCP's own inlineenv = {...}line, causing Codex to fail parsingconfig.tomlentirely.User Impact
codex mcp add uLoopMCP ...rewrites the whole[mcp_servers.uLoopMCP]section in table style, replacing the inlineenv = {...}line with a[mcp_servers.uLoopMCP.env]child table. That config on its own is valid. uLoopMCP'sAutoConfigurethen replaces only whatSectionRegexmatches, and that regex stops at the child table's own[, so the table survives and the rebuilt block adds an inlineenvline back — leaving two definitions of the same key.config.tomlwith a duplicate-key parse error, so every MCP server in that file stopped working, not just uLoopMCP.AutoConfigure,UpdateDevelopmentSettings, andDeleteConfigurationall strip that table before writing, so re-saving the config (which already happens automatically) heals it.Changes
LegacyEnvTableRegexto match the table-style[mcp_servers.uLoopMCP.env]section (the existingSectionRegexonly matches up to the next top-level[, so it never covered this child table).RemoveLegacyEnvTable(content)helper and apply it inAutoConfigure's content-building step,UpdateDevelopmentSettings, andDeleteConfiguration.AutoConfigure's string-building logic intoBuildAutoConfiguredContentso the write flow can be covered by tests at the string level, without touching disk.BuildDeletedContentandBuildDevelopmentSettingsContentfor the same reason, so the strip applied on the delete and development-settings paths is covered by tests instead of only by the write path.BuildDeletedContentkeeps the "nothing was removed" short-circuit, so a config holding no uLoopMCP entries still keeps its blank lines untouched;BuildDevelopmentSettingsContentreports whether the section exists, which collapsesUpdateDevelopmentSettings' two consecutiveAutoConfigureretries into one.IsUpdateNeedednow also returnstruewhen the table-style section is present, so an existing bad config gets rewritten. This check is placed after the server-bundle existence guard, so an environment missing the TypeScript server bundle still returnsfalseinstead of reachingAutoConfigure's throw path.AutoConfigure/UpdateDevelopmentSettingsregenerate the env values uLoopMCP manages. Any custom keys that only existed in the table are intentionally discarded, matchingAutoConfigure's existing behavior of rebuilding the section.Supersedes #1858
This supersedes #1858, which reported and fixed the same bug but had a few issues this PR avoids:
Regex.Replace(result, @"(\r?\n){3,}", Environment.NewLine + Environment.NewLine)to the entire file content, rewriting blank lines in sections unrelated to uLoopMCP, and using the platform-dependentEnvironment.NewLine, which can introduce CRLF into an otherwise-LF file on Windows. This PR'sRemoveLegacyEnvTabledoes not touch line endings anywhere in the file.IsUpdateNeededbefore the TypeScript server bundle guard, so an environment without the server bundle present would returntrueand letAutoConfigurethrow. This PR places the check after the guard.AutoConfigureassembles the final content would not have been caught. This PR adds a regression test that runs the extractedBuildAutoConfiguredContentwrite-flow function directly.Credit
The bug was originally reported and fixed by @rougebleu in #1858. The branch commit carries the
trailer below; because this repository squashes with an empty commit body, it has to be supplied
in the squash message at merge time to survive:
Verification
Assets/Tests/Editor/CodexConfigTests.cs:RemoveLegacyEnvTable(removal, no-op when absent, end-of-file table, CRLF preservation), and write-flow regression tests forBuildAutoConfiguredContent,BuildDeletedContent, andBuildDevelopmentSettingsContent.CodexConfigTests+CodexConfigDeleteTestssuites in Unity 2022.3.62f3 EditMode batch mode: 26/26 passed, 0 failed, 0 compile errors.{projectRoot}/.codex/config.tomlseeded with both an inlineenvline and a legacy table, drivingIsConfigured/IsUpdateNeeded/AutoConfigure,DeleteConfiguration, andUpdateDevelopmentSettingsin Unity batch mode. All three produced a singleenvdefinition (or removed the section entirely, for delete), andcodex mcp list(codex-cli 0.145.0,CODEX_HOMEpointed at that directory) listed both servers successfully.origin/mainas a control: the legacy table survived, andcodex mcp listfailed withduplicate keyat the[mcp_servers.uLoopMCP.env]line. Same harness, opposite outcome — the healing is this PR's effect.Summary
Fix Codex TOML configuration parsing for uLoopMCP configs that contain both an inline TOML
env = { ... }entry and a legacy[mcp_servers.uLoopMCP.env]table.LegacyEnvTableRegexand a pureRemoveLegacyEnvTablehelper to remove only the legacyenvtable while preserving the inlineenv, unrelated sections, and existing line endings (including CRLF).IsUpdateNeededto detect the legacy table (after confirming the TypeScript server bundle exists), and routed write flows through legacy cleanup:BuildAutoConfiguredContentstrips the legacy table before updating/inserting the[mcp_servers.uLoopMCP]block.DeleteConfigurationnow usesBuildDeletedContentto remove the uLoopMCP section and discard the legacy env table, returning unchanged content when nothing is removed.UpdateDevelopmentSettingsnow strips the legacy table up front viaBuildDevelopmentSettingsContentbefore applying development/debug log changes.Assets/Tests/Editor/CodexConfigTests.csfor legacy table removal (including end-of-file), unchanged/no-op cases, CRLF preservation, and ensuring the output contains a singleenv =definition when both forms exist. Reflection-based helpers and aCountOccurrencesutility were added to support the new assertions.Codex configuration and deletion test suites pass 22/22 tests in Unity 2022.3.62f3.