fix(mcp): bind tenant to session — bearer context was lost over HTTP (#226)
CI / Check (push) Skipped
CI / Detect Changes (push) Successful in 2s
CI / Deploy Agent (push) Skipped
CI / Deploy Dashboard (push) Skipped
CI / Deploy Docs (push) Skipped
CI / Deploy MCP (push) Successful in 1m57s

This commit was merged in pull request #226.
This commit is contained in:
2026-07-22 09:30:07 +00:00
parent 3e233da128
commit 7d5c95ddb8
2 changed files with 25 additions and 22 deletions
+16 -9
View File
@@ -42,7 +42,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let pool_for_factory = pool.clone();
let service = StreamableHttpService::new(
move || Ok(ComplianceMcpServer::new(pool_for_factory.clone())),
move || {
// The factory runs in the request task, still inside the bearer
// middleware's `TENANT_ID` scope, and BEFORE rmcp spawns the
// session task (which would lose the task_local). So bind the
// tenant into the session's server instance here, once.
let tenant_id = auth::current_tenant_id().ok_or_else(|| {
std::io::Error::other("no tenant context when creating MCP session")
})?;
Ok(ComplianceMcpServer::new(
pool_for_factory.clone(),
tenant_id,
))
},
Arc::new(LocalSessionManager::default()),
StreamableHttpServerConfig::default(),
);
@@ -69,16 +81,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
tenant_id = %synth_tenant,
"stdio transport — using synthetic tenant id; DO NOT use in production"
);
let server = ComplianceMcpServer::new(pool);
let server = ComplianceMcpServer::new(pool, synth_tenant);
let transport = rmcp::transport::stdio();
use rmcp::ServiceExt;
auth::TENANT_ID
.scope(synth_tenant, async {
let handle = server.serve(transport).await?;
handle.waiting().await?;
Ok::<_, Box<dyn std::error::Error>>(())
})
.await?;
let handle = server.serve(transport).await?;
handle.waiting().await?;
}
Ok(())