Skip to content

tests: add MCP auth e2e collection covering discovery, credential matrix, OAuth issuance, refresh rotation, revocation window, and runtime mode flip - #4525

Merged
Pratham-Mishra04 merged 1 commit into
devfrom
06-18-feat_mcp_oauth_server_e2e_tests
Jun 30, 2026
Merged

tests: add MCP auth e2e collection covering discovery, credential matrix, OAuth issuance, refresh rotation, revocation window, and runtime mode flip#4525
Pratham-Mishra04 merged 1 commit into
devfrom
06-18-feat_mcp_oauth_server_e2e_tests

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

Adds a comprehensive end-to-end test suite for MCP inbound authentication, covering all three server auth modes (headers, both, oauth) in a single Postman collection driven by a dedicated Newman runner.

Changes

  • Added bifrost-v1-mcp-auth.postman_collection.json with five new test folders:
    • Config validation: asserts that unknown mcp_server_auth_mode values and oauth2_server_config payloads sent with headers mode are rejected with 400, and that the boot mode round-trips correctly through GET /api/config.
    • Full OAuth flow (virtual-key identity): covers dynamic client registration, PKCE-S256 authorize, consent bound to a virtual key, token exchange, JWT connect to /mcp, refresh rotation, and stolen-token family revocation (replaying a rotated refresh token revokes the entire grant family).
    • Revocation window: issues a fresh grant, revokes it via the management API, then asserts that the refresh token is immediately rejected while the already-issued short-lived access token continues to connect until expiry.
    • Full OAuth flow (session identity): consent mints a server-side session identity, the resulting JWT connects to /mcp, and then enabling enforce_auth_on_inference at runtime causes that same session token to be rejected.
    • Runtime config flip (headers → both): from a headers-mode boot, upgrades to both via PUT /api/config, confirms discovery endpoints come alive, and verifies header-VK connections are unaffected.
  • All test scripts branch on the auth_mode env-var so a single collection encodes the full credential matrix across modes; steps that do not apply to a given mode are skipped with a passing no-op assertion.
  • Added --ignore-redirects to the Newman invocation in run-newman-mcp-auth-tests.sh so that authorize redirects are captured as 302 responses rather than followed, allowing the collection to extract flow IDs from Location headers.
  • Updated README.md with a full description of the new collection and runner, including per-mode assertion summaries and local run instructions.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

Run the MCP auth test suite locally from tests/e2e/api:

./runners/individual/run-newman-mcp-auth-tests.sh --binary /path/to/bifrost-http

# Optional flags
# --port <port>   (default 8090)
# --html          emit HTML report
# --json          emit JSON report
# --verbose       verbose Newman output
# --bail          stop on first failure

The runner builds and starts the upstream MCP server (examples/mcps/http-no-ping-server), boots a fresh server instance per mcp_server_auth_mode, pre-seeds an MCP client and two virtual keys (one active, one inactive), and executes the collection against each mode in sequence. A built bifrost-http binary is required.

Screenshots/Recordings

N/A

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

The collection exercises the full OAuth 2.0 issuance surface including PKCE, refresh rotation, stolen-token family revocation, and the revocation window. No secrets are introduced; all credentials are ephemeral test values seeded by the runner.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Pratham-Mishra04 commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Pratham-Mishra04, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 7 minutes and 15 seconds. Learn how PR review limits work.

To continue reviewing without waiting, enable usage-based billing in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2452eed3-fca9-4446-96a2-c8446362809a

📥 Commits

Reviewing files that changed from the base of the PR and between fb2ee5f and 6071377.

📒 Files selected for processing (3)
  • tests/e2e/api/README.md
  • tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
  • tests/e2e/api/runners/individual/run-newman-mcp-auth-tests.sh
📝 Walkthrough

Walkthrough

Extends the MCP auth Postman collection with config validation, full OAuth virtual-key identity and session identity flows, revocation window tests, and a runtime config flip scenario. The Newman runner gains --ignore-redirects, and the README gains a new MCP Auth Tests documentation section.

Changes

MCP Auth E2E Test Suite Expansion

