You have an MCP server running at a URL. Right now the only way anyone finds it is a link you hand them. This tutorial gives it a name that any MCP-compatible client can resolve to your endpoint, your capabilities and your pricing model, with a signature that proves the wallet that owns the name published all of it.
The whole flow is one payment, one wallet signature and one transaction.
Prerequisites #
- An MCP server reachable over
https://. Streamable HTTP or SSE both work; the manifest only stores the URL. - A browser wallet (MetaMask or any injected wallet) on Polygon, with a little POL for gas.
- Node 20 or newer for the verification steps.
- A name in mind. Labels are 1 to 63 characters of
a-z,0-9and-, with no hyphen at either end.
Step 1: register the name #
Open /register and type the label. The page tells you whether it is available and shows the price with the renewal price beside it. A standard name is $10 per year. Pick a term from 1 to 10 years; year one is charged at the registration price and each further year at the renewal price.
Pay by card, a one-off payment for the term you chose. Renewals later are wallet-paid in USDC or POL on Polygon. Enter the wallet address that should own the name. After payment the site mints the name to that wallet and the page polls until the mint confirms. Your name page at /name/<label> goes live at that point.
If you already hold a .agt from before Registry v2, skip this step and migrate instead. Migration is free apart from gas, and the name becomes perpetual.
Step 2: open the editor and load the name #
Go to /manifest. Click Connect wallet and approve the connection in your wallet. Type the label and click Load name.
The editor checks that the connected wallet owns <label>.agt on Polygon, then loads whatever the name already publishes. For a fresh name you will see:
No manifest published yet. This will be the first.
If you connected the wrong wallet, the editor refuses with the owning address so you can switch.
Step 3: fill in the manifest #
Work down the form. Every field has inline validation and the publish button tells you why it is disabled until the form is clean.
- Description. One or two sentences on what the agent does. This shows on your name page and in the directory.
- Website andIcon are optional. The icon placeholder offers your own badge,
https://agtnames.com/api/badge/<label>.svg, which is a reasonable default. - Endpoints. The first row defaults to protocol
mcp. Paste your URL. It must behttps://. Click**+ Add endpoint** fora2a,http,wsorgrpcif you have them. Each protocol gets one record. - Capabilities. Type to search the shared vocabulary (70 ids in 8 categories). Comma adds exactly what you typed; arrow keys then Enter adds the highlighted suggestion. Unknown ids are allowed and marked custom. For a research-style server you might pick
research,summarizationandquestion-answering. - Pricing. Choose
Free,Paid,FreemiumorContact for Pricing. It is written aspricing.modelso clients can tell a free agent from a paid one before calling. - Payment address. Optional. A USDC-on-Polygon address, written as a
payments[]entry withrail: "evm".
The preview panel on the right shows the exact document you are about to sign, minus updated and signature, which are set at signing time. It looks like this:
{
"agt": "3.0",
"name": "yourname.agt",
"owner": "0xYourWallet",
"description": "Searches and summarizes technical papers over MCP.",
"endpoints": [{ "protocol": "mcp", "url": "https://mcp.yourname.example/mcp" }],
"capabilities": [{ "id": "research" }, { "id": "summarization" }, { "id": "question-answering" }],
"pricing": { "model": "free" },
"updated": "<set when you sign>"
}
Step 4: choose where the document lives #
Under Where to host the document there are two options.
- Hosted URL on agts.dev. The signed document is served at
https://agts.dev/<label>.json. Republishing replaces the document at the same URL, so the on-chain pointer rarely needs to change. The signature stays yours; the host is only a cache. In the project's words: agts.dev can serve a stale document, it cannot forge one. - IPFS. A content-addressed
ipfs://pin. Immutable: every republish is a new CID and a new on-chain pointer.
Pick agts.dev for a first publish. You can switch later.
Step 5: Sign & publish #
Click Sign & publish. The button walks through four states: Sign in your wallet..., then pinning, then writing, then confirming.
The wallet prompt is an EIP-191 personal_sign over the canonical manifest: signature removed, keys sorted at every level, no whitespace. Your key never leaves the wallet. The site verifies that the signature recovers to the on-chain owner, stores the document, and returns the URI. Then a single multicall transaction on the resolver writes setAgentManifest with that URI, one setAgentEndpoint per endpoint, setAddr for your wallet and, if you gave one, setAgentWallet. Approve it. When it confirms you see:
Published
Manifest pointer set on yourname.agt (hosted at agts.dev).
Step 6: verify from the outside #
Resolution reads the chain live, so this works immediately.
npx agt-resolve resolve yourname.agt
Expected output, trimmed:
{
"name": "yourname.agt",
"registered": true,
"active": true,
"records": {
"manifestUri": "https://agts.dev/yourname.json",
"endpoints": { "mcp": "https://mcp.yourname.example/mcp" }
},
"manifestSource": "onchain",
"cid": "not-ipfs",
"verified": true,
"reasons": []
}
cid reads not-ipfs for a hosted manifest; the signature check still applies. Now the same check through the MCP server, from Claude Code or any MCP-compatible client with @agtnames/mcp registered:
agt_endpoint({ name: "yourname.agt", protocol: "mcp" })
{
"name": "yourname.agt",
"protocol": "mcp",
"url": "https://mcp.yourname.example/mcp",
"source": "verified-manifest",
"verified": true,
"pricing": "free",
"reasons": []
}
source: "verified-manifest" is the outcome you want. If it said resolver-record with verified: false, the endpoint record wrote but the manifest did not verify; the reasons will say why.
For a live reference, launchpad.agt publishes exactly this way. Its document is at agts.dev/launchpad.json and it resolves with verified: true.
Step 7: how clients discover it #
The directory lists every active name with the endpoint protocols it has on chain:
curl "https://agtnames.com/api/agents?protocol=mcp"
{
"success": true,
"count": 1,
"agents": [{
"domain": "yourname.agt",
"protocols": ["mcp"],
"endpoints": [{ "protocol": "mcp", "url": "https://mcp.yourname.example/mcp" }],
"capabilities": [],
"owner": "0xYourWallet",
"manifestUri": "https://agts.dev/yourname.json"
}]
}
Two things to know. The directory is built by an indexer and trails the chain by up to ten minutes, so your name appears a little after the transaction. And capabilities is empty in directory results because capabilities live inside the signed manifest, not on chain. A client takes the protocol-filtered list, resolves each candidate, and reads manifest.capabilities only when verified is true. That is the loop in Discover an agent, then connect to it.
Troubleshooting #
- "is owned by 0x... Connect that wallet to edit it." The connected account is not the owner. Switch accounts in the wallet and click Load name again.
- Publish button disabled. Read the reason beside it. Common ones: an endpoint URL is not
https://, two rows share a protocol, or nothing changed since the last publish. - Signature rejected (409 from the pin step). The signature does not recover to the wallet that owns the name on chain right now. Re-sign with the owner wallet.
verified: falsewith"could not load manifest". The pointer wrote but the document could not be fetched. Retry in a minute; if it persists, republish.- Name missing from
/api/agents. Wait for the indexer, up to ten minutes.npx agt-resolve resolveis the ground truth in the meantime. - Changing the endpoint later. Load the name in the editor, change the URL, Sign & publish again. A verified manifest's endpoints take precedence in
agt_endpoint, so update both the record and the manifest, which the editor does for you.
Next #
Your MCP server now has a name that resolves to its URL, its capabilities and its pricing, signed by the wallet that owns it. Any MCP-compatible client can find it by name and check the signature before connecting. Open /manifest to publish yours, or read the publish-identity guide for the fields the editor does not expose yet (agent keys, text records, delegation) and how to write them from code. The document format in full is the Manifest Spec.