llms.txt and MCP Endpoints

How do you detect whether a company exposes an MCP endpoint?

You detect an MCP endpoint by probing the paths a remote MCP server conventionally uses (often /mcp or /sse) and confirming the protocol: a JSON-RPC 2.0 handshake over Streamable HTTP, or a text/event-stream response on the SSE transport. A completed initialize call returns the server's protocol version and capabilities. Bassethound runs that check in the AI-readiness layer of its five-layer dossier and treats a live MCP endpoint as a top-tier shipping signal, in one keyless call.

Best move: probe the conventional MCP paths and read the transport signatures, not the marketing copy.

Why it works: a remote MCP server speaks a fixed protocol (JSON-RPC 2.0 over Streamable HTTP or SSE) at predictable paths, and that handshake behavior is hard to fake and cheap to confirm.

Key takeaways

  • MCP detection is protocol probing: you check conventional paths and confirm a JSON-RPC 2.0 handshake, not scan the homepage for the word “MCP”.
  • Remote MCP servers use one of two HTTP transports: Streamable HTTP (a single endpoint, often /mcp, returning an Mcp-Session-Id header) or the older HTTP+SSE transport (a text/event-stream on a path like /sse).
  • A completed initialize exchange returns the server’s protocolVersion, serverInfo, and capabilities, which confirms the endpoint and reveals what it exposes to agents.
  • An MCP endpoint is one of Bassethound’s strongest shipping signals: a machine-facing endpoint means a company built for agents, not just wrote about them.
  • OAuth-gated MCP servers return 401 before the handshake completes, so you can confirm the endpoint exists but cannot read its capabilities, and Bassethound reports that gap honestly.

Which paths and headers reveal a remote MCP server?

Start with the conventions. Streamable HTTP, the current transport, exposes a single endpoint that handles both POST (client to server) and GET (server to client streaming). Most teams mount it at /mcp. The older HTTP+SSE transport splits in two: an SSE endpoint, often /sse, that opens a text/event-stream, and a separate POST path for messages.

Two headers give the game away. Mcp-Session-Id, which a Streamable HTTP server returns to track a session, and Content-Type: text/event-stream on the SSE path. A GET that answers with an event stream instead of HTML is a strong tell. So is a 405 or 406 on a method the transport rejects, because the server is enforcing MCP’s method rules rather than serving a generic page.

None of this needs credentials. You send a request, you read the status code and headers, you move on. The paths are a starting hypothesis, not a conclusion: plenty of servers mount the endpoint somewhere custom. That is why probing feeds into a handshake check rather than standing alone. A matching path with the right headers is a lead worth confirming, not a verdict.

How does the MCP handshake confirm an endpoint?

A path that looks right is a lead. The handshake is proof. MCP runs on JSON-RPC 2.0, and every session opens with an initialize request carrying a protocolVersion and the client’s capabilities. A real MCP server answers with its own protocolVersion, its serverInfo (name and version), and the capabilities it supports (tools, resources, prompts).

That response is unambiguous. Nothing but an MCP server returns that exact envelope. So you confirm the endpoint by sending a minimal initialize and checking for a well-formed JSON-RPC result with a protocolVersion field. If you get HTML, a redirect, or a generic 404, it is not MCP. If you get a JSON-RPC error that still follows the 2.0 envelope, the endpoint is live and rejecting your request, which is itself a positive detection.

The handshake also tells you what the server does. A capabilities block listing tools means the company exposes callable functions to agents, not just a read-only resource feed. Follow with a tools/list call on an open server and you get the exact surface. That moves detection past “an endpoint exists” and into “here is what it lets an agent do.”

Can you detect an MCP endpoint behind OAuth?

Often, yes, but with a ceiling. The MCP authorization spec puts many production servers behind OAuth 2.1. When you hit a protected endpoint unauthenticated, a compliant server returns 401 with a WWW-Authenticate header pointing at its authorization server metadata. That 401 is a detection, not a dead end. It confirms an MCP endpoint exists and is guarded.

What you lose is the capability read. Without a token, the initialize handshake never completes, so you cannot enumerate the server’s tools or resources. The dossier marks the endpoint present and auth-gated, then flags the capability list as unreachable rather than filling it with a guess.

That distinction carries weight in scoring. An auth-gated MCP server still fires the shipping verdict, because the endpoint’s existence is the signal, and a company that bothered to protect its MCP surface is running it for real. Reading what sits inside would require credentials you should not have and would not take. Detection stops at the trust boundary on purpose. Presence and posture, yes. Contents behind auth, no.

