Skip to content

feat: propagate request context through mcp client connection - #3768

Merged
Pratham-Mishra04 merged 1 commit into
devfrom
05-26-feat_adds_ctx_propogation_in_create_mcp_connection
May 27, 2026
Merged

feat: propagate request context through mcp client connection#3768
Pratham-Mishra04 merged 1 commit into
devfrom
05-26-feat_adds_ctx_propogation_in_create_mcp_connection

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

AddMCPClient and connectToMCPClient previously used the manager's background context when running connection hooks, which meant request-scoped values (such as HTTP headers extracted by the transport layer) were invisible to MCP plugins during the connect phase. This PR threads the caller's context.Context through AddMCPClient so that connect-time hooks can read request-scoped values while keeping persistent transport lifetimes bound to the manager context.

Changes

  • MCPManager.AddClient, Bifrost.AddMCPClient, and the internal connectToMCPClient now accept a context.Context parameter. The BifrostContext passed to connect/list-tools hooks is derived from the caller's context rather than the manager's background context.
  • ReconnectClient, EnableClient, and UpdateClientConnection continue to use the manager context (m.ctx) since they are infrastructure-initiated and have no caller request context.
  • NewMCPManager passes manager.ctx when calling AddClient during startup initialization, preserving existing behavior.
  • The HTTP transport's addMCPClient, completeMCPClientOAuth, and flowSubmit handlers now convert the incoming fasthttp.RequestCtx to a BifrostContext before calling AddMCPClient and related verification methods, so HTTP request headers are available to MCP plugins.
  • MCPManagerInterface updated to reflect the new AddClient signature.
  • The mcp-only plugin example logs request headers received in PreMCPConnectionHook to demonstrate the new capability.

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

go test ./core/...
go test ./transports/...

To verify that request headers are visible in a connect hook, configure the mcp-only plugin example with EnableLogging: true and call the POST /mcp/clients endpoint with custom headers. The plugin's PreMCPConnectionHook log line will print the headers extracted from the incoming request.

Breaking changes

  • Yes
  • No

MCPManagerInterface.AddClient and Bifrost.AddMCPClient now require a context.Context as the first argument. Any callers implementing or calling these interfaces directly must add a context argument (e.g. context.Background() as a minimal migration).

Related issues

Security considerations

Request headers passed through the context may contain credentials or tokens. MCP plugin authors should treat values read from BifrostContextKeyRequestHeaders as sensitive and avoid logging them in production.

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

@coderabbitai

coderabbitai Bot commented May 26, 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 2 minutes and 55 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more 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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fd420f6f-33e8-4424-80e9-06e34c12d6be

📥 Commits

Reviewing files that changed from the base of the PR and between fdf6555 and bab9c2e.

