Skip to content

feat(cli): --bearer / --header for auth-gated MCP endpoints - #27

Merged
reaatech merged 3 commits into
mainfrom
feat/cli-bearer-header-auth
Jun 29, 2026
Merged

feat(cli): --bearer / --header for auth-gated MCP endpoints#27
reaatech merged 3 commits into
mainfrom
feat/cli-bearer-header-auth

Conversation

@reaatech

Copy link
Copy Markdown
Owner

Closes #26.

mcp-contract-kit test connected anonymously, so MCP servers whose transport requires auth returned HTTP 401 and ran 0 suites. The header pipeline already existed end-to-end (runTests → createMCPClient → HttpTransport); it just wasn't reachable — no CLI flag, and runTestCommand dropped headers.

Changes

  • config.ts: parse --bearer <token> (→ Authorization: Bearer) and repeatable --header "Name: Value"; documented in --help.
  • test.command.ts: forward headers into runTests.
  • 6 unit tests for the parsing.
  • changeset: @reaatech/mcp-contract-cli minor → 0.2.0.

Verified

Build, typecheck, biome, and vitest all green. End-to-end against the MediaLocker MCP gateway: --bearer resolves the 401 (the kit now authenticates and proceeds past the auth hook).

reaatech added 3 commits June 29, 2026 12:53
`mcp-contract-kit test` connected anonymously, so MCP servers whose transport
requires auth returned HTTP 401 on connect and ran 0 suites. The header
pipeline already existed end-to-end (runTests → createMCPClient → HttpTransport);
it just wasn't reachable: the CLI had no flag, and runTestCommand dropped
`headers` when building RunOptions.

- config.ts: parse `--bearer <token>` (→ Authorization: Bearer) and repeatable
  `--header "Name: Value"`; document both in --help.
- test.command.ts: forward `headers` into runTests.
- tests: cover parsing (bearer, header trimming, repeats, colon-in-value, error).

Closes #26.
…-RPC errors

Make the conformance client work end-to-end against an MCP Streamable HTTP
server (auth-gated or not). Previously, after `initialize` succeeded, every
follow-up request failed and the suites couldn't run.

- transport: send `Accept: application/json, text/event-stream` by default
  (servers answer HTTP 406 without it); normalize header names to lowercase so
  an explicit `--header Accept`/`--bearer` cleanly overrides defaults.
- client: capture the server-assigned `Mcp-Session-Id` from the initialize
  response and echo it on all later requests (previously a throwaway id → 400).
- transport: when a non-2xx response carries a valid JSON-RPC body (e.g. 400
  "Invalid Request"), return it instead of throwing, so validators see the real
  JSON-RPC error.
- validators(jsonrpc): per spec, allow a null id on Invalid Request (-32600) and
  Parse error (-32700) responses instead of flagging an id mismatch.

Adds client tests (Accept default, session capture/echo, header override).
Verified against the MediaLocker MCP gateway: protocol + security suites pass
0 critical.

Bumps client minor (0.2.0), validators patch (0.1.2), cli patch (0.2.1).
…ring>

The root `tsc -p tsconfig.typecheck.json` (the CI Type Check job) includes test
files and is stricter than the per-package typecheck. The `extra` ternary
widened to `{ 'mcp-session-id'?: undefined }`, which isn't assignable to the
mock's `Record<string, string>` headers param. Annotate it explicitly. Test-only
change; the published dist is unaffected.
@reaatech
reaatech merged commit 2a0fcca into main Jun 29, 2026
10 of 12 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.

test: support authenticating to Bearer-gated MCP endpoints (--bearer/--header)

1 participant