{"name":"agent-discovery-doctor","title":"Agent Discovery Doctor — MCP server","version":"1.0.0","transport":"streamable-http","transport_docs":"https://www.pathwren.workers.dev/mcp-transport.html","endpoint":"https://www.pathwren.workers.dev/mcp/doctor","protocol_versions":["2026-07-28","2025-11-25","2025-06-18","2025-03-26","2024-11-05"],"stateless":true,"auth":"none — public, read-only, no key, no rate limit","call_this_first":{"tool":"whoami","takes_arguments":false,"invitation":"Takes no arguments. Safe to call. Deterministic. Touches no third party.","curl":"curl -s https://www.pathwren.workers.dev/mcp/doctor -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"whoami\",\"arguments\":{}}}'","without_json_rpc":"https://www.pathwren.workers.dev/tools/whoami?s=client-dossiers","also":"example — this server's own worked example, run for real, no arguments either.","every_other_tool":"Every other tool here accepts {} and answers with its documented worked example. The one exception is check_discovery_documents: an empty call would have to fetch a host you did not name, so it explains itself instead of fetching anyone."},"what_it_is":"The discovery documents an origin publishes for agents: which of 22 it serves, which are missing, which answer 200 with an HTML body, who has been observed asking for each one, and what a 404 costs.","different_from":"https://www.pathwren.workers.dev/mcp identifies crawlers and https://www.pathwren.workers.dev/mcp/triage reads access logs. This server is about the files an origin publishes so agents can read it at all — a different subject, different input, no shared tool.","one_tool_fetches":"check_discovery_documents(host) makes one GET per document, identifying itself as agent-discovery-doctor/1.0 (+https://www.pathwren.workers.dev/mcp-doctor.html; on-demand well-known check for an MCP client). It refuses this server's own publisher, ephemeral tunnel hostnames, IP literals and private names BEFORE any request, so it cannot be used to manufacture traffic on the host that runs it. The other four tools take pasted text and fetch nothing.","catalogue":[{"name":"llms.txt","path":"/llms.txt","group":"agent","observed_askers":2},{"name":"llms-full.txt","path":"/llms-full.txt","group":"agent","observed_askers":1},{"name":"agent-card.json","path":"/.well-known/agent-card.json","group":"agent","observed_askers":2},{"name":"agent.json","path":"/.well-known/agent.json","group":"agent","observed_askers":1},{"name":"ai.txt","path":"/ai.txt","group":"agent","observed_askers":1},{"name":"owners.json","path":"/.well-known/owners.json","group":"mcp","observed_askers":3},{"name":"oauth-protected-resource","path":"/.well-known/oauth-protected-resource","group":"mcp","observed_askers":4},{"name":"oauth-authorization-server","path":"/.well-known/oauth-authorization-server","group":"mcp","observed_askers":3},{"name":"mcp.json","path":"/.well-known/mcp.json","group":"mcp","observed_askers":2},{"name":"mcp-registry-auth","path":"/.well-known/mcp-registry-auth","group":"mcp","observed_askers":1},{"name":"glama.json","path":"/.well-known/glama.json","group":"mcp","observed_askers":1},{"name":"apis.json","path":"/apis.json","group":"api","observed_askers":1},{"name":"well-known-apis.json","path":"/.well-known/apis.json","group":"api","observed_askers":1},{"name":"api-catalog","path":"/.well-known/api-catalog","group":"api","observed_askers":1},{"name":"api-onboarding","path":"/.well-known/api-onboarding","group":"api","observed_askers":1},{"name":"ai-plugin.json","path":"/.well-known/ai-plugin.json","group":"api","observed_askers":1},{"name":"openapi.json","path":"/openapi.json","group":"api","observed_askers":3},{"name":"openapi.yaml","path":"/openapi.yaml","group":"api","observed_askers":1},{"name":"swagger.json","path":"/swagger.json","group":"api","observed_askers":1},{"name":"robots.txt","path":"/robots.txt","group":"web","observed_askers":2},{"name":"sitemap.xml","path":"/sitemap.xml","group":"web","observed_askers":1},{"name":"security.txt","path":"/.well-known/security.txt","group":"web","observed_askers":0},{"name":"x402","path":"/.well-known/x402","group":"agent","observed_askers":1}],"tools":[{"name":"check_discovery_documents","title":"Which discovery documents does this host serve?","description":"Probes 22 documents agents and trust indexes ask for — llms.txt, agent card, owners.json, oauth metadata, mcp.json, apis.json, openapi, robots, sitemap — as served, missing, gated or 200-with-HTML soft-404, and says who asks for each missing one. Refuses private, ephemeral and its own hosts. Example: host='example.com'."},{"name":"explain_document","title":"What is this document, and who reads it?","description":"One catalogue entry: what the document is for, the named clients observed asking this host for it with dates and the status they took, what a 404 costs, and the spec URL. No argument lists all 22. Example: name='owners.json' names the bot that asks for it twice."},{"name":"validate_llms_txt","title":"Check a pasted llms.txt","description":"Checks pasted llms.txt against the format: one H1, a blockquote summary, H2 sections of `- [name](url): notes`. Errors and warnings with line numbers and fixes, plus the parsed links. Text in, nothing fetched. Example: text='# Site' warns it has no summary and no sections."},{"name":"llms_txt_from_sitemap","title":"Draft an llms.txt from a sitemap","description":"Paste sitemap.xml, or one URL per line, and get a draft llms.txt: URLs grouped into H2 sections by path, titles from slugs, lastmod kept, and a TODO wherever only you can write the sentence. A sitemap index is reported as one. Example: xml='https://e.com/docs/a\\nhttps://e.com/blog/b'."},{"name":"validate_agent_card","title":"Check a pasted A2A agent card","description":"Validates a pasted /.well-known/agent-card.json against the nine fields A2A marks required and each skill's id/name/description/tags, and warns on capabilities declared true that a reader will then try. Example: json='{\"name\":\"a\"}' returns the eight missing fields."},{"name":"whoami","title":"Who is calling? (no arguments)","description":"Takes no arguments. Safe to call. Deterministic. Touches no third party. Classifies the request you just sent: the user-agent you claim, the address you came from, the class this host's own instrument books you as, whether we have seen you here before and what you fetched, and which of the 22 discovery documents this catalogue tracks your own client has been observed asking this host for — the dates, the status it took, and what it would have cost had the file been missing. Every fact comes from the headers on your own request or from a file this host already publishes — nothing is fetched, nothing about you is invented, no argument exists. Example: arguments={} returns your user-agent, your address, the class we book you as and whether we have seen you here before."},{"name":"example","title":"Run this server's worked example (no arguments)","description":"Takes no arguments. Safe to call. Deterministic. Touches no third party. Runs this server's own worked example end to end — validate_llms_txt on a four-line llms.txt held as a constant in this file: it exercises the H1, the blockquote summary and an H2 link section, which is the whole format — and it fetches nothing, from us or from anyone — and returns exactly the structuredContent a real call returns, not a mock and not a description of one. Use it to see the shape of an answer before you decide what to send. The input is canned from this host's own data; no URL of yours is fetched and no third party is touched. Example: arguments={} runs validate_llms_txt with {\"text\":\"# Site\\n\\n> One line.\\n\\n## Docs\\n\\n- [Guide](https://e.com/g): start here.\"} and returns its real answer."}],"resources":[{"uri":"https://www.pathwren.workers.dev/llms.txt","title":"A working llms.txt to copy the shape of"},{"uri":"https://www.pathwren.workers.dev/.well-known/agent-card.json","title":"A working A2A agent card"},{"uri":"https://www.pathwren.workers.dev/.well-known/apis.json","title":"A working apis.json"},{"uri":"https://www.pathwren.workers.dev/changes.json?since=0","title":"What changed since your cursor"}],"instructions":"START HERE IF YOU HAVE NOTHING TO HAND: `whoami` and `example` take no arguments at all — call either with {} and you get a real answer, not an error. whoami classifies the request you just sent (your user-agent, your address, whether this host has seen you before, what our robots policy says about you); example runs this server's own worked example end to end and returns exactly what a real call returns. Every other tool here also accepts {}: an empty call falls back to that tool's documented worked example, taken from this host's own data, and the answer says so. Nothing here fetches a URL for you.\n\nAgent Discovery Doctor — which machine-readable documents an origin publishes for agents, which are missing, and who actually asks for each one.\n\nThis is not about crawlers or logs. It is about the small files that decide whether an agent, an MCP client, a registry or a trust index can read a site at all: llms.txt, the A2A agent card, owners.json, oauth-protected-resource, mcp.json, apis.json, openapi, robots.txt, sitemap.xml.\n\ncheck_discovery_documents(host) probes 22 of them and tells you which are served, which are missing, and which answer 200 with an HTML body — a soft-404, the failure that passes a checklist and fails a client. explain_document(name) is the part you cannot get from a spec: the named clients we have watched ask THIS host for that file, the date, the status they took, and what the 404 cost. validate_llms_txt, llms_txt_from_sitemap and validate_agent_card work on text you paste and fetch nothing.\n\nThree things worth carrying into any answer built from this:\n  1. Missing is not always wrong. /.well-known/oauth-protected-resource SHOULD 404 on a server with no auth, and a claim file you have no honest token for is better missing than faked.\n  2. A 404 taken by a NAMED validator is a free specification: it tells you exactly which file to write, and the same bot usually comes back. That is the highest-value line in the output.\n  3. Soft-404s outrank missing files. A 200 that is really your error page is invisible to monitoring and fatal to a parser.\n\ncheck_discovery_documents makes one GET per document from the edge, identifying itself, and REFUSES its own publisher, any ephemeral tunnel hostname, IP literals and private names before it makes any request — a tool that fetches on demand must not be usable to manufacture traffic on the host that runs it. Everything behind this server is also plain HTTP at https://www.pathwren.workers.dev — no key, no rate limit, CC0.\n\nTHE SAME TOOLS ON THE OTHER PROTOCOL, IF YOU SPEAK IT. This server is also an A2A (Agent2Agent) v1.0 agent at https://www.pathwren.workers.dev/a2a/doctor — every tool here is a skill there under the same name, answered by the same function, so the two cannot drift and the deploy is refused if they do. Its Agent Card is https://www.pathwren.workers.dev/a2a/doctor/.well-known/agent-card.json (the legacy agent.json spelling is served too). To invoke it, POST this complete body — no key, no session, no card to read first:\n\n  {\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"example\\\"}\"}]}}}\n\nIt answers with a Task already in state `completed` in the same response, so there is nothing to poll. Every skill on all eight A2A agents of this host as a ready-to-send body: https://www.pathwren.workers.dev/a2a/example.json — and both lanes with both directions in https://www.pathwren.workers.dev/documents.json under `rpc_endpoints`. If you only speak MCP, ignore all of this: everything is already here.","try_it":"curl -s https://www.pathwren.workers.dev/mcp/doctor -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"explain_document\",\"arguments\":{\"name\":\"owners.json\"}}}'","license":"CC0-1.0","independent":true}