Conversation
Cargo.toml
Outdated
|
|
||
| [patch.crates-io] | ||
| v8 = { path = "vendor/v8" } | ||
| rmcp = { path = "../rust-sdk/crates/rmcp" } |
There was a problem hiding this comment.
will update this when modelcontextprotocol/rust-sdk#742 merges and releases
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3d68b492bc
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Cargo.toml
Outdated
|
|
||
| [patch.crates-io] | ||
| v8 = { path = "vendor/v8" } | ||
| rmcp = { path = "../rust-sdk/crates/rmcp" } |
There was a problem hiding this comment.
Remove machine-local rmcp patch override
The new [patch.crates-io] entry hard-pins rmcp to ../rust-sdk/crates/rmcp, which is outside this repository and not present in a standard checkout. That makes dependency resolution fail for contributors/CI that only have this repo, so the project cannot build or test without an extra unpublished sibling directory.
Useful? React with 👍 / 👎.
| let timeout_duration = | ||
| Duration::from_secs(timeout.unwrap_or(crate::config::DEFAULT_EXTENSION_TIMEOUT)); | ||
|
|
||
| let roots_dir = std::env::current_dir().unwrap_or_default(); |
There was a problem hiding this comment.
Use session working dir for streamable HTTP roots
This sets MCP roots for streamable HTTP extensions from std::env::current_dir() instead of the per-session working_dir passed into ExtensionManager::add_extension. In sessions started with a different workspace path, servers that call roots/list will be given the wrong directory and may operate on the wrong files or fail to find project data.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| fn working_dir_roots(dir: &std::path::Path) -> ListRootsResult { | ||
| let uri = format!("file://{}", dir.display()); |
There was a problem hiding this comment.
Build roots URI with proper file-URL encoding
Constructing the root URI via string formatting (file://{dir.display()}) does not perform file-URL normalization/escaping, so paths with spaces, #, non-UTF-8 bytes, or Windows separators produce invalid or ambiguous URIs. MCP servers consuming roots/list can misparse or reject these roots; use a file-URL constructor instead of raw formatting.
Useful? React with 👍 / 👎.
|
the codex comments seem worth paying attention to, especially the one about the current folder and there's the thing, we talked about this before, but should the working_dir be the root for the MCP servers? that means that technically they shouldn't have access to anything outside the working_dir. our developer extension definitely does that and would then ignore the root. ¯_(ツ)_/¯ |
3d68b49 to
b5cda10
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b5cda109bc
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| let roots_dir = effective_working_dir | ||
| .clone() | ||
| .unwrap_or_else(|| std::env::current_dir().unwrap_or_default()); |
There was a problem hiding this comment.
Derive roots path from validated working directory
When working_dir is provided but does not exist, this function logs a warning and skips command.current_dir(dir), so the MCP process runs in the parent process directory; however, roots_dir is still taken from the invalid effective_working_dir. In that scenario, roots/list returns a non-existent root that does not match the server's actual cwd, and root-aware MCP servers can fail file operations even though the extension started successfully.
Useful? React with 👍 / 👎.
b5cda10 to
3d64f80
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3d64f80e33
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| &self, | ||
| _context: RequestContext<RoleClient>, | ||
| ) -> impl std::future::Future<Output = Result<ListRootsResult, ErrorData>> + Send + '_ { | ||
| std::future::ready(Ok(working_dir_roots(&self.working_dir))) |
There was a problem hiding this comment.
Update roots after working directory changes
list_roots always returns the working_dir captured when the MCP client is first connected, so roots become stale if a session's working directory is changed later (for example via ACP working_dir/update, which updates session state without recreating extension clients). In that scenario, root-aware MCP servers receive an outdated root and can resolve files against the wrong project until the extension is reconnected.
Useful? React with 👍 / 👎.
3d64f80 to
255956e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 255956e5d1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| let timeout_duration = | ||
| Duration::from_secs(timeout.unwrap_or(crate::config::DEFAULT_EXTENSION_TIMEOUT)); | ||
|
|
||
| let roots_dir = std::env::current_dir().unwrap_or_default(); |
There was a problem hiding this comment.
Pass session working dir to streamable HTTP MCP clients
ExtensionManager::add_extension receives a per-session working_dir, but create_streamable_http_client always derives roots_dir from std::env::current_dir() before calling McpClient::connect. In sessions where the workspace differs from the process cwd, roots/list will advertise the wrong directory to streamable HTTP servers, so root-aware tools can read/write against the wrong project tree.
Useful? React with 👍 / 👎.
| let roots_dir = effective_working_dir | ||
| .clone() | ||
| .unwrap_or_else(|| std::env::current_dir().unwrap_or_default()); |
There was a problem hiding this comment.
Derive roots from the validated child-process working dir
child_process_client validates effective_working_dir before calling command.current_dir, but roots_dir is still taken from effective_working_dir even when that validation fails. If working_dir (or GOOSE_WORKING_DIR) points to a missing/non-directory path, the MCP process runs with a different cwd while roots/list advertises the invalid path, which can break root-based file operations.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| fn working_dir_roots(dir: &std::path::Path) -> ListRootsResult { | ||
| let uri = format!("file://{}", dir.display()); |
There was a problem hiding this comment.
Build roots URI via proper file-URL conversion
working_dir_roots creates the root URI with raw string formatting (file://{dir.display()}), which skips file-URL escaping/normalization. Paths containing spaces, #, non-UTF8 bytes, Windows separators, or relative segments can produce malformed or ambiguous URIs, and MCP servers that parse roots as URLs may reject or misresolve them.
Useful? React with 👍 / 👎.
06f1483 to
997499c
Compare
997499c to
49492a4
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 49492a4695
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if let Some(session) = self.sessions.lock().await.get(&req.session_id) { | ||
| session | ||
| .agent | ||
| .extension_manager | ||
| .update_working_dir(&path) |
There was a problem hiding this comment.
Drop sessions lock before awaiting roots update
on_update_working_dir borrows a session from self.sessions.lock().await.get(...) and then awaits extension_manager.update_working_dir, which keeps the sessions mutex held for the entire async update path. If any extension is slow or blocked while handling roots/list_changed, other ACP requests that need session lookup will block behind this lock, making the agent appear hung after a working-dir change.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
unclear to me how to test this in an ACP client, but if anything is bad in the UX we can followup.
@codefromthecrypt do you know how to trigger the working dir change in an example ACP client?
| let extensions = self.extensions.lock().await; | ||
| for (name, ext) in extensions.iter() { | ||
| if let Err(e) = ext.client.update_working_dir(new_dir.to_path_buf()).await { |
There was a problem hiding this comment.
Release extensions mutex before notifying MCP clients
ExtensionManager::update_working_dir holds self.extensions.lock() while awaiting each ext.client.update_working_dir(...) call. Because those calls perform network I/O (notify_roots_list_changed), one slow extension can block the extensions map lock and stall concurrent extension operations (tool listing/calls, add/remove) until the await completes.
Useful? React with 👍 / 👎.
* main: (270 commits) test(acp): align provider and server test parity (#7822) fix(acp): register MCP extensions when resuming a session (#7806) fix(goose): load .gitignore in prompt_manager for hint file filtering (#7795) fix: remap max_completion_tokens to max_tokens for OpenAI-compatible providers (#7765) fix(openai): preserve Responses API tool call/output linkage (#7759) chore(deps): bump @hono/node-server from 1.19.9 to 1.19.11 in /evals/open-model-gym/mcp-harness (#7687) fix: return ContextLengthExceeded when prompt exceeds effective KV cache size (#7815) feat: MCP Roots support (#7790) fix(google): use `includeThoughts/part.thought` for thinking handling (#7593) refactor: simplify tokenizer initialization — remove unnecessary Result wrapper (#7744) Fix model selector showing wrong model in tabs (#7784) Stop collecting goosed stderr after startup (#7814) fix: avoid word splitting by space for windows shell commands (#7781) (#7810) Simplify and make it not break on linux (#7813) Add preferred microphone selection (#7805) Remove dependency on posthog-rs (#7811) feat: load hints in nested subdirs (#7772) feat(acp): add read tool and delegate filesystem I/O to ACP clients (#7668) Support secret interpolation in streamable HTTP extension URLs (#7782) More logging for command injection classifier model training (#7779) ...
fixes #6556
needs modelcontextprotocol/rust-sdk#742
demo
demo of it with a server that has a tool which lists roots from client and returns them from the tool