<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: J</title>
    <description>The latest articles on DEV Community by J (@joney).</description>
    <link>https://dev.to/joney</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3873162%2F84080476-5dcd-4232-b1cd-9e30cf4d8384.png</url>
      <title>DEV Community: J</title>
      <link>https://dev.to/joney</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joney"/>
    <language>en</language>
    <item>
      <title>I Built an MCP Server That Lets Claude Talk to a Blockchain — And It Paid Me Crypto</title>
      <dc:creator>J</dc:creator>
      <pubDate>Sat, 11 Apr 2026 08:21:45 +0000</pubDate>
      <link>https://dev.to/joney/i-built-an-mcp-server-that-lets-claude-talk-to-a-blockchain-and-it-paid-me-4n69</link>
      <guid>https://dev.to/joney/i-built-an-mcp-server-that-lets-claude-talk-to-a-blockchain-and-it-paid-me-4n69</guid>
      <description>&lt;p&gt;What if your AI assistant could check your crypto wallet balance, monitor mining rewards, and browse open bounties —&lt;br&gt;&lt;br&gt;
  all from a single chat? That's exactly what I built: an MCP (Model Context Protocol) server that connects Claude Code &lt;br&gt;
  directly to the RustChain blockchain.&lt;/p&gt;

&lt;p&gt;Here's the walkthrough.                &lt;/p&gt;




&lt;p&gt;What is RustChain?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Scottcjn/Rustchain" rel="noopener noreferrer"&gt;https://github.com/Scottcjn/Rustchain&lt;/a&gt; is a Proof-of-Antiquity (PoA) blockchain with a twist: old hardware earns more &lt;br&gt;
  than new hardware. A PowerPC G4 Mac from 2002 gets a higher antiquity multiplier than a brand-new GPU server. The&lt;br&gt;&lt;br&gt;
  chain pays out RTC tokens every epoch (~10 minutes) to miners who attest their hardware fingerprint.&lt;/p&gt;

&lt;p&gt;What makes it interesting from a developer standpoint is the REST API — the node exposes endpoints for balances, epoch&lt;br&gt;
   info, miner lists, and more. That makes it a perfect candidate for an MCP integration.&lt;/p&gt;




&lt;p&gt;What is MCP?&lt;/p&gt;

&lt;p&gt;Model Context Protocol (MCP) is Anthropic's open standard for connecting AI assistants to external tools and data&lt;br&gt;
  sources. Think of it like a plugin system for Claude: you write a server that exposes "tools" (functions the AI can&lt;br&gt;&lt;br&gt;
  call), and Claude can invoke them during a conversation.&lt;/p&gt;

&lt;p&gt;The key insight: the LLM decides when to call your tools, based on natural language context. You describe what a tool &lt;br&gt;
  does, and Claude figures out when to use it.&lt;/p&gt;




&lt;p&gt;Building the Server&lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://github.com/jlowin/fastmcp" rel="noopener noreferrer"&gt;https://github.com/jlowin/fastmcp&lt;/a&gt; — a Python framework that turns decorated functions into MCP tools&lt;br&gt;
  automatically.&lt;/p&gt;

&lt;p&gt;Setup                                                                                                                 &lt;/p&gt;

&lt;p&gt;pip install fastmcp httpx                                                                                             &lt;/p&gt;

&lt;p&gt;# rustchain_mcp/server.py&lt;br&gt;
  from fastmcp import FastMCP&lt;br&gt;
  import httpx&lt;/p&gt;

&lt;p&gt;NODE_URL = "&lt;a href="https://50.28.86.131" rel="noopener noreferrer"&gt;https://50.28.86.131&lt;/a&gt;"&lt;br&gt;
  mcp = FastMCP("RustChain MCP")&lt;/p&gt;

&lt;p&gt;Tool 1: Check Node Health&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool()&lt;br&gt;&lt;br&gt;
  async def rustchain_health() -&amp;gt; dict:&lt;br&gt;
      """Check if the RustChain node is online and healthy."""&lt;br&gt;
      async with httpx.AsyncClient(verify=False, timeout=10) as client:&lt;br&gt;
          r = await client.get(f"{NODE_URL}/health")&lt;br&gt;&lt;br&gt;
          r.raise_for_status()&lt;br&gt;
          data = r.json()&lt;br&gt;&lt;br&gt;
          return {&lt;br&gt;&lt;br&gt;
              "ok": data.get("ok"),&lt;br&gt;
              "version": data.get("version"),&lt;br&gt;&lt;br&gt;
              "uptime_hours": round(data.get("uptime_s", 0) / 3600, 1),&lt;br&gt;
          }                                                                                                             &lt;/p&gt;

&lt;p&gt;Simple: decorate a function with &lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool(), give it a docstring Claude can understand, and return structured data.  &lt;/p&gt;

&lt;p&gt;Tool 2: Wallet Balance (with USD conversion)                                                                          &lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool()&lt;br&gt;
  async def rustchain_balance(wallet_id: str) -&amp;gt; dict:&lt;br&gt;
      """&lt;br&gt;
      Get the RTC token balance for a wallet.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Args:
      wallet_id: The miner/wallet identifier (e.g. 'my-miner-name')                                                 
  """                                
  async with httpx.AsyncClient(verify=False, timeout=10) as client:
      r = await client.get(
          f"{NODE_URL}/wallet/balance",                                                                             
          params={"miner_id": wallet_id},
      )                                                                                                             
      r.raise_for_status()           
      data = r.json()
      amount_rtc = data.get("amount_rtc", 0)
      RTC_PRICE_USD = 0.10                                                                                          
      return {
          "wallet": wallet_id,                                                                                      
          "balance_rtc": amount_rtc, 
          "balance_usd": round(amount_rtc * RTC_PRICE_USD, 2),
      }                                                                                                             
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;







&lt;p&gt;Tool 3: Epoch Status                                                                                                  &lt;/p&gt;

&lt;p&gt;Each RustChain epoch lasts ~100 slots at 10 minutes each. At the end of every epoch, the pot is distributed&lt;br&gt;
  proportionally to active miners.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool()&lt;br&gt;
  async def rustchain_epoch() -&amp;gt; dict:&lt;br&gt;&lt;br&gt;
      """Get current epoch number, time remaining, and pot size."""&lt;br&gt;
      async with httpx.AsyncClient(verify=False, timeout=10) as client:&lt;br&gt;&lt;br&gt;
          r = await client.get(f"{NODE_URL}/epoch")&lt;br&gt;&lt;br&gt;
          r.raise_for_status()&lt;br&gt;
          data = r.json()&lt;br&gt;&lt;br&gt;
          return {&lt;br&gt;&lt;br&gt;
              "epoch": data.get("epoch"),&lt;br&gt;
              "slots_remaining": data.get("slots_remaining"),&lt;br&gt;&lt;br&gt;
              "pot_rtc": data.get("pot_rtc"),&lt;br&gt;
          }                                                                                                             &lt;/p&gt;

&lt;p&gt;Tool 4: List Active Miners                                                                                            &lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool()&lt;br&gt;&lt;br&gt;
  async def rustchain_miners() -&amp;gt; dict:&lt;br&gt;&lt;br&gt;
      """List all active miners and their hardware types."""&lt;br&gt;
      async with httpx.AsyncClient(verify=False, timeout=10) as client:&lt;br&gt;
          r = await client.get(f"{NODE_URL}/miners")&lt;br&gt;&lt;br&gt;
          r.raise_for_status()&lt;br&gt;
          data = r.json()&lt;br&gt;&lt;br&gt;
          return {&lt;br&gt;&lt;br&gt;
              "count": len(data.get("miners", [])),&lt;br&gt;
              "miners": data.get("miners", [])[:10],&lt;br&gt;&lt;br&gt;
          }&lt;/p&gt;

&lt;p&gt;Tool 5: Browse Open Bounties           &lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool()&lt;br&gt;
  async def rustchain_bounties() -&amp;gt; dict:&lt;br&gt;
      """List open bounties available for contribution."""&lt;br&gt;&lt;br&gt;
      async with httpx.AsyncClient(verify=False, timeout=10) as client:&lt;br&gt;
          r = await client.get(f"{NODE_URL}/bounties")&lt;br&gt;&lt;br&gt;
          r.raise_for_status()&lt;br&gt;&lt;br&gt;
          data = r.json()&lt;br&gt;
          return {&lt;br&gt;&lt;br&gt;
              "open": [b for b in data.get("bounties", []) if b.get("status") == "open"],&lt;br&gt;
          }                                                                                                             &lt;/p&gt;







