Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bitcoin Gateway Guard

Enterprise Bitcoin Intelligence with RBAC, Rate Limiting & Audit Trails

Hackathon Submission: Secure & Govern MCP category Built with agentgateway + bitcoin-mcp


The Problem

AI agents accessing financial data without guardrails is a disaster waiting to happen.

bitcoin-mcp exposes 49 tools for querying the Bitcoin network: block analysis, fee estimation, mempool inspection, address lookups, and more. Two of those tools are write operations -- send_raw_transaction (broadcasts a signed transaction to the network) and generate_keypair (creates private key material).

In a production environment, you need answers to hard questions:

  • Who is calling these tools?
  • What are they allowed to do?
  • How often can they call?
  • Where is the audit trail?

Bitcoin Gateway Guard answers all four by placing agentgateway in front of bitcoin-mcp, enforcing JWT authentication, role-based access control, per-consumer rate limiting, and full OpenTelemetry tracing to Jaeger.


Architecture

                         agentgateway (port 3000)
                    +---------------------------------+
                    |                                 |
  AI Agent -------->|  JWT Auth                       |
  (Claude,          |    |                            |
   GPT,             |    v                            |
   custom)          |  RBAC Policy Engine             |-------> Jaeger (port 16686)
                    |    |                            |  OTLP
                    |    v                            |
                    |  Rate Limiter (10 req/min)      |
                    |    |                            |
                    |    v                            |
                    |  bitcoin-mcp (49 tools)         |
                    |                                 |
                    +---------------------------------+

  Roles:
    reader  --> 47 read-only tools (blocks, fees, mempool, addresses...)
    admin   --> all 49 tools (includes send_raw_transaction, generate_keypair)

Every request flows through four security layers before reaching bitcoin-mcp. No exceptions, no bypasses.


Security Model at a Glance

Layer What It Does Config
JWT Authentication Validates signed tokens, rejects anonymous access RSA-256, custom issuer/audience
RBAC reader blocked from write tools, admin gets full access CEL expressions on jwt.role + mcp.tool.name
Rate Limiting 10 requests/minute per consumer, token bucket algorithm localRateLimit policy
Audit Trail Every tool call traced with full context OpenTelemetry --> Jaeger

Tool Classification

  • 47 read-only tools: get_block_count, get_blockchain_info, get_fee_estimates, analyze_mempool, get_address_balance, validate_address, decode_raw_transaction, and 40 more
  • 2 write/sensitive tools: send_raw_transaction (broadcasts transactions), generate_keypair (creates private keys)

See SECURITY_MODEL.md for the full breakdown.


Quick Start

1. Generate JWT Keys and Tokens

pip install pyjwt cryptography
python scripts/generate_keys.py

This creates keys/pub-key.pem, keys/priv-key.pem, keys/reader.jwt, and keys/admin.jwt.

2. Launch the Stack

docker compose up -d

This starts three services:

  • bitcoin-mcp -- the MCP server with 49 Bitcoin tools
  • agentgateway -- the security gateway on port 3000
  • jaeger -- the tracing UI on port 16686

3. Test the Security

# Reader can query blocks (ALLOWED)
python scripts/test_rbac.py --user reader --tool get_block_count

# Reader cannot broadcast transactions (DENIED)
python scripts/test_rbac.py --user reader --tool send_raw_transaction

# Admin can do everything (ALLOWED)
python scripts/test_rbac.py --user admin --tool send_raw_transaction

# Rate limiting kicks in after 10 rapid requests
python scripts/test_rbac.py --user reader --tool get_block_count --burst 15

Testing the Security (3 Scenarios)

Scenario 1: Reader Calls a Read-Only Tool

$ python scripts/test_rbac.py --user reader --tool get_block_count

[Bitcoin Gateway Guard] Testing RBAC
  User:  reader
  Tool:  get_block_count
  Token: keys/reader.jwt

  Result: ALLOWED
  Response: {"block_count": 889241}

Scenario 2: Reader Tries a Write Tool

$ python scripts/test_rbac.py --user reader --tool send_raw_transaction

[Bitcoin Gateway Guard] Testing RBAC
  User:  reader
  Tool:  send_raw_transaction
  Token: keys/reader.jwt

  Result: DENIED
  Error:  Authorization denied: role "reader" cannot access tool "send_raw_transaction"

Scenario 3: Rate Limiting Under Burst

$ python scripts/test_rbac.py --user reader --tool get_fee_estimates --burst 15

