Skip to main content

FastMCP server for Obol DVT cluster troubleshooting and monitoring

Project description

Obol MCP

PyPI version Python 3.10+

FastMCP server for comprehensive Obol DVT cluster troubleshooting and monitoring.

This project provides a FastMCP server that acts as a comprehensive read-only interface to the public Obol Network API. It exposes 22 Obol API GET endpoints as callable tools accessible via the Model Context Protocol (MCP).

This enables Large Language Models (LLMs) or other MCP-compatible clients to troubleshoot, monitor, and analyze Obol Distributed Validator (DVT) clusters, operator performance, exit coordination, and network-wide statistics without needing direct HTTP request logic.

Features / Implemented Tools (22 Total)

This server implements the following categories of Obol API tools:

🏥 Health & System Status (2 tools)

  • obol_api_health: Check API health including database and beacon node connectivity (GET /v1/_health)
  • obol_api_metrics: Retrieve Prometheus-style metrics from the API (GET /metrics)

🔒 Cluster Lock Operations (5 tools)

  • obol_cluster_lock_by_hash: Get complete cluster lock by lock_hash (GET /v1/lock/{lockHash})
  • obol_lock_by_config_hash: Get cluster lock by config_hash (GET /v1/lock/configHash/{configHash})
  • obol_locks_by_network: List cluster locks on a network with pagination/filtering (GET /v1/lock/network/{network})
  • obol_cluster_search: Search clusters by partial lock_hash or name (GET /v1/lock/search/{network})
  • obol_network_summary: Get network-wide cluster statistics (GET /v1/lock/network/summary/{network})

📊 Cluster Health & Monitoring (2 tools)

  • obol_cluster_effectiveness: Get per-validator effectiveness metrics (GET /v1/effectiveness/{lockHash})
  • obol_cluster_validator_states: Get beacon chain states of all validators in cluster (GET /v1/state/{lockHash})

👥 Operator Management (5 tools)

  • obol_operator_clusters: List all clusters where an address is an operator (GET /v1/lock/operator/{address})
  • obol_operator_info: Get operator statistics on a network (GET /v1/address/network/{network})
  • obol_search_operators: Search operators by partial address (GET /v1/address/search/{network})
  • obol_operator_badges: Get operator badges (lido, etherfi, etc.) (GET /v1/address/badges/{address})
  • obol_operator_techne: Get Techne credentials (bronze, silver, gold) (GET /v1/address/techne/{address})
  • obol_operator_incentives: Get Obol token incentives for an operator (GET /v1/address/incentives/{network}/{address})

🚪 Exit Coordination (2 tools)

  • obol_cluster_exit_status_summary: Get exit status summary for cluster (GET /v1/exp/exit/status/summary/{lockHash})
  • obol_cluster_exit_status: Get detailed exit status with filtering (GET /v1/exp/exit/status/{lockHash})

🔧 DKG & Cluster Definitions (2 tools)

  • obol_cluster_definition: Get cluster definition/proposal by config_hash (GET /v1/definition/{configHash})
  • obol_operator_definitions: List cluster definitions an operator is part of (GET /v1/definition/operator/{address})

🔬 Advanced Features (4 tools)

  • obol_migrateable_validators: Get validators eligible for migration to DVT (GET /v1/address/migrateable-validators/{network}/{withdrawalAddress})
  • obol_owr_tranches: Get OWR (Optimistic Withdrawal Recipient) tranche info (GET /v1/owr/{network}/{address})
  • obol_terms_signed_status: Check if address signed latest Terms & Conditions (GET /v1/termsAndConditions/{address})

Note: This server focuses on read-only operations for troubleshooting and monitoring. POST/PUT operations for cluster creation/updates require authentication and are not included.

Requirements

Installation

Quick Start (Recommended)

Install from PyPI:

pip install obol-mcp

Then configure for Claude Desktop by editing your config file (see Configuration below), or use uvx:

uvx obol-mcp

Alternative Installation Methods

From GitHub (Development)

git clone https://github.com/ObolNetwork/obol-mcp.git
cd obol-mcp
pip install -e ".[dev]"
fastmcp install claude-desktop server.py

Or run directly:

fastmcp dev server.py

Configuration

Claude Desktop

Config Location:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add to your configuration:

{
  "mcpServers": {
    "Obol MCP": {
      "command": "uvx",
      "args": ["obol-mcp"]
    }
  }
}

After updating:

  1. Restart Claude Desktop completely
  2. Look for the 🔨 icon in the bottom-right
  3. Click it to see 22 Obol MCP tools

Cursor IDE