Layer / File(s) Summary
Newman runner flag and README documentation
tests/e2e/api/runners/individual/run-newman-mcp-auth-tests.sh, tests/e2e/api/README.md
Adds --ignore-redirects to newman run in the MCP auth runner and introduces a README section documenting the collection paths, per-mode boot strategy, per-mode acceptance/rejection expectations, and the local run command with options.
Config validation tests
tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
Adds a Config validation suite that PUTs invalid mcp_server_auth_mode and incompatible oauth2_server_config to /api/config (expecting 400), then round-trips a GET to confirm the boot mode persists.
Full OAuth flows: virtual-key identity and revocation window
tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
Adds end-to-end virtual-key identity OAuth tests (DCR, PKCE S256 authorize, virtual-key consent binding, token exchange, /mcp connection, refresh rotation, stolen-family revocation after replay) and revocation window tests (management API revocation, immediate refresh failure, access token still valid within window).
Session identity flow and runtime config flip
tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
Adds session-mode OAuth consent tests confirming /mcp connectivity when enforce_auth_on_inference is off and rejection after runtime enable, plus a headers-boot-only test that flips mcp_server_auth_mode to both, confirms discovery endpoints appear, and verifies header-based virtual-key /mcp remains non-401.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • akshaydeo
  • danpiths

Poem

🐇 Hoppity-hop through the OAuth maze,
Where tokens rotate and sessions ablaze,
The rabbit checks headers, then flips the mode switch,
Revocation windows — no token can snitch!
With --ignore-redirects, we leap without fear,
The MCP auth tests have finally arrived here. 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically summarizes the main change: adding a comprehensive MCP auth e2e test collection covering multiple scenarios (discovery, OAuth issuance, refresh rotation, revocation window, runtime mode flip).
Description check ✅ Passed The PR description is well-structured and substantially complete. It includes a clear summary, detailed changes breakdown, type of change selection, affected areas, comprehensive testing instructions, security considerations, and properly completed checklist items.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 06-18-feat_mcp_oauth_server_e2e_tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Test-only addition; no production code is touched and no existing tests are modified.

All three changed files are test infrastructure: a Postman collection, a Newman runner shell script (one-line change), and a README update. The collection logic is sound — PKCE setup is consistent between client and server, the snapshot-based grant isolation cleanly addresses the ordering ambiguity flagged in a prior review, and the mode-branching skip pattern is applied uniformly. The --ignore-redirects flag is scoped to this runner only and is necessary to capture the authorize 302. No regressions to existing tests and no production paths are affected.

No files require special attention.

Important Files Changed

Filename Overview
tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json Adds five new test folders covering Config validation, VK-identity OAuth flow with PKCE/refresh rotation/family revocation, Revocation window (using snapshot-based grant isolation), session-identity OAuth flow with enforce_auth_on_inference flip, and headers→both runtime upgrade; mode-branching pattern is consistent and correct throughout.
tests/e2e/api/runners/individual/run-newman-mcp-auth-tests.sh Single-line addition of --ignore-redirects to the Newman invocation, required for capturing the 302 from /oauth2/authorize rather than following it to the (non-existent) callback URI; no logic changes to server boot or cleanup paths.
tests/e2e/api/README.md Adds documentation for the new MCP auth collection and runner, including per-mode assertion summaries and local run instructions; accurate and consistent with the implementation.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant NM as Newman
    participant BF as Bifrost HTTP
    participant DB as SQLite

    Note over NM,DB: Full OAuth flow (both/oauth modes)

    NM->>BF: POST /oauth2/register
    BF-->>NM: "201 {client_id}"

    NM->>BF: "GET /oauth2/authorize?code_challenge=S256&..."
    BF-->>NM: "302 Location: /oauth/consent?flow={flow_id}"

    NM->>BF: "PUT /api/oauth2/consent/flows/{flow_id}"
    BF->>DB: bind identity to flow
    BF-->>NM: "200 {redirect_url?code=auth_code}"

    NM->>BF: POST /oauth2/token (authorization_code + code_verifier)
    BF->>DB: validate PKCE + issue tokens
    BF-->>NM: "200 {access_token, refresh_token, expires_in:600}"

    NM->>BF: POST /mcp (Authorization: Bearer access_token)
    BF-->>NM: 200 MCP initialize response

    NM->>BF: POST /oauth2/token (refresh_token RT1)
    BF->>DB: rotate refresh token
    BF-->>NM: "200 {access_token, refresh_token:RT2}"

    NM->>BF: POST /oauth2/token (replay RT1)
    BF->>DB: detect theft, revoke family
    BF-->>NM: 400 invalid_grant

    NM->>BF: POST /oauth2/token (RT2 after family revocation)
    BF-->>NM: 400 invalid_grant

    Note over NM,DB: Revocation window
    NM->>BF: GET /api/oauth2/sessions (pre-snapshot)
    BF-->>NM: "200 {sessions:[existing ids]}"
    NM->>BF: authorize + consent + exchange (new grant)
    NM->>BF: GET /api/oauth2/sessions
    BF-->>NM: 200 (set-diff isolates new grant id)
    NM->>BF: "DELETE /api/oauth2/sessions/{rev_grant_id}"
    BF-->>NM: 204
    NM->>BF: POST /oauth2/token (refresh after revoke)
    BF-->>NM: 400 invalid_grant
    NM->>BF: POST /mcp (access token still within window)
    BF-->>NM: 200 (stateless JWT not yet expired)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant NM as Newman
    participant BF as Bifrost HTTP
    participant DB as SQLite

    Note over NM,DB: Full OAuth flow (both/oauth modes)

    NM->>BF: POST /oauth2/register
    BF-->>NM: "201 {client_id}"

    NM->>BF: "GET /oauth2/authorize?code_challenge=S256&..."
    BF-->>NM: "302 Location: /oauth/consent?flow={flow_id}"

    NM->>BF: "PUT /api/oauth2/consent/flows/{flow_id}"
    BF->>DB: bind identity to flow
    BF-->>NM: "200 {redirect_url?code=auth_code}"

    NM->>BF: POST /oauth2/token (authorization_code + code_verifier)
    BF->>DB: validate PKCE + issue tokens
    BF-->>NM: "200 {access_token, refresh_token, expires_in:600}"

    NM->>BF: POST /mcp (Authorization: Bearer access_token)
    BF-->>NM: 200 MCP initialize response

    NM->>BF: POST /oauth2/token (refresh_token RT1)
    BF->>DB: rotate refresh token
    BF-->>NM: "200 {access_token, refresh_token:RT2}"

    NM->>BF: POST /oauth2/token (replay RT1)
    BF->>DB: detect theft, revoke family
    BF-->>NM: 400 invalid_grant

    NM->>BF: POST /oauth2/token (RT2 after family revocation)
    BF-->>NM: 400 invalid_grant

    Note over NM,DB: Revocation window
    NM->>BF: GET /api/oauth2/sessions (pre-snapshot)
    BF-->>NM: "200 {sessions:[existing ids]}"
    NM->>BF: authorize + consent + exchange (new grant)
    NM->>BF: GET /api/oauth2/sessions
    BF-->>NM: 200 (set-diff isolates new grant id)
    NM->>BF: "DELETE /api/oauth2/sessions/{rev_grant_id}"
    BF-->>NM: 204
    NM->>BF: POST /oauth2/token (refresh after revoke)
    BF-->>NM: 400 invalid_grant
    NM->>BF: POST /mcp (access token still within window)
    BF-->>NM: 200 (stateless JWT not yet expired)
