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

# MCP

> How to proxy MCP traffic through the Formal Connector

## Overview

MCP (Model Context Protocol) resources let you intercept and control HTTP traffic
originating from AI agents. Formal sits in the path to enforce policies and log all activity.

## Connecting via the Desktop App (Transparent Proxy)

<Note>
  Transparent proxy mode is only supported on **macOS**. The Formal network
  extension must be installed (`formal transparent-proxy install`) before use.
</Note>

Use the Desktop App's transparent proxy to intercept outbound traffic without reconfiguring the MCP client itself.

```bash theme={null}
formal connect mcp-resource-name
```

Replace `mcp-resource-name` with the name of your MCP resource in Formal.

### Creating an MCP Resource

```hcl theme={null}
resource "formal_resource" "github_mcp" {
  name       = "github-mcp"
  technology = "mcp"
  hostname   = "api.githubcopilot.com"
  port       = 443
}
```

## Connecting without the Desktop App

If your MCP client runs in a cloud environment, route its traffic through a
Connector by updating the upstream hostname.

Replace the target API hostname with the Connector hostname (and the resource subdomain if using smart routing):

* **Before:** `https://api.githubcopilot.com/mcp`
* **After:** `https://<your connector hostname>/mcp`

Like with the HTTP technology, set `X-Formal-User-Username` and `X-Formal-User-Password` headers to associate
requests with a Formal identity.

## Policy Evaluation

Formal supports the following policy evaluation stages for MCP:

* **Session**: Evaluate and enforce policies at connection time
* **Request**: Evaluate and enforce policies before the request is forwarded
* **Response**: Evaluate and enforce policies after the response is received

At the request and response stages, `input.mcp` is populated when the
request is an MCP tool call. See [MCP policy inputs](/docs/guides/policies/evaluation#mcp-resources)
for the full list of available fields.

### Example: Block a specific tool

```rego theme={null}
package formal.v2

import future.keywords.if

default request := {"action": "allow"}

request := {"action": "block", "type": "block_with_formal_message"} if {
  input.mcp.tool_name == "list_pull_requests"
}
```

## Authentication

The Connector forwards authentication headers from the MCP client transparently.
You can also inject credentials using [Native Users](/docs/guides/core-concepts/resources/native_users)
so the MCP client does not need to hold secrets directly.
