Skip to content

Commit 28a8717

Browse files
authored
feat(facade): session-aware in-process capability sources (#1454)
* feat(facade): session-aware in-process capability sources - sources module: CapabilitySource trait (optional SessionCtx per call, requires_session gating), SessionTokens registry (broker mints one opaque token per agent session, constant-time resolve, revoke on evict), per-request identity resolution from the Authorization header via the HTTP parts rmcp injects into request extensions. - facade: with_sources/serve_http_with; discovery merges source tools (downstream names win, shadowed source tools published as provider:tool); execution dispatches sources first with the same schema pre-flight the meta-tool applies, audit lines carry channel. - Session-bound sources are invisible AND unreachable to anonymous clients (no dangling catalog entries, nothing to probe). - Anonymous behavior with zero sources is byte-identical to before. Groundwork for routing #1447's per-session browser capability through the facade (one listener, one discovery surface). * test(facade): source visibility/exec/validation coverage + fix call sites * style: fmt * fix(facade): downstream-first execution precedence + full-HTTP e2e for session tokens Self-review findings: - BUG: execution dispatched sources before the downstream catalog while discovery publishes downstream-wins-bare-name — a source tool sharing a downstream tool's name would hijack calls addressed to the downstream tool. Execution now resolves the catalog first (mirroring the publish rule); shadowed source tools stay reachable via provider:tool. - GAP: the rmcp Parts-into-extensions mechanism (which token resolution rides on) had no end-to-end coverage. Added build_router + a tower oneshot test driving real HTTP initialize→tools/call with/without/ wrong Authorization, asserting source visibility flips accordingly. - constant_time_eq: black_box the accumulator so the claim is enforced, not asserted in a comment. * test: supply Host header (oneshot bypasses hyper) * chore: drop unused imports after router extraction * style: fmt * fix(facade): source-vs-source name collisions + audit parity for source calls Self-review round 2: - Discovery's collision set now grows as sources publish, so two sources sharing a tool name no longer produce duplicate catalog entries — the first registrant keeps the bare name, later ones publish as provider:tool (matching execution's registration-order resolution). - Source-call audit lines now carry args_sha256 like the meta_tool dispatcher's — one audit shape across both dispatch paths. * style: fmt --------- Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>
1 parent 2f93ad9 commit 28a8717

5 files changed

Lines changed: 639 additions & 30 deletions

File tree

crates/openab-mcp/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,7 @@ axum = { version = "0.8", default-features = false, features = ["http1", "tokio"
4646
libc = "0.2"
4747

4848
[dev-dependencies]
49+
tower = { version = "0.5", features = ["util"] }
50+
http-body-util = "0.1"
4951
tempfile = "3"
5052
temp-env = "0.3.6"

0 commit comments

Comments
 (0)