codexmgr 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codexmgr-0.2.1 → codexmgr-0.3.0}/PKG-INFO +69 -37
- {codexmgr-0.2.1 → codexmgr-0.3.0}/README.md +67 -36
- {codexmgr-0.2.1 → codexmgr-0.3.0}/pyproject.toml +4 -1
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/__init__.py +1 -1
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/interface/parsers/mcp.py +8 -8
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/mcp/__init__.py +38 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/mcp/apply.py +16 -9
- codexmgr-0.3.0/src/codexmgr/mcp/cli.py +242 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/mcp/fields.py +9 -20
- codexmgr-0.3.0/src/codexmgr/mcp/project.py +181 -0
- codexmgr-0.3.0/src/codexmgr/mcp/resolution.py +112 -0
- codexmgr-0.3.0/src/codexmgr/mcp/sources.py +186 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/project/apply.py +31 -137
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/project/generated.py +10 -6
- codexmgr-0.3.0/src/codexmgr/project/resolution.py +180 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/rules/listing.py +21 -13
- codexmgr-0.3.0/src/codexmgr/rules/tree.py +206 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/app.py +79 -90
- codexmgr-0.3.0/src/codexmgr/tui/focus.py +182 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/items.py +1 -57
- codexmgr-0.3.0/src/codexmgr/tui/mcp_items.py +50 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/mutations.py +14 -0
- codexmgr-0.3.0/src/codexmgr/tui/panels.py +113 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/rendering.py +5 -0
- codexmgr-0.3.0/src/codexmgr/tui/rule_items.py +56 -0
- codexmgr-0.3.0/src/codexmgr/tui/rule_tree.py +141 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/sections.py +1 -1
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/state.py +17 -14
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_mcp_apply_cli.py +81 -6
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_mcp_cli.py +190 -96
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_package_metadata.py +8 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_rules_cli.py +59 -3
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_tui_app.py +125 -0
- codexmgr-0.3.0/tests/test_tui_selection_focus.py +142 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_tui_state.py +44 -13
- {codexmgr-0.2.1 → codexmgr-0.3.0}/uv.lock +1 -1
- codexmgr-0.2.1/src/codexmgr/mcp/cli.py +0 -197
- codexmgr-0.2.1/src/codexmgr/tui/rule_items.py +0 -58
- {codexmgr-0.2.1 → codexmgr-0.3.0}/.github/actions/install_package/action.yml +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/.github/workflows/py_test.yml +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/.github/workflows/version_publish_main.yml +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/.gitignore +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/pytest.toml +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/agents/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/agents/file.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/agents/manager.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/agents/renderer.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/commands/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/commands/codex.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/commands/codex_jit.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/commands/config_mutations.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/commands/health.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/commands/navigation.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/commands/rules.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/core/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/core/errors.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/core/options.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/core/paths.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/core/toml_io.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/custom_agents/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/custom_agents/cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/custom_agents/config.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/custom_agents/copies.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/custom_agents/listing.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/custom_agents/resolution.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/custom_agents/sources.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/hooks/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/hooks/config.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/hooks/copies.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/hooks/listing.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/hooks/merge.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/hooks/resolution.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/hooks/sources.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/interface/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/interface/cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/interface/parser.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/interface/parsers/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/interface/parsers/agents.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/mcp/config.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/mcp/discovery.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/mcp/tables.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/packages/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/packages/cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/packages/config.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/packages/listing.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/packages/mutation.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/packages/sources.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/project/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/project/config.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/project/snapshot.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/project/state.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/project/sync.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/py.typed +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/rules/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/rules/config.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/rules/copies.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/rules/resolution.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/rules/sources.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/skills/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/skills/config.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/skills/copies.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/skills/listing.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/skills/resolution.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/skills/sources.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/__init__.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/diff.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/models.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/package_refs.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/package_selection.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/package_state.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/src/codexmgr/tui/staged_packages.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/conftest.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_agents_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_agents_file.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_agentsmd_list_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_agentsmd_tools_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_apply_check_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_cd_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_codex_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_empty_skill_config_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_home_resolution_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_hooks_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_packages_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_paths.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_python_compatibility.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_renderer.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_skill_copies_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_skill_home_sources_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_skill_list_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_skills_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_status_doctor_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_sync_cli.py +0 -0
- {codexmgr-0.2.1 → codexmgr-0.3.0}/tests/test_toml_io.py +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codexmgr
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Manage project-local Codex configuration from reusable templates
|
|
5
|
+
Project-URL: Repository, https://github.com/JulianKimmig/codexmgr/
|
|
5
6
|
Keywords: agents,cli,codex,configuration,skills
|
|
6
7
|
Classifier: Development Status :: 4 - Beta
|
|
7
8
|
Classifier: Environment :: Console
|
|
@@ -24,9 +25,9 @@ Description-Content-Type: text/markdown
|
|
|
24
25
|
# codexmgr
|
|
25
26
|
|
|
26
27
|
`codexmgr` manages reusable Codex project setup. Keep shared `AGENTS.md`
|
|
27
|
-
snippets, skills, hooks, custom agents, rule files, packages, and
|
|
28
|
-
|
|
29
|
-
from `.codex/codexmgr.toml`.
|
|
28
|
+
snippets, skills, hooks, custom agents, rule files, packages, and reusable MCP
|
|
29
|
+
source files in one manager home, then sync the selected pieces into each
|
|
30
|
+
project from `.codex/codexmgr.toml`.
|
|
30
31
|
|
|
31
32
|
The tool is for people who use Codex in several repositories and do not want to
|
|
32
33
|
copy the same agent instructions by hand. When a shared rule changes, update it
|
|
@@ -37,7 +38,7 @@ Use `codexmgr` when a project should:
|
|
|
37
38
|
- build `AGENTS.md` from reusable instruction snippets
|
|
38
39
|
- share skills, hooks, custom agents, and rule files across repositories
|
|
39
40
|
- enable packaged Codex setups made from those reusable pieces
|
|
40
|
-
- keep
|
|
41
|
+
- keep reusable MCP server definitions out of the user-level Codex config
|
|
41
42
|
- check whether generated Codex files match the project config
|
|
42
43
|
- run `codex` with project `.codex/config.toml` values passed as `-c` overrides
|
|
43
44
|
|
|
@@ -148,7 +149,7 @@ file for you, and you can also edit it by hand when that is clearer.
|
|
|
148
149
|
- `.codex/codexmgr.lock`: resolved AGENTS.md, agent, skill, hook, rule, and MCP
|
|
149
150
|
state
|
|
150
151
|
- `.codex/config.toml`: project-local Codex config, including generated
|
|
151
|
-
`[[skills.config]]` entries and `[mcp_servers.<id>]`
|
|
152
|
+
`[[skills.config]]` entries and `[mcp_servers.<id>]` server definitions
|
|
152
153
|
- `.codex/hooks.json`: generated hook config for enabled reusable hook bundles
|
|
153
154
|
- `.codex/hooks/<name>`: copied support files for enabled hook bundles
|
|
154
155
|
- `.codex/agents/<name>.toml`: copied custom-agent definitions
|
|
@@ -170,7 +171,7 @@ Manual content outside this block is preserved. If the block is missing,
|
|
|
170
171
|
|
|
171
172
|
`.codex/codexmgr.toml` can opt into each resource type independently. A minimal
|
|
172
173
|
file may only contain `[agents_md]`; larger projects can add skills, custom
|
|
173
|
-
agents, hooks, reusable rules, and MCP
|
|
174
|
+
agents, hooks, reusable rules, and MCP sources or overlays as needed. Package commands
|
|
174
175
|
write those same tables rather than a separate package table.
|
|
175
176
|
|
|
176
177
|
```toml
|
|
@@ -188,6 +189,8 @@ disabled = ["experimental-hook"]
|
|
|
188
189
|
[rules]
|
|
189
190
|
enabled = ["react/", "python/testing.md"]
|
|
190
191
|
disabled = ["react/materials/"]
|
|
192
|
+
[mcp]
|
|
193
|
+
enabled = ["browsermcp"]
|
|
191
194
|
[mcp.servers.browsermcp]
|
|
192
195
|
enabled = true
|
|
193
196
|
bearer_token_env_var = "BROWSERMCP_TOKEN"
|
|
@@ -232,6 +235,9 @@ Rule refs resolve under `$CODEXMGR_HOME/rules/` and use POSIX-style relative
|
|
|
232
235
|
paths. Folder refs have a trailing slash and copy regular files recursively into
|
|
233
236
|
`.rules/` while preserving relative paths.
|
|
234
237
|
|
|
238
|
+
Rule listings are grouped by folder. `codexmgr rules list` prints an indented
|
|
239
|
+
tree, while the TUI Rules screen shows the same refs in a collapsible tree.
|
|
240
|
+
|
|
235
241
|
File rule refs copy one file. Extensionless refs prefer an existing `<ref>.md`.
|
|
236
242
|
Enabled refs expand first, then disabled file or folder refs remove entries from
|
|
237
243
|
that candidate set.
|
|
@@ -292,7 +298,8 @@ These commands run `apply` automatically unless `--no-sync` is passed.
|
|
|
292
298
|
|
|
293
299
|
`codexmgr tui` opens a Textual-based terminal UI for project-local
|
|
294
300
|
configuration. It shows `AGENTS.md` snippets, skills, hooks, custom agents,
|
|
295
|
-
|
|
301
|
+
packages, and reusable MCP sources in selectable lists. Rules are shown
|
|
302
|
+
in a collapsible folder tree.
|
|
296
303
|
|
|
297
304
|
Changes are staged in memory while you navigate. Press `s` to save; the save
|
|
298
305
|
writes `.codex/codexmgr.toml` once and runs `apply` once unless `--no-sync` was
|
|
@@ -300,7 +307,9 @@ used.
|
|
|
300
307
|
|
|
301
308
|
For resources with explicit enable and disable lists, `space` cycles the
|
|
302
309
|
highlighted row through available, enabled, and disabled states. Package
|
|
303
|
-
profiles appear as separate selectable rows under their package.
|
|
310
|
+
profiles appear as separate selectable rows under their package. In the Rules
|
|
311
|
+
tree, cycling a file or folder node updates the full canonical rule ref behind
|
|
312
|
+
that basename label.
|
|
304
313
|
|
|
305
314
|
```bash
|
|
306
315
|
codexmgr tui
|
|
@@ -312,9 +321,10 @@ The dashboard shows generated-file sync state. By default it lists stale
|
|
|
312
321
|
generated paths; with `--show-diff`, it shows unified diffs for the staged
|
|
313
322
|
configuration.
|
|
314
323
|
|
|
315
|
-
MCP editing in the TUI is intentionally limited to
|
|
316
|
-
|
|
317
|
-
commands
|
|
324
|
+
MCP editing in the TUI is intentionally limited to loading and unloading
|
|
325
|
+
reusable `$CODEXMGR_HOME/mcp/*.toml` sources. Advanced per-server overlay fields
|
|
326
|
+
remain available through the `codexmgr mcp ...` commands or direct
|
|
327
|
+
`.codex/codexmgr.toml` edits.
|
|
318
328
|
|
|
319
329
|
## Template Format
|
|
320
330
|
|
|
@@ -421,8 +431,9 @@ codexmgr rules enable [--no-sync] <rule-ref> [...]
|
|
|
421
431
|
codexmgr rules disable [--no-sync] <rule-ref> [...]
|
|
422
432
|
```
|
|
423
433
|
|
|
424
|
-
`skill list`, `agents list`,
|
|
425
|
-
|
|
434
|
+
`skill list`, `agents list`, and `hooks list` print available resources and
|
|
435
|
+
mark configured entries as enabled, disabled, or missing. `rules list` prints
|
|
436
|
+
the same state in an indented folder hierarchy.
|
|
426
437
|
|
|
427
438
|
Enable commands validate manager-home sources when the source type must already
|
|
428
439
|
exist. Enable and disable lists stay mutually exclusive, and repeated commands
|
|
@@ -465,40 +476,62 @@ The wrapper can run with a just-in-time package/profile overlay without changing
|
|
|
465
476
|
codexmgr codex --package repo-rules --profile strict python -- exec "review this"
|
|
466
477
|
```
|
|
467
478
|
|
|
468
|
-
## Project MCP
|
|
479
|
+
## Project MCP Sources
|
|
469
480
|
|
|
470
|
-
`codexmgr mcp ...`
|
|
481
|
+
`codexmgr mcp ...` loads reusable MCP definitions from `$CODEXMGR_HOME/mcp`
|
|
482
|
+
into project-local configuration:
|
|
471
483
|
|
|
472
|
-
- source state is stored in `.codex/codexmgr.toml` under
|
|
473
|
-
|
|
474
|
-
- `apply` writes generated
|
|
484
|
+
- reusable source state is stored in `.codex/codexmgr.toml` under `[mcp]`
|
|
485
|
+
- per-project server overlays are stored under `[mcp.servers.<id>]`
|
|
486
|
+
- `apply` writes generated server definitions into `.codex/config.toml` under
|
|
475
487
|
`[mcp_servers.<id>]`
|
|
476
488
|
- `$CODEX_HOME/config.toml` and `~/.codex/config.toml` are never modified
|
|
477
489
|
|
|
478
490
|
Mutating MCP commands require a project `.codex/` directory and run `apply`
|
|
479
|
-
automatically unless `--no-sync` is passed.
|
|
480
|
-
|
|
481
|
-
|
|
491
|
+
automatically unless `--no-sync` is passed.
|
|
492
|
+
|
|
493
|
+
Create reusable source files in the same `mcp_servers` shape Codex reads from
|
|
494
|
+
`config.toml`:
|
|
495
|
+
|
|
496
|
+
```toml
|
|
497
|
+
# ~/.codexmgr/mcp/browsermcp.toml
|
|
498
|
+
[mcp_servers.browsermcp]
|
|
499
|
+
command = "browsermcp"
|
|
500
|
+
args = ["--port", "3000"]
|
|
501
|
+
env_vars = ["BROWSERMCP_TOKEN"]
|
|
502
|
+
```
|
|
482
503
|
|
|
483
|
-
List
|
|
504
|
+
List reusable sources and show project state:
|
|
484
505
|
|
|
485
506
|
```bash
|
|
486
507
|
codexmgr mcp list
|
|
487
|
-
codexmgr mcp show
|
|
508
|
+
codexmgr mcp show browsermcp
|
|
488
509
|
codexmgr mcp validate
|
|
489
510
|
```
|
|
490
511
|
|
|
491
|
-
|
|
492
|
-
discovery. It does not edit user configuration.
|
|
493
|
-
|
|
494
|
-
Enable or disable an existing server without deleting its definition:
|
|
512
|
+
Enable or disable reusable sources for the current project:
|
|
495
513
|
|
|
496
514
|
```bash
|
|
497
|
-
codexmgr mcp
|
|
498
|
-
codexmgr mcp
|
|
515
|
+
codexmgr mcp enable browsermcp context7
|
|
516
|
+
codexmgr mcp disable browsermcp
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
`disable` unloads the source from `[mcp].enabled`. It does not keep a generated
|
|
520
|
+
server definition with `enabled = false`.
|
|
521
|
+
|
|
522
|
+
Use `[mcp.servers.<id>]` for project-local overlays. Overlays merge after source
|
|
523
|
+
files, so they can override or add fields:
|
|
524
|
+
|
|
525
|
+
```toml
|
|
526
|
+
[mcp]
|
|
527
|
+
enabled = ["browsermcp"]
|
|
528
|
+
|
|
529
|
+
[mcp.servers.browsermcp]
|
|
530
|
+
enabled = false
|
|
531
|
+
bearer_token_env_var = "BROWSERMCP_TOKEN"
|
|
499
532
|
```
|
|
500
533
|
|
|
501
|
-
Update token and environment references
|
|
534
|
+
Update common token and environment references from the CLI:
|
|
502
535
|
|
|
503
536
|
```bash
|
|
504
537
|
codexmgr mcp set-token-env figma FIGMA_TOKEN
|
|
@@ -508,7 +541,7 @@ codexmgr mcp set-env-header figma Authorization FIGMA_AUTH_HEADER
|
|
|
508
541
|
codexmgr mcp unset-env-header figma Authorization
|
|
509
542
|
```
|
|
510
543
|
|
|
511
|
-
Set a small allowlist of
|
|
544
|
+
Set a small allowlist of overlay fields from TOML literals:
|
|
512
545
|
|
|
513
546
|
```bash
|
|
514
547
|
codexmgr mcp set-field context7 required true
|
|
@@ -518,12 +551,11 @@ codexmgr mcp set-field context7 default_tools_approval_mode '"prompt"'
|
|
|
518
551
|
|
|
519
552
|
Supported `set-field` names are `required`, `startup_timeout_sec`,
|
|
520
553
|
`tool_timeout_sec`, `enabled_tools`, `disabled_tools`, and
|
|
521
|
-
`default_tools_approval_mode`.
|
|
522
|
-
the `enabled` field.
|
|
554
|
+
`default_tools_approval_mode`.
|
|
523
555
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
`env_vars`, and `env_http_headers
|
|
556
|
+
Source files and hand-written overlays can use the full Codex `mcp_servers`
|
|
557
|
+
shape. Prefer environment variable references such as `bearer_token_env_var`,
|
|
558
|
+
`env_vars`, and `env_http_headers` for secrets.
|
|
527
559
|
|
|
528
560
|
## Development
|
|
529
561
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# codexmgr
|
|
2
2
|
|
|
3
3
|
`codexmgr` manages reusable Codex project setup. Keep shared `AGENTS.md`
|
|
4
|
-
snippets, skills, hooks, custom agents, rule files, packages, and
|
|
5
|
-
|
|
6
|
-
from `.codex/codexmgr.toml`.
|
|
4
|
+
snippets, skills, hooks, custom agents, rule files, packages, and reusable MCP
|
|
5
|
+
source files in one manager home, then sync the selected pieces into each
|
|
6
|
+
project from `.codex/codexmgr.toml`.
|
|
7
7
|
|
|
8
8
|
The tool is for people who use Codex in several repositories and do not want to
|
|
9
9
|
copy the same agent instructions by hand. When a shared rule changes, update it
|
|
@@ -14,7 +14,7 @@ Use `codexmgr` when a project should:
|
|
|
14
14
|
- build `AGENTS.md` from reusable instruction snippets
|
|
15
15
|
- share skills, hooks, custom agents, and rule files across repositories
|
|
16
16
|
- enable packaged Codex setups made from those reusable pieces
|
|
17
|
-
- keep
|
|
17
|
+
- keep reusable MCP server definitions out of the user-level Codex config
|
|
18
18
|
- check whether generated Codex files match the project config
|
|
19
19
|
- run `codex` with project `.codex/config.toml` values passed as `-c` overrides
|
|
20
20
|
|
|
@@ -125,7 +125,7 @@ file for you, and you can also edit it by hand when that is clearer.
|
|
|
125
125
|
- `.codex/codexmgr.lock`: resolved AGENTS.md, agent, skill, hook, rule, and MCP
|
|
126
126
|
state
|
|
127
127
|
- `.codex/config.toml`: project-local Codex config, including generated
|
|
128
|
-
`[[skills.config]]` entries and `[mcp_servers.<id>]`
|
|
128
|
+
`[[skills.config]]` entries and `[mcp_servers.<id>]` server definitions
|
|
129
129
|
- `.codex/hooks.json`: generated hook config for enabled reusable hook bundles
|
|
130
130
|
- `.codex/hooks/<name>`: copied support files for enabled hook bundles
|
|
131
131
|
- `.codex/agents/<name>.toml`: copied custom-agent definitions
|
|
@@ -147,7 +147,7 @@ Manual content outside this block is preserved. If the block is missing,
|
|
|
147
147
|
|
|
148
148
|
`.codex/codexmgr.toml` can opt into each resource type independently. A minimal
|
|
149
149
|
file may only contain `[agents_md]`; larger projects can add skills, custom
|
|
150
|
-
agents, hooks, reusable rules, and MCP
|
|
150
|
+
agents, hooks, reusable rules, and MCP sources or overlays as needed. Package commands
|
|
151
151
|
write those same tables rather than a separate package table.
|
|
152
152
|
|
|
153
153
|
```toml
|
|
@@ -165,6 +165,8 @@ disabled = ["experimental-hook"]
|
|
|
165
165
|
[rules]
|
|
166
166
|
enabled = ["react/", "python/testing.md"]
|
|
167
167
|
disabled = ["react/materials/"]
|
|
168
|
+
[mcp]
|
|
169
|
+
enabled = ["browsermcp"]
|
|
168
170
|
[mcp.servers.browsermcp]
|
|
169
171
|
enabled = true
|
|
170
172
|
bearer_token_env_var = "BROWSERMCP_TOKEN"
|
|
@@ -209,6 +211,9 @@ Rule refs resolve under `$CODEXMGR_HOME/rules/` and use POSIX-style relative
|
|
|
209
211
|
paths. Folder refs have a trailing slash and copy regular files recursively into
|
|
210
212
|
`.rules/` while preserving relative paths.
|
|
211
213
|
|
|
214
|
+
Rule listings are grouped by folder. `codexmgr rules list` prints an indented
|
|
215
|
+
tree, while the TUI Rules screen shows the same refs in a collapsible tree.
|
|
216
|
+
|
|
212
217
|
File rule refs copy one file. Extensionless refs prefer an existing `<ref>.md`.
|
|
213
218
|
Enabled refs expand first, then disabled file or folder refs remove entries from
|
|
214
219
|
that candidate set.
|
|
@@ -269,7 +274,8 @@ These commands run `apply` automatically unless `--no-sync` is passed.
|
|
|
269
274
|
|
|
270
275
|
`codexmgr tui` opens a Textual-based terminal UI for project-local
|
|
271
276
|
configuration. It shows `AGENTS.md` snippets, skills, hooks, custom agents,
|
|
272
|
-
|
|
277
|
+
packages, and reusable MCP sources in selectable lists. Rules are shown
|
|
278
|
+
in a collapsible folder tree.
|
|
273
279
|
|
|
274
280
|
Changes are staged in memory while you navigate. Press `s` to save; the save
|
|
275
281
|
writes `.codex/codexmgr.toml` once and runs `apply` once unless `--no-sync` was
|
|
@@ -277,7 +283,9 @@ used.
|
|
|
277
283
|
|
|
278
284
|
For resources with explicit enable and disable lists, `space` cycles the
|
|
279
285
|
highlighted row through available, enabled, and disabled states. Package
|
|
280
|
-
profiles appear as separate selectable rows under their package.
|
|
286
|
+
profiles appear as separate selectable rows under their package. In the Rules
|
|
287
|
+
tree, cycling a file or folder node updates the full canonical rule ref behind
|
|
288
|
+
that basename label.
|
|
281
289
|
|
|
282
290
|
```bash
|
|
283
291
|
codexmgr tui
|
|
@@ -289,9 +297,10 @@ The dashboard shows generated-file sync state. By default it lists stale
|
|
|
289
297
|
generated paths; with `--show-diff`, it shows unified diffs for the staged
|
|
290
298
|
configuration.
|
|
291
299
|
|
|
292
|
-
MCP editing in the TUI is intentionally limited to
|
|
293
|
-
|
|
294
|
-
commands
|
|
300
|
+
MCP editing in the TUI is intentionally limited to loading and unloading
|
|
301
|
+
reusable `$CODEXMGR_HOME/mcp/*.toml` sources. Advanced per-server overlay fields
|
|
302
|
+
remain available through the `codexmgr mcp ...` commands or direct
|
|
303
|
+
`.codex/codexmgr.toml` edits.
|
|
295
304
|
|
|
296
305
|
## Template Format
|
|
297
306
|
|
|
@@ -398,8 +407,9 @@ codexmgr rules enable [--no-sync] <rule-ref> [...]
|
|
|
398
407
|
codexmgr rules disable [--no-sync] <rule-ref> [...]
|
|
399
408
|
```
|
|
400
409
|
|
|
401
|
-
`skill list`, `agents list`,
|
|
402
|
-
|
|
410
|
+
`skill list`, `agents list`, and `hooks list` print available resources and
|
|
411
|
+
mark configured entries as enabled, disabled, or missing. `rules list` prints
|
|
412
|
+
the same state in an indented folder hierarchy.
|
|
403
413
|
|
|
404
414
|
Enable commands validate manager-home sources when the source type must already
|
|
405
415
|
exist. Enable and disable lists stay mutually exclusive, and repeated commands
|
|
@@ -442,40 +452,62 @@ The wrapper can run with a just-in-time package/profile overlay without changing
|
|
|
442
452
|
codexmgr codex --package repo-rules --profile strict python -- exec "review this"
|
|
443
453
|
```
|
|
444
454
|
|
|
445
|
-
## Project MCP
|
|
455
|
+
## Project MCP Sources
|
|
446
456
|
|
|
447
|
-
`codexmgr mcp ...`
|
|
457
|
+
`codexmgr mcp ...` loads reusable MCP definitions from `$CODEXMGR_HOME/mcp`
|
|
458
|
+
into project-local configuration:
|
|
448
459
|
|
|
449
|
-
- source state is stored in `.codex/codexmgr.toml` under
|
|
450
|
-
|
|
451
|
-
- `apply` writes generated
|
|
460
|
+
- reusable source state is stored in `.codex/codexmgr.toml` under `[mcp]`
|
|
461
|
+
- per-project server overlays are stored under `[mcp.servers.<id>]`
|
|
462
|
+
- `apply` writes generated server definitions into `.codex/config.toml` under
|
|
452
463
|
`[mcp_servers.<id>]`
|
|
453
464
|
- `$CODEX_HOME/config.toml` and `~/.codex/config.toml` are never modified
|
|
454
465
|
|
|
455
466
|
Mutating MCP commands require a project `.codex/` directory and run `apply`
|
|
456
|
-
automatically unless `--no-sync` is passed.
|
|
457
|
-
|
|
458
|
-
|
|
467
|
+
automatically unless `--no-sync` is passed.
|
|
468
|
+
|
|
469
|
+
Create reusable source files in the same `mcp_servers` shape Codex reads from
|
|
470
|
+
`config.toml`:
|
|
471
|
+
|
|
472
|
+
```toml
|
|
473
|
+
# ~/.codexmgr/mcp/browsermcp.toml
|
|
474
|
+
[mcp_servers.browsermcp]
|
|
475
|
+
command = "browsermcp"
|
|
476
|
+
args = ["--port", "3000"]
|
|
477
|
+
env_vars = ["BROWSERMCP_TOKEN"]
|
|
478
|
+
```
|
|
459
479
|
|
|
460
|
-
List
|
|
480
|
+
List reusable sources and show project state:
|
|
461
481
|
|
|
462
482
|
```bash
|
|
463
483
|
codexmgr mcp list
|
|
464
|
-
codexmgr mcp show
|
|
484
|
+
codexmgr mcp show browsermcp
|
|
465
485
|
codexmgr mcp validate
|
|
466
486
|
```
|
|
467
487
|
|
|
468
|
-
|
|
469
|
-
discovery. It does not edit user configuration.
|
|
470
|
-
|
|
471
|
-
Enable or disable an existing server without deleting its definition:
|
|
488
|
+
Enable or disable reusable sources for the current project:
|
|
472
489
|
|
|
473
490
|
```bash
|
|
474
|
-
codexmgr mcp
|
|
475
|
-
codexmgr mcp
|
|
491
|
+
codexmgr mcp enable browsermcp context7
|
|
492
|
+
codexmgr mcp disable browsermcp
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
`disable` unloads the source from `[mcp].enabled`. It does not keep a generated
|
|
496
|
+
server definition with `enabled = false`.
|
|
497
|
+
|
|
498
|
+
Use `[mcp.servers.<id>]` for project-local overlays. Overlays merge after source
|
|
499
|
+
files, so they can override or add fields:
|
|
500
|
+
|
|
501
|
+
```toml
|
|
502
|
+
[mcp]
|
|
503
|
+
enabled = ["browsermcp"]
|
|
504
|
+
|
|
505
|
+
[mcp.servers.browsermcp]
|
|
506
|
+
enabled = false
|
|
507
|
+
bearer_token_env_var = "BROWSERMCP_TOKEN"
|
|
476
508
|
```
|
|
477
509
|
|
|
478
|
-
Update token and environment references
|
|
510
|
+
Update common token and environment references from the CLI:
|
|
479
511
|
|
|
480
512
|
```bash
|
|
481
513
|
codexmgr mcp set-token-env figma FIGMA_TOKEN
|
|
@@ -485,7 +517,7 @@ codexmgr mcp set-env-header figma Authorization FIGMA_AUTH_HEADER
|
|
|
485
517
|
codexmgr mcp unset-env-header figma Authorization
|
|
486
518
|
```
|
|
487
519
|
|
|
488
|
-
Set a small allowlist of
|
|
520
|
+
Set a small allowlist of overlay fields from TOML literals:
|
|
489
521
|
|
|
490
522
|
```bash
|
|
491
523
|
codexmgr mcp set-field context7 required true
|
|
@@ -495,12 +527,11 @@ codexmgr mcp set-field context7 default_tools_approval_mode '"prompt"'
|
|
|
495
527
|
|
|
496
528
|
Supported `set-field` names are `required`, `startup_timeout_sec`,
|
|
497
529
|
`tool_timeout_sec`, `enabled_tools`, `disabled_tools`, and
|
|
498
|
-
`default_tools_approval_mode`.
|
|
499
|
-
the `enabled` field.
|
|
530
|
+
`default_tools_approval_mode`.
|
|
500
531
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
`env_vars`, and `env_http_headers
|
|
532
|
+
Source files and hand-written overlays can use the full Codex `mcp_servers`
|
|
533
|
+
shape. Prefer environment variable references such as `bearer_token_env_var`,
|
|
534
|
+
`env_vars`, and `env_http_headers` for secrets.
|
|
504
535
|
|
|
505
536
|
## Development
|
|
506
537
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "codexmgr"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Manage project-local Codex configuration from reusable templates"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -21,6 +21,9 @@ classifiers = [
|
|
|
21
21
|
"Typing :: Typed",
|
|
22
22
|
]
|
|
23
23
|
|
|
24
|
+
[project.urls]
|
|
25
|
+
Repository = "https://github.com/JulianKimmig/codexmgr/"
|
|
26
|
+
|
|
24
27
|
[project.scripts]
|
|
25
28
|
codexmgr = "codexmgr.interface.cli:entrypoint"
|
|
26
29
|
|
|
@@ -19,21 +19,21 @@ def add_mcp_parser(
|
|
|
19
19
|
Returns:
|
|
20
20
|
None. The parser is mutated in place.
|
|
21
21
|
"""
|
|
22
|
-
mcp = subparsers.add_parser("mcp", help="Manage project MCP
|
|
22
|
+
mcp = subparsers.add_parser("mcp", help="Manage project MCP sources and overrides")
|
|
23
23
|
mcp_subparsers = mcp.add_subparsers(dest="mcp_command", required=True)
|
|
24
24
|
|
|
25
|
-
mcp_subparsers.add_parser("list", help="List
|
|
25
|
+
mcp_subparsers.add_parser("list", help="List reusable MCP sources")
|
|
26
26
|
|
|
27
|
-
show = mcp_subparsers.add_parser("show", help="Show one
|
|
28
|
-
show.add_argument("server_id", help="MCP
|
|
27
|
+
show = mcp_subparsers.add_parser("show", help="Show one reusable MCP source")
|
|
28
|
+
show.add_argument("server_id", help="MCP source name")
|
|
29
29
|
|
|
30
|
-
enable = mcp_subparsers.add_parser("enable", help="Enable
|
|
30
|
+
enable = mcp_subparsers.add_parser("enable", help="Enable reusable MCP sources")
|
|
31
31
|
add_no_sync_argument(enable)
|
|
32
|
-
enable.add_argument("server_ids", nargs="+", help="MCP
|
|
32
|
+
enable.add_argument("server_ids", nargs="+", help="MCP source names")
|
|
33
33
|
|
|
34
|
-
disable = mcp_subparsers.add_parser("disable", help="Disable
|
|
34
|
+
disable = mcp_subparsers.add_parser("disable", help="Disable reusable MCP sources")
|
|
35
35
|
add_no_sync_argument(disable)
|
|
36
|
-
disable.add_argument("server_ids", nargs="+", help="MCP
|
|
36
|
+
disable.add_argument("server_ids", nargs="+", help="MCP source names")
|
|
37
37
|
|
|
38
38
|
token = mcp_subparsers.add_parser(
|
|
39
39
|
"set-token-env",
|
|
@@ -26,31 +26,69 @@ from .fields import (
|
|
|
26
26
|
validate_field,
|
|
27
27
|
validate_override,
|
|
28
28
|
)
|
|
29
|
+
from .project import (
|
|
30
|
+
disable_mcp_sources,
|
|
31
|
+
enable_mcp_sources,
|
|
32
|
+
mcp_source_names,
|
|
33
|
+
set_mcp_source_enabled_in_config,
|
|
34
|
+
)
|
|
35
|
+
from .resolution import (
|
|
36
|
+
McpResolution,
|
|
37
|
+
empty_mcp_resolution,
|
|
38
|
+
resolve_project_mcp,
|
|
39
|
+
validate_mcp_config,
|
|
40
|
+
)
|
|
41
|
+
from .sources import (
|
|
42
|
+
McpSource,
|
|
43
|
+
available_mcp_source_names,
|
|
44
|
+
load_mcp_source,
|
|
45
|
+
load_mcp_sources,
|
|
46
|
+
mcp_source_file,
|
|
47
|
+
mcp_sources_dir,
|
|
48
|
+
require_mcp_source,
|
|
49
|
+
resolve_mcp_source,
|
|
50
|
+
)
|
|
29
51
|
|
|
30
52
|
__all__ = [
|
|
31
53
|
"APPROVAL_MODES",
|
|
32
54
|
"CodexMcpServer",
|
|
55
|
+
"McpResolution",
|
|
56
|
+
"McpSource",
|
|
33
57
|
"SAFE_FIELDS",
|
|
34
58
|
"SET_FIELD_NAMES",
|
|
35
59
|
"add_env_var",
|
|
36
60
|
"apply_mcp_overrides",
|
|
61
|
+
"available_mcp_source_names",
|
|
37
62
|
"available_state",
|
|
38
63
|
"configured_overrides",
|
|
64
|
+
"disable_mcp_sources",
|
|
39
65
|
"discover_codex_servers",
|
|
66
|
+
"empty_mcp_resolution",
|
|
67
|
+
"enable_mcp_sources",
|
|
40
68
|
"is_string_map",
|
|
41
69
|
"known_fields",
|
|
70
|
+
"load_mcp_source",
|
|
71
|
+
"load_mcp_sources",
|
|
42
72
|
"mcp_lock_data",
|
|
73
|
+
"mcp_source_file",
|
|
74
|
+
"mcp_source_names",
|
|
75
|
+
"mcp_sources_dir",
|
|
43
76
|
"parse_value",
|
|
44
77
|
"remove_env_var",
|
|
78
|
+
"require_mcp_source",
|
|
79
|
+
"resolve_mcp_source",
|
|
45
80
|
"require_string_list",
|
|
81
|
+
"resolve_project_mcp",
|
|
46
82
|
"resolve_overrides",
|
|
47
83
|
"set_enabled",
|
|
84
|
+
"set_mcp_source_enabled_in_config",
|
|
48
85
|
"set_env_header",
|
|
49
86
|
"set_field",
|
|
50
87
|
"set_token_env",
|
|
51
88
|
"unset_env_header",
|
|
52
89
|
"unsupported_field_warnings",
|
|
53
90
|
"validate_field",
|
|
91
|
+
"validate_mcp_config",
|
|
54
92
|
"validate_override",
|
|
55
93
|
"validate_overrides",
|
|
56
94
|
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Apply project MCP
|
|
1
|
+
"""Apply project MCP server tables to generated Codex config and lock data."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Mapping, MutableMapping
|
|
4
4
|
from typing import Any
|
|
@@ -9,14 +9,14 @@ from ..core.toml_io import ensure_toml_table
|
|
|
9
9
|
|
|
10
10
|
def apply_mcp_overrides(
|
|
11
11
|
codex_config: MutableMapping[str, Any],
|
|
12
|
-
|
|
12
|
+
servers: Mapping[str, Mapping[str, Any]],
|
|
13
13
|
previous_lock: Mapping[str, Any],
|
|
14
14
|
) -> None:
|
|
15
|
-
"""Apply MCP
|
|
15
|
+
"""Apply MCP server tables to a local Codex config document.
|
|
16
16
|
|
|
17
17
|
Args:
|
|
18
18
|
codex_config: Mutable .codex/config.toml document.
|
|
19
|
-
|
|
19
|
+
servers: Current generated MCP server tables.
|
|
20
20
|
previous_lock: Previous codexmgr lock data.
|
|
21
21
|
"""
|
|
22
22
|
mcp_servers = ensure_toml_table(
|
|
@@ -25,7 +25,7 @@ def apply_mcp_overrides(
|
|
|
25
25
|
".codex/config.toml [mcp_servers] must be a table",
|
|
26
26
|
)
|
|
27
27
|
_remove_previous_fields(mcp_servers, previous_lock)
|
|
28
|
-
for server_id, fields in
|
|
28
|
+
for server_id, fields in servers.items():
|
|
29
29
|
target = ensure_toml_table(
|
|
30
30
|
mcp_servers,
|
|
31
31
|
server_id,
|
|
@@ -34,16 +34,23 @@ def apply_mcp_overrides(
|
|
|
34
34
|
target.update(known_fields(fields))
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
def mcp_lock_data(
|
|
38
|
-
|
|
37
|
+
def mcp_lock_data(
|
|
38
|
+
enabled_sources: list[str],
|
|
39
|
+
servers: Mapping[str, Mapping[str, Any]],
|
|
40
|
+
) -> dict[str, Any]:
|
|
41
|
+
"""Build lock data for generated MCP state.
|
|
39
42
|
|
|
40
43
|
Args:
|
|
41
|
-
|
|
44
|
+
enabled_sources: Reusable MCP source names enabled by the project.
|
|
45
|
+
servers: Current generated MCP server tables.
|
|
42
46
|
|
|
43
47
|
Returns:
|
|
44
48
|
Lockfile MCP data.
|
|
45
49
|
"""
|
|
46
|
-
return {
|
|
50
|
+
return {
|
|
51
|
+
"enabled": list(enabled_sources),
|
|
52
|
+
"servers": {key: known_fields(value) for key, value in servers.items()},
|
|
53
|
+
}
|
|
47
54
|
|
|
48
55
|
|
|
49
56
|
def _remove_previous_fields(
|