⛔ Files ignored due to path filters (3)
  • examples/mcps/temperature/package-lock.json is excluded by !**/package-lock.json
  • examples/mcps/test-tools-server/package-lock.json is excluded by !**/package-lock.json
  • examples/plugins/mcp-only/go.sum is excluded by !**/*.sum
📒 Files selected for processing (16)
  • core/bifrost.go
  • core/internal/mcptests/agent_filtering_test.go
  • core/internal/mcptests/client_management_test.go
  • core/internal/mcptests/concurrency_advanced_test.go
  • core/internal/mcptests/connect_ping_listtools_test.go
  • core/internal/mcptests/error_handling_protocol_test.go
  • core/internal/mcptests/health_monitoring_test.go
  • core/internal/mcptests/integration_test.go
  • core/mcp/clientmanager.go
  • core/mcp/interface.go
  • core/mcp/mcp.go
  • examples/plugins/mcp-only/main.go
  • transports/bifrost-http/handlers/mcp.go
  • transports/bifrost-http/handlers/mcp_per_user_headers.go
  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/server/server.go
📝 Walkthrough

Walkthrough

The pull request updates MCP client connection operations to accept and thread request-scoped context through the call stack. Method signatures are updated at the interface and implementation layers; HTTP handlers convert fasthttp contexts to Bifrost-aware contexts; and all call sites, including tests and examples, provide context parameters to enable connection hooks to observe per-request values.

Changes

MCP Request Context Threading

Layer / File(s) Summary
Interface and public API signature update
core/mcp/interface.go, core/bifrost.go
AddClient method signature updated to accept context.Context as first parameter in both the manager interface and bifrost public API, with inline documentation example updated to show new calling pattern.
Manager core context handling
core/mcp/clientmanager.go, core/mcp/mcp.go
MCPManager.AddClient accepts request-scoped context and connectToMCPClient is wired to use it for the connection-plugin gate BifrostContext. Reconnect and update paths pass manager context; parallel client registration during initialization is updated to provide explicit context.
HTTP handler context conversion and propagation
transports/bifrost-http/handlers/mcp.go, transports/bifrost-http/handlers/mcp_per_user_headers.go, transports/bifrost-http/lib/config.go, transports/bifrost-http/server/server.go
Incoming fasthttp request contexts are converted to Bifrost-aware contexts via lib.ConvertToBifrostContext and propagated through MCP tool verification, discovery, OAuth completion, and client registration operations.
Plugin example demonstrating request header access
examples/plugins/mcp-only/main.go
PreMCPConnectionHook updated to read and log request headers from the propagated Bifrost context using BifrostContextKeyRequestHeaders.
Test suite context integration
core/internal/mcptests/*_test.go
All test files updated to import context and provide context.Background() when calling manager.AddClient() across agent filtering, client management, concurrency, connection/ping, error handling, health monitoring, and integration test suites.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • danpiths
  • roroghost17

Poem

I’m a rabbit threading context strings,
Hopping headers through connection wings,
Hooks peek in and find the trace,
Request-scoped values in their place,
A tiny hop to steady the rings. 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature: propagating request context through MCP client connection, which is the central theme across all file changes in this PR.
Description check ✅ Passed The description is comprehensive and addresses all template sections including summary, changes, type, affected areas, testing, breaking changes, and security considerations with appropriate detail and clarity.
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 05-26-feat_adds_ctx_propogation_in_create_mcp_connection

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

@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.

@greptile-apps

greptile-apps Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 3/5

The connect-phase context threading works as advertised, but the list-tools phase that immediately follows still uses the manager context, so plugin hooks reading request headers during list-tools will silently receive nil.

The connect gate (runConnectWithPluginPipeline) correctly receives requestCtx, but toolRetrievalCtx at line 1444 of clientmanager.go is derived from m.ctx, not requestCtx. Any plugin that reads BifrostContextKeyRequestHeaders inside PreMCPHook or PostMCPHook when RequestType == MCPRequestTypeListTools will silently get nil — directly contradicting the PR description's explicit claim that list-tools hooks also use the caller's context.

core/mcp/clientmanager.go around the toolRetrievalCtx construction (line 1444)

Important Files Changed

Filename Overview
core/mcp/clientmanager.go Threads requestCtx through connect plugin gate but reverts to m.ctx for the immediately-following list-tools gate, making request headers unavailable in list-tools hooks despite the PR description claiming otherwise.
core/bifrost.go AddMCPClient updated to accept and propagate context.Context; delegation to MCPManager.AddClient is correct.
transports/bifrost-http/handlers/mcp.go addMCPClient and completeMCPClientOAuth now create a BifrostContext via ConvertToBifrostContext and pass it through; reconnect handler passes raw fasthttp.RequestCtx without header conversion in the fallback path, consistent with the PR's stated intent for reconnects.
transports/bifrost-http/server/server.go ReconnectMCPClient fallback path passes the caller context to AddMCPClient; since it's a raw context.Context (not a BifrostContext with headers), request headers won't propagate to connect hooks in this path.
examples/plugins/mcp-only/main.go Adds request-header logging to PreMCPConnectionHook for demonstration purposes (headers sensitivity concern already flagged in prior thread).

Comments Outside Diff (1)

  1. core/mcp/clientmanager.go, line 1444-1446 (link)

    P1 List-tools hook gate uses manager context, not the caller's request context

    The PR description states "The BifrostContext passed to connect/list-tools hooks is derived from the caller's context rather than the manager's background context." However, toolRetrievalCtx at line 1444 is derived from m.ctx, not from requestCtx. As a result, PreMCPHook/PostMCPHook callbacks that run with RequestType == MCPRequestTypeListTools will have ctx.Value(schemas.BifrostContextKeyRequestHeaders) return nil, even though the caller's context carries those headers into the connect phase (one step earlier). A plugin author following the mcp-only example who also reads headers in their list-tools hook will silently get nil.

Reviews (4): Last reviewed commit: "feat: adds ctx propogation in create mcp..." | Re-trigger Greptile

Comment thread examples/plugins/mcp-only/main.go
Comment thread core/mcp/clientmanager.go

@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: 2

🤖 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 `@core/bifrost.go`:
- Around line 3644-3648: The example calls AddMCPClient with a value but the
function now expects a *schemas.MCPClientConfig; fix by constructing the config
as a literal and passing its address (e.g. cfg := &schemas.MCPClientConfig{
Name: "my-mcp-client", ConnectionType: schemas.MCPConnectionTypeHTTP,
ConnectionString: &url }; err := bifrost.AddMCPClient(ctx, cfg)), referencing
AddMCPClient and schemas.MCPClientConfig so the code compiles.

In `@examples/plugins/mcp-only/main.go`:
- Around line 232-233: The current fmt.Printf logs raw header values from
ctx.Value(schemas.BifrostContextKeyRequestHeaders) which can leak secrets;
instead, replace the direct print with a sanitized log: retrieve the headers
(allHeaders), iterate over them and either (A) log only header names and counts
or (B) redact values for sensitive keys (e.g., "Authorization", "Cookie",
"Set-Cookie", "Proxy-Authorization", "X-Api-Key") by replacing their values with
"[REDACTED]" before formatting. Update the println call that references
allHeaders to call this sanitizer and log the sanitized map or names only.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5d4e3706-b1fb-49bc-8f67-ad1d0d714c79

📥 Commits

Reviewing files that changed from the base of the PR and between c30f927 and 098d015.

⛔ Files ignored due to path filters (3)
  • examples/mcps/temperature/package-lock.json is excluded by !**/package-lock.json
  • examples/mcps/test-tools-server/package-lock.json is excluded by !**/package-lock.json
  • examples/plugins/mcp-only/go.sum is excluded by !**/*.sum
📒 Files selected for processing (16)
  • core/bifrost.go
  • core/internal/mcptests/agent_filtering_test.go
  • core/internal/mcptests/client_management_test.go
  • core/internal/mcptests/concurrency_advanced_test.go
  • core/internal/mcptests/connect_ping_listtools_test.go
  • core/internal/mcptests/error_handling_protocol_test.go
  • core/internal/mcptests/health_monitoring_test.go
  • core/internal/mcptests/integration_test.go
  • core/mcp/clientmanager.go
  • core/mcp/interface.go
  • core/mcp/mcp.go
  • examples/plugins/mcp-only/main.go
  • transports/bifrost-http/handlers/mcp.go
  • transports/bifrost-http/handlers/mcp_per_user_headers.go
  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/server/server.go

Comment thread core/bifrost.go Outdated
Comment thread examples/plugins/mcp-only/main.go
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 27, 2026

Pratham-Mishra04 commented May 27, 2026

Copy link
Copy Markdown
Collaborator Author

Merge activity

  • May 27, 10:30 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 27, 10:54 AM UTC: Graphite rebased this pull request as part of a merge.
  • May 27, 10:55 AM UTC: @Pratham-Mishra04 merged this pull request with Graphite.

@Pratham-Mishra04
Pratham-Mishra04 changed the base branch from 05-25-docs_adds_custom_mcp_plugin_reference to graphite-base/3768 May 27, 2026 10:50
@Pratham-Mishra04
Pratham-Mishra04 changed the base branch from graphite-base/3768 to dev May 27, 2026 10:53
@Pratham-Mishra04
Pratham-Mishra04 dismissed coderabbitai[bot]’s stale review May 27, 2026 10:53

The base branch was changed.

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 05-26-feat_adds_ctx_propogation_in_create_mcp_connection branch from fdf6555 to bab9c2e Compare May 27, 2026 10:53
@Pratham-Mishra04
Pratham-Mishra04 merged commit e6553f7 into dev May 27, 2026
12 of 14 checks passed
@Pratham-Mishra04
Pratham-Mishra04 deleted the 05-26-feat_adds_ctx_propogation_in_create_mcp_connection branch May 27, 2026 10:55
akshaydeo pushed a commit that referenced this pull request May 29, 2026
## Summary

`AddMCPClient` and `connectToMCPClient` previously used the manager's background context when running connection hooks, which meant request-scoped values (such as HTTP headers extracted by the transport layer) were invisible to MCP plugins during the connect phase. This PR threads the caller's `context.Context` through `AddMCPClient` so that connect-time hooks can read request-scoped values while keeping persistent transport lifetimes bound to the manager context.

## Changes

- `MCPManager.AddClient`, `Bifrost.AddMCPClient`, and the internal `connectToMCPClient` now accept a `context.Context` parameter. The `BifrostContext` passed to connect/list-tools hooks is derived from the caller's context rather than the manager's background context.
- `ReconnectClient`, `EnableClient`, and `UpdateClientConnection` continue to use the manager context (`m.ctx`) since they are infrastructure-initiated and have no caller request context.
- `NewMCPManager` passes `manager.ctx` when calling `AddClient` during startup initialization, preserving existing behavior.
- The HTTP transport's `addMCPClient`, `completeMCPClientOAuth`, and `flowSubmit` handlers now convert the incoming `fasthttp.RequestCtx` to a `BifrostContext` before calling `AddMCPClient` and related verification methods, so HTTP request headers are available to MCP plugins.
- `MCPManagerInterface` updated to reflect the new `AddClient` signature.
- The `mcp-only` plugin example logs request headers received in `PreMCPConnectionHook` to demonstrate the new capability.

## Type of change

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

## Affected areas

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

## How to test

```sh
go test ./core/...
go test ./transports/...
```

To verify that request headers are visible in a connect hook, configure the `mcp-only` plugin example with `EnableLogging: true` and call the `POST /mcp/clients` endpoint with custom headers. The plugin's `PreMCPConnectionHook` log line will print the headers extracted from the incoming request.

## Breaking changes

- [x] Yes
- [ ] No

`MCPManagerInterface.AddClient` and `Bifrost.AddMCPClient` now require a `context.Context` as the first argument. Any callers implementing or calling these interfaces directly must add a context argument (e.g. `context.Background()` as a minimal migration).

## Related issues

## Security considerations

Request headers passed through the context may contain credentials or tokens. MCP plugin authors should treat values read from `BifrostContextKeyRequestHeaders` as sensitive and avoid logging them in production.

## 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
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