DEV Community

Cover image for How to build a paid MCP tool that AI agents pay to use
M M
M M

Posted on • Originally published at monapi.dev

How to build a paid MCP tool that AI agents pay to use

MCP is everywhere right now. Everyone is building MCP servers — for search, for databases, for file systems. But there's one thing nobody is talking about: how do you get paid when an AI agent uses your MCP tool?

Today we'll build a complete MCP server with a paid tool. An AI agent calls your tool, pays per use, and gets the result. No API keys, no subscriptions, no signup.

This isn't theoretical. We'll build it, run it, and test it.

What we're building

A code review MCP server. An AI agent sends a code snippet, pays $0.05, and gets a structured review back — issues found, suggestions, severity ratings.

Why code review? Because it's expensive to run (it calls an LLM under the hood), so charging for it makes sense. And it's a tool that AI agents actually want — coding agents like Cursor, Windsurf, and Claude Code could use a second opinion on the code they write.

How payment works in MCP

Quick primer if you haven't seen this before.

MCP tools normally work like this: agent calls tool → tool returns result. Free.

With x402 payment, there's one extra step: agent calls tool → server says "pay $0.05 first" → agent pays in USDC → server runs the tool → agent gets the result.

This happens automatically. x402-compatible agents (Coinbase AgentKit, Cloudflare Workers, Vercel AI SDK) handle payment without any human intervention. The agent has a wallet, sees the price, decides if it's worth it, pays, and gets the data.

Prerequisites

  • Node.js 18+
  • A wallet address (Coinbase Wallet or MetaMask — free, takes 2 minutes)

Step 1: Set up the project

mkdir code-review-mcp && cd code-review-mcp
npm init -y
npm install @modelcontextprotocol/sdk @monapi/sdk @x402/mcp zod
npm install -D tsx typescript @types/node
Enter fullscreen mode Exit fullscreen mode

Add "type": "module" to your package.json.

Step 2: Build the MCP server

Create server.ts:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { monapiMcp } from "@monapi/sdk/mcp";
import { z } from "zod";

const server = new McpServer({
  name: "code-review",
  version: "1.0.0",
});

const paid = monapiMcp({
  wallet: process.env.MONAPI_WALLET!,
  price: 0.05,
  network: "base-sepolia",
});
Enter fullscreen mode Exit fullscreen mode

This sets up the MCP server and creates a payment wrapper. Every tool wrapped with paid() will cost $0.05. We're using base-sepolia (testnet) for development.

Step 3: Add a free discovery tool

server.tool(
  "list_capabilities",
  {},
  async () => ({
    content: [
      {
        type: "text",
        text: JSON.stringify({
          name: "code-review",
          description: "Automated code review for any language",
          tools: {
            review_code: {
              price: "$0.05",
              description: "Analyze code for bugs, security issues, and style",
            },
          },
        }, null, 2),
      },
    ],
  })
);
Enter fullscreen mode Exit fullscreen mode

No paid() wrapper means no payment required. This tool is free.

Why does this exist? An AI agent connecting to your MCP server for the first time has no idea what you offer or what it costs. The discovery tool answers both questions in machine-readable JSON. The agent can parse this, decide if review_code is worth $0.05, and proceed.

This is the equivalent of a storefront window. If you lock everything behind a paywall, agents will disconnect and move on.

Step 4: Add the paid tool

server.tool(
  "review_code",
  {
    code: z.string().describe("The code snippet to review"),
    language: z.string().describe("Programming language"),
  },
  paid(async (args) => {
    const review = analyzeCode(args.code, args.language);
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify(review, null, 2),
        },
      ],
    };
  })
);
Enter fullscreen mode Exit fullscreen mode

The paid() wrapper is doing all the work. When an agent calls review_code:

  1. monapi checks if the request includes a valid payment
  2. No payment → the agent gets a 402 response with the price ($0.05), token (USDC), network (Base), and wallet address
  3. The agent pays and retries
  4. Payment verified → your handler runs and returns the review

You write the handler. monapi handles everything else.

Step 5: The analysis logic

function analyzeCode(code: string, language: string) {
  const issues: Array<{
    severity: "error" | "warning" | "info";
    line: string;
    message: string;
    suggestion: string;
  }> = [];

  const lines = code.split("\n");

  for (const line of lines) {
    if (line.includes("eval(")) {
      issues.push({
        severity: "error",
        line: line.trim(),
        message: "Use of eval() is a security risk",
        suggestion: "Use JSON.parse() for data, or a sandboxed interpreter",
      });
    }

    if (/password\s*=\s*["']/.test(line)) {
      issues.push({
        severity: "error",
        line: line.trim(),
        message: "Hardcoded password detected",
        suggestion: "Use environment variables: process.env.PASSWORD",
      });
    }

    if (line.includes("catch") && line.includes("{}")) {
      issues.push({
        severity: "warning",
        line: line.trim(),
        message: "Empty catch block swallows errors silently",
        suggestion: "Log the error or re-throw",
      });
    }

    if (line.includes(".forEach") && line.includes("await")) {
      issues.push({
        severity: "warning",
        line: line.trim(),
        message: "await inside forEach doesn't work as expected",
        suggestion: "Use for...of for sequential, or Promise.all() for parallel",
      });
    }
  }

  return {
    language,
    linesAnalyzed: lines.length,
    issues,
    summary:
      issues.length === 0
        ? "No issues found. Code looks clean."
        : `Found ${issues.length} issue(s): ${issues.filter((i) => i.severity === "error").length} errors, ${issues.filter((i) => i.severity === "warning").length} warnings, ${issues.filter((i) => i.severity === "info").length} info.`,
  };
}
Enter fullscreen mode Exit fullscreen mode

This is deliberately simple — pattern matching for common issues. In production, you'd call an LLM (OpenAI, Anthropic, etc.) to do the actual review. That's exactly why charging $0.05 makes sense: if you're spending $0.02 on an LLM call under the hood, you need to charge more than that.

Step 6: Start the server

const transport = new StdioServerTransport();
await server.connect(transport);
Enter fullscreen mode Exit fullscreen mode

Run it:

MONAPI_WALLET=0xYourWalletAddress npx tsx server.ts
Enter fullscreen mode Exit fullscreen mode

In production, you'd register it in an MCP client config:

{
  "mcpServers": {
    "code-review": {
      "command": "npx",
      "args": ["tsx", "/path/to/server.ts"],
      "env": {
        "MONAPI_WALLET": "0xYourWalletAddress"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Go to production

One change for real payments:

const paid = monapiMcp({
  wallet: process.env.MONAPI_WALLET!,
  price: 0.05,
  network: "base", // was "base-sepolia"
});
Enter fullscreen mode Exit fullscreen mode

Same code, real money. Payments settle in under 2 seconds on Base. USDC is always $1.

What makes this different from a regular paid API

An Express API with monapi works for HTTP clients — agents that make web requests. But MCP is a different protocol. MCP tools are discovered and called by AI assistants directly, inside their runtime. Claude, GPT, Cursor — they all speak MCP.

By building a paid MCP tool instead of (or in addition to) a paid HTTP API, you're available where agents already are. They don't need to know your URL. They discover you through their MCP configuration.

Pricing your MCP tools

Some rules of thumb:

  • Discovery/metadata tools: Free. Always. Agents need to evaluate you before paying.
  • Cheap lookups (cached data, simple transforms): $0.001–$0.01
  • Moderate work (API calls, database queries): $0.01–$0.05
  • Expensive operations (LLM calls, heavy compute): $0.05–$0.50

Price based on your cost, not your value. Agents are cost-optimizing machines. If your tool costs $0.50 and a competitor does the same for $0.10, the agent picks the cheaper one every time. Race to the best cost/quality ratio, not the highest margin.

Full source

Everything in this post is a complete, runnable project.

  • GitHub — full SDK with MCP support
  • monapi.dev — docs and quickstart
  • npmnpm install @monapi/sdk

Or use the CLI to scaffold it:

npx monapi init
Enter fullscreen mode Exit fullscreen mode

It auto-detects MCP from your package.json and generates the boilerplate.


This is part 2 of a series on monetizing APIs for AI agents. Part 1: How to monetize your API with one line of code

Top comments (2)

Collapse
 
ali_muwwakkil_a776a21aa9c profile image
Ali Muwwakkil

To successfully build a paid MCP (Multi-Channel Platform) tool that AI agents can pay to use, it's essential to understand both the technical architecture and the value proposition for AI agents. In our accelerator, we emphasize a few key strategies that have proven effective. Firstly, focus on building a robust API gateway. This gateway should handle authentication, billing, and usage monitoring efficiently. Tools like Kong or Apigee can be integrated to manage API requests, throttle usage, and ensure secure access, which is crucial when AI agents are interacting with your MCP tool. Secondly, consider implementing a microservices architecture. This allows for modular development and scalability. Services can be independently deployed and scaled, which is especially beneficial as usage patterns from AI agents might fluctuate. Kubernetes can be particularly helpful here, offering automated load balancing and scaling. For billing, usage-based pricing models are becoming increasingly popular. These models align with the unpredictable nature of AI agent usage. Integrating a system like Stripe or Chargebee can streamline the payment process, ensuring you capture revenue efficiently. Finally, ensure your platform is developer-friendly. Comprehensive documentation, SDKs in multiple languages, and robust support channels can significantly enhance the developer experience, encouraging adoption and integration. These elements form a solid foundation for creating a paid MCP tool that AI

Collapse
 
m_m_f2442c87a19635b7a1de2 profile image
M M

Thanks for sharing! Just a small note — MCP in this article refers to the Model Context Protocol, which is a standard for AI agents to discover and use tools directly.

The payment side is handled by 402 at the HTTP layer, so no need for API gateways or Stripe in this case. But appreciate the thoughtful response!