{
  "markdown": "# alienprobe-who-mcp\n\nAn MCP server that gives any agent one legal-entity fact — LEI, legal name, jurisdiction, entity and registration status — for **$0.05 USDC on Base**, paid per call over [x402](https://github.com/x402-foundation/x402). No signup, no API key, no account. The wallet is the account.\n\nTwo tools:\n\n| Tool | Cost | What it does |\n|---|---|---|\n| `who_terms` | **free** | Returns the advertised price, network, payee and coverage. Never pays. Works with no wallet. |\n| `who` | **$0.05, real money** | Returns the entity record. Misses and ambiguities cost nothing. |\n\n## Client config\n\nThree lines. Claude Desktop (`claude_desktop_config.json`) or Cursor (`.cursor/mcp.json`):\n\n```json\n{ \"mcpServers\": { \"who\": { \"command\": \"npx\", \"args\": [\"-y\", \"@alienprobe/who-mcp\"],\n  \"env\": { \"PRIVATE_KEY\": \"0x...\", \"MAX_USD_PER_SESSION\": \"1.00\" } } } }\n```\n\nDrop the `env` block entirely and the server still starts — `who_terms` works, `who` refuses with `wallet_not_configured`. That is the safe way to try it.\n\n## Environment\n\n| Var | Default | Meaning |\n|---|---|---|\n| `PRIVATE_KEY` | *(none)* | A **throwaway** Base-mainnet wallet holding a little USDC. Optional. Never logged, echoed, or returned in a tool result. |\n| `MAX_USD_PER_CALL` | `0.10` | Hard ceiling on one lookup. The lookup is advertised at $0.05. |\n| `MAX_USD_PER_SESSION` | `1.00` | Hard ceiling on everything this server process spends before restart. |\n\nSee `.env.example`. Never commit a real key. Fund a wallet that holds nothing else — about $1 of USDC covers 20 lookups. This repo does not tell you how to get USDC onto Base; see https://docs.base.org/base-chain/tools/bridges/.\n\n## Spend caps\n\nThe server preflights every `who` call with a plain, unwrapped `fetch` — no signer exists on that path — reads the advertised price out of the 402, and only then decides. If the price exceeds `MAX_USD_PER_CALL`, or would push the running total past `MAX_USD_PER_SESSION`, it refuses with a result the model can read and act on:\n\n```json\n{\n  \"error\": \"spend_cap_exceeded\",\n  \"scope\": \"per_session\",\n  \"price_usd\": 0.05,\n  \"cap_usd\": 1.0,\n  \"spent_usd_this_session\": 1.0,\n  \"remaining_usd\": 0.0,\n  \"hint\": \"the session budget is spent; raise MAX_USD_PER_SESSION and restart the MCP server to buy more\"\n}\n```\n\nA session is one server process. Restarting the client resets the counter, so the per-session cap is a brake, not a ledger — the wallet balance is the real ceiling. Keep it small.\n\n## What comes back\n\nA paid hit is the API's body verbatim plus `paid_usd`:\n\n```json\n{\n  \"schema_version\": \"who-lookup.v1\",\n  \"subject\": { \"type\": \"who\", \"value\": \"apple.com\" },\n  \"answer\": {\n    \"lei\": \"HWUPKR0MPOU8FGXBT394\",\n    \"legal_name\": \"Apple Inc.\",\n    \"jurisdiction\": \"US-CA\",\n    \"entity_status\": \"ACTIVE\",\n    \"registration_status\": \"ISSUED\",\n    \"match\": { \"by\": \"domain\", \"rule\": \"domain_exact\" },\n    \"official_website\": \"https://apple.com/\"\n  },\n  \"source\": { \"name\": \"...\", \"vintage\": \"...\", \"coverage\": \"...\" },\n  \"paid_usd\": 0.05\n}\n```\n\n`q` is a company name, a registrable domain, or a 20-character LEI. To disambiguate a name, append a jurisdiction in the same string: `\"Acme Corp;US-DE\"`.\n\n### `paid_usd` is the authorized price, not the receipt\n\n`paid_usd` is the amount the server *authorized* — the price the API advertised in its 402 and that the spend caps were judged against. It is not read back from the chain.\n\nOne case where it overstates: **a wallet's first successful lookup on this pricing shelf settles at $0** (first-can-free; a property of the service, not of this client). That call still reports `\"paid_usd\": 0.05`. Every subsequent call actually moves $0.05.\n\nThe server's session counter inherits the same overstatement, which is the safe direction — it stops you early, never late. If you need the truth, the on-chain USDC `Transfer` from your wallet is the only receipt. Do not use `paid_usd` for accounting.\n\n## Free refusals\n\nThese never pay, and they come back as ordinary tool results the model can reason about — not exceptions:\n\n| Upstream | Result |\n|---|---|\n| `400` | `{\"error\":\"invalid_subject\",\"reason\":\"empty\"}` |\n| `404` | `{\"error\":\"not_found\",\"coverage\":\"...\"}` |\n| `409` | `{\"error\":\"ambiguous\",\"candidates\":[...],\"hint\":\"re-ask with the exact legal_name, then a ;jurisdiction suffix if it still collides\"}` |\n| `503` | `{\"error\":\"source_unavailable\"}` |\n\nThe API only charges once it can commit to one entity, so an ambiguous re-ask is still free while it stays ambiguous.\n\n## What this does not do\n\n- No street addresses, no officers or directors, no ownership graph.\n- No guessing. A miss is a `404`, not a best-effort answer.\n- Legal names that normalize to fewer than 2 Latin alphanumerics (CJK, Cyrillic, Greek, Arabic, Hebrew, Thai) are absent from this data vintage entirely — every door, not just the name door.\n- Domains match only where the source links an LEI to an official website, on the exact registrable domain. A subdomain misses.\n\n## Development\n\n```bash\nnpm install\nnpm test     # 28 contract rows over a mocked fetch: no network, no wallet, no payment\nnpm run smoke  # spawns the server, drives initialize/tools/list/who_terms over real stdio\n```\n\n`npm run smoke` hits the live endpoint to fetch the 402. It runs with `PRIVATE_KEY` blank and asserts the advertised `amount` is `\"50000\"` ($0.05). It cannot pay.\n\n`src/core.mjs` holds the transport-free logic and takes an injected `fetch`, which is why the tests never need a wallet. `src/index.mjs` is only the MCP wiring; `@x402/*` and `viem` are imported lazily, on a call already cleared to pay.\n\nBuilt on [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) 1.30.0. See `SPEC.md` for the full contract and the distribution plan.\n\n## License\n\nMIT © Brent Bryson. See `LICENSE`.\n",
  "bytes": 5814,
  "sha": "8c19ef12f1b07f49431429b58bc8800d5259f7b20223ee8674459de7a8f9055f",
  "repo_slug": "bbrysonelite-max/alienprobe-who-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_bbrysonelite_max_alienprobe_wh_b8f26357/readme"
}