[Bitcoin Gateway Guard] Burst test: 15 requests
  Request  1: 200 OK (2ms)
  Request  2: 200 OK (1ms)
  ...
  Request 10: 200 OK (2ms)
  Request 11: 429 Rate Limited (0ms)
  Request 12: 429 Rate Limited (0ms)
  ...
  Request 15: 429 Rate Limited (0ms)

  Summary: 10 allowed, 5 rate-limited

Configuration Deep Dive

The entire security policy lives in config.yaml:

Tracing

config:
  tracing:
    otlpEndpoint: http://jaeger:4317
    randomSampling: true

All tool invocations are exported as OpenTelemetry spans to Jaeger. Every span includes the tool name, the JWT claims (role, subject), the response status, and timing data.

Rate Limiting

localRateLimit:
  - maxTokens: 10
    tokensPerFill: 1
    fillInterval: 60s

Token bucket algorithm: 10 tokens max, refills 1 token per second, bucket resets every 60 seconds. This gives a sustained rate of 1 req/sec with burst capacity up to 10.

JWT Authentication

jwtAuth:
  issuer: bitcoin-gateway-guard
  audiences: [bitcoin-mcp]
  jwks:
    file: ./keys/pub-key.pem

Every request must carry a valid JWT signed with the RSA private key. The gateway validates the signature, issuer, audience, and expiration. No token = no access.

RBAC Rules

mcpAuthorization:
  rules:
  - 'jwt.role == "admin"'
  - 'jwt.role == "reader" && mcp.tool.name != "send_raw_transaction" && mcp.tool.name != "generate_keypair"'

Rules are evaluated as CEL expressions. A request is authorized if any rule evaluates to true. The admin rule matches all tools. The reader rule explicitly excludes the two write operations.


Jaeger Audit Trail

After running some test queries, open http://localhost:16686 to see the full audit trail:

  1. Select service agentgateway from the dropdown
  2. Click Find Traces
  3. Each trace shows:
    • Tool name called
    • JWT subject (who called it)
    • JWT role (reader or admin)
    • Authorization result (allowed or denied)
    • Duration (latency through the gateway)
    • Response status

This gives security teams a complete, searchable, time-ordered record of every AI agent interaction with Bitcoin data. Feed it into your SIEM, set up alerts on denied requests, detect anomalous access patterns.


Production Considerations

Key Rotation

The generate_keys.py script is for development. In production:

  • Use a proper secrets manager (HashiCorp Vault, AWS KMS) for JWT signing keys
  • Rotate keys on a schedule and update the gateway config
  • Use JWKS endpoints instead of file-based keys for zero-downtime rotation

Network Isolation

  • Run bitcoin-mcp and agentgateway in the same private network
  • Only expose agentgateway's port (3000) to AI agents
  • Never expose bitcoin-mcp directly

Rate Limit Tuning

The default 10 req/min is conservative. Adjust based on your use case:

  • Dashboard refresh: 30 req/min may be appropriate
  • Batch analytics: Use a separate admin-tier rate limit
  • Real-time monitoring: Consider per-tool rate limits

Scaling

agentgateway is stateless. For high availability:

  • Run multiple gateway instances behind a load balancer
  • Use Redis-backed distributed rate limiting
  • Export traces to a production-grade Jaeger or Grafana Tempo cluster

Monitoring

Set up alerts for:

  • Authorization denied events (potential privilege escalation attempts)
  • Rate limit violations (runaway agents)
  • Elevated error rates from bitcoin-mcp
  • JWT validation failures (token theft or forgery attempts)

Repository Structure

submissions/security/
  README.md              # This file
  SECURITY_MODEL.md      # Detailed security model documentation
  blog.md                # dev.to-ready blog post
  config.yaml            # agentgateway configuration
  docker-compose.yml     # Full stack: bitcoin-mcp + agentgateway + jaeger
  Dockerfile.bitcoin-mcp # Bitcoin MCP server container
  scripts/
    generate_keys.py     # Generate RSA keys and JWT tokens
    test_rbac.py         # Test RBAC, rate limiting, auth
  keys/                  # Generated keys and tokens (gitignored in production)

Credits

  • bitcoin-mcp -- 49-tool MCP server for Bitcoin network intelligence
  • agentgateway -- Open-source gateway for securing MCP servers
  • Jaeger -- Distributed tracing platform

Built for the Secure & Govern MCP Hackathon. Because AI agents with access to financial infrastructure deserve the same security posture as the humans they assist.

About

MCP Hackathon: Secure & Govern — Enterprise Bitcoin Intelligence with RBAC, Rate Limiting & Audit Trails via agentgateway

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages