{"version":"1.0","protocolVersion":"2026-07-28","serverInfo":{"name":"aadhar.sh","title":"Aadharsh Site","version":"2.1.0","description":"Bounded public utilities for aadhar.sh: search, music, photos, coffee availability, Change Radar, Lens, ephemeral image inspection/transforms, exact published-photo recipe matching, an HTTP representation vault, and the site's published page resources."},"transport":{"type":"streamable-http","url":"https://aadhar.sh/mcp"},"capabilities":{"tools":true,"resources":true,"prompts":false},"authentication":{"required":false},"documentationUrl":"https://aadhar.sh/llms.txt","tools":[{"name":"ask","title":"Ask","description":"Ask aadhar.sh a natural-language question and get NLWeb-shaped results: for each match a url, name, site, score (0-100), description, and a schema.org schema_object. Retrieval is lexical over the site's own corpus and descriptions are extractive, so this returns the passages that answer the question rather than a written answer. mode=summarize and mode=generate are refused by name: this origin runs no language model.","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"the question, in natural language"},"site":{"type":"string","description":"NLWeb site token; this origin serves one site, so \"aadhar.sh\" or \"all\""},"mode":{"type":"string","enum":["list","summarize","generate"],"description":"list (the only one served here); summarize and generate are refused rather than degraded"},"prev":{"type":"array","items":{"type":"string"},"description":"previous queries. Received and NOT resolved, since decontextualization needs a model; send decontextualized_query instead"},"decontextualized_query":{"type":"string","description":"the fully self-contained form of a follow-up question. When present this is what gets searched"},"top_k":{"type":"integer","minimum":1,"maximum":50}},"required":["query"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"search_site","title":"Search Site","description":"Search the public pages, writing, garage notes, and utility descriptions on aadhar.sh.","inputSchema":{"type":"object","properties":{"q":{"type":"string","description":"case-insensitive search query"},"limit":{"type":"integer","minimum":1,"maximum":50}},"required":["q"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"now_playing","title":"Now Playing","description":"Read the cached current rn playlist and its tracks. A cold cache may refresh from the public Spotify embed using AadharshBot.","inputSchema":{"type":"object","properties":{}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"photo_query","title":"Photo Query","description":"Query the published photo archive by caption, camera, lens, film simulation, film-recipe setting, or date range. `q` is free text scored per term across the caption, the EXIF and an offline term expansion, so \"classic chrome bridge\" matches the film simulation AND the subject; the named parameters stay exact filters. Results are ranked and carry `score` and `matched` (which fields answered). `ranking.mode` says whether every term was covered (all-terms), only some (partial), or none (no-match), and `ranking.dropped` / `ranking.common` name terms ignored as stopwords or as too widespread to tell photos apart. Each result carries a `recipe` card naming the in-camera settings the shot was made with, so a look can be read back and re-shot. GPS and unlisted EXIF fields are never returned.","inputSchema":{"type":"object","properties":{"q":{"type":"string","description":"free-text query, ranked; multiple words are scored independently"},"camera":{"type":"string"},"lens":{"type":"string"},"film":{"type":"string","description":"film simulation name, e.g. \"Classic Chrome\", \"Nostalgic Neg\", \"Acros\""},"recipe":{"type":"string","description":"substring match anywhere in the recipe card, e.g. \"DR400\", \"Clarity: -2\", \"Grain Effect: Strong, Large\", \"+2 Red\""},"from":{"type":"string","description":"inclusive YYYY-MM-DD prefix"},"to":{"type":"string","description":"inclusive YYYY-MM-DD prefix"},"limit":{"type":"integer","minimum":1,"maximum":100},"offset":{"type":"integer","minimum":0,"maximum":10000}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"coffee_availability","title":"Coffee Availability","description":"Read bookable coffee slots in the host timezone. If the calendar is stale or unavailable, the result is explicitly unavailable and contains no slots.","inputSchema":{"type":"object","properties":{}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"change_radar","title":"Change Radar","description":"Read the bounded historical diff of the latest AadharshBot neighborhood observations. Raw crawled bodies are not stored or returned.","inputSchema":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":100}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"lens_inspect","title":"Lens Inspect","description":"Inspect one public HTTP(S) URL through Lens and return a compact agent-readiness observation. Private, local, and non-HTTP targets are rejected.","inputSchema":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"lens_page","title":"Lens Page","description":"Read one public URL and return only what derives from the page's own bytes: anatomy, structured data, a markdown rendering, and what it costs an agent to ingest. Skips the origin-level fan-out entirely, so it is far cheaper and far faster than lens_inspect. Readiness, agent doors and terms are ABSENT from the result (not zero) because they were not checked; `phases.discovery` is false. Use lens_inspect when you need those.","inputSchema":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"lens_compare","title":"Lens Compare","description":"Inspect two public HTTP(S) URLs and compare status, content, readiness, spectrum, agent doors, and discovery surfaces.","inputSchema":{"type":"object","properties":{"left":{"type":"string"},"right":{"type":"string"}},"required":["left","right"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"find_events","title":"Find Events","description":"Search the Serendipity event pool (community events worth going to, and who's RSVP'd) by keyword. Returns events the pool's contributors actually said yes to; pass rsvp:\"all\" to include events that were only browsed.","inputSchema":{"type":"object","properties":{"q":{"type":"string","description":"optional keyword filter on event name, place, or contributor"},"when":{"type":"string","enum":["upcoming","past","all"],"description":"defaults to upcoming"},"rsvp":{"type":"string","enum":["going","all","discovered"],"description":"defaults to going (the events with real rosters)"},"topic":{"type":"string","enum":["crypto","ai","fintech","devtools","bio","climate","hardware","consumer","startups","culture","other"],"description":"optional: only events classified as this topic; unclassified events are counted in `untagged`"},"format":{"type":"string","enum":["talks","conference","hackathon","demo","workshop","meal","social","meetup","other"],"description":"optional: only events classified as this format (talks, meal, social, ...)"},"limit":{"type":"integer","minimum":1,"maximum":200}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"image_inspect","title":"Image Inspect","description":"Inspect an image's dimensions, format, and animation/frame information. Image bytes are processed ephemerally and are not stored.","inputSchema":{"type":"object","properties":{"image_data":{"type":"string","description":"base64 image bytes, optionally as a data URL"},"mime_type":{"type":"string"},"source_url":{"type":"string","description":"public HTTPS image URL"}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"image_transform","title":"Image Transform","description":"Run a bounded web image transform through Cloudflare Images and return the transformed image inline plus an exact byte receipt. The output is ephemeral.","inputSchema":{"type":"object","properties":{"image_data":{"type":"string"},"mime_type":{"type":"string"},"source_url":{"type":"string"},"preset":{"type":"string","enum":["web","thumbnail","universal","og"]},"width":{"type":"integer","minimum":1,"maximum":2400},"height":{"type":"integer","minimum":1,"maximum":2400},"fit":{"type":"string","enum":["cover","contain","crop","scale-down","pad","squeeze"]},"format":{"type":"string","enum":["avif","webp","jpeg"]},"quality":{"type":"integer","minimum":1,"maximum":100},"rotate":{"type":"integer","enum":[0,90,180,270]}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"image_compare","title":"Image Compare","description":"Encode one image into up to three bounded format variants and report exact byte sizes and hashes. It does not pretend to score visual quality.","inputSchema":{"type":"object","properties":{"image_data":{"type":"string"},"mime_type":{"type":"string"},"source_url":{"type":"string"},"formats":{"type":"array","maxItems":3,"items":{"type":"string","enum":["avif","webp","jpeg"]}},"preset":{"type":"string","enum":["web","thumbnail","universal","og"]},"width":{"type":"integer","minimum":1,"maximum":2400},"height":{"type":"integer","minimum":1,"maximum":2400},"fit":{"type":"string"},"quality":{"type":"integer","minimum":1,"maximum":100}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"photo_recipe","title":"Photo Recipe","description":"Return the exact public Fuji recipe for a named archive photo, archive URL, or exact published thumbnail bytes. Arbitrary visual lookalikes are not treated as matches.","inputSchema":{"type":"object","properties":{"stem":{"type":"string"},"source_url":{"type":"string"},"image_data":{"type":"string","description":"base64 bytes from a published thumbnail"}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"representation_capture","title":"Representation Capture","description":"Capture bounded public HTTP representations under browser, bot, Markdown, or identity request profiles and store only normalized headers, metadata, and body digests. Writes: each call persists a new snapshot row, so this tool is not read-only and not idempotent.","inputSchema":{"type":"object","properties":{"url":{"type":"string"},"profiles":{"type":"array","maxItems":4,"items":{"type":"string","enum":["browser","bot","markdown","identity"]}}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true}},{"name":"representation_read","title":"Representation Read","description":"Read one normalized HTTP representation snapshot from the vault. Raw response bodies are never returned because they are never stored.","inputSchema":{"type":"object","properties":{"snapshot_id":{"type":"string"}},"required":["snapshot_id"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"representation_compare","title":"Representation Compare","description":"Refetch the same HTTP representation profile, compare it with a stored snapshot, and persist the new normalized observation. Writes: each call persists a new snapshot row, so this tool is not read-only and not idempotent.","inputSchema":{"type":"object","properties":{"snapshot_id":{"type":"string"},"url":{"type":"string","description":"optional replacement URL, otherwise the snapshot URL"}},"required":["snapshot_id"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true}},{"name":"finger","title":"Finger","description":"Look up who runs aadhar.sh, as a drivable terminal program. Panes: overview, writing, reading, listening, photos, around, coffee, deploys, search. Send `keys` to move (1-9 pane, j/k cursor, <cr> open, h back, ? help) and pass the returned `url`'s params back to continue. Returns a rendered 80-column frame.","inputSchema":{"type":"object","properties":{"keys":{"type":"string","description":"a key sequence, up to 32 keys, e.g. \"2jj<cr>\""},"pane":{"type":"string","enum":["overview","writing","reading","listening","photos","around","coffee","deploys","search"]},"cursor":{"type":"integer","minimum":0,"maximum":4999},"open":{"type":"string","description":"id of the row to open (slug, index, or version number)"},"q":{"type":"string","description":"query for the search pane"}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"photos","title":"Photos","description":"Browse the published photo archive as a terminal frame, filterable by caption, film simulation, body, and lens. Opening a frame shows its exposure and the in-camera recipe it was shot with. Send `keys` (j/k cursor, <cr> open, n/p page).","inputSchema":{"type":"object","properties":{"keys":{"type":"string"},"q":{"type":"string"},"film":{"type":"string"},"camera":{"type":"string"},"lens":{"type":"string"},"page":{"type":"integer","minimum":0,"maximum":200},"cursor":{"type":"integer","minimum":0,"maximum":4999},"open":{"type":"string","description":"photo stem to open"}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"radar","title":"Radar","description":"Render signal readings you have already measured (wifi/Bluetooth RSSI) as a terminal instrument: concentric strength bands, a meter and trend per source, and findphone's field calibration (-45 arm's reach, -60 same table, -72 same room). This origin has no antenna and does not sense anything; you supply the samples. Nothing is stored. Angles in the plot are decorative because RSSI carries no bearing.","inputSchema":{"type":"object","properties":{"samples":{"type":"array","maxItems":40,"items":{"type":"object","properties":{"name":{"type":"string"},"rssi":{"type":"number","description":"dBm, negative; e.g. -58"},"kind":{"type":"string","description":"optional tag, e.g. wifi or ble"},"history":{"type":"array","items":{"type":"number"},"description":"optional trailing readings for the trend"}},"required":["name","rssi"]}},"source":{"type":"string","description":"optional label for what did the sampling"}},"required":["samples"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}},{"name":"encode","title":"Encode","description":"Read a JPEG or AVIF at a URL and report what its encoder actually did: chroma subsampling, baseline vs progressive and the scan count, an estimated quality with the deviation from the IJG Annex K table shown, AVIF bit depth, and whether ICC/EXIF/XMP is riding along. NO PIXELS ARE DECODED — every fact comes from the container — so this works on files a Worker could never decode.","inputSchema":{"type":"object","properties":{"url":{"type":"string"}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"agent_ready","title":"Agent Ready","description":"Grade how much of an origin a machine can actually use: llms.txt, a markdown twin, an agent card, an API catalog, and a real tools/list against its MCP server. Doors are COUNTED, never scored — a check that could not run is reported as unreadable rather than as a failure. Called with no url it audits aadhar.sh itself and prints what building that cost in files and lines.","inputSchema":{"type":"object","properties":{"url":{"type":"string"}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"dict","title":"Dict","description":"Will a browser ever actually use the compression dictionary a URL is serving? Compression dictionaries fail in total silence — Chromium declines to register a perfectly good one because of a cache directive, with no warning anywhere. Returns a rendered frame grading every registration rule, plus whether a delta-serving response varies on available-dictionary. Same route as /dict.","inputSchema":{"type":"object","properties":{"url":{"type":"string"}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"cache","title":"Cache","description":"Does a URL's ETag ever actually 304? A BEHAVIORAL probe rather than a header read: fetches twice to see whether the validator survives two identical requests, then replays it with If-None-Match and reports what the origin did. Also checks Accept negotiation against Vary. Returns a rendered frame. Same route as /cache.","inputSchema":{"type":"object","properties":{"url":{"type":"string"}}},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}},{"name":"lens","title":"Lens","description":"Inspect one public HTTP(S) URL and render the observation as a terminal frame: readability, agent doors, and what a single scan costs to read. Same rate limit and same refusals as lens_inspect; use lens_inspect instead if you want the fields rather than the frame.","inputSchema":{"type":"object","properties":{"url":{"type":"string"},"doors":{"type":"boolean","description":"also READ what is behind the agent doors: llms.txt, the markdown twin, the agent card, and a real tools/list against their MCP server. Their catalog is listed, never called."}},"required":["url"]},"outputSchema":{"type":"object","additionalProperties":true},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}}]}