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.0.tar.gz (9.2 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.0-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file fastmcp_ironbook-0.1.0.tar.gz.

File metadata

  • Download URL: fastmcp_ironbook-0.1.0.tar.gz
  • Upload date:
  • Size: 9.2 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.0.tar.gz
Algorithm Hash digest
SHA256 cee5ad3dd4cda6d83fcee55b135db61218971aa1ffb0371bae7601f1bc60690c
MD5 f617423ef917902a7d106418c4e58ee0
BLAKE2b-256 ff6a378db22d7a7a9c21ee12768fe239deb724e7c1b450e843d88c8daa0d786d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for fastmcp_ironbook-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2a35d896e305f9ffe00bfa818e71ee4eacf5876a21725a9886e4566b304f6eba
MD5 bbfaf5615c010ff969346fe932ba1bc6
BLAKE2b-256 d2ac83b02bad73d7760707f25282cba9317ae98b834b13db0d58f40aba11dc6b

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