What you get
When a workspace connects your MCP server with Send who is chatting turned on, every request from Noxus to your server carries one extra header:The values you need
Open the connection in Noxus (Workspace control, Connections, the connection, Identity token). It shows every value below, ready to copy.
The token also carries
scope: the tools it may call. It changes per call, so the
connection does not show it.
The claims
sub is the Noxus user id. It is stable for the person. email is the email of
their Noxus account. Map either one to a user in your system.
scope lists the tools this token may call, separated by spaces. It holds the
tools the agent may use on your server (or the one tool an MCP Tool node calls),
minus the tools the workspace turned off. When Noxus only lists your tools, for
example when an admin presses Refresh tools, scope is empty.
Checks your server must make
Reject the request (HTTP 401) unless every check passes:- The
X-Noxus-Identityheader is present. - The algorithm is
ES256. Fix it in your verify call and accept nothing else. - The key id (
kidin the token header) is in the published key set. If it is not, fetch the key set again once, then reject. - The signature verifies.
issequals the issuer andaudis a workspace you allow. One Noxus deployment signs tokens for all of its workspaces, so the audience check is what makes the token yours.- The token has not expired. Allow about 60 seconds of clock skew.
token_useismcp_identity.
sub or email to your user, and return 403 if you do not know them.
For a tool call (tools/call), also return an error unless the tool name is in
scope. Listing tools (tools/list) does not need a scope.
A tool the server added after the last Refresh tools is not in scope until
an admin presses Refresh tools in Noxus.
Protect every MCP route. With the SSE transport that is both the stream (GET /sse) and the message endpoint (POST /messages), because tool calls arrive on
the message endpoint.
Cache the key set. Fetch it on start, refresh it every few hours, and when a
token names a key id you have not seen. Do not fetch it per request.
Example: TypeScript with jose
jwtVerify selects the key by kid, checks the signature, issuer, audience
(the workspace) and expiry. The if line checks the token type. Before a tool
runs, check that req.scope has its name.
Example: Python with PyJWT
When there is no token
Noxus sends the token only when a signed-in person is behind the call. Calls from a workspace API key, a trigger, or a chat channel without a Noxus user stop inside Noxus and never reach your server. The person sees why in the chat or in the run error.Do not
- Trust an email or user header without a signature. Anyone who knows your URL can send one.
- Skip the audience or scope checks.
- Forward the token to another service. It names the workspace, not your server.
- Log the raw token. Log
sub,audand the result instead.