# Cat-1 live probes — raw evidence Target: `https://api.arcade.st.dev/mcp/zeb-gateway-test` (auth mode: Arcade Headers — API key + `Arcade-User-ID`). Client: `lib/mcp_client.py` (official `mcp` SDK, streamable HTTP). Date: 2026-06-18. ## Connect + list (as User A) — protocol compliance `connect_and_list` initialized an MCP session and returned 7 tools, no custom adapter: ``` Brightdata_ScrapeAsMarkdown GoogleDocs_CreateBlankDocument GoogleDocs_CreateDocumentFromText GoogleDocs_GetDocumentAsDocmd GoogleDocs_GetDocumentById Slack_SendMessage Slack_WhoAmI ``` Minor: client logs `Session termination failed: 202` on session close (server returns 202 to the streamable-HTTP session DELETE; benign — listing/calls succeed). Note as a protocol nit. ## Per-user visibility (User A vs User B) — criterion 3 Listed as `ARCADE_USER_A` and `ARCADE_USER_B`: ``` A count: 7 | B count: 7 A == B set?: True only in A: set() | only in B: set() ``` **Finding:** on a single gateway in Arcade-Headers mode the curated tool list is **gateway-wide, identical for every `Arcade-User-ID`** — not per-user. Per-user list differentiation would need Contextual Access (cat 3) or separate gateways / a User Source. (Token vault is still per-user_id.) ## Ungranted / unknown tool — benchmark Q5 Calling a tool not exposed by the gateway, as User A: ``` call_tool("Github_CreateIssue", {}) -> McpError: tool not enabled for this gateway ``` Clean rejection at the Engine; no leak, no execution. ## Invocation of an auth-requiring tool (Slack_WhoAmI) as User A — error responses ``` isError: True content: "unsupported authorization provider type ID '' (providerID 'slack')" ``` The Engine processed the call and failed cleanly because the Slack OAuth provider isn't configured (the gateway's "Missing Requirements"). Demonstrates: invocation routes through the Engine, returns a structured error result, and does **not** fall back to a shared credential. Clean per-call invocation without per-user OAuth + a project secret (e.g. serp_api_key) is deferred to the reference server (`echo`). ## Dynamic registration (2.5) — criteria 7 & 8, benchmark Q3 Edited `zeb-gateway-test` in the dashboard: removed `Brightdata_ScrapeAsMarkdown`, added `Youtube_SearchForVideos`. A fresh `tools/list`: ``` added since first probe: ['Youtube_SearchForVideos'] removed since first probe: ['Brightdata_ScrapeAsMarkdown'] ``` **PASS** — change took effect on the next list with **no engine/server restart** (gateway = pure metadata). Corollary: the edit did **not** propagate while unsaved (draft); it appeared only after **Save** — correct/expected, not a defect. Propagation was effectively immediate (next poll). ## Mixed prebuilt + custom + whoami execution proof (2.7, 2.4) — full self-hosted chain Registered the reference server (`arcade-mcp`, toolkit `ArcadeEvalRef`) as a **self-hosted Arcade server** via a Cloudflare tunnel (dashboard Add Server → **Arcade** type; URI = trycloudflare URL, Secret = `ARCADE_WORKER_SECRET`), then added Echo/Add/Whoami to `zeb-gateway-test`. (`arcade deploy` hosted is cloud-only — see LIVE-POC finding — so the register path is used.) Gateway lists **10 tools in one flat list — prebuilt + custom coexist**: ``` prebuilt (7): GoogleDocs x4, Slack x2, Youtube x1 (Arcade-cloud `main`) custom (3): ArcadeEvalRef_Add, _Echo, _Whoami (our self-hosted server, via tunnel) ``` Invocation (full chain client -> gateway -> Engine -> Cloudflare tunnel -> local server): ``` ArcadeEvalRef_Echo(text="hello-from-A") as A -> "hello-from-A" (isError: False) ``` **Per-user EXECUTION proof (whoami):** ``` whoami as A (user-a@servicetitan.com) -> "user-a@servicetitan.com" whoami as B (user-b@servicetitan.com) -> "user-b@servicetitan.com" ``` Each caller's `Arcade-User-ID` is injected into `context.user_id` and returned — the tool provably executes as the calling user (distinct identity per caller, no shared/service identity). Also validates **cat-9 Stage-2** (full tunnel-registration chain) end-to-end. ## Named MCP clients, no custom adapter (2.2) — criterion 4 **Claude Code:** added via `claude mcp add --transport http arcade-eval-cc -H 'Authorization: Bearer ${ARCADE_API_KEY}' -H 'Arcade-User-ID: ...'` (local scope). `claude mcp list`: ``` arcade-eval-cc: https://api.arcade.st.dev/mcp/zeb-gateway-test (HTTP) - ✔ Connected ``` No custom adapter. Key is **not** persisted: `~/.claude.json` holds `Bearer ${ARCADE_API_KEY}` (raw key count = 0, reference count = 1), expanded at runtime from the env. **Cursor:** `.cursor/mcp.json` (git-ignored) configured with the same gateway URL + `Bearer ${env:ARCADE_API_KEY}` header (Cursor resolves `${env:VAR}` in url/headers). Verified in the Cursor UI (launched from a shell with `.env` loaded). [user-confirmed — record result here]