MCP server
Give your coding agent live web access. One URL, two tools, no local process to install or keep running.
/mcp/webThis is a remote Model Context Protocol server speaking the Streamable HTTP transport. Point any MCP client at the URL and your agent gains two tools: web_search and web_fetch. Nothing to install, nothing running on your machine.
Setup#
claude mcp add --transport http xkiro-web https://api.xkiro.com/mcp/web \
--header "Authorization: Bearer $XKIRO_API_KEY"
# Check it connected:
claude mcp listNothing to install
Most MCP servers are local programs you install and launch. This one is hosted — the URL is the server. That also means it works the same on every machine you use, and updates without you doing anything.
The two tools#
| Field | Type | Description |
|---|---|---|
web_search | search | Search the live web. Returns ranked results with title, URL, snippet, source and publication date. Arguments: query (required), max_results, search_domain_filter, search_recency_filter, country. |
web_fetch | read | Read full pages as markdown. Arguments: urls (required, up to 10) and max_content_tokens. Each URL is metered separately. |
Your agent decides when to call them. A typical run searches once, then fetches only the one or two pages it actually needs — which is also the cheapest way to use it.
Allowances and pricing#
Identical to the standalone endpoints — the MCP server is a different way to reach the same capability, not a separate product. Calls from your agent draw on the same daily allowance and show up in the same usage reports.
| Field | Type | Description |
|---|---|---|
Free | 20 | Then pay-as-you-go at $0.01 each, from your wallet. |
Pro | 100 | 10 calls/minute · 3 at a time. |
Pro Plus | 200 | 15 calls/minute · 3 at a time. |
Max | 300 | 20 calls/minute · 4 at a time. |
Ultra | 1,500 | 30 calls/minute · 6 at a time. |
Power | 3,000 | 60 calls/minute · 8 at a time. |
Running out does not break your agent
When the allowance is used up, the tool returns a normal result with isError: true and a sentence saying so — not a protocol failure. Your agent reads that, tells you, and carries on with the rest of the task instead of dying mid-run.
Protocol details#
You only need this section if you are writing your own client. Everything here follows the 2025-06-18 Streamable HTTP spec.
| Field | Type | Description |
|---|---|---|
POST /mcp/web | JSON-RPC | The only endpoint. Send one JSON-RPC message per request. A request gets application/json back; a notification gets 202 with no body. |
GET /mcp/web | 405 | The server never initiates messages, so there is no server-to-client stream to open. Clients should skip it and use POST. |
Sessions | stateless | No Mcp-Session-Id is issued and none is expected. Every POST stands alone, so requests can land on any server behind the load balancer. DELETE returns 405 for the same reason. |
Protocol versions | 2025-06-18 | Also accepts 2025-03-26 and 2024-11-05. Ask for a version we do not know and initialize replies with ours rather than failing, so newer clients can negotiate down. |
Capabilities | tools | Tools only — no resources, prompts, sampling or logging. |
Auth | header | Authorization: Bearer <key> or x-api-key. Keys in the query string are not accepted. Missing or invalid key is HTTP 401. |
Try it with curl
curl https://api.xkiro.com/mcp/web \
-H "Authorization: Bearer $XKIRO_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": { "protocolVersion": "2025-06-18", "capabilities": {},
"clientInfo": { "name": "curl", "version": "1.0" } }
}'
curl https://api.xkiro.com/mcp/web \
-H "Authorization: Bearer $XKIRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'curl https://api.xkiro.com/mcp/web \
-H "Authorization: Bearer $XKIRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0", "id": 3, "method": "tools/call",
"params": {
"name": "web_search",
"arguments": { "query": "latest stable Node.js LTS", "max_results": 3 }
}
}'Errors
- Something went wrong running the tool — allowance used up, rate limited, page unreachable, URL rejected — comes back as a normal result with
isError: trueand readable text, so the model can act on it. - Something is wrong with the request itself — unknown tool, bad parameters — comes back as a JSON-RPC
error. These still carry HTTP200: the transport worked, the call did not. - A missing or invalid key is HTTP
401, and an unsupportedMCP-Protocol-Versionheader is HTTP400. Both have a JSON-RPC error body.
Only http and https URLs
web_fetch rejects anything else at the door — file://, gopher:// and friends. Worth knowing because the URL comes from a model, not from you, and a model can be talked into asking for odd things.
Keys go in headers, not the URL
There is no ?key= form, on purpose. A key in a URL ends up in server logs, CDN logs, browser history and Referer headers — places that are kept for a long time, backed up, and readable by more people than you would expect. Every client above can set a header.
If your client genuinely cannot send headers, tell us rather than putting your key in a query string: the right answer is a separate narrow-scope token, not your main API key. And if you think a key has leaked, rotate it.
