> ## 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.

# Formal Docs MCP

> Search Formal documentation, read guides and API references, and report documentation issues.

Knowledge Publisher: Formal

Route Formal Docs MCP traffic through Formal to control and log what AI agents do in Formal Docs:

* **Block** tools you don't want agents to call, such as `submit_feedback`.
* **Mask** sensitive data in tool results, such as emails and phone numbers in `search_formal_documentation` responses.
* **Log** every tool call with the user, the MCP client and its parameters.

Cloud agents

Laptop / VM

Endpoint

[https://docs.formal.ai/mcp](https://docs.formal.ai/mcp)

Connector

![](https://docs.formal.ai/static/brands/formal.svg)

## 0. Prepare your Connector

The Connector needs an MCP listener and a hostname with wildcard DNS and TLS.
Set them up once by following [Deploy the Connector](https://docs.formal.ai/docs/guides/core-concepts/connectors/mcp-gateway.md#deploy-the-connector). Every MCP server reuses them.

## 1. Add Formal Docs MCP server to your Resources

> [tab] UI
>
> 1. Open the [Admin Catalog](https://app.formal.ai/catalog) and click **Add MCP**.
> 2. Select the **Formal Docs MCP** template.
> 3. Enter a DNS-label **Name**, such as `formal-docs`.
> 4. Choose the **Space** containing your Connector, such as `default`.
> 5. Configure upstream authentication as described below, then save.
>
> If no Connector is in the selected Space, the **Configuration** tab shows **MCP clients can't connect directly yet**.
> The reason reads: `No Connector is in this server's Space.`
>
> Adding Formal Docs MCP to the Admin Catalog

> [tab] Terraform
>
> Set `space_id` to the ID of the Space containing your Connector.
>
> ```hcl theme={"languages":{"custom":["/languages/cel.json","/languages/rego.json"]}}
> resource "formal_resource" "formal_docs" {
>   name                    = "formal-docs"
>   technology              = "mcp"
>   hostname                = "docs.formal.ai"
>   space_id                = "<SPACE_ID>"
>   native_users_v3_enabled = true
>   port                    = 443
>   tags = {
>     "mcp-endpoint" = "/mcp"
>   }
> }
> ```
>
> This public server does not need `formal_resource_oauth_settings`.

> [tab] Pulumi
>
> Set `spaceId` to the ID of the Space containing your Connector.
>
> ```ts theme={"languages":{"custom":["/languages/cel.json","/languages/rego.json"]}}
> import * as formal from "@formalco/pulumi";
>
> const resource = new formal.Resource("mcp", {
>   name: "formal-docs",
>   technology: "mcp",
>   hostname: "docs.formal.ai",
>   port: 443,
>   spaceId: "<SPACE_ID>",
>   tags: { "mcp-endpoint": "/mcp" },
>   nativeUsersV3Enabled: true,
> });
>
> ```

> [tab] API
>
> Create a Resource with the MCP endpoint and its Space ID.
>
> ```bash theme={"languages":{"custom":["/languages/cel.json","/languages/rego.json"]}}
> export FORMAL_API_KEY="<YOUR_API_KEY>"
> RESOURCE_RESPONSE=$(curl --fail --silent --show-error \
>   --request POST \
>   https://api.formal.ai/core.v1.ResourceService/CreateResource \
>   --header "x-api-key: ${FORMAL_API_KEY}" \
>   --header "Content-Type: application/json" \
>   --data-binary @- <<JSON
>   {
>     "name": "formal-docs",
>     "hostname": "docs.formal.ai",
>     "port": 443,
>     "technology": "mcp",
>     "spaceId": "<SPACE_ID>",
>     "tags": [
>       {
>         "key": "mcp-endpoint",
>         "value": "/mcp"
>       }
>     ]
>   }
> JSON
> )
>
> ```

## 2. Setup Authentication

Formal Docs MCP is a public server and needs no credential. Choose **Pass Through**.

![Pass Through selected under How does Formal authenticate to this resource?](https://mintcdn.com/formal/R-3CwVgs8IU6liji/assets/images/mcp-servers/auth-pass-through.png?fit=max\&auto=format\&n=R-3CwVgs8IU6liji\&q=85\&s=c14ae61de2dba8b567626cba03aae2cf)

Nothing in the request identifies the Formal user. Formal attributes these requests only when they come through the [Formal Endpoint](https://docs.formal.ai/docs/guides/core-concepts/connectors/mcp-gateway.md#identity-headers). Pass-through servers have no Connector address, so cloud agents can't use them.

## 3. Route Endpoint traffic

Auth is managed at the Connector level when you use Linked Accounts or Shared Credentials, so the Endpoint needs to forward the MCP traffic to it.
Laptops and VMs with the Formal Endpoint keep using `https://docs.formal.ai/mcp`, and a network rule sends that traffic to the Connector.

> [tab] UI
>
> 1. Go to [Network Rules](https://app.formal.ai/network-rules) and create a rule named `formal-docs-mcp`.
> 2. Paste this expression, set the rule to **Active**, then save:
>
> ```javascript theme={"languages":{"custom":["/languages/cel.json","/languages/rego.json"]}}
> {
>   "condition": {
>     "pre_tcp": process.is_agent,
>     // Every MCP server added to Formal: process.is_agent && resource.technology == "mcp"
>     "pre_tls": process.is_agent && hostname == "docs.formal.ai",
>     "post_tls": true
>   },
>   "outputs": {
>     "forward_to_connector": true
>   }
> }
> ```

> [tab] Terraform
>
> ```hcl theme={"languages":{"custom":["/languages/cel.json","/languages/rego.json"]}}
> resource "formal_network_rule" "formal_docs_mcp" {
>   name        = "formal-docs-mcp"
>   description = "Forward Formal Docs MCP MCP traffic from agents to the Connector"
>   status      = "active"
>
>   # Every MCP server added to Formal: set pre_tls to process.is_agent && resource.technology == "mcp"
>   cel_expression = <<-EOT
>     {
>       "condition": {
>         "pre_tcp": process.is_agent,
>         "pre_tls": process.is_agent && hostname == "docs.formal.ai",
>         "post_tls": true
>       },
>       "outputs": {
>         "forward_to_connector": true
>       }
>     }
>   EOT
> }
> ```

> [tab] Pulumi
>
> ```ts theme={"languages":{"custom":["/languages/cel.json","/languages/rego.json"]}}
> import * as formal from "@formalco/pulumi";
>
> new formal.NetworkRule("formalDocsMcp", {
>   name: "formal-docs-mcp",
>   description: "Forward Formal Docs MCP MCP traffic from agents to the Connector",
>   status: "active",
>   // Every MCP server added to Formal: set pre_tls to process.is_agent && resource.technology == "mcp"
>   celExpression: `
>     {
>       "condition": {
>         "pre_tcp": process.is_agent,
>         "pre_tls": process.is_agent && hostname == "docs.formal.ai",
>         "post_tls": true
>       },
>       "outputs": {
>         "forward_to_connector": true
>       }
>     }
>   `,
> });
> ```

> [tab] API
>
> ```bash theme={"languages":{"custom":["/languages/cel.json","/languages/rego.json"]}}
> export FORMAL_API_KEY="<YOUR_API_KEY>"
> # Every MCP server added to Formal: set pre_tls to process.is_agent && resource.technology == "mcp"
> CEL_EXPRESSION=$(cat <<'CEL'
> {
>   "condition": {
>     "pre_tcp": process.is_agent,
>     "pre_tls": process.is_agent && hostname == "docs.formal.ai",
>     "post_tls": true
>   },
>   "outputs": {
>     "forward_to_connector": true
>   }
> }
> CEL
> )
> jq -n --arg cel "${CEL_EXPRESSION}" '{
>   name: "formal-docs-mcp",
>   description: "Forward Formal Docs MCP MCP traffic from agents to the Connector",
>   status: "active",
>   celExpression: $cel
> }' | curl --fail --silent --show-error \
>   --request POST \
>   https://api.formal.ai/core.v1.DesktopService/CreateDesktopRoutingRule \
>   --header "x-api-key: ${FORMAL_API_KEY}" \
>   --header "Content-Type: application/json" \
>   --data-binary @-
> ```

The rule matches [known agents](https://docs.formal.ai/docs/guides/network-rules.md#known-agent-identities) only.
See [Identity headers](https://docs.formal.ai/docs/guides/core-concepts/connectors/mcp-gateway.md#identity-headers).

Cloud agents such as Claude, ChatGPT and Cursor Cloud Agents don't run the Endpoint.
Point them at this server's Connector address, `https://formal-docs.<connector-hostname>/mcp`.
Find it in the [Admin Catalog](https://app.formal.ai/catalog): open Formal Docs MCP, then copy **Connector address** on the **Configuration** tab.

## 4. Create policies

### Tools

The Admin Catalog lists these tools for Formal Docs MCP:

| Tool | Description |
| - | - |
| `search_formal_documentation` | Search Formal documentation, code examples, and API references. |
| `query_docs_filesystem_formal_documentation` | Read documentation pages and search documentation files and OpenAPI specs. |
| `submit_feedback` | Report incorrect, outdated, or incomplete Formal documentation. |

### Policies examples

> [tab] Block a tool
>
> This policy blocks the tools that change data, so agents can only read Formal Docs MCP.
>
> ```rego theme={"languages":{"custom":["/languages/cel.json","/languages/rego.json"]}}
> package formal.v2
>
> import future.keywords.if
> import future.keywords.in
>
> write_tools := {
>   "submit_feedback",
> }
>
> request := {
>   "action": "block",
>   "type": "block_with_custom_message",
>   "message": "Writing to Formal Docs MCP is not allowed.",
> } if {
>   input.resource.name == "formal-docs"
>   input.mcp.method == "tools/call"
>   input.mcp.tool_name in write_tools
> }
> ```

See [MCP resources](https://docs.formal.ai/docs/guides/policies/evaluation.md#mcp-resources) for the `input.mcp` fields and [Rewrite Action](https://docs.formal.ai/docs/guides/policies/enforcement.md#rewrite-action) for body rewrites.

## 5. Check the logs

Open [Logs](https://app.formal.ai/logs) and search for `resource.name:formal-docs`.
Each Formal Docs MCP tool call is one `request` log with the user, the MCP client and the tool.
Open a log to see its tool parameters and the policies it triggered.
A blocked write shows the block policy and its message.

Formal Docs MCP tool calls in Logs, including a masked response and a blocked write

See [Logs](https://docs.formal.ai/docs/guides/observability/logs.md) for search syntax and filters.

## Troubleshooting

> [accordion] Laptop traffic doesn't appear in Logs
>
> **Cause:** The Endpoint isn't running, or the network rule doesn't match the client.
>
> **Fix:** Check the Endpoint is connected. The rule above only matches [known agents](https://docs.formal.ai/docs/guides/network-rules.md#known-agent-identities). Other clients, such as a browser, reach Formal Docs MCP directly unless the rule also matches them. See [Network rules](https://docs.formal.ai/docs/guides/network-rules.md).

> [accordion] MCP clients can't connect directly yet
>
> **Cause:** The **Configuration** tab lists the reason, most often `No Connector is in this server's Space.`
>
> **Fix:** Edit the server and choose the Space containing its Connector.

## Next Steps

> [card] [MCP Gateway](https://docs.formal.ai/docs/guides/core-concepts/connectors/mcp-gateway.md)
>
> Configure Connector routing and downstream access

> [card] [All MCP servers](https://docs.formal.ai/docs/guides/core-concepts/connectors/mcp-servers/index.md)
>
> Browse every MCP server template


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.