FastMCP server for Obol DVT cluster troubleshooting and monitoring
Project description
Obol MCP
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
- Python 3.10+
- FastMCP 2.x (tested with 2.11.3)
- httpx
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:
- Restart Claude Desktop completely
- Look for the 🔨 icon in the bottom-right
- Click it to see 22 Obol MCP tools
Cursor IDE
Cursor requires manual configuration:
- Cursor → File → Preferences → Cursor Settings → MCP
- Click "Add new global MCP server"
- Add to
mcp.json:
{
"mcpServers": {
"Obol MCP": {
"command": "uvx",
"args": ["obol-mcp"]
}
}
}
- 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 inserver.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_hashorconfig_hashis 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_healthtool - Consider implementing retry logic with exponential backoff
Use Cases
This MCP server enables:
- DVT Cluster Monitoring - Real-time monitoring of validator states, effectiveness, and performance
- Operator Auditing - Track operator participation, badges, and reputation across networks
- Exit Coordination - Monitor and coordinate voluntary exit signatures across distributed validator operators
- DKG Troubleshooting - Debug cluster definition and DKG ceremony issues
- Network Analysis - Analyze network-wide patterns, cluster distributions, and aggregate statistics
- 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
-
Check installation:
pip list | grep obol-mcp
-
Verify config:
# macOS cat ~/Library/Application\ Support/Claude/claude_desktop_config.json # Windows type %APPDATA%\Claude\claude_desktop_config.json
-
Check logs:
# macOS tail -f ~/Library/Logs/Claude/mcp*.log # Windows # Check %APPDATA%\Claude\logs\mcp*.log
-
Test server manually:
python server.py # OR uvx obol-mcp
-
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
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 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4dd4a838d81e139efc48336ae6d9d861e3a7f0b6c7e3c3d4831fbc4f561397e5
|
|
| MD5 |
62a60e11ce2f10ee94d73ca229999bd3
|
|
| BLAKE2b-256 |
ca288f3c7a2a2ace7bb12fb43c44ae9480920824cfa8fbbb12b18b0069903012
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9599cdef3867dfe46fe37120f9da12412d8ab893509cc42beafe92ed72071bcc
|
|
| MD5 |
31eac2148138557c11813b3b732da0dd
|
|
| BLAKE2b-256 |
4e07802e64bc49cb008369541fd9b800ab1556cefcdff5c9c43ad51fc463f0c0
|