playbook-mcp-publish
Guide pratique : créer et publier un serveur MCP dans le registre officiel. Un guide concis tiré de la publication de Forge Agent Hub : le CLI officiel mcp-publisher en Go (pas le paquet npm du même nom), server.json (description de 100 caractères, espace de noms io.github), connexion par jeton GitHub, remotes contre stdio, et montées de version. ?demo=1 renvoie la table des matières et un extrait, sans paiement.
Point de terminaison
GET|POST https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish
Paramètres
| Nom | Obligatoire | Type | Description |
|---|---|---|---|
| Aucun | |||
Exemple de requête (non payée — attendre un 402)
curl -sS -D - "https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish?"
Exemple de défi 402
Le même objet est aussi envoyé en en-tête PAYMENT-REQUIRED en base64. Les montants sont des unités USDC atomiques (6 décimales).
{
"x402Version": 2,
"error": "Payment required",
"resource": {
"url": "https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish",
"description": "Playbook: build and publish an MCP server to the official registry. A concise guide from Forge Agent Hub's own publish: the official Go mcp-publisher CLI (not the npm namesake), server.json (100-character description, io.github namespace), GitHub-token login, remotes versus stdio, and version bumps. ?demo=1 returns the table of contents and an excerpt, unpaid.",
"mimeType": "application/json"
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "3000000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x7B8bf45ac6AcbA6D4CFB626b57D3f5fF3C9C89F7",
"maxTimeoutSeconds": 120,
"extra": {
"name": "USD Coin",
"version": "2"
}
}
]
}Réessayer avec paiement
curl -sS "https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish?" \ -H "PAYMENT-SIGNATURE: $PAYMENT"
Exemple de réponse
{
"title": "Build and publish an MCP server to the official registry",
"toc": [
"1. What you are publishing",
"2. The official publisher is a Go CLI, not the npm name",
"3. A valid server.json",
"4. Login with a GitHub token (no browser required)",
"5. Stdio package versus the hosted remote",
"6. Version bumps and expired tokens",
"7. Check that the version is live"
],
"body": "Full playbook after payment."
}Démo / échantillon gratuit
Cet outil est sur le worker de la vague 1. ?demo=1 renvoie un échantillon ou un extrait étiqueté en HTTP 200, sans paiement. Le corps n’est pas une donnée réelle. Les 3 premiers appels réels réussis par IP et par jour UTC sont aussi gratuits.
curl -sS "https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish?demo=1"
Réponse de démo étiquetée
{
"demo": true,
"demo_label": "DEMO / SAMPLE — not live data. This is a labelled example response and was not charged.",
"charged": false,
"tool": "/api/playbook-mcp-publish",
"docs": "https://agent-hub.dentreprise.workers.dev/tools/playbook-mcp-publish/",
"how_to_get_live_data": "Call the same URL without demo=1. The first 3 successful real calls per IP per UTC day are free; after that attach an x402 v2 PAYMENT-SIGNATURE (USDC on Base).",
"sample": {
"title": "Build and publish an MCP server to the official registry",
"toc": [
"1. What you are publishing",
"2. The official publisher is a Go CLI, not the npm name",
"3. A valid server.json",
"4. Login with a GitHub token (no browser required)",
"5. Stdio package versus the hosted remote",
"6. Version bumps and expired tokens",
"7. Check that the version is live"
],
"excerpt": "The official publisher is the Go CLI mcp-publisher from the modelcontextprotocol/registry GitHub releases, not the npm package that happens to be named mcp-publisher (that one starts an MCP stdio server). You write a server.json that validates against the official 2025-12-11 schema, log in with mcp-publisher login github --token and a GitHub PAT (this works without a browser), then mcp-publisher publish. Names use the io.github.<org>/<server> namespace; the description field is capped at 100 characters. The rest of this playbook covers remotes versus a stdio package, version bumps, and the expired-token error we had to fix.",
"demo": true,
"demo_label": "DEMO / excerpt — not the full playbook."
}
}JavaScript — @x402/fetch
Client officiel x402 v2. Installez @x402/fetch et @x402/evm. L’ancien nom de paquet x402-fetch est la lignée v1 obsolète et ne doit pas servir pour ces points d’accès.
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
// Official x402 v2 client. The older package name "x402-fetch" is the deprecated v1 line.
const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});
const res = await fetchWithPayment(
"https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish"
);
console.log(await res.json());Python — x402
Paquet officiel PyPI x402. Utilisez x402HttpxClient (async) ou x402_requests (sync) après register_exact_evm_client avec EthAccountSigner.
import asyncio
import os
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
# Official PyPI package: x402
account = Account.from_key(os.environ["EVM_PRIVATE_KEY"])
client = x402Client()
register_exact_evm_client(client, EthAccountSigner(account))
async def main():
async with x402HttpxClient(client) as http:
res = await http.get("https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish")
print(res.json())
asyncio.run(main())
# Sync alternative:
# from x402 import x402ClientSync
# from x402.http.clients import x402_requests
# client = x402ClientSync()
# register_exact_evm_client(client, EthAccountSigner(account))
# with x402_requests(client) as session:
# print(session.get("https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish").json())Serveur MCP — forge-agent-mcp
Le mode stdio couvre tout le catalogue (les deux hôtes d’API). Clonez forge-agent-mcp et pointez votre client MCP vers src/server.mjs. Le remote Streamable HTTP hébergé sur la passerelle d’origine n’expose toujours que les outils de cette passerelle.
{
"mcpServers": {
"forge-agent-hub": {
"command": "node",
"args": ["/path/to/forge-agent-mcp/src/server.mjs"]
},
"forge-agent-api": {
"url": "https://x402-gateway.forge-x402.workers.dev/mcp",
"transport": "streamable-http"
}
}
}Wrapper d’outil LangChain
Enveloppez les mêmes clients x402 en outil LangChain avec DynamicStructuredTool (@langchain/core) ou @tool (langchain_core).
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});
export const playbook_mcp_publish = new DynamicStructuredTool({
name: "playbook_mcp_publish",
description: "Playbook: build and publish an MCP server to the official registry.",
schema: z.object({}),
func: async (input) => {
const res = await fetchWithPayment("https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish" + "?" + new URLSearchParams(input));
return JSON.stringify(await res.json());
},
});import os
from langchain_core.tools import tool
from eth_account import Account
from x402 import x402ClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
account = Account.from_key(os.environ["EVM_PRIVATE_KEY"])
client = x402ClientSync()
register_exact_evm_client(client, EthAccountSigner(account))
@tool
def playbook_mcp_publish() -> str:
"""Playbook: build and publish an MCP server to the official registry."""
with x402_requests(client) as session:
return session.get("https://forge-tools.dentreprise.workers.dev/api/playbook-mcp-publish").text