{"id":"40c4bc94-ea01-4261-b28e-e8db81db6be1","slug":"ayaangazali-eyes","kind":"mcp","name":"eyes","summary":"Eyes: agents pay a nearby human a few dollars to check something in the physical world","owner":"ayaangazali","repoUrl":"https://github.com/ayaangazali/eyes","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-10-17T05:47:05.000Z","addedAt":"2026-10-21T18:19:05.209Z","logoUrl":"https://avatars.githubusercontent.com/u/231403453?u=92ebdc38b2e525b3ff4b356661fd488413a62140&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["utilities"],"tags":[],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-26T08:50:39.086Z","sample":false,"url":"https://conduits.dev/tools/ayaangazali-eyes","language":"TypeScript","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<h1 align=\"center\">👀 Eyes</h1>\n\n<div align=\"center\">\n\n**Your agent asks a question about a real place. A nearby person takes a live photo and answers it.**\n\n[![CI](https://img.shields.io/github/actions/workflow/status/ayaangazali/eyes/ci.yml?branch=main&style=for-the-badge&logo=githubactions&logoColor=white&label=CI)](https://github.com/ayaangazali/eyes/actions/workflows/ci.yml)\n[![Live](https://img.shields.io/badge/live-eyes.pictures-2563eb?style=for-the-badge)](https://eyes.pictures)\n[![MCP](https://img.shields.io/badge/MCP-mcp.eyes.pictures%2Fmcp-0d9488?style=for-the-badge)](https://mcp.eyes.pictures/mcp)\n\n[Site](https://eyes.pictures) · [Worker app](https://app.eyes.pictures) · [Connect](docs/CONNECT.md) · [Deploy](docs/DEPLOY.md) · [Status](docs/archive/hackathon/STATUS.md)\n\n<img src=\"apps/web/landing/public/images/storefront.webp\" alt=\"A corner cafe on 18th St with an OPEN sign on the door and a chalkboard menu on the sidewalk\" width=\"720\">\n\n*The kind of photo Eyes returns: is the cafe open right now? The sign says yes.*\n\n</div>\n\nAgents can read the internet but cannot see the street. Eyes is an MCP server that lets an agent pay a nearby person about $3 to go and look. Built for YC's \"Make Something Agents Want\" hackathon (Oct 17-18, 2026) by Ayaan, Jerry and Shryuk.\n\n## Features\n\n- **[MCP tools](docs/features/mcp-tools.md):** 13 model-visible tools to quote, ask, wait, accept answers, review classifier refusals and manage tasks and money; plus app-only `confirm_ask`. REST and non-UI automation retain direct dispatch.\n- **[ChatGPT and Claude apps](docs/features/chatgpt-claude-apps.md):** configured at the dedicated MCP host; OAuth **Continue** hands a new key to the client automatically. Saving it is optional for direct API use.\n- **[iMessage dispatch](docs/features/imessage-dispatch.md):** the 3 nearest workers get a text; first YES wins.\n- **[Email channel](docs/features/email-channel.md):** reply EMAIL in your existing Eyes iMessage conversation for a link to send your first email; offers, links and sign-in by email, with mobile still required.\n- **[Photo checks](docs/features/photo-checks.md):** GPS within 150 m, taken live and narrowly moderated; no answer-correctness judgment.\n- **[Escrow](docs/features/escrow.md):** bounty plus $0.50 fee held on ask; refunded if no answer.\n- **[Prepaid balance](docs/features/escrow.md):** `get_balance.top_up_url` opens Stripe Checkout to add funds; payments are in test mode.\n- **[Safety](docs/features/safety.md):** rules and an AI check refuse private-person, home, vehicle or face-targeted requests; this is separate from photo moderation and is not a blanket ban on faces in photos.\n- **[Classifier review](docs/features/safety.md):** `report_classifier` and `get_classifier_report`; internal Approve/Reject controls, with approval allowing only an explicit retry of the same agent's exact request for 24 hours—not automatic dispatch or charging.\n- **[Owner controls](docs/features/owner-controls.md):** spend caps, allowed task types, key rotation.\n- **[Worker location](docs/features/worker-location.md):** HERE links, a Shortcut or the iPhone app.\n- **[Ops dashboard](docs/features/ops-dashboard.md):** internal.eyes.pictures: tasks, money, reviews, tickets, live map.\n\n## Quick start\n\n1. **Get a key:** no dashboard needed; the test balance is $20.\n\n   ```sh\n   curl -X POST https://api.eyes.pictures/v1/signup \\\n     -H \"content-type: application/json\" -d '{\"name\":\"my-agent\"}'\n   ```\n\n2. **Connect:** from Claude Code (ChatGPT, claude.ai, Claude Desktop and Cursor are in [docs/CONNECT.md](docs/CONNECT.md)):\n\n   ```sh\n   claude mcp add --transport http eyes https://mcp.eyes.pictures/mcp \\\n     --header \"Authorization: Bearer $EYES_API_KEY\"\n   ```\n\n3. **Ask:** `claude -p 'Use quote_task to check the line at the Ferry Building, San Francisco'`\n\nPrefer the Manufact CLI? `npx -y mcp-use@2.10.1 client connect eyes https://mcp.eyes.pictures/mcp --protocol legacy -H \"Authorization: Bearer $EYES_API_KEY\"`. To be a worker, open https://app.eyes.pictures on an iPhone. Until workers have opted in near a place, `ask_eyes` there returns `no_workers_nearby` and charges nothing. https://api.eyes.pictures/status says which parts are live.\n\n**MCP is live at `https://mcp.eyes.pictures/mcp`, with ChatGPT and Claude configured there.** OAuth issuer and card origins match each host. REST signup, balance, uploads and webhooks stay at `https://api.eyes.pictures`; legacy `api.eyes.pictures/mcp` connectors remain supported. This does not mean every third-party connector has migrated. See [OAuth setup](docs/CONNECT.md).\n\nStripe's provider integration is live, but payments and the $20 signup credit are test-only: no real money moves. Marketplace version 1.0.3 is a configured draft with preflight complete, not submitted or published; legal owner attestations and test-mode limits remain. The new ChatGPT card protocol and live API are verified. Follow-up in-chat visual checks on the operator's test accounts were quota-blocked on 2026-10-18, not unavailable for all users; see [STATUS](docs/archive/hackathon/STATUS.md).\n\n## How it works\n\nIn ChatGPT and Claude connectors, the model prepares a read-only draft and the user confirms in the card before Eyes sends or escrows anything. REST, CLI and non-UI MCP can dispatch directly. All dispatches call one `EyesService`, and each money move is one plpgsql function, so it runs in one transaction ([ADR-003](intent/decisions/ADR-003-seams-and-ownership.md)). The full flow is in [docs/SPEC.md](docs/SPEC.md).\n\nPhoto moderation rejects only confirmed graphic gore or explicit sexual content. Uncertain content is allowed; provider failures fall back to Claude, and no valid provider verdict means manual review with escrow held. The agent decides whether the answer is correct.\n\n```mermaid\nsequenceDiagram\n    participant A as Agent (MCP / REST)\n    participant E as Eyes API (Manufact Cloud)\n    participant W as Worker iPhone (iMessage)\n    participant C as Capture page (app.eyes.pictures)\n    A->>E: quote_task, then ask_eyes\n    E->>E: safety check, escrow $3.50 (InsForge Postgres)\n    E->>W: offer text (Inkbox)\n    W->>E: YES (first YES wins)\n    E->>W: capture link\n    W->>C: live photo + GPS\n    C->>E: upload (InsForge storage)\n    E->>E: GPS, freshness, moderation (clef, Claude on provider failure)\n    A->>E: await_answer (long poll, 55 s per call)\n    E-->>A: answer, photo, checks\n    E->>W: $3 Stripe Connect transfer + paid text\n```\n\n## Repository layout\n\n- [`apps/mcp/`](apps/mcp/): API server: MCP tools, REST, webhooks, OAuth, `/status`.\n- [`apps/edge/`](apps/edge/): Cloudflare Workers: thin API forwarder, cron, uptime monitor—not the MCP/API server host.\n- [`apps/web/`](apps/web/): landing site, worker app and the ops dashboard (internal.eyes.pictures).\n- [`apps/mobile/`](apps/mobile/): Expo iPhone app that sends background location.\n- [`packages/`](packages/): core, engine, db, comms, payments, safety, verify, ui.\n- [`cli/`](cli/): the `eyes` CLI and generated agent docs (`llms-full.txt`, OpenAPI).\n- [`scripts/`](scripts/): live smoke, owner link, task resolve, migrations, intent check.\n- [`evals/`](evals/), [`e2e/`](e2e/): safety evals and the Playwright golden path.\n- [`intent/`](intent/): why each file exists ([INDEX](intent/INDEX.md)), ADRs, verdicts.\n\n## More docs\n\n- [Connect from ChatGPT, Claude, Claude Code and Cursor](docs/CONNECT.md)\n- [Deploy, live smoke, roll back, alerts](docs/DEPLOY.md)\n- [Spec](docs/SPEC.md)\n- [Status and live verification](docs/archive/hackathon/STATUS.md)\n- [Plan](docs/archive/hackathon/PLAN.md)\n- [Demo runbook](docs/archive/hackathon/DEMO.md)\n- [Decisions (ADRs)](intent/decisions)\n- [Agent docs: llms.txt](docs/public/llms.txt)\n- [Report a bug](../../issues/new)\n\nTo develop locally you need Node 26, pnpm and Docker: `pnpm install && pnpm verify:fast` runs lint, typecheck, unit, contract, safety fixtures and the intent check without a database. `pnpm db:up && pnpm db:migrate && pnpm test:integration` adds Postgres, and `pnpm test:e2e` runs Playwright on fakes.\n\n## Built with\n\nEvery outside provider and service Eyes uses, and how. \"Live\" means the deployed server at api.eyes.pictures uses it today; \"test\" means it runs in a sandbox or test mode, so no real money moves.\n\n| Provider | What Eyes uses it for | Where in the repo | Status |\n|---|---|---|---|\n| Manufact Cloud | Hosts the actual MCP/API server (`eyes-prod`), including REST, webhooks, OAuth and the ops dashboard; origin `https://warm-spark-aocdd.run.mcp-use.com`, public MCP `https://mcp.eyes.pictures/mcp` | [apps/mcp](apps/mcp), [Dockerfile](Dockerfile), [docs/DEPLOY.md](docs/DEPLOY.md) §2 | live |\n| Cloudflare Workers | `eyes-api` is a thin forwarder for `mcp.eyes.pictures`, `api.eyes.pictures` and `internal.eyes.pictures` to Manufact; static Workers serve `eyes.pictures` and `app.eyes.pictures` | [apps/edge/api](apps/edge/api), [apps/web/landing](apps/web/landing), [apps/web/worker](apps/web/worker) | live |\n| Manufact gateway (optional) | `https://dark-steel-ofaoa.run.mcp-use.com/mcp` proxies the public MCP endpoint for gateway analytics; this is separate from the Manufact server host | [docs/CONNECT.md](docs/CONNECT.md) | optional |\n| Cloudflare Containers + Durable Objects | Previous API hosting path; not the current production origin | [apps/edge/api/worker.js](apps/edge/api/worker.js) | legacy |\n| Cloudflare KV + Cron | `eyes-monitor` checks `/healthz` every minute, keeps state in KV, texts an alert after two failures | [apps/edge/monitor](apps/edge/monitor) | live |\n| Cloudflare DNS | `eyes.pictures` zone and custom domains, including the dedicated MCP host | wrangler configs above | live |\n| Cloudflare Workers AI (`clef-omni`) | First-pass task safety classifier; photo moderation rejects only confirmed graphic gore or explicit sexual content | [packages/safety](packages/safety), [packages/verify](packages/verify) | live |\n| Cloudflare Browser Integrity rule | Zone security setting on the domains | Cloudflare dashboard only, not in the repo | live (not verifiable from the repo) |\n| InsForge | Postgres with RPC functions and RLS for the ledger, claims and expiry; migrations through the migrations endpoint | [packages/db](packages/db), [scripts/insforge-migrate.ts](scripts/insforge-migrate.ts) | live |\n| InsForge Storage | Public `photos` bucket for captures; faces alone do not reject or delete photos ([photo policy](docs/features/photo-checks.md)) | [packages/db](packages/db) | live |\n| InsForge Sites | Earlier host of the worker web (`*.insforge.site`); replaced by `app.eyes.pictures` | [docs/DEPLOY.md](docs/DEPLOY.md) §3 | earlier |\n| Stripe | Checkout top-ups, Connect Express onboarding, $3 transfers on verified answers, transfer reversals on confirmed fraud, signed webhooks | [packages/payments](packages/payments) | test mode |\n| Inkbox | Shared iMessage line: inbound webhook, offer and paid texts, START/STOP/HELP/HERE replies, texts with location codes and the app link; uptime alerts; first-contact owner/ops email fallback when Primitive refuses delivery | [packages/comms/src/inkbox.ts](packages/comms/src/inkbox.ts) | live |\n| Inkbox (limitation) | An iMessage \"Share My Location\" arrives as a lone U+FFFD, so Eyes replies with a HERE link instead ([ADR-037](intent/decisions/ADR-037-worker-location.md)) | [packages/comms](packages/comms) | live |\n| Primitive | Outbound DNS verified and one owner Gmail delivery confirmed; unrestricted sending is still off, first-contact fallback uses Inkbox, and external custom-alias SPF remains unresolved | [packages/comms/src/primitive.ts](packages/comms/src/primitive.ts) | limited live verification |\n| Anthropic Claude | Fallback for task-safety or photo provider failures only; used alone without Cloudflare | [packages/safety](packages/safety), [packages/verify](packages/verify) | live |\n| OpenStreetMap Nominatim | Geocodes place names in `quote_task` and `ask_eyes` | [apps/mcp/src/geo.ts](apps/mcp/src/geo.ts) | live |\n| OpenStreetMap tiles + Leaflet (unpkg) | Maps on the ops dashboard and live map | [apps/web/dashboard](apps/web/dashboard) | live |\n| Apple Maps / Google Maps links | Reads coordinates from map links a worker texts in; the capture page links to Google Maps directions | [packages/core/src/util.ts](packages/core/src/util.ts), [apps/web/worker/src/capture.ts](apps/web/worker/src/capture.ts) | live |\n| mcp-use | MCP server framework for tools and widgets; Manufact CLI connect path on the landing page | [apps/mcp](apps/mcp), [apps/web/landing](apps/web/landing) | live |\n| OpenAI Apps SDK / MCP Apps | ChatGPT app and Claude connector cards (quote, task, balance) with host-matched OAuth and card origins | [apps/mcp](apps/mcp), [docs/CONNECT.md](docs/CONNECT.md) | supported |\n| Expo / React Native + Apple | iPhone app with persistent connection across task photos; current distribution is [ad hoc](docs/DEPLOY.md#ad-hoc-releases-iphone-app), not TestFlight | [apps/mobile](apps/mobile) | ad hoc |\n| ClickHouse | Optional copy of the ops event log and Trends charts; Postgres stays the source of truth | [apps/web/dashboard/src/clickhouse.ts](apps/web/dashboard/src/clickhouse.ts) | optional, off on the host |\n| Astro, Tailwind, GSAP | Landing and worker web; Better-T-Stack conventions | [apps/web](apps/web) | live |\n| Playwright, Vitest, Biome | E2E, unit/contract/safety/integration tests, lint and format | [e2e](e2e), [vitest.config.ts](vitest.config.ts), [biome.json](biome.json) | test |\n| GitHub | Code, PRs, issues; Actions run CI, live smoke and the safety LLM eval | [.github/workflows](.github/workflows) | live |\n\n`.env.example` also lists keys for Armature analytics and Blaxel sandboxes; no code uses them yet.\n"}