cd /news/ai-agents/one-mcp-server-five-auth-shapes-per-… · home › topics › ai-agents › article
[ARTICLE · art-155688] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

One MCP server, five auth shapes: per-seat door credentials when a client can't send a header

A developer shipped Commons v0.5.0, an MCP server that accepts per-seat "door credentials" in five presentation shapes — Bearer header, URL path, URL query, X-Api-Key header, and Basic auth — all resolving through a single identity function. The change unblocked three URL-only model seats (ChatGPT, Gemini, Copilot) that could not send an Authorization header, without adopting OAuth. Each door secret is stored hashed, shown once at mint time, and revocable independently of the seat's root token.

by read2 min views1 publishedOct 22, 2026

Here's a problem I didn't expect to be the blocker.

I had three model seats — ChatGPT, Gemini, Copilot — already working against one MCP server (my Canonical Vault, which does no transport credential check; governance lives server-side in branch rules). Those surfaces connect URL-only.

My newer MCP server, the Commons, accepted exactly one presentation: Authorization: Bearer <token>.

Result: three credentialed seats, zero connections. Not a permissions problem. A presentation problem.

OAuth was the obvious textbook answer — and the wrong first move. The seats didn't need a new identity system. They needed a door shaped like the one they already walk through.

Ship a per-seat secret that can be presented in whatever shape the client can actually send, all resolving through one identity function:

| Presentation | Shape |

|---|---|
| Bearer (original) | `Authorization: Bearer <secret>` | 

| URL path | POST /mcp/s/<secret> |

| URL query | `POST /mcp?k=<secret>` | 
| API key header | `X-Api-Key: <secret>` | 
| Basic password | `Authorization: Basic <user>:<secret>` | 

Rules that make this safe enough to ship:

003_door_credentials). The plaintext is shown once, at mint time, in a connection sheet the operator hands to that seat's surface.authenticate() path. No shape gets a weaker check. A bogus secret returns unauthenticated in issue-door / revoke-door. Revoking a seat's door does not touch its root token, and vice versa. I verified this on a throwaway door: revoked door → revoked, root token unaffected. Commons v0.5.0, in production:

/mcp/s/<secret>, and ?k= through the one identity functionwhoami through the door itself + every alternate shape, per seat0.5.0 Remaining step is deliberately manual: add each door URL in that seat's own surface. Credentials cross into another vendor's UI only by the operator's hand.

Use door credentials when: Don't use them when:

I demoted OAuth and a REST shim to optional hardening, in that order. The unblocking move was meeting the clients at the presentation they already had — without weakening the one rule that matters: identity is a credential, never a claim, and the server derives it the same way no matter which door you came through.

Part of the "Building Governed Agents" series. Previous: "The Commons: Claims, Never Commands." Code context: the Commons is an append-only MCP pool where models exchange claims under governance — source currently in a private repo, protocol described in the series. Paper: doi.org/10.5281/zenodo.23242126 · Writing: liminaljermo.substack.com

Hit the same wall with an MCP client that can't send headers? I want to hear which shape you shipped.

── more in #ai-agents 4 stories · sorted by recency
── more on @commons 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/one-mcp-server-five-…] indexed:0 read:2min 2026-10-22 · —