Forward the user's auth to your server
Your tool runs as the signed-in user. On every tools/call, DioscHub forwards that user’s auth to
your MCP server, your server authorizes the request against your own
system, and the tool acts with exactly that user’s permissions. This is
BYOA: DioscHub binds to no auth system of its own — it
carries yours through.
Read the auth from the HTTP request headers
Section titled “Read the auth from the HTTP request headers”DioscHub attaches the user’s auth to the tools/call request as HTTP request headers, using the
exact header names your host supplied when it bound the session (see Identity &
auth). Read them the way you would read auth on any inbound HTTP request:
server.tool( 'get_order', 'Look up an order by id for the signed-in user.', { orderId: z.string() }, async ({ orderId }, extra) => { // The signed-in user's auth arrives as standard HTTP request headers. const authorization = extra.requestInfo?.headers['authorization']; const cookie = extra.requestInfo?.headers['cookie']; if (!authorization && !cookie) { throw new Error('Unauthorized: no forwarded user credential'); }
const order = await myApi.getOrder(orderId, { authorization }); // authorize as the user return { content: [{ type: 'text', text: JSON.stringify(order) }] }; },);The header names are whatever your host put into the bind call’s authArtifacts.headers — for example
Authorization: Bearer …, or any custom X-… header your system uses. DioscHub forwards them
verbatim; it does not rename or reinterpret them. Any cookies your host supplied arrive folded into a
single standard Cookie: k=v; k2=v2 header.
Context arrives separately from credentials
Section titled “Context arrives separately from credentials”The JSON-RPC _meta field on the call carries non-credential context only — the user id, the
session and thread ids, and the current page path. It never carries the user’s credential. Read _meta
for telemetry or request context if you like, but never look there for auth:
// _meta is context, not credentials.const { userId, sessionId, currentPath } = extra._meta ?? {};Keeping the credential on the transport and the context in _meta is deliberate: the credential is the
one thing that must not leak into anything the model can read.
Why the model never sees the credential
Section titled “Why the model never sees the credential”DioscHub is Credential Blind. The forwarded auth is:
- Opaque — DioscHub does not parse, decode, or interpret it. It spreads your headers through unchanged.
- Out of the model’s context — the credential is attached to the outbound HTTP call inside the tool invocation. It is never placed into the tool’s arguments (which the model produces and reads) or into any message. The model cannot see, store, or manipulate it.
- Never logged — the forwarding path logs counts and ids, never header or cookie values.
Because the model never holds the credential, a prompt-injection attempt cannot make the Assistant reveal it or act outside the user’s permissions. Your server is the authorization boundary: it receives the user’s credential and enforces what that user may do. Authorize every tool against your own system; never treat a tool call as pre-authorized because it came from the Assistant.
When your server rejects the auth
Section titled “When your server rejects the auth”Your server should reject a call it cannot authorize. DioscHub distinguishes two cases by HTTP status:
401 Unauthorized— the credential is missing, expired, or unrecognized. DioscHub treats this as recoverable: it pauses the turn and asks the host to re-establish the user’s session (a re-bind). After a successful re-bind it retries the call once with the fresh credential. Return401when the right fix is a newer credential for the same user.403 Forbidden— the credential is valid but not allowed to do this. DioscHub treats this as terminal for the call: it does not re-authenticate, and the failure surfaces to the Assistant as a normal tool error the model can explain to the user. Return403when the user simply may not perform the action.
Choosing the right status matters: a 401 drives a re-authentication loop, a 403 does not. Return
403 for genuine authorization denials so DioscHub does not send the user through a pointless re-auth.