Why does an MCP endpoint count as a shipping signal?

Because exposing one is a build decision, not a marketing decision. A company mounts an MCP server so external agents can call its product. That takes engineering: a transport, auth, tool definitions, and a surface someone maintains. You do not stand one up to look current.

In Bassethound’s AI-readiness layer, a live MCP endpoint is a machine-facing signal that trips the shipping verdict on its own, the same tier as a technical llms.txt or a populated .well-known AI file. It also pushes the icp_signal toward hot, because a company that exposes tools to agents already thinks in the terms your product speaks.

Compare that to a chat widget or an “AI-powered” line, which any team can add in an afternoon and which say nothing about what runs underneath. The MCP endpoint says the company decided to be part of the agent ecosystem and wired the plumbing to prove it. That is the whole point of reading the stack instead of the story: you want the signals that cost something to fake, and a maintained protocol endpoint is near the top of that list.

Where else does a company advertise its MCP endpoint?

Blind probing finds the obvious paths. Declarations find the rest. Read three places.

First, llms.txt. A technical llms.txt often links the MCP endpoint directly, and its presence alone is a machine-facing signal. Second, the .well-known directory, where AI and agent metadata files are starting to land and may name the MCP server or its authorization metadata. Third, developer docs and connector pages, which publish the MCP URL for integrators to paste into a client.

Bassethound reads all three in the same crawl that probes the paths, then correlates them. A documented endpoint that also answers a handshake is a confident, corroborated detection, stronger than either signal alone. A declared endpoint that fails to respond is worth flagging too, because a dead link in llms.txt tells you the company aimed at the agent ecosystem and has not finished wiring it.

The honest caveat holds. An endpoint that is never linked, never declared, and sits on an unadvertised subdomain can stay invisible to an outside crawl. Purely server-side or fully proxied setups can hide the same way. Bassethound reports that limit rather than pretending completeness.

Bassethound perspective

An MCP endpoint is worth more than a dozen “AI-powered” badges, and we score it that way. Most AI-readiness tools weight funding rounds, headcount, or homepage keywords, then call the sum “intent.” We think that ranks the wrong things. A funding round tells you a company has money. A live MCP endpoint tells you a company built a surface for agents to drive, maintained it, and decided to be reachable by the ecosystem you sell into. One is a press release. The other is a protocol handshake you can verify in a single request.

So we put a machine-facing endpoint above the firmographic signals, not beside them. A company with a working MCP server and a thin marketing site outranks a well-funded company with a glossy “AI” page and nothing behind it. A vendor selling intent data would dispute that ordering, because their model runs on the firmographics we discount. We will take the endpoint that answers over the story that reads well, every time. Read the stack, not the story.

Sources

Frequently asked questions

Can you detect an MCP endpoint without authenticating?

Often, yes. An unprotected server completes the initialize handshake and hands back its capabilities. A protected server returns 401 with a WWW-Authenticate header, which still confirms the endpoint exists. You lose the capability read without a token, and Bassethound records that as a gap rather than a guess.

What is the difference between the /mcp and /sse endpoints?

They are two transports. /mcp is the convention for Streamable HTTP, a single endpoint that handles POST and GET and returns an Mcp-Session-Id header. /sse belongs to the older HTTP+SSE transport, which opens a text/event-stream and pairs with a separate POST path for messages. Both are valid MCP.

Does an MCP endpoint guarantee a company ships AI?

It is the strongest single tell short of reading source. Standing up an MCP server takes a transport, auth, and maintained tool definitions, so it is a build decision, not a tagline. In Bassethound's scoring a live endpoint fires the shipping verdict on its own.

Can Bassethound list the tools an MCP server exposes?

When the endpoint is open, yes. The initialize response and a tools/list call enumerate the callable surface. Behind OAuth the handshake never completes, so the dossier marks the endpoint present and auth-gated and flags the tool list as unreachable.

What if the MCP server sits on a subdomain or is never linked?

Then an outside crawl can miss it. Bassethound probes conventional paths and reads llms.txt, .well-known files, and docs for declared endpoints, but an unadvertised server on an unlinked host can stay invisible. The dossier reports that limit instead of implying completeness.

Sniff a domain.

Run sniff_domain on any site and read its five-layer dossier in one call.

Sniff a domain