--- title: "Configuring Kong" slug: "configuring-kong" updated: 2026-08-06T11:17:06Z published: 2026-08-06T11:17:06Z canonical: "docs.plainid.io/configuring-kong" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.plainid.io/llms.txt > Use this file to discover all available pages before exploring further. # Configuring Kong This page walks through installing the Plugin on Kong Gateway, then configuring it on a route in two common patterns: governing MCP tool calls, and authorizing and masking a REST API response. The PlainID Integration (`plainid-authz`) installs once on Kong Gateway and then applies per route, so you can bring MCP servers and REST APIs under the same Policies without changing either upstream service. Because the Plugin reads Policies from PlainID at request time, you can adjust who can call what, or what they see back, without continuously managing your Kong configuration. ## Prerequisites Before you start, ensure you have: - Kong Gateway 3.15 or later, either self-hosted or on Konnect. - A PlainID PDP endpoint and a Client ID. If you plan to use masking, you also need a Client Secret. - If you plan to use masking, Download the JSON Filtering Authorizer container from the Platform. See the [Managing the JSON Filtering Authorizer](/v1/docs/managing-the-json-filtering-authorizer) documentation for more information. ## Install the Plugin You can install `plainid-authz` in either of the following ways: - [Adding it to your Kong image](/v1/docs/configuring-kong#adding-it-to-your-kong-image) - [Registering the plugin schema on Konnect](/v1/docs/configuring-kong#registering-the-plugin-schema-on-konnect) ### Adding it to Your Kong image **To add it to your Kong image**: 1. Copy the plugin into your Kong image and enable it through `KONG_PLUGINS`: ``` FROM kong/kong-gateway:3.15 USER root COPY plainid-authz /usr/local/share/lua/5.1/kong/plugins/plainid-authz USER kong ENV KONG_PLUGINS=bundled,plainid-authz ``` 1. Build and run the image: ``` docker build -t kong-plainid:latest . docker run -d --name kong \ -e KONG_PLUGINS=bundled,plainid-authz \ -p 8000:8000 kong-plainid:latest ``` *A Helm chart or a `lua_package_path` directory works the same way, if you deploy Kong that way instead.* ### Registering the Plugin Schema on Konnect If managing Kong through Konnect, register the plugin once at the control plane level: 1. Open Gateway Manager and select your control plane. 2. Go to **Plugins** > **Custom Plugins**. 3. Select **+ New Custom Plugin**. 4. Upload `schema.lua`. After the plugin is installed or registered, you configure it per route. See [Kong Konnect's documentation](https://developer.konghq.com/custom-plugins/konnect-hybrid-mode/) for more information. ## Govern MCP tool calls This example puts three plugins on a route in front of an MCP server, so that each one handles a distinct step: - Verifying who is calling, - Deciding what they can do - Swapping in the credential the upstream service expects. **Code Example**: ``` services: - name: snowflake-mcp url: https://.snowflakecomputing.com/api/v2/.../mcp-servers/ routes: - name: snowflake paths: [/snowflake] plugins: # 1. Validate the caller's token. - name: ai-mcp-oauth2 config: authorization_servers: [https:///v2.0] passthrough_credentials: true # 2. Ask PlainID which tools this caller may use. - name: plainid-authz config: plainid_url: https:///api client_id: authentication_method: token mcp_resource_type: MCP-TOOL # 3. Replace the caller's token with the upstream's credential. - name: request-transformer config: replace: headers: - Authorization:Bearer ``` With this configuration, Kong Gateway checks each tool call against PlainID before it reaches the MCP server. An Agent querying the server only sees the tools its Policies allow. If the Agent tries to call a tool it isn't authorized to use, Kong Gateway blocks the call and returns an error, and the request never reaches the upstream server. ## Authorize and Mask a REST API response This example uses `plainid-authz` on its own to authorize each call and mask fields in the response. ``` services: - name: cases-api url: https:// routes: - name: cases paths: [/cases] plugins: - name: plainid-authz config: plainid_url: https:///api client_id: client_secret: # PlainID resolves the identity from the caller's own token. token_forward_headers: [Authorization] # Mask fields in permitted responses. masking_enabled: true masking_url: http://:5002 masking_asset_type: ``` Your API returns its usual response, unchanged: ``` { "data": { "cases": [ { "caseId": "acc123", "caseType": "Business", "contactDetails": { "contactName": "John Doe", "contactDoB": "1974-11-09" } } ] } } ``` `plainid-authz` masks fields per Policy before Kong Gateway returns the response, so different callers can receive different values for the same request: ``` { "data": { "cases": [ { "caseId": "acc123", "caseType": "Business", "contactDetails": { "contactName": "*****", "contactDoB": "1974-11-09" } } ] } } ``` Array order and object structure stay the same. Only the field values change, so existing clients continue to parse the response normally. Use `masking_root` to scope masking to a specific part of the response body if you only want part of the document to go through the Authorizer. ## Configuration reference | Key | Description | | --- | --- | | `plainid_url` | The URL of your PlainID PDP endpoint. | | `client_id` | The client ID PlainID issued for this integration. | | `client_secret` | The client secret for this integration. Required when `masking_enabled` is `true`. | | `authentication_method` | How the Plugin authenticates to PlainID, for example `token`. | | `mcp_resource_type` | The resource type PlainID uses to evaluate MCP tool calls, for example `MCP-TOOL`. | | `token_forward_headers` | Which incoming headers the Plugin forwards to PlainID so it can resolve the caller's identity. | | `masking_enabled` | Turns on response masking for this route. | | `masking_url` | The URL of your JSON Filtering Authorizer instance. | | `masking_asset_type` | The Asset Type PlainID uses to evaluate masking Policies for this route. | | `masking_root` | *Optional*. Limits masking to a specific part of the response body. |