You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Summary
🤖 Generated with [Nori](https://www.npmjs.com/package/nori-ai)
- **Fix OAuth tokens not reaching ACP agent:** Stored OAuth tokens (from
browser login via keyring or `.credentials.json`) are now loaded and
injected as `Authorization: Bearer` headers when converting MCP server
configs to SACP protocol types. Previously only `bearer_token_env_var`
was checked — tokens from OAuth login were stored but never sent to the
agent.
- **Fix disabled servers being sent:** MCP servers with `enabled ==
false` are now filtered out of the SACP conversion instead of being sent
to the agent.
- **Fix OAuth branding:** DCR client name changed from "Codex" to "Nori"
so OAuth login pages show the correct app name. Keyring service name
changed to "Nori TUI MCP Credentials".
## Test Plan
- [x] Unit tests for OAuth token injection
(`http_server_with_stored_oauth_tokens_gets_auth_header`)
- [x] Unit test for bearer token env var precedence over stored OAuth
(`bearer_token_env_var_takes_precedence_over_stored_oauth`)
- [x] Unit test for disabled server filtering
(`disabled_servers_are_excluded`)
- [x] TUI verification via tmux: `/mcp` picker renders, HTTP server can
be added, config is persisted to `config.toml`
- [ ] Manual test: Add Linear MCP server, complete OAuth login, restart
session, verify agent can use Linear tools
Share Nori with your team: https://www.npmjs.com/package/nori-skillsets
Co-authored-by: Nori <contact@tilework.tech>
Environment variable references (`bearer_token_env_var`, `env_http_headers`, `env_vars`) are resolved eagerly from the current process environment at conversion time. Missing variables are logged as warnings and skipped -- they do not cause errors. The `client_id` and `client_secret_env_var` fields on `StreamableHttp` are not forwarded to the agent -- they are only used by the TUI/rmcp-client layer for OAuth login flows (see `@/nori-rs/rmcp-client/docs.md`). All servers are included regardless of the `enabled` flag; the agent decides how to handle them. Results are sorted by server name for deterministic ordering.
573
+
Disabled servers (`enabled == false`) are filtered out before conversion. Environment variable references (`bearer_token_env_var`, `env_http_headers`, `env_vars`) are resolved eagerly from the current process environment at conversion time. Missing variables are logged as warnings and skipped -- they do not cause errors. The `client_id` and `client_secret_env_var` fields on `StreamableHttp` are not forwarded to the agent -- they are only used by the TUI/rmcp-client layer for OAuth login flows (see `@/nori-rs/rmcp-client/docs.md`). Results are sorted by server name for deterministic ordering.
574
+
575
+
**OAuth token injection for HTTP servers:** For `StreamableHttp` servers, `to_sacp_mcp_servers()` resolves authentication headers using a priority chain:
576
+
1.`bearer_token_env_var` -- if present and the env var resolves, used as `Authorization: Bearer` header
577
+
2. Stored OAuth tokens -- if no bearer token env var was resolved, `load_oauth_tokens()` from `@/nori-rs/rmcp-client/src/oauth.rs` is called to load credentials from the system keyring or `CODEX_HOME/.credentials.json` fallback file
578
+
3. No auth -- if neither source produces a token, the server is forwarded without an `Authorization` header
579
+
580
+
This means `to_sacp_mcp_servers()` has side effects (reads from keyring/file system) rather than being a pure config transformation. The `acp` crate depends on `codex-rmcp-client`'s `load_oauth_tokens` for this purpose.
574
581
575
582
`create_session()` accepts a `mcp_servers: Vec<McpServer>` parameter that is populated by calling `to_sacp_mcp_servers()` at each session creation site:
576
583
-`spawn_and_relay.rs` -- initial session creation during backend spawn
Copy file name to clipboardExpand all lines: nori-rs/rmcp-client/docs.md
+8-3Lines changed: 8 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,8 @@ The rmcp-client crate provides a high-level MCP client for connecting to remote
8
8
9
9
### How it fits into the larger codebase
10
10
11
-
Used by `@/nori-rs/core/` (`mcp_connection_manager.rs`) to establish connections to configured MCP servers that provide additional tools to the AI model.
11
+
- Used by `@/nori-rs/core/` (`mcp_connection_manager.rs`) to establish connections to configured MCP servers that provide additional tools to the AI model
12
+
- Used by `@/nori-rs/acp/src/connection/mcp.rs` to load stored OAuth tokens at session creation time, so the ACP agent receives credentials for MCP servers that were authenticated via the OAuth browser flow
12
13
13
14
### Core Implementation
14
15
@@ -23,6 +24,7 @@ Used by `@/nori-rs/core/` (`mcp_connection_manager.rs`) to establish connections
23
24
- Two OAuth login entry points, both backed by the same `wait_for_callback_or_cancel()` mechanism (biased `tokio::select!` between callback, cancel signal, and 5-minute timeout):
24
25
-`perform_oauth_login()` - Blocking/interactive flow that uses `println!` for status and `stdin` Enter for cancellation. Used by CLI contexts where TUI suspension is acceptable.
25
26
-`start_oauth_login()` - Non-blocking async flow that returns an `OAuthLoginHandle`. The handle exposes a `cancel_tx: Option<oneshot::Sender<()>>` for programmatic cancellation and a `task: JoinHandle<Result<()>>` for awaiting completion. Used by the TUI to run OAuth inline without suspending the terminal. Accepts optional `client_id` and `client_secret` parameters to select between two OAuth paths (see below).
27
+
- Dynamic client registration (DCR) uses `"Nori"` as the client name presented to OAuth servers
26
28
- Token refresh handling via `OAuthPersistor`, which is called after every MCP request
-`load_oauth_tokens` is public and used by `@/codex-rs/acp/src/connection/mcp.rs` to inject stored OAuth tokens when forwarding MCP server configs to ACP agents
51
+
- Keyring service name: `"Nori TUI MCP Credentials"`. Credentials stored under the previous service name are not migrated
52
+
- Fallback file: `CODEX_HOME/.credentials.json` (used when keyring is unavailable or fails)
0 commit comments