As you might have noticed, until now, there's no security mechanism defined to protect the MCP Tool exposed by the Kong AI Gateway. As usual, you can take advantage of the historical plugins the Kong API Gateway provides to implement Authentication and Security processes to your MCP Tool, such as Key Auth, OpenID Connect, Open Policy Agent, etc.
On the other hand, the MCP community has defined Authorization specifications, based on OAuth 2 standards. To be fully compliant with the specs, the Kong AI Gateway provides a second plugin, responsible for implementing those specs: the AI MCP OAuth2 Plugin.
The AI MCP Proxy Plugin
To exercise the new plugin, let's extend the decK declaration one more time:
The exercise relies on Keycloak, as the external Identity Provider. In this sense, Keycloak is responsible for issuing Access Tokens and validating them during the MCP Tool consuming time. The validation follows the OAuth2 Token Introspection specification.
The following diagram shows the relationship between the Kong AI Gateway and the Identity Provider (IdP) for the Introspection flow:
- The MCP Consumer presents its credentials (Client ID + Client Secret) to the IdP.
- The IdP authenticates the Consumer, issues an Access Token and returns it to the Consumer.
- The MCP Consumer sends a request to the Gateway with the Access Token injected.
- The AI/MCP Gateway sends a request to the IdP's Introspection Endpoint to get the Access Token validated.
- If the Token is still valid the Gateway calls the Tool.

To get Keycloak installed you can follow the Quickstarts available.
The declaration refers to some Keycloak endpoints and secrets, besides the actual Authorization URL. Let's go through them:
MCP_AUTH_URL: that's the MCP Tool URL, exposed by the Kong Data Plane. Considering our declaration should be like this: http://<DATA_PLANE_DN>:<DATA_PLANE_PORT>/weather.
KEYCLOAK_AUTHZ_URL: that's the Keycloak Authorization endpoint. Assuming an existing Keycloak realm, called “kong”, in our case, it should be something like: http://<KEYCLOAK_DN>:<KEYCLOAK_PORT>/realms/kong/protocol/openid-connect/auth.
KEYCLOAK_INTROSPECTION_URL: that's the Keycloak Introspection endpoint. In our case, http://<KEYCLOAK_DN:KEYCLOAK_PORT/realms/kong/protocol/openid-connect/token/introspect.
CLIENT_ID and CLIENT_SECRET: these are the secrets of an existing Keycloak Client.
Keycloak provides the standard endpoint http://<KEYCLOAK_DN:KEYCLOAK_PORT/realms/kong/.well-known/openid-configuration where you can get these and several other Keycloak configuration parameters.
Exploring the Introspection Endpoint
To exercise the Introspection Endpoint, let's send some requests to Keycloak, acting as the Consumer and the Gateway.
In the first request, we play the Consumer role, using the Client Credential Grant to get our Access Token
You can decode the Access Token with:
You should get an output like this:
Now, playing the Gateway role, we are going to consume the Introspection Endpoint asking the IdP to validate the Access Token:
Here's a typical response. The “active” at the bottom says the plugin is still good.
However, if you wait for the Access Token timeout (in Keycloak is 10min, by default), the Endpoint returns a different output saying so:
MCP Client and OAuth2
Now, let's evolve our MCP Client and protect it with the AI MCP OAuth2 Plugin. The code has a new function called “get_access_token” which is responsible for hitting the Keycloak's Authorization Endpoint to get the Access Token. The token is then used to start the Streamable HTTP Session.
The code checks if a specific environment variable is defined with an Access Token. If it is, the code uses it to start the Session. One nice way to test the code would be running the code, setting the environment variable with the token, waiting for the timeout and running the code again. You should see an error message related to it.