使用说明
比特币MCP服务器
用于比特币区块链连接和分析的全面模型上下文协议(MCP)服务器,提供与比特币节点和外部API的无缝集成,以实现全面的区块链数据访问。
🏗️ 项目结构
bitcoin-mcp-server/
├── src/ # Main source code directory
│ ├── __init__.py # Package initialization
│ ├── main.py # FastAPI application entry point and MCP routing
│ ├── config.py # Configuration management with Pydantic
│ ├── bitcoin_client.py # Bitcoin RPC client with connection management
│ ├── mcp_protocol.py # MCP Protocol implementation
│ ├── tools/ # MCP tool implementations
│ │ ├── __init__.py # Tools package initialization
│ │ ├── blockchain.py # Blockchain query tools (blocks, transactions)
│ │ ├── network.py # Network monitoring tools (mempool, mining)
│ │ ├── address.py # Address analysis tools (balance, UTXOs)
│ │ └── market.py # Market data tools (price, stats)
│ └── utils/ # Utility modules
│ ├── __init__.py # Utils package initialization
│ ├── validation.py # Input validation utilities
│ └── errors.py # Custom error classes and handling
├── requirements.txt # Python dependencies
├── Dockerfile # Docker container configuration
├── docker-compose.yml # Docker Compose for easy deployment
├── .env.example # Environment variables template
└── README.md # Project documentation
📦 依赖项
核心依赖关系
- 快速 API (0.104.1):用于构建API的现代web框架
- 乌维科恩 (0.24.0):用于运行FastAPI应用程序的ASGI服务器
- httpx (0.25.2):用于外部API调用的异步HTTP客户端
- 派丹蒂克 (1.10.13):数据验证和设置管理
- python dotenv (1.0.0):环境变量加载
比特币特定依赖关系
- 基地58 (2.1.1): 比特币地址验证和编码工具
- 用于验证不同格式(P2PKH、P2SH、Bech32、Bech32m)的比特币地址
- 为主网、测试网和regtest网络提供强大的地址格式检查
外部API依赖项
该服务器与多个外部API集成,提供全面的比特币数据:
- 比特币RPC节点:区块链信息的主要数据源
- Mempool.space API:地址余额和交易历史
- CoinGecko API:市场价格数据和统计
- Alternative.me API:市场情绪的恐惧与贪婪指数
🔧 MCP协议合规性
此服务器完全符合模型上下文协议(MCP)规范。它实现了所有必需的MCP方法:
核心MCP方法
initialize:服务器初始化和能力协商tools/list:列出具有模式的可用工具tools/call:使用适当的参数验证执行工具调用resources/list:列出可用资源resources/read:读取资源内容
工具定义
所有工具都使用正确的JSON模式定义,包括:
- 名字:工具标识符
- 描述:人类可读的描述
- inputSchema:输入参数的JSON模式
- outputSchema:输出格式的JSON模式
资源定义
资源定义如下:
- 统一资源标识符:资源标识符
- 名字:人类可读名称
- 描述:资源描述
- mimeType:内容类型
📁 文件描述
核心应用程序文件
src/main.py
用途:FastAPI应用入口点和MCP协议路由
主要特点:
- MCP协议方法路由(
initialize,tools/list,tools/call等等) - JSON-RPC 2.0协议的实现
- 遗留方法支持向后兼容性
- 全局错误处理和日志记录
- 应用程序生命周期管理
- CORS中间件配置
开发者笔记:这是主要的切入点。MCP方法通过MCPProtocol类路由。
src/mcprotocol.py
目的:MCP协议实施和工具/资源定义
主要特点:
- 完整的MCP协议方法实现
- 使用JSON模式的工具定义
- 带有元数据的资源定义
- 工具执行路线
- 参数验证
开发人员说明:在此处添加新的工具和资源。所有工具都必须定义正确的模式。
src/config.py
目的:使用Pydantic进行集中配置管理
主要特点:
- 环境变量加载
- 配置验证
- 网络类型枚举(主网、测试网、regtest)
- API端点和凭据管理
开发人员说明:在此处添加新的配置参数。所有配置在启动时都经过验证。
src/bitcoin_client.py
用途:异步具有高级功能的比特币RPC客户端
主要特点:
- 带身份验证的HTTP连接管理
- 速率限制和重试逻辑
- 失败请求的指数回退
- 比特币核心的JSON-RPC 1.0协议实现
- 用于正确清理资源的上下文管理器
开发者说明:这处理所有比特币节点通信。添加新的RPC方法作为异步函数。
工具模块
src/tools/blockchain.py
目的:区块链数据检索和分析
可用的MCP工具:
- get_blockchain_info():网络统计和状态
- get_block_by_height():按高度分块数据
- get_block_by_hash():按哈希值阻止数据
- get_transaction():交易详细信息
- get_latest_blocks():最近块列表
- search_blocks():阻止范围查询
开发者说明:在此处添加新的区块链查询方法。确保对所有输入进行正确验证。
src/tools/network.py
目的:比特币网络监控和状态
可用的MCP工具:
- get_network_status():全面的网络概述
- get_memool_stats():内存池统计和费用估算
- get_mining_info():挖掘难度和哈希率
- get_per_info():网络对等体信息
开发者笔记:网络工具主要使用比特币RPC。费用估算目标可以定制。
src/tools/address.py
目的:比特币地址分析和UTXO管理
可用的MCP工具:
- validate_address():地址格式验证
- get_address_balance():通过外部API进行余额检查
- get_address_transactions():事务历史记录
- get_address_utxos():未使用的事务输出
- analyze_address_activity():全面的地址分析
开发人员说明:使用mempool.space API获取地址数据。Bitcoin Core在没有钱包功能的情况下不会跟踪任意地址。
src/tools/market.py
目的:比特币市场数据和价格信息
可用的MCP工具:
- get_current_price():各种货币的实时价格
- get_price_history():历史价格数据
- get_market_stats():综合市场统计
- get_fear_greed_index():市场情绪指标
开发者说明:使用CoinGecko和Alternative.me API。可以添加API密钥以获得更高的速率限制。
实用模块
src/utils/validation.py
目的:比特币特定数据类型的输入验证
主要功能:
- validate_bitcoin_address():多格式地址验证
- validate_transaction_hash():64个字符的十六进制验证
- validate_block_hash():块哈希格式验证
- validate_block_height():块高度范围验证
开发人员说明:在此处添加新的验证函数。使用base58进行地址验证。
src/utils/errors.py
用途:自定义异常类和JSON-RPC错误格式化
关键类别:
- BitcoinMCP错误:JSON-RPC格式的基本异常
- BitcoinRPCError: 比特币节点通信错误
- ValidationError:输入验证失败
- 网络错误:网络连接问题
- RateLimitError:违反速率限制
开发人员注意:所有自定义错误都应该继承自BitcoinMCPError,以便进行一致的处理。
🚀 特性
核心能力
- MCP协议合规性:全面实施MCP规范
- 区块链查询:完成区块和交易数据访问
- 网络监控:实时网络状态和内存池分析
- 地址分析:余额检查、交易历史、UTXO跟踪
- 市场数据:价格信息、历史数据、市场情绪
- 速率限制:可配置的请求速率限制
- 错误处理:全面的错误处理和详细的消息
- Docker支持:生产就绪的集装箱化
- 向后兼容:传统方法支持
MCP协议方法
核心协议
initialize:服务器初始化和能力协商tools/list:列出具有模式的可用工具tools/call:执行带有参数验证的工具调用resources/list:列出可用资源resources/read:读取资源内容
可用工具(共20个)
- 区块链:6个工具(信息、区块、交易、搜索)
- 网络:4个工具(状态、内存池、挖掘、对等体)
- 地址:5个工具(验证、余额、交易、UTXO、分析)
- 市场:5个工具(价格、历史、统计、情绪、当前)
🔧 错误处理和响应代码
JSON-RPC错误代码
| 代码 | 名称 | 描述 |
|---|---|---|
| -32000 | 比特币MCP错误 | 一般比特币MCP服务器错误 |
| -32001 | BitcoinRPCError | 比特币节点 RPC 通信错误 |
| -32002 | 验证错误 | 输入验证失败 |
| -32003 | 网络错误 | 网络连接问题 |
| -32004 | RateLimitError | 超出速率限制 |
| -32600 | 无效请求 | JSON-RPC格式错误 |
| -32601 | 找不到方法 | 请求的方法未知 |
| -32602 | 参数无效 | 方法参数无效 |
| -32603 | 内部错误 | 服务器内部错误 |
| -32700 | 分析错误 | JSON格式无效 |
错误响应格式
{
"jsonrpc": "2.0",
"error": {
"code": -32002,
"message": "Invalid Bitcoin address format",
"data": {
"field": "address"
}
},
"id": 1
}
速率限制
服务器实现了可配置的速率限制来保护比特币节点:
- 默认:每个客户端每分钟60个请求
- 可配置的:通过
RATE_LIMIT_PER_MINUTE环境变量 - 错误响应:退货
-32004超出时的错误代码 - 实施:滑动窗口速率限制
BitcoinRPCClient
📊 API响应示例
成功响应格式
{
"jsonrpc": "2.0",
"result": {
// Method-specific data
},
"id": 1
}
区块链信息响应
{
"jsonrpc": "2.0",
"result": {
"chain": "main",
"blocks": 800000,
"headers": 800000,
"bestblockhash": "0000000000000000000...",
"difficulty": 123456789.123456789,
"mediantime": 1640995200,
"verificationprogress": 0.999999,
"initialblockdownload": false,
"chainwork": "0000000000000000000...",
"size_on_disk": 123456789,
"pruned": false,
"pruneheight": 0,
"automatic_pruning": false,
"prune_target_size": 0,
"softforks": {...},
"bip9_softforks": {...},
"warnings": ""
},
"id": 1
}
地址验证响应
{
"jsonrpc": "2.0",
"result": {
"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"is_valid": true,
"is_script": false,
"is_witness": false,
"witness_version": null,
"witness_program": null,
"script_type": "pubkeyhash",
"address_type": "P2PKH"
},
"id": 2
}
市场价格反应
{
"jsonrpc": "2.0",
"result": {
"currency": "usd",
"price": 45000.50,
"change_24h": 2.5,
"change_percentage_24h": 5.88,
"market_cap": 850000000000,
"volume_24h": 25000000000,
"last_updated": "2024-01-01T12:00:00Z"
},
"id": 3
}
🛠️ 开发者指南
添加新方法
在相应的工具模块中创建方法实现:
async def new_method(self, param1: str, param2: int) -> Dict[str, Any]:
"""Method description."""
# Validate inputs
if not param1:
raise ValidationError("Missing parameter", "param1")
# Implementation
result = await self.client.some_rpc_call(param1, param2)
return result
在src/main.py中添加方法路由:
elif method == "new_method":
param1 = params.get("param1")
param2 = params.get("param2", default_value)
if not param1:
raise ValidationError("Missing 'param1' parameter", "param1")
return await tool_instance.new_method(param1, param2)
将方法添加到get_server_status()中的可用方法列表中:
"available_methods": [
# ... existing methods
"new_method",
]
体系结构模式
错误处理策略
# Always use custom exceptions for consistent error responses
try:
result = await some_operation()
return result
except SomeSpecificError as e:
raise ValidationError(f"Operation failed: {str(e)}", "field_name")
except Exception as e:
raise BitcoinRPCError(f"Unexpected error: {str(e)}")
异步上下文管理器
# Use context managers for resource cleanup
class NewTool:
async def __aenter__(self):
self.client = httpx.AsyncClient()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
if hasattr(self, 'client'):
await self.client.aclose()
配置管理
# Add new config parameters in config.py
class Config(BaseSettings):
NEW_API_KEY: Optional[str] = None
NEW_API_URL: str = "https://api.example.com"
@validator('NEW_API_URL')
def validate_new_api_url(cls, v):
if not v.startswith('http'):
raise ValueError('API URL must start with http')
return v
测试策略
使用curl进行手动测试
# Test blockchain info
curl -X POST http://localhost:8000/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "get_blockchain_info",
"params": {},
"id": 1
}'
# Test address validation
curl -X POST http://localhost:8000/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "validate_address",
"params": {"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"},
"id": 2
}'
# Test rate limiting
for i in {1..65}; do
curl -X POST http://localhost:8000/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "get_blockchain_info", "params": {}, "id": '$i'}'
done
单元测试框架
# Example test structure (add to tests/ directory)
import pytest
import httpx
from src.main import app
@pytest.fixture
async def client():
async with httpx.AsyncClient(app=app, base_url="http://test") as client:
yield client
async def test_get_blockchain_info(client):
response = await client.post("/", json={
"jsonrpc": "2.0",
"method": "get_blockchain_info",
"params": {},
"id": 1
})
assert response.status_code == 200
data = response.json()
assert data["jsonrpc"] == "2.0"
assert "result" in data
async def test_invalid_method(client):
response = await client.post("/", json={
"jsonrpc": "2.0",
"method": "invalid_method",
"params": {},
"id": 1
})
assert response.status_code == 200
data = response.json()
assert data["error"]["code"] == -32601
性能注意事项
速率限制实施
- 默认值:每个客户端每分钟60个请求
- 可通过RATE_LIMIT_PER_MINUTE环境变量进行配置
- 在BitcoinRPCClient中实现。_check_rate_limit()
连接池
- HTTP客户端自动使用连接池
- 比特币RPC客户端在上下文中重复使用连接
- 外部API客户端具有单独的连接池
缓存策略
# Add caching for expensive operations (future enhancement)
from functools import lru_cache
from datetime import datetime, timedelta
class CachedTool:
def __init__(self):
self.cache = {}
self.cache_ttl = timedelta(minutes=5)
async def cached_method(self, key: str):
now = datetime.utcnow()
if key in self.cache:
data, timestamp = self.cache[key]
if now - timestamp < self.cache_ttl:
return data
# Fetch new data
result = await self.expensive_operation(key)
self.cache[key] = (result, now)
return result
安全最佳实践
环境变量
# Never commit sensitive data
BITCOIN_RPC_PASSWORD=your_secure_password
API_KEYS=your_api_keys
# Use different credentials for different environments
BITCOIN_RPC_URL_MAINNET=https://mainnet.node.com/
BITCOIN_RPC_URL_TESTNET=https://testnet.node.com/
输入消毒
# Always validate and sanitize inputs
def sanitize_input(value: str, max_length: int = 100) -> str:
if not isinstance(value, str):
raise ValidationError("Input must be string")
# Remove potentially dangerous characters
sanitized = re.sub(r'[^\w\-.]', '', value)
if len(sanitized) > max_length:
raise ValidationError(f"Input too long, max {max_length} characters")
return sanitized
🚀 快速开始
开发设置
克隆和设置:
git clone <repository-url>
cd bitcoin-mcp-server
cp .env.example .env
安装依赖项:
pip install -r requirements.txt
配置环境变量:
# Edit .env file with your Bitcoin RPC credentials
BITCOIN_RPC_URL=https://bitcoin.two.nono.casa/
BITCOIN_RPC_USER=user
BITCOIN_RPC_PASSWORD=pass
运行开发服务器:
python -m uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
使用Docker进行生产部署
构建并运行:
docker-compose up -d
检查健康状况:
curl http://localhost:8000/health
查看日志:
docker-compose logs -f bitcoin-mcp-server
部署到Render.com
创建render.yaml:
services:
- type: web
name: bitcoin-mcp-server
env: docker
dockerfilePath: ./Dockerfile
plan: starter
envVars:
- key: PORT
value: 10000
- key: BITCOIN_RPC_URL
value: https://bitcoin.two.nono.casa/
- key: BITCOIN_RPC_USER
value: user
- key: BITCOIN_RPC_PASSWORD
value: pass
healthCheckPath: /health
部署:
- 将您的GitHub存储库连接到Render
- 在Render仪表板中设置环境变量
- 在git推送上自动部署
📊 API示例
获取当前比特币价格
{
"jsonrpc": "2.0",
"method": "get_current_price",
"params": {"currency": "usd"},
"id": 1
}
分析比特币地址
{
"jsonrpc": "2.0",
"method": "analyze_address_activity",
"params": {"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"},
"id": 2
}
获取最新区块
{
"jsonrpc": "2.0",
"method": "get_latest_blocks",
"params": {"count": 5},
"id": 3
}
🔧 配置选项
| 变量 | 默认值 | 描述 |
|---|---|---|
| 主机 | 0.0.0.0 | 服务器绑定地址 |
| PORT | 8000 | 服务器端口 |
| DEBUG | false | 启用调试日志记录 |
| 比特币_RPC_URLhttps://bitcoin.two.nono.casa/Bitcoin RPC 终端 | ||
| BITCOIN_RPC_USER | 用户 | Bitcoin RPC 用户名 |
| BITCOIN_RPC_PASSWORD | 通过 | 比特币RPC密码 |
| BITCOIN_NETWORK | 主网 | 网络类型(主网/测试网/注册测试) |
| REQUEST_TIMEOUT | 30 | HTTP请求超时(秒) |
| MAX_RETRIES | 3 | 最大重试次数 |
| RATE_LIMIT_PER_MINUTE | 60 | 每分钟请求数限制 |
| 内存POOL_SPACE_API_URL | https://mempool.space/api | Mempool.space API端点 |
| BLOCKCHAIR_API_KEY | null | 可选BLOCKCHAIR API密钥 |
📈 监控和日志记录
健康检查端点
# Check server health
curl http://localhost:8000/health
# Response format
{
"status": "healthy",
"bitcoin_connected": true,
"timestamp": "2024-01-01T12:00:00.000Z"
}
日志记录配置
# Logs are structured with timestamps and levels
2024-01-01 12:00:00,000 - bitcoin_mcp - INFO - Bitcoin MCP Server started on 0.0.0.0:8000
2024-01-01 12:00:01,000 - bitcoin_mcp - ERROR - Bitcoin RPC Error: Connection refused
2024-01-01 12:00:02,000 - bitcoin_mcp - DEBUG - Rate limit check passed for client
Docker日志
# View real-time logs
docker-compose logs -f bitcoin-mcp-server
# View last 100 lines
docker-compose logs --tail=100 bitcoin-mcp-server
🔍 故障排除指南
常见问题
比特币RPC连接失败
# Check if Bitcoin node is accessible
curl --user user:pass --data-binary '{"jsonrpc":"1.0","id":"test","method":"getblockchaininfo","params":[]}' \
-H 'content-type: text/plain;' https://bitcoin.two.nono.casa/
# If this fails, check:
# 1. Network connectivity
# 2. RPC credentials
# 3. Node availability
超出费率限制
{
"jsonrpc": "2.0",
"error": {
"code": -32004,
"message": "Rate limit of 60 requests per minute exceeded"
},
"id": 1
}
// Solution: Increase RATE_LIMIT_PER_MINUTE or implement client-side throttling
地址验证失败
# Common causes:
# 1. Invalid address format
# 2. Wrong network (mainnet address on testnet)
# 3. Unsupported address type
# Debug with validate_address method
{
"jsonrpc": "2.0",
"method": "validate_address",
"params": {"address": "your_address_here"},
"id": 1
}
开发调试
启用调试模式
# In .env file
DEBUG=true
# Or via environment
DEBUG=true python -m uvicorn src.main:app --reload
添加自定义日志记录
import logging
logger = logging.getLogger(__name__)
async def your_method(self):
logger.debug(f"Processing request with params: {params}")
try:
result = await some_operation()
logger.info(f"Operation successful: {result}")
return result
except Exception as e:
logger.error(f"Operation failed: {str(e)}", exc_info=True)
raise
网络安全
# Add IP whitelisting for production
ALLOWED_IPS = ["127.0.0.1", "10.0.0.0/8", "192.168.0.0/16"]
@app.middleware("http")
async def ip_whitelist_middleware(request: Request, call_next):
client_ip = request.client.host
if client_ip not in ALLOWED_IPS:
return JSONResponse(
status_code=403,
content={"error": "Access denied"}
)
return await call_next(request)
输入验证安全
# Implement comprehensive input validation
def validate_amount(amount: Union[str, int, float]) -> float:
try:
amount_float = float(amount)
if amount_float < 0:
raise ValidationError("Amount cannot be negative")
if amount_float > 21_000_000: # Max Bitcoin supply
raise ValidationError("Amount exceeds maximum Bitcoin supply")
return amount_float
except (ValueError, TypeError):
raise ValidationError("Invalid amount format")
# Sanitize string inputs
def sanitize_string(value: str, max_length: int = 255) -> str:
if not isinstance(value, str):
raise ValidationError("Value must be a string")
# Remove potentially dangerous characters
sanitized = re.sub(r'[<>"\']', '', value.strip())
if len(sanitized) > max_length:
raise ValidationError(f"String too long (max {max_length} chars)")
return sanitized
# Validate pagination parameters
def validate_pagination(offset: int = 0, limit: int = 25) -> tuple:
if offset < 0:
raise ValidationError("Offset cannot be negative")
if limit <= 0 or limit > 100:
raise ValidationError("Limit must be between 1 and 100")
return offset, limit
API速率限制
# Advanced rate limiting with Redis (optional enhancement)
import redis
from datetime import datetime, timedelta
class AdvancedRateLimiter:
def __init__(self, redis_client):
self.redis = redis_client
async def check_rate_limit(self, client_id: str, limit: int = 60, window: int = 60):
key = f"rate_limit:{client_id}"
current_time = datetime.utcnow()
# Sliding window rate limiting
pipe = self.redis.pipeline()
pipe.zremrangebyscore(key, 0, current_time.timestamp() - window)
pipe.zcard(key)
pipe.zadd(key, {str(current_time.timestamp()): current_time.timestamp()})
pipe.expire(key, window)
results = pipe.execute()
request_count = results[1]
if request_count >= limit:
raise RateLimitError(f"Rate limit exceeded: {request_count}/{limit} requests")
🤝 贡献
开发工作流程
- 分叉存储库
- 创建要素分支:
git checkout -b feature/new-method - 遵循编码标准:
- 一致使用异步/等待模式
- 实施适当的错误处理
- 为所有参数添加输入验证
- 遵循既定的工具模块结构
- 添加测试 对于新功能
- 更新文档 新方法
- 提交拉取请求
代码风格指南
- python:使用async/await模式遵循PEP 8
- 错误处理:使用自定义例外
src/utils/errors.py - 验证:使用实现输入验证
src/utils/validation.py - 文档:为所有公共方法添加文档字符串
- 类型提示:对所有函数参数和返回值使用类型提示
测试指南
- 单元测试:测试单个方法和错误条件
- 集成测试:测试JSON-RPC请求/响应周期
- 错误测试:测试所有错误条件和边缘情况
- 速率限制:测试速率限制行为
- 验证:所有参数的测试输入验证
📄 许可证
此项目根据MIT许可证获得许可-有关详细信息,请参阅许可证文件。
🙏 致谢
- 比特币核心 对于RPC接口
- Mempool.space 用于地址和交易数据
- CoinGecko 的 市场价格数据
- 备选.me 恐惧与贪婪指数
- 快速 API 优秀的web框架
- 派丹蒂克 用于数据验证和设置管理
带有模式的工具定义
工具={ “get_blockchain_info”:{ “name”:“get_blockchain_info”, “description”:“获取全面的区块链信息…”, “inputSchema”:{ “类型”:“对象”, “属性”:{}, “必填”:[] } }, “get_block_by_height”:{ “name”:“get_block_by_height”, “description”:“通过可选交易详细信息按高度获取区块信息”, “inputSchema”:{ “类型”:“对象”, “属性”:{ “高度”:{ “type”:“整数”, “description”:“要检索的块高度” }, “包括交易”:{ “type”:“boolean”, “description”:“是否包含完整的交易数据”, “默认”:False } }, “必需”:[“高度”] } } # ...共定义了20个工具 }
资源定义
资源={ “比特币:区块链:信息”: { “uri”:“比特币:区块链:信息”, "name": "比特币区块链信息", “description”:“当前区块链状态和统计数据”, “mimeType”:“应用程序/json” } # ...已定义3个资源 }