10분 안에 당신의 MCP 서버를 수익화하세요.
@blockchain0x/mcp를 설치하고, 프리미엄 도구 내에서 호출자가 결제하지 않았을 때 requirePayment를 호출하세요 - 이는 호스팅된 체크아웃 URL과 함께 x402 402 챌린지를 생성합니다. 결제.received 웹후크가 정산을 확인하면, 귀하의 상점에서 호출자를 결제된 것으로 표시하고 도구가 실행됩니다. 무료 도구는 무료로 유지됩니다. 일반 HTTP 서버의 경우, 수신 측 x402 어댑터가 동일한 작업을 수행합니다.
시작하기 전에.
- Node 또는 Python에서 공식 모델 컨텍스트 프로토콜 SDK를 사용하는 작동하는 MCP 서버. 아직 없다면 먼저 업스트림 템플릿으로 하나를 스캐폴드하세요.
- Blockchain0x 계정과 에이전트 프로필 (5분 설정을 위한 add-payments-to-agent guide 참조).
- API 키(
sk_test_를 이 가이드에 사용하십시오). - 누가 지불했는지 기억하는 작은 저장소(데이터베이스 행 또는 Redis 키) - 귀하의 코드가 이를 소유하며, 결제 웹훅에 의해 업데이트됩니다.
- 어떤 도구에 대해 요금을 부과할지와 호출당 가격에 대한 명확한 감각. 디자인 패턴에 대한 내용은 유료 MCP 도구 용어집 항목을 참조하십시오.
패키지를 설치하세요.
@blockchain0x/mcp exports requirePayment, a pure function that mints an x402 402 challenge for a tool. It is npm (TypeScript) only. If you run a plain HTTP server instead of an MCP one, install the receive-side x402 adapter and gate routes with it.
# Gate your own MCP tools with the requirePayment 402 builder:
npm install @blockchain0x/mcp
# Or gate a plain HTTP server with the receive-side x402 adapter + SDK:
npm install @blockchain0x/x402 @blockchain0x/noderequirePayment로 도구를 제한하세요.
Inside the tool, check your own paid-state for the caller. If they have not paid, call requirePayment and return the resulting 402 body; if they have, run the work. requirePayment is a pure builder - it does not wrap the handler and does not track payment, so the gating policy stays in your code.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { requirePayment } from "@blockchain0x/mcp";
import { z } from "zod";
const server = new McpServer({ name: "premium-data-mcp", version: "1.0.0" });
server.tool(
"get_quote_realtime",
"Real-time quote (paid)",
{ ticker: z.string() },
async ({ ticker }, extra) => {
if (!hasPaid(extra)) {
// Pure function: mint an x402 402 challenge and hand the body back.
const { body } = requirePayment({
amountUsdc: "0.005",
payTo: "0xYourWallet",
hostedUrl: "https://pay.blockchain0x.com/checkout/abc",
});
return { content: [{ type: "text", text: JSON.stringify(body) }], isError: true };
}
const quote = await fetchLiveQuote(ticker);
return { content: [{ type: "text", text: JSON.stringify(quote) }] };
},
);import express from "express";
import { createX402Middleware } from "@blockchain0x/x402/server/express";
import { createClient } from "@blockchain0x/node";
const sdk = createClient({ apiKey: process.env.BLOCKCHAIN0X_API_KEY! });
const app = express();
// Not an MCP server? Gate a plain HTTP route the same way. The middleware
// answers unpaid requests with a 402 and lets paid ones through.
// Configure the price and recipient per the x402 docs.
app.use("/quote", createX402Middleware({ sdk }));402 본문 requirePayment는 미지급 호출자에게 반환됩니다:
// requirePayment returns { status: 402, body }. The body an unpaid caller sees:
{
"error": "payment_required",
"amountUsdc": "0.005",
"payTo": "0xYourWallet",
"hostedUrl": "https://pay.blockchain0x.com/checkout/abc",
"network": "mainnet"
}결제를 확인한 후 누가 지불했는지 기억하십시오.
When a caller pays the checkout, Blockchain0x POSTs a signed payment.received event to your webhook. Verify it with webhooks.verify from @blockchain0x/node, then write the paid state to a store you control - a database row, a Redis key, your call. That store is what the tool checks in Step 2. There is no shipped receipt cache; you own where paid-state lives and how long it lasts.
import express from "express";
import { webhooks } from "@blockchain0x/node";
const app = express();
app.use(express.raw({ type: "application/json" }));
app.post("/webhooks/payment", (req, res) => {
const result = webhooks.verify({
headers: req.headers,
rawBody: req.body, // RAW bytes
secret: process.env.BLOCKCHAIN0X_WEBHOOK_SECRET!,
});
if (!result.ok) return res.status(400).json({ code: result.code });
if (result.eventType === "payment.received") {
// Remember the payer however you like - a DB row, a Redis key, your call.
markPaid(result.eventId);
}
res.status(200).send("ok");
});결제가 얼마나 오랜 시간 동안 접근을 허용하는지는 귀하의 결정입니다 - 단일 호출, 세션, 한 시간. 도구의 가격 책정에 맞춰 유료 상태 키의 만료를 설정하세요. 일반 세션이 하나의 결제를 재사용할 수 있을 만큼 충분히 길고, 남용이 제한될 수 있을 만큼 충분히 짧아야 합니다.
배포 및 검증.
서버를 배포하세요. 무료 도구는 여전히 즉시 결과를 반환해야 하며; 제한된 도구는 새 클라이언트의 첫 번째 호출에서 402 본문을 반환한 후, 해당 호출자가 결제된 것으로 표시되면 실행해야 합니다. 라이브로 전환하기 전에 sk_test_ 키로 Base Sepolia에서 두 경로를 모두 확인하세요.
첫날 주의해야 할 두 가지 신호: 반환된 402의 수(상단 퍼널)와 402 이후 성공적인 도구 실행 수(전환). 전환이 예상보다 훨씬 낮다면 가격이 잘못되었을 가능성이 높습니다. 유료 상태 저장소의 적중률도 주의하세요 - 거의 0에 가깝다면 접근 창이 너무 짧고 결제하는 호출자가 다시 결제를 요청받고 있습니다.
처음 MCP를 수익화하는 사람들을 괴롭히는 다섯 가지 사항.
우연히 무료 도구를 게이트
모든 도구를 '혹시나 해서' 게이트하고 싶을 수 있지만, 그렇게 하지 마세요. 유료 MCP 서버의 전체 가치는 무료 도구가 유료 도구와 함께 동일한 서버에서 공존할 수 있다는 것입니다. 따라서 클라이언트는 무료 발견 및 메타데이터 도구를 사용하면서 결제할 필요가 없습니다. 실제로 프리미엄 자원을 소비하는 도구에 대해서만 402를 생성하고, 나머지는 일반 결과로 남겨두세요.
requirePayment는 빌더이며 미들웨어가 아닙니다.
requirePayment는 순수 함수입니다: 도구가 미지급 상태일 때 호출하면 { status: 402, body }를 반환하고, 그 본문을 반환합니다. 이는 귀하의 핸들러를 래핑하지 않으며 누가 지불했는지 추적하지 않습니다. amountUsdc, payTo, hostedUrl, 및 선택적 네트워크와 설명을 받습니다 - 그 외에는 없습니다. 호출자가 지불했는지 여부는 귀하의 상점에서 실행하는 확인입니다.
배포된 영수증 캐시가 없습니다.
Blockchain0x는 402 빌더와 정산 웹후크를 제공하며, 영수증 저장 도우미는 아닙니다. '이 호출자가 지불한' 위치를 결정합니다 - 데이터베이스 행, Redis 키, 단일 프로세스를 위한 메모리 내 맵 등 - 그리고 payment.received 웹후크가 도착할 때 이를 전환합니다. 이는 정책(지불이 접근을 부여하는 기간)을 완전히 귀하의 손에 유지합니다.
클라이언트가 가지고 있다고 주장하는 영수증을 신뢰
호출자가 지불했다고 주장하지 않도록 하십시오. 진실의 출처는 payment.received 웹후크이며, 이는 귀하의 웹후크 비밀에 대해 webhooks.verify(또는 문서화된 HMAC)로 검증됩니다. 검증된 이벤트 후에만 지불자를 지불한 것으로 표시하고, 도구를 해당 서버 측 상태에 따라 게이트하십시오 - 클라이언트가 보낸 것에 따라서는 절대 하지 마십시오.
유료 도구 지연에 대한 메트릭 없음
클라이언트와 도구 실행 사이에 결제 단계를 추가하면 호출자가 첫 번째 호출에서 결제하고 정산하는 데 걸리는 시간이 추가되며, 결제가 완료된 후에는 거의 제로에 가깝습니다. 두 가지 경로를 모두 계측하여 고객이 불만을 제기할 때 '도구가 느리다'와 '결제가 느리다'를 구분할 수 있습니다. 메트릭이 없으면 병목 현상을 잘못 진단할 수 있습니다.
유료 트래픽이 흐르기 시작하면.
수익화가 이루어지면 가장 유용한 후속 조치는 신뢰할 수 있는 웹훅 처리(결제 이벤트를 놓치지 않도록), 지출 통제(다른 에이전트에게도 지급하는 MCP 서버가 한정되도록), 그리고 테스트넷 우선 흐름(실제 돈을 소모하지 않고 가격 변경을 배포할 수 있도록)입니다.
전체 API 참조는 docs.blockchain0x.com에 있습니다. 관련 제품 표면: MCP 통합.