Loading

Reviews (20): Last reviewed commit: "feat: mcp oauth server e2e tests" | Re-trigger Greptile

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 395dd0c to a5fa0bd Compare June 18, 2026 12:22
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch 2 times, most recently from 32e4bc0 to 0fc852e Compare June 18, 2026 12:47
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from a5fa0bd to fb2ee5f Compare June 18, 2026 12:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/e2e/api/README.md`:
- Around line 268-269: The documentation comment for MCP auth runner options is
missing the `--mcp-port` flag from the list of supported options. Update the
comment line that documents the runner options (currently showing `--port`,
`--html`, `--json`, `--verbose`, `--bail`) to also include `--mcp-port` with an
appropriate description (e.g., default port number for MCP server). This will
allow users to easily discover and use the flag when configuring local test
runs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 76273975-5e1a-4083-b462-b4bf00757edd

📥 Commits

Reviewing files that changed from the base of the PR and between 395dd0c and fb2ee5f.

📒 Files selected for processing (3)
  • tests/e2e/api/README.md
  • tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
  • tests/e2e/api/runners/individual/run-newman-mcp-auth-tests.sh

Comment thread tests/e2e/api/README.md Outdated
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from 0fc852e to 69dff03 Compare June 22, 2026 13:15
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from fb2ee5f to 6071377 Compare June 22, 2026 13:15
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from 69dff03 to a0d848e Compare June 22, 2026 16:58
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 6071377 to 401b8ea Compare June 22, 2026 16:58
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from a0d848e to e2e77f5 Compare June 23, 2026 05:30
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 401b8ea to bbcb5a4 Compare June 23, 2026 05:30
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from 6d48620 to ae74b23 Compare June 28, 2026 17:52
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from a8ff1fa to 349ffaa Compare June 28, 2026 17:52
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from ae74b23 to 8407ccc Compare June 29, 2026 10:59
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 349ffaa to 4b068be Compare June 29, 2026 10:59
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 4b068be to e340e87 Compare June 29, 2026 18:18
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from 8407ccc to 4aead7a Compare June 29, 2026 18:18
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from e340e87 to 96fc3d0 Compare June 30, 2026 07:53
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from 4aead7a to 6a8e256 Compare June 30, 2026 07:53
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 96fc3d0 to f4f46cd Compare June 30, 2026 11:43
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from 6a8e256 to fc9b3f1 Compare June 30, 2026 11:43
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from f4f46cd to de7872f Compare June 30, 2026 13:44
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from fc9b3f1 to d3dfd70 Compare June 30, 2026 13:44

Pratham-Mishra04 commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator Author

Merge activity

  • Jun 30, 1:53 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 30, 2:26 PM UTC: Graphite rebased this pull request as part of a merge.
  • Jun 30, 2:27 PM UTC: @Pratham-Mishra04 merged this pull request with Graphite.

@Pratham-Mishra04
Pratham-Mishra04 changed the base branch from 06-18-feat_adds_mcp_oauth_server_type_e2e_tests to graphite-base/4525 June 30, 2026 14:22
@Pratham-Mishra04
Pratham-Mishra04 changed the base branch from graphite-base/4525 to dev June 30, 2026 14:25
@Pratham-Mishra04
Pratham-Mishra04 dismissed coderabbitai[bot]’s stale review June 30, 2026 14:25

The base branch was changed.

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from de7872f to 685fcec Compare June 30, 2026 14:25
@Pratham-Mishra04
Pratham-Mishra04 merged commit 0de80a8 into dev Jun 30, 2026
15 of 16 checks passed
@Pratham-Mishra04
Pratham-Mishra04 deleted the 06-18-feat_mcp_oauth_server_e2e_tests branch June 30, 2026 14:27
akshaydeo pushed a commit that referenced this pull request Jul 1, 2026
…rix, OAuth issuance, refresh rotation, revocation window, and runtime mode flip (#4525)

## Summary

Adds a comprehensive end-to-end test suite for MCP inbound authentication, covering all three server auth modes (`headers`, `both`, `oauth`) in a single Postman collection driven by a dedicated Newman runner.

## Changes

- Added `bifrost-v1-mcp-auth.postman_collection.json` with five new test folders:
  - **Config validation:** asserts that unknown `mcp_server_auth_mode` values and `oauth2_server_config` payloads sent with `headers` mode are rejected with 400, and that the boot mode round-trips correctly through `GET /api/config`.
  - **Full OAuth flow (virtual-key identity):** covers dynamic client registration, PKCE-S256 authorize, consent bound to a virtual key, token exchange, JWT connect to `/mcp`, refresh rotation, and stolen-token family revocation (replaying a rotated refresh token revokes the entire grant family).
  - **Revocation window:** issues a fresh grant, revokes it via the management API, then asserts that the refresh token is immediately rejected while the already-issued short-lived access token continues to connect until expiry.
  - **Full OAuth flow (session identity):** consent mints a server-side session identity, the resulting JWT connects to `/mcp`, and then enabling `enforce_auth_on_inference` at runtime causes that same session token to be rejected.
  - **Runtime config flip (headers → both):** from a `headers`-mode boot, upgrades to `both` via `PUT /api/config`, confirms discovery endpoints come alive, and verifies header-VK connections are unaffected.
- All test scripts branch on the `auth_mode` env-var so a single collection encodes the full credential matrix across modes; steps that do not apply to a given mode are skipped with a passing no-op assertion.
- Added `--ignore-redirects` to the Newman invocation in `run-newman-mcp-auth-tests.sh` so that authorize redirects are captured as 302 responses rather than followed, allowing the collection to extract flow IDs from `Location` headers.
- Updated `README.md` with a full description of the new collection and runner, including per-mode assertion summaries and local run instructions.

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [ ] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

Run the MCP auth test suite locally from `tests/e2e/api`:

```sh
./runners/individual/run-newman-mcp-auth-tests.sh --binary /path/to/bifrost-http

# Optional flags
# --port <port>   (default 8090)
# --html          emit HTML report
# --json          emit JSON report
# --verbose       verbose Newman output
# --bail          stop on first failure
```

The runner builds and starts the upstream MCP server (`examples/mcps/http-no-ping-server`), boots a fresh server instance per `mcp_server_auth_mode`, pre-seeds an MCP client and two virtual keys (one active, one inactive), and executes the collection against each mode in sequence. A built `bifrost-http` binary is required.

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

The collection exercises the full OAuth 2.0 issuance surface including PKCE, refresh rotation, stolen-token family revocation, and the revocation window. No secrets are introduced; all credentials are ephemeral test values seeded by the runner.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
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