API

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 matching MCP-Protocol-Version, Mcp-Method and (for tools/call) Mcp-Name headers; mismatches return 400 with -32020 HeaderMismatch. Methods: server/discover, tools/list, tools/call, ping.
  • Legacy (2025-11-25, 2025-06-18, 2025-03-26): initialize negotiates the version (the client's if supported, otherwise 2025-11-25). No Mcp-Session-Id is issued; every request is served independently. Methods: initialize, tools/list, tools/call, ping .
  • Transport: Streamable HTTP, POST only. Every response is a single application/json object; the server never opens an SSE stream. GET and DELETE return 405. Notifications (no id) return 202 with no body. Batches are rejected.
  • Origin: requests without an Origin header (all non-browser clients) and same-origin requests are accepted. Browser requests from other origins return 403 unless the deployment lists them in MCP_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: true whose text explains how to fix it.
  • Errors: protocol problems are JSON-RPC errors (-32700 parse, -32600 invalid request, -32601 method not found, -32602 unknown tool or bad params, -32020 header mismatch, -32022 unsupported version with data.supported). Problems with tool arguments come back as a normal result with isError: true and 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.