mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Keep executor plugin MCP paths URI-native (#29628)
## Why
Executor-owned plugin roots are `PathUri`, but MCP config normalization
still converts them into a native `Path` using the app-server host's
rules. Relative `cwd` values can therefore resolve against the wrong
filesystem when host and executor path conventions differ.
This PR keeps executor MCP paths URI-native until the selected
environment launches the server, while retaining the existing host
parser behavior.
## What changed
- Keep one shared MCP normalization path with narrow host-`Path` and
executor-`PathUri` entrypoints.
- Preserve native host resolution for locally installed plugin MCP
configs.
- For executor configs, default `cwd` to the plugin root and resolve
relative working directories with the root URI's path convention.
- Accept explicit executor `file:` URIs only when they remain within the
selected plugin root.
- Preserve the selected environment id and existing remote
environment-variable ownership rules.
- Route the executor plugin provider through the URI-native entrypoint
without converting the root on the host.
- Ensure `codex doctor` does not probe executor-owned stdio commands or
foreign working directories on the host.
- Cover foreign Windows roots, relative and absolute executor working
directories, traversal rejection, runtime resolution, and doctor
behavior.
```text
plugin root: file:///C:/plugins/demo
configured cwd: scripts
|
v
resolved cwd: file:///C:/plugins/demo/scripts
|
v
launch through the selected executor
```
No new provider or filesystem abstraction is introduced.
## Stack
1. #29614 — add lexical `PathUri` containment.
2. #29620 — share URI-native manifest path resolution.
3. #28918 — keep selected plugin roots and resources URI-native.
4. #29626 — load executor skills without host path conversion.
5. **This PR** — resolve executor MCP working directories without host
path conversion.
This commit is contained in:
@@ -28,7 +28,6 @@ use codex_core_skills::config_rules::skill_config_rules_from_stack;
|
||||
use codex_core_skills::loader::SkillRoot;
|
||||
use codex_core_skills::loader::load_skills_from_roots;
|
||||
use codex_exec_server::LOCAL_FS;
|
||||
use codex_mcp::PluginMcpServerPlacement;
|
||||
use codex_mcp::parse_plugin_mcp_config;
|
||||
use codex_plugin::AppConnectorId;
|
||||
use codex_plugin::AppDeclaration;
|
||||
@@ -1282,17 +1281,16 @@ async fn load_mcp_servers_from_file(
|
||||
let Ok(contents) = tokio::fs::read_to_string(mcp_config_path.as_path()).await else {
|
||||
return PluginMcpDiscovery::default();
|
||||
};
|
||||
let parsed =
|
||||
match parse_plugin_mcp_config(plugin_root, &contents, PluginMcpServerPlacement::Declared) {
|
||||
Ok(parsed) => parsed,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
path = %mcp_config_path.display(),
|
||||
"failed to parse plugin MCP config: {err}"
|
||||
);
|
||||
return PluginMcpDiscovery::default();
|
||||
}
|
||||
};
|
||||
let parsed = match parse_plugin_mcp_config(plugin_root, &contents) {
|
||||
Ok(parsed) => parsed,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
path = %mcp_config_path.display(),
|
||||
"failed to parse plugin MCP config: {err}"
|
||||
);
|
||||
return PluginMcpDiscovery::default();
|
||||
}
|
||||
};
|
||||
for error in parsed.errors {
|
||||
warn!(
|
||||
plugin = %plugin_root.display(),
|
||||
@@ -1311,11 +1309,7 @@ fn load_mcp_servers_from_manifest_object(
|
||||
plugin_root: &Path,
|
||||
object_config: &str,
|
||||
) -> PluginMcpDiscovery {
|
||||
let parsed = match parse_plugin_mcp_config(
|
||||
plugin_root,
|
||||
object_config,
|
||||
PluginMcpServerPlacement::Declared,
|
||||
) {
|
||||
let parsed = match parse_plugin_mcp_config(plugin_root, object_config) {
|
||||
Ok(parsed) => parsed,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
|
||||
Reference in New Issue
Block a user