API Documentation
POST /v1/diff
Compare two structured JSON values and return a structured diff.
Request Body
{
"left": { }, // required — JSON object or array
"right": { }, // required — JSON object or array
"options": { // optional
"includeUnchanged": false, // count unchanged leaves in stats
"maxDepth": 64 // recursion limit (1–256)
}
}
Validation Rules
leftandrightare required.- Top-level
leftandrightmust each be a JSON object or array. null, strings, numbers, and booleans are rejected for top-level diff inputs.options.includeUnchangedmust be boolean if provided.options.maxDepthmust be an integer between 1 and 256 if provided.
Success Response 200
{
"ok": true,
"stats": {
"added": 1,
"removed": 0,
"changed": 1,
"unchanged": 1,
"processingTimeMs": 0.08
},
"diff": [
{ "op": "replace", "path": "/name", "oldValue": "Alice", "newValue": "Bob" },
{ "op": "add", "path": "/role", "value": "admin" }
]
}
Diff Operations
| Op | Meaning | Fields |
|---|---|---|
add | Present in right, absent in left | path, value |
remove | Present in left, absent in right | path, value |
replace | Present in both, values differ | path, oldValue, newValue |
Path Format
Paths use JSON Pointer (RFC 6901). Special characters are escaped: ~ → ~0, / → ~1.
Error Cases
400when the body is not valid JSON.422when required fields are missing or the top-level diff inputs are not JSON objects or arrays.
POST /v1/image/exif-summary
Extract essential EXIF metadata from a JPEG image.
Request
Send raw binary image data. Max upload: 5 MB.
curl -X POST https://utilsforagents.com/v1/image/exif-summary \
--data-binary @photo.jpg -H "Content-Type: image/jpeg"
Success Response 200
{
"ok": true,
"processingTimeMs": 0.12,
"exif": {
"make": "Apple",
"model": "iPhone 15 Pro",
"software": "17.4",
"dateTime": "2026:03:15 14:30:00",
"dateTimeOriginal": "2026:03:15 14:30:00",
"orientation": 1,
"imageWidth": 4032,
"imageHeight": 3024,
"exposureTime": "1/120",
"fNumber": 1.8,
"iso": 100,
"focalLength": 6.9,
"gps": {
"latitude": 40.446111,
"longitude": -79.982222,
"altitude": 350.5
}
}
}
Validation and Edge Cases
- Only JPEG uploads are supported.
415is returned both for invalid/non-JPEG uploads and for JPEGs that do not contain an EXIF segment.- Images smaller than the minimum valid size return
400.
POST /v1/image/scrub-metadata
Strip all metadata (EXIF, XMP, ICC, IPTC) from a JPEG or PNG and return the cleaned binary.
Request
Send raw binary image data. Max upload: 5 MB. Supports JPEG and PNG.
curl -X POST https://utilsforagents.com/v1/image/scrub-metadata \
--data-binary @photo.jpg -H "Content-Type: image/jpeg" -o clean.jpg
Success Response 200
Returns the cleaned image binary with Content-Type: image/jpeg or image/png.
Guarantees
- JPEG outputs preserve pixel data while removing APP metadata segments such as EXIF, XMP, ICC, and IPTC payloads.
- PNG outputs preserve rendering-critical chunks and remove ancillary metadata chunks.
- If the image has no removable metadata, the endpoint still returns a valid image payload.
POST /v1/html/to-markdown
Convert HTML to clean Markdown. Strips script, style, iframe, and other dangerous tags before conversion.
Request (JSON)
curl -X POST https://utilsforagents.com/v1/html/to-markdown \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Title</h1><p>Hello world</p>"}'
Request (raw HTML)
curl -X POST https://utilsforagents.com/v1/html/to-markdown \
-H "Content-Type: text/html" \
-d '<h1>Title</h1><p>Hello world</p>'
Success Response 200
{
"ok": true,
"processingTimeMs": 0.42,
"charsBefore": 42,
"charsAfter": 22,
"markdown": "# Title\n\nHello world"
}
Validation and Edge Cases
- JSON requests must include a non-empty
htmlstring. - Raw-body requests must not be empty.
- Script, style, iframe, and other non-content tags are stripped before conversion.
POST /v1/html/fetch-markdown
Fetch a remote URL and convert the HTML response to Markdown. Includes SSRF protection (blocks private IPs, localhost, metadata endpoints).
Request
curl -X POST https://utilsforagents.com/v1/html/fetch-markdown \
-H "Content-Type: application/json" \
-d '{"url":"https://quotes.toscrape.com"}'
Success Response 200
{
"ok": true,
"processingTimeMs": 1.2,
"sourceUrl": "https://quotes.toscrape.com",
"charsBefore": 1256,
"charsAfter": 423,
"markdown": "# Example Domain\n\nThis domain is for use in..."
}
Validation and Edge Cases
- Only public
httpandhttpsURLs are allowed. - Remote responses must complete within 5 seconds and stay under 2 MB.
- Non-2xx upstream responses are returned as
400with a problem detail body.
SSRF Protection
The fetch-markdown endpoint blocks requests to:
| Target | Reason |
|---|---|
| 127.0.0.0/8, ::1, localhost | Loopback |
| 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 | Private networks |
| 169.254.169.254 | Cloud metadata |
| *.internal, *.local, *.localhost | Internal DNS |
Max remote response: 2 MB. Timeout: 5 seconds.
POST /v1/text/fetch-content
Fetch a remote URL, detect its content format, and return both the decoded response body and a normalized readable text form. This preserves backward compatibility for existing clients that read markdown while exposing an explicit content field for the fetched body text.
Request
curl -X POST https://utilsforagents.com/v1/text/fetch-content \
-H "Content-Type: application/json" \
-d '{"url":"https://quotes.toscrape.com/api/projects.json"}'
Success Response 200
{
"ok": true,
"processingTimeMs": 0.8,
"sourceUrl": "https://quotes.toscrape.com/api/projects.json",
"contentType": "application/json",
"detectedFormat": "json",
"charsBefore": 2048,
"charsAfter": 512,
"content": "{\"projects\":[{\"title\":\"Project One\",...}]}",
"text": "## Project One\n\nFirst project description...\n\n## Project Two\n\n...",
"markdown": "## Project One\n\nFirst project description...\n\n## Project Two\n\n..."
}
Response Fields
content: The fetched response body decoded as text.text: The normalized readable text representation of that body.markdown: Backward-compatible alias oftext.contentType: Upstream response content type without charset parameters when available.
Format Detection
| Detected As | Condition | Processing |
|---|---|---|
json | Content-Type: application/json or .json extension | content contains the raw JSON text. text/markdown contain recursively extracted readable text. |
html | Content-Type: text/html or .html/.htm extension | Full HTML→Markdown conversion (same as /v1/html/fetch-markdown) |
markdown | .md extension | Returned as-is (trimmed) |
text | Everything else (.txt, plain text, etc.) | Returned as-is (trimmed) |
Same SSRF protection as fetch-markdown. Max remote response: 2 MB. Timeout: 5 seconds. Non-2xx upstream responses are surfaced as 400 problem details.
POST /v1/url/metadata
Fetch a remote URL and return structured metadata from the document head without returning the full page body.
Request
curl -X POST https://utilsforagents.com/v1/url/metadata \
-H "Content-Type: application/json" \
-d '{"url":"https://quotes.toscrape.com"}'
Success Response 200
{
"ok": true,
"processingTimeMs": 1.1,
"sourceUrl": "https://quotes.toscrape.com",
"metadata": {
"title": "Example Domain",
"description": "This domain is for use in illustrative examples.",
"canonical": "https://quotes.toscrape.com/",
"language": "en",
"favicon": "https://quotes.toscrape.com/favicon.ico",
"feeds": [],
"openGraph": {},
"twitterCard": {},
"meta": { "robots": "index,follow" }
}
}
Metadata Guarantees
- Scalar fields such as
title,description,canonical,language, andfaviconarenullwhen absent. feedsis always an array and defaults to empty.openGraph,twitterCard, andmetaare always objects and default to empty.- The endpoint parses the raw upstream HTML response only; it does not execute JavaScript.
Validation and Limits
- Only public
httpandhttpsURLs are allowed. - Same SSRF protection, 5-second timeout, and 2 MB limit as the other fetch endpoints.
- Non-2xx upstream responses are returned as
400problem details.
POST /v1/utilities/count-tokens
Count tokens in text or estimate tokens for base64-encoded images using exact or approximate tokenizer strategies.
Request
curl -X POST https://utilsforagents.com/v1/utilities/count-tokens \
-H "Content-Type: application/json" \
-d '{"text":"Hello, world!","encoding":"cl100k_base","content_type":"text"}'
Success Response 200
{
"ok": true,
"processingTimeMs": 1.23,
"encoding": "cl100k_base",
"method": "exact",
"tokenCount": 4,
"characterCount": 13,
"utf8Sanitized": false
}
Supported Encodings
cl100k_base: exact WASM BPE for GPT-4, GPT-4 Turbo, GPT-4o-class tokenizers.o200k_base: exact WASM BPE for larger OpenAI tokenizer families.claude: high-fidelity estimate for Claude-family models.gemini: high-fidelity estimate for Gemini-family models.
Validation and Edge Cases
textis required and must be a non-empty string.- Maximum request size is 50 MB.
- Set
content_typetoimagefor base64-encoded image token estimation. Common image prefixes are also auto-detected. - Unknown encoding names return
400problem details.
POST /v1/feedback
Submit product feedback or feature requests for future UtilsForAgents endpoints. This route is intentionally free and does not require x402 payment.
Request
curl -X POST https://utilsforagents.com/v1/feedback \
-H "Content-Type: application/json" \
-d '{"text":"Add an endpoint that extracts JSON-LD and schema.org blocks from pages."}'
Request Body
{
"text": "Short feature request or bug report (max 600 chars after trimming)"
}
Success Response 202
{
"ok": true,
"accepted": true,
"maxChars": 600
}
The server trims leading and trailing whitespace before validating the length, logs the feedback for internal review, rejects trimmed-empty payloads, and does not echo the submitted text back in the response.
Validation Rules
textmust be a string.- The trimmed text must contain 1 to 600 characters.
400is returned for non-string, empty-after-trim, and too-long submissions.
Error Responses
All errors return application/problem+json per RFC 9457.
| Status | Type | When |
|---|---|---|
| 400 | bad-request | Body too small or malformed |
| 400 | invalid-json | Body is not valid JSON (diff endpoint) |
| 404 | not-found | Unknown route |
| 405 | method-not-allowed | Wrong HTTP method |
| 413 | payload-too-large | Upload exceeds 5 MB |
| 415 | unsupported-media-type | Invalid image type, invalid image structure, or JPEG without EXIF |
| 422 | invalid-schema | Missing required fields or invalid structured input |
{
"type": "https://utilsforagents.com/errors/payload-too-large",
"title": "Payload Too Large",
"status": 413,
"detail": "Upload exceeds the 5MB limit."
}
GET /health
Returns service status.
{ "status": "ok", "service": "utilsforagents", "version": "1.5.0" }
Machine-Readable Spec
For AI agents, the full API contract is available at /agents.md in plain Markdown.
MCP Server
Use these tools directly from Claude Desktop or any MCP-compatible client with automatic x402 payment handling.
Install
npx utilsforagents-mcp
Claude Desktop Configuration
Add to claude_desktop_config.json:
{
"mcpServers": {
"utilsforagents": {
"command": "npx",
"args": ["utilsforagents-mcp"],
"env": {
"EVM_PRIVATE_KEY": "0x<your-private-key>"
}
}
}
}
Use SOLANA_PRIVATE_KEY instead if you want the MCP server to pay from a Solana wallet.
Environment Variables
| Variable | Description | Required |
|---|---|---|
EVM_PRIVATE_KEY | EVM private key (hex, with or without 0x) with USDC on Base | Provide this or SOLANA_PRIVATE_KEY |
SOLANA_PRIVATE_KEY | Solana private key in base58, 0x-hex, or JSON byte-array form with USDC on Solana mainnet | Provide this or EVM_PRIVATE_KEY |
RESOURCE_SERVER_URL | API base URL (default: https://utilsforagents.com) | No |
Available Tools
| Tool | Endpoint | Input |
|---|---|---|
json-diff | POST /v1/diff | left, right (any JSON) |
exif-summary | POST /v1/image/exif-summary | imageBase64 (base64 JPEG) |
scrub-metadata | POST /v1/image/scrub-metadata | imageBase64, contentType |
html-to-markdown | POST /v1/html/to-markdown | html (string) |
fetch-markdown | POST /v1/html/fetch-markdown | url |
fetch-content | POST /v1/text/fetch-content | url |
url-metadata | POST /v1/url/metadata | url |
count-tokens | POST /v1/utilities/count-tokens | text, encoding?, content_type? |
submit-feedback | POST /v1/feedback | text (max 600 chars after trimming) |
How It Works
Claude Desktop → MCP Server → paid POST /v1/* utility routes → HTTP 402
← Payment Requirements
x402 wrapper → Sign USDC payment → Retry
← 200 + data → Claude
The @x402/axios wrapper automatically intercepts 402 responses, signs a USDC payment on Base or Solana using your configured private key, and retries the request. No manual payment handling needed.
Source: GitHub · npm: utilsforagents-mcp