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:
| Form | URL | Use when |
|---|---|---|
| Global | https://api.formael.com/mcp/v1 | Federated JWT where tenancy resolves from the token's (iss, aud) tuple |
| Per-org | https://api.formael.com/mcp/v1/org/{orgSlug} | Mixing API keys and federated JWTs under one endpoint |
| Per-federation | https://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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxOr 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:
| Notification | Trigger |
|---|---|
tools/list_changed | A capability is added to or removed from the org registry |
notifications/resources/updated | A 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 API | MCP | |
|---|---|---|
| Discovery | Manual, from documentation | Dynamic at runtime via tools/list |
| Schema | IntentEnvelope JSON Schema | MCP tool inputSchema |
| Deferred results | Poll GET /v1/intents/:id | resources/read + push notifications |
| Best for | Custom integrations, server-side code | AI agent frameworks (LangChain, CrewAI, Claude, etc.) |
| Auth | Same - API key or federated JWT | Same - API key or federated JWT |
| Governance | Full pipeline | Full pipeline (identical) |