Skip to main content

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 clientInfo and capabilities from 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 action to the function name
  • Sets resource to mcp://{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 instance
  • ironbook_client: Iron Book SDK client instance
  • client_info_cache: Dictionary for caching MCP client info
  • agent_registry: Dictionary for caching agent registrations
  • developer_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

  1. Decorator policy_id (highest priority)
  2. Default policy_id from setup()
  3. 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:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastmcp_ironbook-0.1.1.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastmcp_ironbook-0.1.1-py3-none-any.whl (11.7 kB view details)

Uploaded Python 3

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

Hashes for fastmcp_ironbook-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f393ac5f0e5eda7e57ffd4c570992feb689b73a4d3207dd448cbf9a7be76e590
MD5 ebd8294dbd34be5b716777d17c3dee3a
BLAKE2b-256 beccfcff682a58198b3b64201e8c3c3237aabd8efe4efb5c4a7225c995c6a930

See more details on using hashes here.

File details

Details for the file fastmcp_ironbook-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for fastmcp_ironbook-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 58659005d2b233335ae0f461c83486d86b3f79909a09ae3cd6346df84f61b4c2
MD5 fc12bb9c96179f019acecf0ba0dad297
BLAKE2b-256 e4c18b051f5df10523235f937d1560757a12ce8dfc1fc9fd11ecff635563a3f8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page