&lt;p&gt;Tool 6: Submit Attestation                                                                                            &lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool()&lt;br&gt;&lt;br&gt;
  async def rustchain_submit_attestation(miner_id: str, hardware_fingerprint: str) -&amp;gt; dict:&lt;br&gt;
      """&lt;br&gt;&lt;br&gt;
      Submit a hardware attestation to earn RTC tokens.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Args:                              
      miner_id: Your miner identifier
      hardware_fingerprint: Hardware fingerprint string from the miner client                                       
  """
  async with httpx.AsyncClient(verify=False, timeout=10) as client:                                                 
      r = await client.post(                                                                                        
          f"{NODE_URL}/attest",
          json={"miner_id": miner_id, "fingerprint": hardware_fingerprint},                                         
      )                                                                                                             
      r.raise_for_status()
      return r.json()                                                                                               
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Tool 7: Create Wallet&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/mcp"&gt;@mcp&lt;/a&gt;.tool()&lt;br&gt;
  async def rustchain_create_wallet(miner_id: str) -&amp;gt; dict:&lt;br&gt;
      """&lt;br&gt;&lt;br&gt;
      Create a new RustChain wallet/miner identity.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Args:                              
      miner_id: Desired miner name (must be unique on the network)
  """                                                                                                               
  async with httpx.AsyncClient(verify=False, timeout=10) as client:
      r = await client.post(                                                                                        
          f"{NODE_URL}/wallet/create",                                                                              
          json={"miner_id": miner_id},
      )                                                                                                             
      r.raise_for_status()           
      return r.json()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;Running It&lt;/p&gt;

&lt;p&gt;# Install dependencies&lt;br&gt;
  pip install fastmcp httpx                                                                                             &lt;/p&gt;

&lt;p&gt;# Run the MCP server&lt;br&gt;
  python -m rustchain_mcp.server&lt;/p&gt;

&lt;p&gt;Then in your Claude Code settings.json:                                                                               &lt;/p&gt;

&lt;p&gt;{&lt;br&gt;&lt;br&gt;
    "mcpServers": {&lt;br&gt;&lt;br&gt;
      "rustchain": {&lt;br&gt;
        "command": "python",&lt;br&gt;
        "args": ["-m", "rustchain_mcp.server"]&lt;br&gt;
      }&lt;br&gt;&lt;br&gt;
    }&lt;br&gt;
  }                                                                                                                     &lt;/p&gt;







&lt;p&gt;What I Learned                                                                                                        &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Structured data beats prose. Return dicts with clear keys — Claude reasons better over {"balance_rtc": 42} than&lt;br&gt;
"Your balance is 42 RTC".                                                                                             &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docstrings are your API contract. Claude reads your docstrings to decide when and how to call your tools. Write&lt;br&gt;&lt;br&gt;
them like you're explaining to a smart colleague, not a compiler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Async all the way. FastMCP is async-native. Mix sync and async and you'll hit subtle deadlocks. Just go full async &lt;br&gt;
from the start.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TLS cert quirks. The RustChain node uses a self-signed cert. verify=False in httpx handles it — but log a warning&lt;br&gt;&lt;br&gt;
in production so you don't forget it's there.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;The Result&lt;/p&gt;

&lt;p&gt;Once connected, Claude can answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What's my RustChain balance?"
&lt;/li&gt;
&lt;li&gt;"How many slots until the next epoch payout?"&lt;/li&gt;
&lt;li&gt;"What bounties are open right now?"
&lt;/li&gt;
&lt;li&gt;"Create a new wallet called my-powerpc-miner"
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All from natural language, no manual API calls.                                                                       &lt;/p&gt;




&lt;p&gt;Try It&lt;/p&gt;

&lt;p&gt;The full source is in the &lt;a href="https://github.com/Scottcjn/rustchain-bounties" rel="noopener noreferrer"&gt;https://github.com/Scottcjn/rustchain-bounties&lt;/a&gt;. If you want to earn RTC while contributing&lt;br&gt;
  to open source, check the open bounties — there's usually something for every skill level.                            &lt;/p&gt;




&lt;p&gt;Built with FastMCP + httpx + Claude Code. RustChain is open source and actively developed.&lt;/p&gt;




&lt;p&gt;복사 다 됐으면 오른쪽 위 Publish 버튼 눌러서 발행하고 URL 나오면 나한테 알려줘.                        &lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>claude</category>
      <category>mcp</category>
      <category>rust</category>
    </item>
  </channel>
</rss>
