> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usechar.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Policy Decision Point Interceptor

> Plug in LangGuard or your own PDP to allow, notify, or block MCP calls.

<Note>
  **Private Beta** — [Contact us](mailto:alex@mcp-b.ai?subject=Enterprise%20Governance) to get set up.
</Note>

The Policy Decision Point (PDP) Interceptor extends MCP with a standardized webhook flow for evaluating MCP calls before they execute. The callee posts a JSON-RPC request to your interceptor service, which returns a validation result: **success**, **notify**, or **failure**.

Char does not provide a managed policy engine for custom governance logic. Use LangGuard or any BYO service that implements this contract.

## Provider options

* **LangGuard** for a ready-to-use external policy platform.
* **BYO interceptor service** for internal or vendor governance engines.

## What is authoritative

* Identity and role claims come from your IdP.
* Policy decisions come from your configured interceptor provider.
* UI-level warnings are not authoritative enforcement.

## When to use a PDP interceptor

* Enforce enterprise policy beyond guardrails (e.g., geographic restrictions, tool allowlists).
* Route sensitive requests to humans for approval.
* Centralize policy decisions across multiple MCP servers.

## Configuration

Configure the PDP provider per organization in **SaaS UI**:

1. Open `/beta/governance/integrations`.
2. Choose `LangGuard` or `Bring Your Own`.
3. Set `Interceptor URL`, `Interceptor Name`, and optional `API Key`.
4. Test the connection and save.
5. Enable the provider for active enforcement.

If no provider is configured (or if the provider is disabled), tool calls bypass governance checks.

For API-driven setup, use:

* `GET /governance/providers/config`
* `PATCH /governance/providers/config`
* `POST /governance/providers/test`
* `DELETE /governance/providers/config`

<Expandable title="Dynamic discovery (future)">
  MCP clients may discover interceptors via the standard `interceptors/list` JSON-RPC method:

  ```json theme={null}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "interceptors/list"
  }
  ```

  Example response:

  ```json theme={null}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
      "interceptors": [
        {
          "name": "policy-byo",
          "version": "1.0.0",
          "description": "Acts as a Policy Decision Point (PDP) for MCP policy decisions",
          "events": ["tools/call"],
          "type": "policy-decision",
          "phase": "both",
          "compat": {
            "minProtocol": "2024-11-05"
          }
        }
      ]
    }
  }
  ```
</Expandable>

## Decision point request

The callee sends a JSON-RPC request to the configured interceptor service URL.

**HTTP**

* **Method:** `POST`
* **Content-Type:** `application/json`
* **Authorization:** `Bearer <token>`

**JSON-RPC envelope**

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "call-12345",
  "method": "interceptor/validate",
  "params": {
    "interceptor_name": "policy-byo",
    "event": "tools/call",
    "phase": "request",
    "context": {
      "mcp_call_id": "call-12345",
      "caller_identity": "usr_abc123",
      "source": {
        "tabId": "12345",
        "origin": "https://example.com",
        "url": "https://example.com/page",
        "title": "Example Page"
      },
      "mcp_call": {
        "method": "tools/call",
        "params": {
          "name": "write_note",
          "arguments": {
            "slug": "morning",
            "content": "Start your day with clarity and confidence."
          }
        }
      }
    }
  }
}
```

### Request fields

| Field                            | Type   | Description                                                 |
| -------------------------------- | ------ | ----------------------------------------------------------- |
| `jsonrpc`                        | string | Always `"2.0"`.                                             |
| `id`                             | string | Request identifier for correlation (same as `mcp_call_id`). |
| `method`                         | string | Always `"interceptor/validate"`.                            |
| `params.interceptor_name`        | string | The configured interceptor name.                            |
| `params.event`                   | string | The MCP event being intercepted (e.g., `"tools/call"`).     |
| `params.phase`                   | string | `"request"` or `"response"` depending on lifecycle.         |
| `params.context`                 | object | Original MCP call details used for policy evaluation.       |
| `params.context.mcp_call_id`     | string | Unique identifier for the MCP call.                         |
| `params.context.caller_identity` | string | Opaque user identifier (internal user ID).                  |
| `params.context.source`          | object | Browser context: `tabId`, `origin`, `url`, `title`.         |
| `params.context.mcp_call`        | object | The original MCP method and parameters.                     |

## Decision point response

The interceptor responds with a JSON-RPC `result` that contains a validation outcome.

**HTTP Status Code:** `200 OK` (for a valid JSON-RPC response)

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "call-12345",
  "result": {
    "status": "success",
    "message": "All policies passed.",
    "violations": []
  }
}
```

### Response fields

| Field               | Type   | Description                                    |
| ------------------- | ------ | ---------------------------------------------- |
| `result.status`     | string | `"success"`, `"notify"`, or `"failure"`.       |
| `result.message`    | string | High-level description of the outcome.         |
| `result.violations` | array  | List of policy violations (empty for success). |

### Violation object

| Field       | Type   | Description                                        |
| ----------- | ------ | -------------------------------------------------- |
| `policy_id` | string | Identifier of the violated policy.                 |
| `status`    | string | `"notify"` for escalation or `"block"` for denial. |
| `details`   | string | Optional human-readable message.                   |

Example blocked response:

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": "call-12345",
  "result": {
    "status": "failure",
    "message": "The call was denied due to multiple policy violations.",
    "violations": [
      {
        "policy_id": "POLICY_GEO_RESTRICTION",
        "status": "notify",
        "details": "Request originated from a restricted geographic area."
      },
      {
        "policy_id": "POLICY_UNSANCTIONED_TOOL",
        "status": "block",
        "details": "The requested tool is not sanctioned for use in this context."
      }
    ]
  }
}
```

## Decision flow

<Steps>
  <Step title="Receive MCP call">
    An MCP request arrives at the callee.
  </Step>

  <Step title="Prepare the policy request">
    Wrap the MCP call in the JSON-RPC `interceptor/validate` payload.
  </Step>

  <Step title="Invoke the interceptor">
    POST the payload to your interceptor service URL.
  </Step>

  <Step title="Evaluate the response">
    Verify the HTTP status is 200, then read `result.status` and `result.violations`.
  </Step>

  <Step title="Decide the outcome">
    **Success:** proceed with the MCP call. **Notify:** log the notification for review and proceed with the MCP call. **Failure:** block the MCP call and log violations.
  </Step>
</Steps>

## Error handling

* **Non-200 HTTP responses:** treat as a policy failure and block the request.
* **Timeouts:** default to block and log for follow-up.
* **Malformed JSON-RPC:** treat as failure and return an internal error to the caller.

## Security considerations

* Authenticate the interceptor endpoint with a bearer token.
* **Data exposure:** Tool call arguments are forwarded to the interceptor service for policy evaluation. Review your interceptor provider's data handling policies to ensure compliance with your organization's privacy requirements.
* Log all validation outcomes to your audit system.
* Keep a deny-by-default stance for transport or parsing errors.

<Info>
  Need help wiring this into your MCP server? Reach out at [alex@mcp-b.ai](mailto:alex@mcp-b.ai).
</Info>