Cursor requires manual configuration:

  1. Cursor → File → Preferences → Cursor Settings → MCP
  2. Click "Add new global MCP server"
  3. Add to mcp.json:
{
  "mcpServers": {
    "Obol MCP": {
      "command": "uvx",
      "args": ["obol-mcp"]
    }
  }
}
  1. Restart Cursor

Usage

Once installed, interact with your DVT clusters through Claude:

"Show me cluster effectiveness for lock_hash 0x..."
"List all clusters on mainnet"
"Check validator states for lock_hash 0x..."
"Show me operator info for address 0x..."
"Get exit status summary for my cluster"

Running the Server Manually

You can also run the server directly:

# As installed command
obol-mcp

# Or directly with Python
python server.py

# Or with uvx
uvx obol-mcp

Usage

Once the server is running, you can interact with it using any MCP-compatible client.

Example using the FastMCP Python client:

# client_example.py
import asyncio
from fastmcp import Client

client = Client("server.py")

async def main():
    async with client:
        print("Connected to Obol DVT Cluster Monitor MCP Server.")

        # Example 1: Check API Health
        health = await client.call_tool("obol_api_health")
        print("\nAPI Health:")
        print(health)

        # Example 2: Get Network Summary
        summary = await client.call_tool("obol_network_summary", {"network": "holesky"})
        print("\nHolesky Network Summary:")
        print(summary)

        # Example 3: Search for a specific cluster
        lock_hash = "0xYOUR_CLUSTER_LOCK_HASH_HERE"  # Replace with real lock_hash
        if lock_hash != "0xYOUR_CLUSTER_LOCK_HASH_HERE":
            # Get complete cluster lock
            cluster = await client.call_tool("obol_cluster_lock_by_hash", {"lock_hash": lock_hash})
            print(f"\nCluster Lock for {lock_hash}:")
            print(cluster)
            
            # Get effectiveness metrics
            effectiveness = await client.call_tool("obol_cluster_effectiveness", {"lock_hash": lock_hash})
            print(f"\nEffectiveness Metrics:")
            print(effectiveness)
            
            # Get validator states
            states = await client.call_tool("obol_cluster_validator_states", {"lock_hash": lock_hash})
            print(f"\nValidator States:")
            print(states)
            
            # Get exit status summary
            exit_summary = await client.call_tool("obol_cluster_exit_status_summary", {"lock_hash": lock_hash})
            print(f"\nExit Status Summary:")
            print(exit_summary)

        # Example 4: Check operator info
        operator_address = "0xYOUR_OPERATOR_ADDRESS_HERE"  # Replace with real address
        if operator_address != "0xYOUR_OPERATOR_ADDRESS_HERE":
            # Get all clusters for operator
            clusters = await client.call_tool("obol_operator_clusters", {
                "address": operator_address,
                "limit": 10
            })
            print(f"\nClusters for operator {operator_address}:")
            print(clusters)
            
            # Get operator badges
            badges = await client.call_tool("obol_operator_badges", {"address": operator_address})
            print(f"\nOperator Badges:")
            print(badges)
            
            # Get Techne credentials
            techne = await client.call_tool("obol_operator_techne", {"address": operator_address})
            print(f"\nTechne Credentials:")
            print(techne)

if __name__ == "__main__":
    asyncio.run(main())

Run the client example: python client_example.py

Common DVT Troubleshooting Scenarios

Scenario 1: Investigating cluster performance issues

# Get cluster lock to see configuration
lock = await client.call_tool("obol_cluster_lock_by_hash", {"lock_hash": "0x..."})

# Check effectiveness metrics for underperforming validators
effectiveness = await client.call_tool("obol_cluster_effectiveness", {"lock_hash": "0x..."})

# Check if any validators are in unexpected states
states = await client.call_tool("obol_cluster_validator_states", {"lock_hash": "0x..."})

Scenario 2: Coordinating voluntary exits

# Get exit status summary to see which operators have signed
summary = await client.call_tool("obol_cluster_exit_status_summary", {"lock_hash": "0x..."})

# Get detailed status for specific validators
status = await client.call_tool("obol_cluster_exit_status", {
    "lock_hash": "0x...",
    "validatorPubkey": "0x...",
    "page": 1,
    "limit": 10
})

Scenario 3: Auditing operator participation

# Find all clusters an operator is part of
clusters = await client.call_tool("obol_operator_clusters", {"address": "0x..."})

# Get operator stats across the network
stats = await client.call_tool("obol_operator_info", {
    "network": "mainnet",
    "sortBy": "avg_effectiveness",
    "sortOrder": "desc",
    "limit": 100
})

Using with Claude Desktop

For local development, you can install this server into Claude Desktop using the FastMCP CLI:

fastmcp install claude-desktop server.py

This will automatically configure Claude Desktop to use the local server. You can then interact with DVT clusters directly through Claude!

Cloud Hosting (Optional)

