Skip to main content

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.

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)

Transparent proxy mode is only supported on macOS. The Formal network extension must be installed (formal transparent-proxy install) before use.
Use the Desktop App’s transparent proxy to intercept outbound traffic without reconfiguring the MCP client itself.
formal connect mcp-resource-name
Replace mcp-resource-name with the name of your MCP resource in Formal.

Creating an MCP Resource

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 for the full list of available fields.

Example: Block a specific tool

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 so the MCP client does not need to hold secrets directly.