MCP - The Agent-Native Protocol

How Formael implements the Model Context Protocol as a native interface for AI agents - tool discovery, intent submission, deferred results, and real-time notifications.

Documentation

MCP - The Agent-Native Protocol

Formael implements the Model Context Protocol (MCP) as a first-class agent interface alongside its REST API. MCP is a protocol designed specifically for AI agent tooling - every capability in your Formael registry is automatically exposed as an MCP tool, ready for consumption by any MCP-compatible agent framework.


Why MCP

The REST Agent Plane API gives agents full control over intent submission. MCP gives agents something different: a self-describing tool surface that they can discover dynamically, call naturally, and receive structured results from - without any hardcoded knowledge of Formael's API contract.

An agent using MCP does not need to know about IntentEnvelope schemas, domain/action/entity tuples, or polling patterns. It calls a tool by name, passes parameters, and receives a result. The translation to Formael's intent pipeline is invisible.


Connecting to the MCP Server

Formael's MCP server has three endpoint forms:

FormURLUse when
Globalhttps://api.formael.com/mcp/v1Federated JWT where tenancy resolves from the token's (iss, aud) tuple
Per-orghttps://api.formael.com/mcp/v1/org/{orgSlug}Mixing API keys and federated JWTs under one endpoint
Per-federationhttps://api.formael.com/mcp/v1/f/{federationEndpointId}Recommended for federated deployments - binds the session to one specific federation

The per-federation endpoint ID is shown in the dashboard after you create an identity federation (under Identity → Federations).

The server implements Streamable HTTP transport - MCP's standard stateful transport for HTTP-based agents.

Authentication

Authenticate with the same credentials used for the REST API:

Authorization: Bearer fml_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Or with a federated JWT from your enterprise IdP:

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Agent scope enforcement is identical to the REST API - the MCP session is bound to the same agent identity.


Tool Discovery

Once connected, the agent requests the tool list:

{ "method": "tools/list" }

Formael returns one tool per capability available to the authenticated agent, filtered by the agent's scope:

{
  "tools": [
    {
      "name": "document-signing.create.contract",
      "description": "Create a new contract and send it for e-signature. Requires: signerName, signerEmail, templateId. Risk: MEDIUM - sends external communication to a third party.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "signerName": { "type": "string" },
          "signerEmail": { "type": "string", "format": "email" },
          "templateId": { "type": "string" }
        },
        "required": ["signerName", "signerEmail", "templateId"]
      }
    }
  ]
}

Tool names follow the pattern {domain}.{action}.{entity}. Tool descriptions embed capability metadata including risk classification, making the tool's governance implications visible to the model without additional calls.

Tools not in the agent's allowed scope are not returned - the agent cannot discover capabilities it is not authorized to use.


Calling a Tool

Invoke a tool with tools/call:

{
  "method": "tools/call",
  "params": {
    "name": "document-signing.create.contract",
    "arguments": {
      "signerName": "Jane Smith",
      "signerEmail": "[email protected]",
      "templateId": "tmpl_mutual_nda"
    }
  }
}

Formael translates the tool call into an IntentEnvelope and runs it through the full governance pipeline - policy evaluation, budget checks, connector execution - identically to the REST API. The MCP protocol surface is a peer interface, not a bypass.

Immediate result

If the intent executes synchronously:

{
  "content": [
    {
      "type": "text",
      "text": "{\"iecId\":\"01HX...\",\"outcome\":\"executed\",\"state\":\"SUCCEEDED\",\"result\":{\"contractId\":\"env_2Xm...\",\"status\":\"sent\"}}"
    }
  ]
}

Deferred result (human approval required)

If the intent requires human approval, Formael returns a resource reference instead of a final result:

{
  "content": [
    {
      "type": "resource",
      "resource": {
        "uri": "formael://iec/01HX4K2M9V3T7P8Q5N6R0J1W2Y",
        "mimeType": "application/json",
        "text": "{\"iecId\":\"01HX...\",\"outcome\":\"deferred\",\"state\":\"PENDING_APPROVAL\"}"
      }
    }
  ]
}

The agent can read the resource later using resources/read to check the approval status, rather than polling a REST endpoint.


Reading Deferred Results

Poll for a deferred intent resolution via resources/read:

{
  "method": "resources/read",
  "params": {
    "uri": "formael://iec/01HX4K2M9V3T7P8Q5N6R0J1W2Y"
  }
}

The response follows the same state structure as the REST API - PENDING_APPROVAL, SUCCEEDED, DENIED, or CLOSED.


Real-Time Notifications

Formael emits MCP notifications to keep the connected agent informed of state changes without polling:

NotificationTrigger
tools/list_changedA capability is added to or removed from the org registry
notifications/resources/updatedA deferred intent resolves (approved or denied)

When a notifications/resources/updated notification arrives for a URI the agent is tracking, it can call resources/read immediately to retrieve the final state.


MCP vs REST API

Both interfaces are fully equivalent in capability - every intent that can be submitted via REST can be submitted via MCP. The choice depends on your agent architecture:

REST APIMCP
DiscoveryManual, from documentationDynamic at runtime via tools/list
SchemaIntentEnvelope JSON SchemaMCP tool inputSchema
Deferred resultsPoll GET /v1/intents/:idresources/read + push notifications
Best forCustom integrations, server-side codeAI agent frameworks (LangChain, CrewAI, Claude, etc.)
AuthSame - API key or federated JWTSame - API key or federated JWT
GovernanceFull pipelineFull pipeline (identical)