Skip to content

feat(mcp): authenticated remote MCP server support (bearer token + custom headers)#39

Merged
mudler merged 7 commits into
masterfrom
feat/mcp-remote-auth
Jul 1, 2026
Merged

feat(mcp): authenticated remote MCP server support (bearer token + custom headers)#39
mudler merged 7 commits into
masterfrom
feat/mcp-remote-auth

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

Summary

wiz already supports remote MCP servers over HTTP (Streamable) and SSE transports, but had no way to authenticate to them. This adds bearer-token and custom-header auth support, per docs/superpowers/specs/2026-07-01-mcp-remote-auth-design.md (local-only spec, not part of this diff since docs/superpowers/ is gitignored).

  • types.MCPServer gains BearerToken and Headers fields (types/config.go), validated in Configurator.AddMCPServer: only valid for remote (url-based) servers, and rejected if BearerToken and a Headers["Authorization"] entry are both set (case-insensitive).
  • A new mcp/auth.go builds a *http.Client that injects the token/headers into every outgoing request via a header-injecting http.RoundTripper, built once and statically from config (no per-request resolution, no token refresh). Returns nil when no auth is configured, preserving today's behavior for unauthenticated remote servers.
  • Wired into TransportForServer (mcp/clienttransport.go) via the HTTPClient field already exposed by both SSEClientTransport and StreamableClientTransport in go-sdk v1.0.0.
  • CLI: nib mcp add <name> --url <url> --token <token> / --header K=V (repeatable), mirroring the existing --env flag pattern.
  • Agent self-config tool: add_mcp_server gains token/headers args (same KEY=VALUE shape as the existing env arg).
  • Redaction: nib mcp list and the list_mcp_servers agent tool show (authenticated) for configured servers and never print the token/header values — enforced structurally via a computed MCPServerInfo.Authenticated bool that carries no secret fields.
  • Secrets are stored plaintext in the user config file, same trust model as the existing Env field — no keychain, no env-var interpolation (deliberate, matches the rest of the config).

Implemented via TDD across 7 sequential tasks (docs/superpowers/plans/2026-07-01-mcp-remote-auth.md, also local-only), each independently reviewed, plus a final whole-branch review (verdict: ready to merge) and one fix pass closing the review's Minor coverage findings.

Test plan

  • go build ./... and go test ./... pass across all packages
  • New unit tests: header-injection via real httptest servers (mcp/auth_test.go), validation rules incl. the case-insensitive Authorization conflict (manage/mcpconfig_test.go), transport wiring (mcp/clienttransport_test.go), CLI flag parsing incl. =-containing header values (cmd/mcpmanage_test.go), self-config tool + redaction leak-check (chat/selfconfig_test.go)
  • Manual CLI smoke test of nib mcp add --token / nib mcp list / nib mcp remove against a built binary

🤖 Generated with Claude Code

mudler and others added 7 commits July 1, 2026 13:25
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…cp_servers

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- mcp/auth_test.go: assert combined BearerToken + custom Headers both
  land on the same request at the http.Client level.
- manage/mcpconfig_test.go: cover the headers-only -> Authenticated=true
  branch (the len(Headers) > 0 side of the OR).
- cmd/mcpmanage_test.go: assert --header X-Foo=a=b parses value "a=b"
  (strings.Cut splits on first = only).
- manage/mcpconfig.go: document that Authenticated marks ANY custom
  header, not just real auth tokens (deliberate simplification).

Test-only + one doc comment; no production behavior change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@mudler mudler merged commit 63b9b96 into master Jul 1, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants