Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.semanticpay.io/llms.txt

Use this file to discover all available pages before exploring further.

MCP (Model Context Protocol) is an open standard for connecting AI agents to external tools and services. Semantic supports MCP as a transport for x402, meaning AI agents can discover, call, and pay for tools through a standard MCP server.

How it works

A normal MCP flow: an agent connects to an MCP server, discovers available tools via listTools(), and calls them via callTool(). With x402, the server can require payment for specific tools. The @x402/mcp package handles the payment flow transparently:
  1. Agent calls a tool via MCP
  2. Server responds with a 402 Payment Required challenge (embedded in the MCP response)
  3. The x402 MCP client automatically signs a payment authorization
  4. Client retries the tool call with the payment header
  5. The facilitator settles on-chain, and the tool returns its result
From the agent’s perspective, it just calls a tool. Payment happens in the background.

Install

npm install @x402/mcp @x402/evm @modelcontextprotocol/sdk

Client setup

Use createx402MCPClient to create an MCP client with built-in x402 payment handling.
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { createx402MCPClient } from "@x402/mcp";
import { WalletAccountEvm } from "@tetherto/wdk-wallet-evm";

// WDK wallet as the payment signer
const account = new WalletAccountEvm(process.env.SEED_PHRASE, {
  provider: "https://rpc.plasma.to",
});

// Create x402-enabled MCP client
const mcpClient = createx402MCPClient({
  name: "my-agent",
  version: "1.0.0",
  schemes: [
    { network: "eip155:9745", client: new ExactEvmScheme(account) },
  ],
  autoPayment: true,
  onPaymentRequested: async (context) => {
    const price = context.paymentRequired.accepts[0];
    console.log(`Payment: ${price.amount} on ${price.network} for ${context.toolName}`);
    return true; // approve
  },
});

// Connect to MCP server
const transport = new SSEClientTransport(new URL("http://localhost:4022/sse"));
await mcpClient.connect(transport);

Discovering and calling tools

Once connected, use standard MCP methods. Payment is handled automatically when a tool requires it.
// Discover available tools
const { tools } = await mcpClient.listTools();

for (const tool of tools) {
  console.log(`${tool.name}: ${tool.description}`);
}

// Call a tool — payment happens automatically if required
const result = await mcpClient.callTool("get-weather", { city: "Dubai" });

console.log(result.content[0]?.text);

// Check if payment was made
if (result.paymentMade) {
  console.log("Settled:", result.paymentResponse.transaction);
}

Payment control

The onPaymentRequested callback gives you control over which payments to approve. Return true to pay, false to reject.
const mcpClient = createx402MCPClient({
  // ...
  autoPayment: false, // require explicit approval
  onPaymentRequested: async (context) => {
    const price = context.paymentRequired.accepts[0];
    const amount = Number(price.amount) / 1e6; // USDT0 has 6 decimals

    // Reject anything over $1
    if (amount > 1.0) {
      console.log(`Rejected: $${amount} is too expensive`);
      return false;
    }

    return true;
  },
});

Using with LLMs

The standard pattern is: connect to MCP, convert tools to your LLM’s format, let the LLM decide when to call tools, execute via MCP.

OpenAI

import OpenAI from "openai";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// Convert MCP tools to OpenAI function calling format
const { tools } = await mcpClient.listTools();

const openaiTools: OpenAI.ChatCompletionTool[] = tools.map((tool) => ({
  type: "function",
  function: {
    name: tool.name,
    description: tool.description || "",
    parameters: tool.inputSchema as Record<string, unknown>,
  },
}));

// Let the LLM decide which tools to call
const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: "What's the weather in Dubai?" }],
  tools: openaiTools,
  tool_choice: "auto",
});

// Execute tool calls via MCP (payment handled automatically)
for (const toolCall of response.choices[0].message.tool_calls || []) {
  const args = JSON.parse(toolCall.function.arguments);
  const result = await mcpClient.callTool(toolCall.function.name, args);
  console.log(result.content[0]?.text);
}

Anthropic

import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

// Convert MCP tools to Anthropic format
const { tools } = await mcpClient.listTools();

const anthropicTools = tools.map((tool) => ({
  name: tool.name,
  description: tool.description || "",
  input_schema: tool.inputSchema,
}));

const response = await anthropic.messages.create({
  model: "claude-sonnet-4-20250514",
  max_tokens: 1024,
  messages: [{ role: "user", content: "What's the weather in Dubai?" }],
  tools: anthropicTools,
});

// Execute tool calls via MCP
for (const block of response.content) {
  if (block.type === "tool_use") {
    const result = await mcpClient.callTool(block.name, block.input);
    console.log(result.content[0]?.text);
  }
}

Multi-network support

Register multiple chains so the client can pay on whichever network the server requires:
const mcpClient = createx402MCPClient({
  name: "my-agent",
  version: "1.0.0",
  schemes: [
    { network: "eip155:9745", client: new ExactEvmScheme(plasmaAccount) },
    { network: "eip155:988", client: new ExactEvmScheme(stableAccount) },
  ],
  autoPayment: true,
});

Cleanup

Always close the client when done:
await mcpClient.close();

Next steps

Last modified on February 13, 2026