Iron Book agent-based security integration for FastMCP servers
Project description
fastmcp-ironbook
Iron Book agent-based security integration for FastMCP servers.
Overview
fastmcp-ironbook provides a simple way to add Iron Book's agent-based security and policy enforcement to your FastMCP servers. It automatically identifies MCP clients, registers them as agents with Iron Book, and enforces policies on tool calls.
Features
- Automatic Agent Registration: Agents are automatically registered with Iron Book based on MCP client info
- MCP Specification Compliant: Uses standard MCP
clientInfoandcapabilitiesfrom initialization - Policy Enforcement: Integrate Iron Book's policy engine with a simple decorator
- Version Tracking: Tracks client versions in agent names (e.g.,
cursor-agent-v1.0.0) - Capability-Based Access: Uses MCP capabilities directly for policy decisions
Installation
pip install fastmcp-ironbook
Quick Start
import os
from fastmcp import FastMCP
from ironbook_sdk import IronBookClient
import fastmcp_ironbook
from fastmcp_ironbook import ClientInfoMiddleware, require_policy
# Initialize caches
mcp_client_info_cache = {}
agent_registry = {}
# Initialize Iron Book client
ironbook = IronBookClient(
api_key=os.getenv("IRONBOOK_API_KEY"),
base_url=os.getenv("IRONBOOK_BASE_URL", "https://api.ironbook.identitymachines.com")
)
# Create MCP server
mcp = FastMCP("my-server")
# Add middleware to capture client info
mcp.add_middleware(ClientInfoMiddleware(mcp_client_info_cache))
# Initialize fastmcp-ironbook
fastmcp_ironbook.setup(
mcp_server=mcp,
ironbook_client=ironbook,
client_info_cache=mcp_client_info_cache,
agent_registry=agent_registry,
default_policy_id="policy_abc123" # Your Iron Book policy ID
)
# Now you can use the @require_policy decorator on your tools!
@mcp.tool()
@require_policy(lambda name: {"name": name})
async def greet(name: str) -> str:
"""Greet a user by name."""
return f"Hello, {name}!"
@mcp.tool()
@require_policy(lambda a, b: {"operation": "addition", "a": a, "b": b})
async def add_numbers(a: float, b: float) -> dict:
"""Add two numbers together."""
result = a + b
return {
"result": result,
"operation": f"{a} + {b} = {result}"
}
# Run the server
if __name__ == "__main__":
mcp.run()
How It Works
1. Client Identification
The ClientInfoMiddleware captures MCP client information during the initialization phase per the MCP specification:
{
"clientInfo": {
"name": "Cursor",
"version": "1.0.0"
},
"capabilities": {
"roots": {"listChanged": true},
"sampling": {}
}
}
This creates an agent named cursor-agent-v1.0.0 with capabilities ["roots", "sampling"].
2. Agent Registration
On the first tool call, the agent is automatically registered with Iron Book:
- Agent name: Based on client name and version
- Capabilities: MCP capabilities from the initialize message
- Developer DID: Configurable (default:
did:web:identitymachines.com)
3. Policy Enforcement
The @require_policy decorator automatically:
- Sets
actionto the function name - Sets
resourcetomcp://{server_name} - Gets/registers the agent
- Enforces the Iron Book policy
- Passes optional context for policy decisions
API Reference
setup()
Initialize the package before using the decorator.
fastmcp_ironbook.setup(
mcp_server: FastMCP,
ironbook_client: IronBookClient,
client_info_cache: dict,
agent_registry: dict,
developer_did: str = "did:web:identitymachines.com"
)
Parameters:
mcp_server: Your FastMCP server instanceironbook_client: Iron Book SDK client instanceclient_info_cache: Dictionary for caching MCP client infoagent_registry: Dictionary for caching agent registrationsdeveloper_did: Optional developer DID for agent registration
@require_policy()
Decorator to enforce Iron Book policy on MCP tools.
@require_policy(context_fn: Optional[Callable] = None)
Parameters:
context_fn: Optional callable that takes function arguments and returns a context dict
Examples:
# No context
@mcp.tool()
@require_policy()
async def simple_tool() -> str:
return "Hello!"
# With context
@mcp.tool()
@require_policy(lambda data: {"data_length": len(data)})
async def process_data(data: str) -> dict:
return {"processed": len(data)}
ClientInfoMiddleware
Middleware to capture MCP client information during initialization.
middleware = ClientInfoMiddleware(cache_dict: dict)
mcp.add_middleware(middleware)
Advanced Usage
Manual Policy Enforcement
If you need more control, you can use the underlying functions directly:
from fastmcp_ironbook import get_or_register_agent, enforce_policy
@mcp.tool()
async def my_tool(param: str) -> dict:
# Get agent info
agent_info = await get_or_register_agent(
ironbook_client=ironbook,
client_info_cache=mcp_client_info_cache,
agent_registry=agent_registry
)
# Enforce policy with custom action/resource
await enforce_policy(
ironbook_client=ironbook,
agent_info=agent_info,
action="custom_action",
resource="custom://resource",
context={"key": "value"}
)
# Execute tool logic
return {"result": "success"}
Custom Developer DID
fastmcp_ironbook.setup(
mcp_server=mcp,
ironbook_client=ironbook,
client_info_cache=mcp_client_info_cache,
agent_registry=agent_registry,
developer_did="did:web:mycompany.com"
)
Policy Configuration
Default Policy ID
Set a default policy ID in setup that applies to all tools:
fastmcp_ironbook.setup(
mcp_server=mcp,
ironbook_client=ironbook,
client_info_cache={},
agent_registry={},
default_policy_id="policy_abc123" # Default for all tools
)
Per-Tool Policy Override
Override the default policy for specific tools:
@mcp.tool()
@require_policy(policy_id="policy_admin_xyz")
async def admin_operation() -> dict:
"""Uses policy_admin_xyz instead of default"""
return {"status": "admin"}
# Or with context and custom policy
@mcp.tool()
@require_policy(
lambda data: {"data_length": len(data)},
policy_id="policy_sensitive"
)
async def sensitive_tool(data: str) -> dict:
return {"processed": len(data)}
Policy ID Priority
- Decorator policy_id (highest priority)
- Default policy_id from setup()
- Error if neither provided
This ensures you never forget to configure a policy.
Example use cases:
# Case 1: Single policy for everything
fastmcp_ironbook.setup(..., default_policy_id="policy_main")
@require_policy()
async def tool1(): ...
@require_policy()
async def tool2(): ...
# Both use policy_main
# Case 2: Default + admin override
fastmcp_ironbook.setup(..., default_policy_id="policy_standard")
@require_policy()
async def regular_tool(): ... # Uses policy_standard
@require_policy(policy_id="policy_admin")
async def admin_tool(): ... # Uses policy_admin
# Case 3: No default (per-tool required)
fastmcp_ironbook.setup(...) # No default_policy_id
@require_policy(policy_id="policy_read")
async def read_tool(): ... # OK
@require_policy()
async def forgot_policy(): ... # ERROR: No policy ID configured!
Policy Rules
Create policies in Iron Book that check MCP capabilities:
# Example policy checking for MCP "roots" capability
allow if {
input.resource == "mcp://my-server"
input.action == "sensitive_operation"
"roots" in input.context.capabilities
}
Environment Variables
Required for Iron Book integration:
IRONBOOK_API_KEY=your_api_key_here
IRONBOOK_BASE_URL=https://api.ironbook.identitymachines.com # Optional
Requirements
- Python >= 3.10
- fastmcp >= 0.2.0
- ironbook-sdk >= 0.3.0
License
MIT
Resources
Support
For issues and questions:
- GitHub Issues: https://github.com/identitymachines/fastmcp-ironbook/issues
- Email: support@identitymachines.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastmcp_ironbook-0.1.1.tar.gz.
File metadata
- Download URL: fastmcp_ironbook-0.1.1.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f393ac5f0e5eda7e57ffd4c570992feb689b73a4d3207dd448cbf9a7be76e590
|
|
| MD5 |
ebd8294dbd34be5b716777d17c3dee3a
|
|
| BLAKE2b-256 |
beccfcff682a58198b3b64201e8c3c3237aabd8efe4efb5c4a7225c995c6a930
|
File details
Details for the file fastmcp_ironbook-0.1.1-py3-none-any.whl.
File metadata
- Download URL: fastmcp_ironbook-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58659005d2b233335ae0f461c83486d86b3f79909a09ae3cd6346df84f61b4c2
|
|
| MD5 |
fc12bb9c96179f019acecf0ba0dad297
|
|
| BLAKE2b-256 |
e4c18b051f5df10523235f937d1560757a12ce8dfc1fc9fd11ecff635563a3f8
|