The MCP specification emphasizes session management and SSE connections maintain state. The On New Session Listener source offers a key point for implementing server-side authentication. This example illustrates a basic flow triggered by this listener, showing how to access the auto-generated sessionId and the HTTP headers sent by the connecting client, which can then be used for custom authentication logic.
This is an example flow that uses the On New Session Listener source:
<flow name="onNewSession">
<mcp:on-new-session-listener config-ref="MCP_Server"/>
<logger level="INFO" message="#['new session id: $(payload.sessionId)']"/>
<logger level="INFO" message="#['http headers: $(payload.additionalProperties)']"/>
</flow>
The flow executes each time a new client connects to the MCP server application. The payload contains the auto-generated sessionId and the additionalProperties, which when using the SSE connection type, maps to the request HTTP headers.
At this point, you can implement your own authentication logic. For instance, the #[payload.additionalProperties.authorization] expression gets the HTTP authorization header, which you can validate later.
Validate OAuth Access Tokens
In this example flow, the access token is validated using the OAuth provider, and the session is rejected if the token is invalid:
<flow name="onNewSession">
<mcp:on-new-session-listener config-ref="MCP_Server">
<mcp:rejection rejectWithStatusCode="#[vars.rejectStatusCode]" rejectWithMessage="#[vars.rejectMessage]" />
</mcp:on-new-session-listener>
<oauth2-provider:validate-token scopes="#[['PUBLIC_READ']]" config-ref="external-oauth2-provider" accessToken="#[payload.additionalProperties.authorization]"/>
<error-handler>
<on-error-continue type="OAUTH2-PROVIDER:TOKEN_UNAUTHORIZED">
<set-variable variableName="rejectWithStatusCode" value="401" />
<set-variable variableName="rejectWithMessage" value="#[error.description]" />
</on-error-continue>
</error-handler>
</flow>
The new session is rejected if either of these things happen:
-
The rejectWithStatusCode parameter is assigned a non-null value (or an expression that resolves to a non-null value), or
-
The flow fails, in which case a status code 500 is reported.
In this example, the OAuth validation error is handled so that the status code is mapped to a 401 - UNAUTHORIZED code.