Connect a Client
Point an MCP client at your endpoint.
Assume the quick start server is listening on http://localhost:3000/mcp.
#MCP Inspector
The fastest way to see what your server exposes:
npx @modelcontextprotocol/inspectorChoose the Streamable HTTP transport and enter http://localhost:3000/mcp. If auth is enabled, add the header there — Authorization: Bearer <token> or x-api-key: <token>.
#Claude Code
claude mcp add --transport http my-server http://localhost:3000/mcpWith auth:
claude mcp add --transport http my-server http://localhost:3000/mcp \
--header "Authorization: Bearer $MCP_TOKEN"#A stdio-Only Client
Clients that only speak stdio need a bridge. mcp-remote is the usual one:
claude_desktop_config.json
{
"mcpServers": {
"my-server": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:3000/mcp"]
}
}
}#Origin Headers
A browser-based client sends Origin, and origin validation will reject it unless allowlisted. This is the single most common "it works with curl but not in the app" cause:
defineMcpHandler({
name: "my-server",
version: "1.0.0",
origin: { allow: ["http://localhost:6274"] }, // e.g. the Inspector's own origin
tools: [/* ... */],
});#Checking It Yourself
No client needed — one POST tells you whether the endpoint is healthy:
curl -X POST http://localhost:3000/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-H 'mcp-protocol-version: 2026-07-28' \
-H 'mcp-method: server/discover' \
-d '{ "jsonrpc": "2.0", "id": 1, "method": "server/discover",
"params": { "_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {} } } }' Read more in More raw requests.
#Testing Without a Network
H3 apps can be called directly, which makes an MCP endpoint trivial to unit-test:
const res = await app.request("/mcp", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list" }),
});
console.log(await res.json());