MCP-compatible HTTP API — your agent manages the coffee money

Built for AI agents

Let your AI agent manage your coffee money. FreeCoffee ships an MCP-compatible HTTP API — agents can create campaigns, fund them, and read the performance stats straight from the ledger.

Create campaigns

Publish a validated campaign array to the live ad feed. Same feed contract the web app speaks: https-only click URLs, cpm clamped 0–100, deduped by id, capped at 20 campaigns.

POST /admin/feedGET /feed.json

Admin routes require a bearer token (Authorization: Bearer …) — set it as an encrypted Worker secret, never in the agent's prompt.

Read performance

Every amount is computed server-side from the served feed — the agent (and everyone else) sees the same numbers the ledger keeps.

GET /earnings/{deviceId}GET /health

The deviceId is the random UUID this browser already uses — no account, no email, no PII. See Profile to find yours.

Fund & settle

Top up campaign balance and settle payout rails from the agent, without opening a dashboard.

Phase 3 — planned

Honest note: payout-provider integration isn't built yet — no endpoint exists today, and this page won't pretend otherwise. Phase 3 wires the same ledger to a payment provider.

MCP-style tool manifest

Hand this to any MCP-capable client — Claude, OpenAI agents, Grok, OpenClaw and friends — as the tool description, and the agent can drive the FreeCoffee API directly.

{
  "name": "freecoffee",
  "description": "Menu-bar advertising on FreeCoffee — create campaigns, read earnings.",
  "tools": [
    {
      "name": "freecoffee_publish_feed",
      "description": "Replace the current ad feed with a validated campaign array (max 20).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "campaigns": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["id", "sponsor"],
              "properties": {
                "id":       { "type": "string", "maxLength": 40 },
                "sponsor":  { "type": "string", "maxLength": 40 },
                "tagline":  { "type": "string", "maxLength": 90 },
                "clickUrl": { "type": "string", "pattern": "^https://" },
                "cpm":      { "type": "number", "minimum": 0, "maximum": 100 },
                "logoText": { "type": "string", "maxLength": 2 },
                "accent":   { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$" }
              }
            }
          }
        },
        "required": ["campaigns"]
      }
    },
    {
      "name": "freecoffee_get_earnings",
      "description": "Read the server-side earnings ledger for a device: totals, rows, counters.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "deviceId": { "type": "string", "pattern": "^[a-f0-9-]{8,64}$" }
        },
        "required": ["deviceId"]
      }
    },
    {
      "name": "freecoffee_health",
      "description": "Platform health check — returns { ok: true } when the API is up.",
      "inputSchema": { "type": "object", "properties": {} }
    }
  ]
}

Works with any MCP-capable client (Claude, OpenAI agents, Grok, OpenClaw…). This manifest is an illustrative shape for the HTTP API below — FreeCoffee doesn't ship a hosted MCP server yet.

curl examples

The same three capabilities over plain HTTP. Point $BASE at your deployed Worker (see backend/README.md).

1 · Publish the feed (admin)

curl -X POST "$BASE/admin/feed" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "id": "camp_001",
      "sponsor": "Acme Coffee Co.",
      "tagline": "Single-origin beans — 20% off first bag",
      "clickUrl": "https://advertiser.example/offer?utm_source=freecoffee",
      "cpm": 6.0,
      "logoText": "AC",
      "accent": "#C98F4E"
    }
  ]'

2 · Read earnings

curl "$BASE/earnings/$DEVICE_ID"

3 · Health check

curl "$BASE/health"

Demo documentation — the endpoints exist in backend/src/worker.js; $BASE is your deployed Worker URL and $ADMIN_TOKEN is a Worker secret, set via wrangler secret put. The demo site itself is simulated data.