MuleSoft’s new Model Context Protocol (MCP) Connector enables Mule as an MCP server. We’ve previously discussed what MCP is and how to build your first MCP server. With this knowledge, we now need to think about MCP server security and why it’s necessary.
Why is MCP server security important?
Access to critical resources inherently introduces security considerations. While MCP is currently in its nascent stages, its rapid evolution is driven by a commitment to robust security.
Exposing MCP tools, like any API, necessitates careful consideration of security. To address this critical aspect, we’ve designed the MCP Connector to seamlessly integrate with the robust security components already available within the MuleSoft platform for securing various API types. Let’s explore how these mechanisms can be applied to safeguard your MCP-enabled applications.
Listen for new sessions
The connector implements MCP’s SSE transport specification. With that in mind, it is intentionally open when it comes to authenticating MCP clients. The latest update to the MCP specification introduced the concept of session as a top level concern. Because the SSE connection is stateful, session creation is the moment at which authentication should happen.
Meet the New Session listener:
<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>
This flow will execute each time a new client connects to our MCP server application. The payload is an object containing the auto-generated sessionId, and the additionalProperties, which when using the SSE connection type, maps to the request Http headers.
2. Apply the security scheme that better suits your case
At this point, you can implement your own authentication logic. You can use the #[payload.additionalProperties.authorization] expression to obtain the Http Authorization header, which you are able to:
- Validate manually
- Validate delegating to an external service (e.g. an authorization service you consume through the Http connector)
- Use Mule’s OAuth Provider to implement and validate OAuth access tokens.
Let’s see an example of the latter:
<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.descripion]" />
</on-error-continue>
</error-handler>
</flow>
The above flows shows how to validate an access token using the OAuth provider, and reject the session if said token is invalid. The new session is rejected if one of two things happens:
- 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 status code 500 will be reported automatically)
In this example, the OAuth validation error is being handled so that the status code is mapped to a 401 – UNAUTHORIZED code.
API security is paramount, even with AI advancements
Despite all the magic surrounding AI and LLMs, securing APIs is still a top concern that must be applied correctly and consistently.
With that in mind, we designed the MCP connector to be compatible with all the security components our platform offers and you’re already familiar with, while retaining the flexibility for your own security standards. For instance: while the examples above revolve around the Http Authorization header, using an X-API-KEY header is also a popular pattern, which is easy to implement with this solution.