feat(mcp): bearer-token auth for the MCP HTTP transport#41
Merged
Conversation
Every /mcp request now requires an Authorization: Bearer token. Loopback binds auto-generate and persist a token on first run (printing client-config guidance); non-loopback binds require an explicit token via --mcp-token/--token or DYNOXIDE_MCP_AUTH_TOKEN. Also adds a configurable bind host (--mcp-host/--host) and a Host-allowlist flag for by-name access. Closes #27, unblocks #24.
Update SECURITY.md's threat model for the bearer-token requirement, add auth flags, client-header config, and rotation/shell-history guidance to the README, and record the breaking change in the changelog.
The new HTTP-options helper landed between run_mcp's cfg attribute and its signature, leaving run_mcp ungated and breaking the http-server-without-mcp feature build.
Trim explicit tokens (consistent with the presented-token and persisted-file paths), bracket IPv6 literals in operator-added Origin allowlist entries, fsync the token file so a lost-create-race reader sees a complete token, and make the token-source error messages subcommand-agnostic. Tolerate a tab after the Bearer scheme, drop the unused HttpOptions::new, and consolidate IPv6 bracketing into one helper. Adds tests: loopback still works alongside --allowed-host, --no-auth+--token still fails off-loopback, and the rejected-token 401 body matches the missing-token body. Documents the library-signature break and the Windows token-file story.
Criterion Benchmark Results
|
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.
Adds bearer-token authentication to the MCP HTTP transport, closing the direct-from-tooling gap the Host+Origin allowlist doesn't cover, plus a configurable bind host so the transport can be reached off-loopback.
Closes #27. Unblocks #24.
Auth model
/mcprequest requiresAuthorization: Bearer <token>. Missing and wrong tokens return a byte-identical401(no oracle) withWWW-Authenticate: Bearer realm="dynoxide-mcp"and noresource_metadata. Constant-time compare.~/.config/dynoxide/mcp-token,0600), printed once with a client snippet; reused silently after.--mcp-token/--tokenorDYNOXIDE_MCP_AUTH_TOKEN) or refuses to start.--no-authis a loopback-only escape hatch (prints a warning).Hoststill gets403.Breaking
mcp::serve_http/serve_http_with_shutdownnow takeHttpOptionsinstead of a bareport.dynoxide mcp --httpclients must now send anAuthorizationheader.Test plan
cargo test,cargo clippy -- -D warnings,cargo fmt --checkcargo check --no-default-features --features encryption,http-serverPost-deploy
Watch for sustained
401s from clients that are sending a valid token (failure signal); a transient bump as clients add the header is expected. Rollback if the auth layer rejects validly-tokened requests.