MCP server
Every API operation is an MCP tool at https://util.caruana.me/mcp. It is a remote, stateless Streamable HTTP server: no install, no account.
Connect
Claude Code
claude mcp add --transport http caruana-utilities https://util.caruana.me/mcp \
--header "Authorization: Basic $(printf '%s' "$CLIENT_ID:$CLIENT_SECRET" | base64)" Listing tools needs no credentials; calling them does. Get a client ID and secret. Any client that can set a request header works; OAuth-capable clients can use the client-credentials token endpoint instead.
Any client with remote MCP support: add a server with transport “Streamable
HTTP” and URL https://util.caruana.me/mcp. No authentication.
Quick check from a shell
curl -s https://util.caruana.me/mcp \
-H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2025-11-25' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' Where your data goes
MCP tools run on the server, exactly like the HTTP API. The arguments your agent sends travel to a Cloudflare Pages Function, are processed in memory for the duration of the call, and the result is returned. Arguments and results are never stored or logged. Each call is recorded as one metadata row against your client ID: operation, time, status, duration, sizes and country. No tool accepts or creates secrets.
Your MCP client may also send tool arguments and results to the model provider as part of the conversation; that is between you and your client.
Tools
All tools are annotated readOnlyHint: true and destructiveHint: false. openWorldHint is false for all
except tls_check, which connects to the host you name. Every tool returns structuredContent matching its outputSchema, plus the same JSON as
text.
| Tool | Title | Idempotent | Reference |
|---|---|---|---|
url_encode | URL: Encode | yes | parameters, output, examples |
url_decode | URL: Decode | yes | parameters, output, examples |
base64_encode | Base64: Encode | yes | parameters, output, examples |
base64_decode | Base64: Decode | yes | parameters, output, examples |
html_encode | HTML entities: Encode | yes | parameters, output, examples |
html_decode | HTML entities: Decode | yes | parameters, output, examples |
hex_encode | Hex: Text → Hex | yes | parameters, output, examples |
hex_decode | Hex: Hex → Text | yes | parameters, output, examples |
punycode_encode | Punycode: To ASCII | yes | parameters, output, examples |
punycode_decode | Punycode: To Unicode | yes | parameters, output, examples |
hash | Hash | yes | parameters, output, examples |
hash_verify | Verify a checksum | yes | parameters, output, examples |
fingerprint | Key and certificate fingerprints | yes | parameters, output, examples |
cert_decode | Decode certificates and CSRs | yes | parameters, output, examples |
tls_check | Check a server's TLS certificate | no (random output) | parameters, output, examples |
jwt_decode | Decode and verify a JWT | yes | parameters, output, examples |
url_parse | Parse a URL | yes | parameters, output, examples |
uuid_generate | Generate UUIDs | no (random output) | parameters, output, examples |
uuid_inspect | Inspect a UUID | yes | parameters, output, examples |
text_inspect | Inspect and count text | yes | parameters, output, examples |
time_now | Current time | no (random output) | parameters, output, examples |
time_convert | Convert a time | yes | parameters, output, examples |
time_diff | Difference between two times | yes | parameters, output, examples |
time_add | Add or subtract a duration | yes | parameters, output, examples |
cron_explain | Explain a cron expression | no (random output) | parameters, output, examples |
text_diff | Compare two texts | yes | parameters, output, examples |
json_format | Format and validate JSON | yes | parameters, output, examples |
json_schema_validate | Validate JSON against a JSON Schema | yes | parameters, output, examples |
json_to_yaml | Convert JSON to YAML | yes | parameters, output, examples |
yaml_to_json | Convert YAML to JSON | yes | parameters, output, examples |
json_query | Query JSON with JMESPath | yes | parameters, output, examples |
yaml_format | Lint and format YAML | yes | parameters, output, examples |
json_lint | Lint JSON | yes | parameters, output, examples |
csv_format | Validate and format CSV | yes | parameters, output, examples |
csv_to_json | Convert CSV to JSON | yes | parameters, output, examples |
json_to_csv | Convert JSON to CSV | yes | parameters, output, examples |
toml_format | Format, validate and lint TOML | yes | parameters, output, examples |
toml_to_json | Convert TOML to JSON | yes | parameters, output, examples |
json_to_toml | Convert JSON to TOML | yes | parameters, output, examples |
tool_request | Request a new tool | no (random output) | parameters, output, examples |
tool_requests | List your tool requests | yes | parameters, output, examples |
Protocol support
- Modern (2026-07-28): stateless per-request metadata. Each
request must carry
params._meta["io.modelcontextprotocol/protocolVersion"]and the matchingMCP-Protocol-Version,Mcp-Methodand (fortools/call)Mcp-Nameheaders; mismatches return400with-32020 HeaderMismatch. Methods:server/discover,tools/list,tools/call,ping. - Legacy (2025-11-25, 2025-06-18, 2025-03-26):
initializenegotiates the version (the client's if supported, otherwise 2025-11-25). NoMcp-Session-Idis issued; every request is served independently. Methods:initialize,tools/list,tools/call,ping. - Transport: Streamable HTTP,
POSTonly. Every response is a singleapplication/jsonobject; the server never opens an SSE stream.GETandDELETEreturn405. Notifications (noid) return202with no body. Batches are rejected. - Origin: requests without an
Originheader (all non-browser clients) and same-origin requests are accepted. Browser requests from other origins return403unless the deployment lists them inMCP_ALLOWED_ORIGINS. - Limits: 1 MiB request bodies, and the same per-client rate limit as the
HTTP API. Credentials that are missing, invalid, expired or rate-limited produce a tool
result with
isError: truewhose text explains how to fix it. - Errors: protocol problems are JSON-RPC errors (
-32700parse,-32600invalid request,-32601method not found,-32602unknown tool or bad params,-32020header mismatch,-32022unsupported version withdata.supported). Problems with tool arguments come back as a normal result withisError: trueand an<code>: <message>text the model can act on.
Example exchanges
Generated by sending each request to the server code at build time.
Modern client (2026-07-28): discover
POST /mcp
MCP-Protocol-Version: 2026-07-28
Mcp-Method: server/discover
{
"jsonrpc": "2.0",
"id": 1,
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "docs",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
} HTTP 200
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"supportedVersions": [
"2026-07-28",
"2025-11-25",
"… 2 more"
],
"capabilities": {
"tools": {
"listChanged": false
}
},
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "caruana-utilities",
"title": "Caruana Utilities",
"version": "0.4.0",
"websiteUrl": "https://util.caruana.me",
"icons": [
{
"src": "https://util.caruana.me/assets/images/logo.png",
"mimeType": "image/png",
"sizes": [
"150x150"
]
}
]
}
},
"instructions": "Developer utilities for agents: encoding (URL, Base64, HTML, hex, Punycode), hashing and checksum verification, key and certificate fingerprints, certificate de… (1305 more characters)",
"ttlMs": 3600000,
"cacheScope": "public"
}
} Modern client: call a tool without credentials (an actionable tool error)
POST /mcp
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: hash
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "hash",
"arguments": {
"input": "abc",
"algorithm": [
"sha256"
]
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "docs",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
} HTTP 200
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "unauthenticated: Credentials required. Register for a client ID and secret: agents via POST https://util.caruana.me/api/auth/register (or A2A SendMessage at https://util.caruana.me/a2a), people via https://util.caruana.me/credentials/. Then send \"Authorization: Basic base64(client_id:client_secret)\" or a Bearer token from https://util.caruana.me/api/auth/token. Docs: https://util.caruana.me/reference/auth/"
}
],
"isError": true
}
} Legacy client (2025-06-18 … 2025-11-25): initialize
POST /mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {},
"clientInfo": {
"name": "docs",
"version": "1.0.0"
}
}
} HTTP 200
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-11-25",
"capabilities": {
"tools": {
"listChanged": false
}
},
"serverInfo": {
"name": "caruana-utilities",
"title": "Caruana Utilities",
"version": "0.4.0",
"websiteUrl": "https://util.caruana.me",
"icons": [
{
"src": "https://util.caruana.me/assets/images/logo.png",
"mimeType": "image/png",
"sizes": [
"150x150"
]
}
]
},
"instructions": "Developer utilities for agents: encoding (URL, Base64, HTML, hex, Punycode), hashing and checksum verification, key and certificate fingerprints, certificate de… (1305 more characters)"
}
} A tool error is a result, not a protocol error
POST /mcp
MCP-Protocol-Version: 2025-11-25
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "base64_decode",
"arguments": {
"input": "not base64!"
}
}
} HTTP 200
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "unauthenticated: Credentials required. Register for a client ID and secret: agents via POST https://util.caruana.me/api/auth/register (or A2A SendMessage at https://util.caruana.me/a2a), people via https://util.caruana.me/credentials/. Then send \"Authorization: Basic base64(client_id:client_secret)\" or a Bearer token from https://util.caruana.me/api/auth/token. Docs: https://util.caruana.me/reference/auth/"
}
],
"isError": true
}
} Unsupported version
POST /mcp
MCP-Protocol-Version: 1900-01-01
Mcp-Method: tools/list
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "1900-01-01",
"io.modelcontextprotocol/clientInfo": {
"name": "docs",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
} HTTP 400
{
"jsonrpc": "2.0",
"id": 4,
"error": {
"code": -32022,
"message": "Unsupported protocol version",
"data": {
"supported": [
"2026-07-28",
"2025-11-25",
"… 2 more"
],
"requested": "1900-01-01"
}
}
} 41 tools. Server name caruana-utilities, version 0.4.0.