You can host this server on FastMCP Cloud for free, which provides:

  • Automatic deployment and updates
  • No local installation required
  • Accessible from any Claude Desktop instance
  • Built-in monitoring and logs

For more details on deployment options, see the FastMCP documentation.

Configuration

  • API URL: The server connects to the public Obol API at https://api.obol.tech. This is configured in server.py.
  • Supported Networks: mainnet, holesky, sepolia (check Obol API documentation for current network support)
  • Authentication: No API keys or authentication are required for read-only GET endpoints. POST/PUT operations require authentication and are not included in this server.
  • Rate Limiting: The server inherits rate limits from the Obol API. Consider implementing request throttling for high-volume use cases.

Supported Networks

The following Ethereum networks are supported:

  • mainnet - Ethereum Mainnet
  • holesky - Holesky Testnet (primary testnet)
  • sepolia - Sepolia Testnet

Troubleshooting Tips

Common Issues

"Cluster not found" errors:

  • Verify the lock_hash or config_hash is correct
  • Ensure the cluster exists on the specified network
  • Check that DKG has completed for cluster definition lookups

"Network not supported" errors:

  • Verify you're using a supported network name (mainnet, holesky, sepolia)
  • Network names are case-sensitive

Empty results for operator queries:

  • Verify the address format is correct (42-character hex string starting with 0x)
  • Check if the operator has participated in any clusters on the specified network

API timeout errors:

  • The Obol API may be under heavy load
  • Check API health status with obol_api_health tool
  • Consider implementing retry logic with exponential backoff

Use Cases

This MCP server enables:

  1. DVT Cluster Monitoring - Real-time monitoring of validator states, effectiveness, and performance
  2. Operator Auditing - Track operator participation, badges, and reputation across networks
  3. Exit Coordination - Monitor and coordinate voluntary exit signatures across distributed validator operators
  4. DKG Troubleshooting - Debug cluster definition and DKG ceremony issues
  5. Network Analysis - Analyze network-wide patterns, cluster distributions, and aggregate statistics
  6. Migration Planning - Identify validators eligible for migration to DVT clusters

Future Work

  • Add data aggregation and analysis tools on top of raw API responses
  • Implement caching for frequently accessed data
  • Add support for additional networks as they become available
  • Create composite tools for common troubleshooting workflows
  • Add filtering and search capabilities across multiple clusters/operators

Troubleshooting

Server not showing in Claude Desktop

  1. Check installation:

    pip list | grep obol-mcp
    
  2. Verify config:

    # macOS
    cat ~/Library/Application\ Support/Claude/claude_desktop_config.json
    
    # Windows
    type %APPDATA%\Claude\claude_desktop_config.json
    
  3. Check logs:

    # macOS
    tail -f ~/Library/Logs/Claude/mcp*.log
    
    # Windows
    # Check %APPDATA%\Claude\logs\mcp*.log
    
  4. Test server manually:

    python server.py
    # OR
    uvx obol-mcp
    
  5. Restart Claude Desktop completely (not just close the window)

Command not found: uvx

If uvx is not available, use the Python module approach in your config:

{
  "mcpServers": {
    "Obol MCP": {
      "command": "python",
      "args": ["-m", "obol_mcp"]
    }
  }
}

Development

# Clone repository
git clone https://github.com/ObolNetwork/obol-mcp.git
cd obol-mcp

# Install in development mode with test dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run in dev mode with Inspector UI
fastmcp dev server.py

# Build package
python -m build

# Check package
twine check dist/*

License

MIT License - see LICENSE file for details.

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

obol_mcp-0.1.1.tar.gz (14.6 kB view details)

Uploaded Source

Built Distribution

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

obol_mcp-0.1.1-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

Details for the file obol_mcp-0.1.1.tar.gz.

File metadata

  • Download URL: obol_mcp-0.1.1.tar.gz
  • Upload date:
  • Size: 14.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for obol_mcp-0.1.1.tar.gz
Algorithm Hash digest
SHA256 4dd4a838d81e139efc48336ae6d9d861e3a7f0b6c7e3c3d4831fbc4f561397e5
MD5 62a60e11ce2f10ee94d73ca229999bd3
BLAKE2b-256 ca288f3c7a2a2ace7bb12fb43c44ae9480920824cfa8fbbb12b18b0069903012

See more details on using hashes here.

File details

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

File metadata

  • Download URL: obol_mcp-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for obol_mcp-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9599cdef3867dfe46fe37120f9da12412d8ab893509cc42beafe92ed72071bcc
MD5 31eac2148138557c11813b3b732da0dd
BLAKE2b-256 4e07802e64bc49cb008369541fd9b800ab1556cefcdff5c9c43ad51fc463f0c0

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