aiden-mcp

mcp
Security Audit
Warn
Health Warn
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Warn
  • network request — Outbound network request in src/canary.ts
  • network request — Outbound network request in src/coffee-fetcher.ts
  • network request — Outbound network request in src/fellow-api.ts
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

MCP server for the Fellow Aiden coffee brewer. Lets Claude push profiles, scrape roaster pages, and apply brewing heuristics. Unofficial.

README.md

aiden-mcp

An MCP server for the Fellow Aiden coffee brewer. Lets Claude (and other MCP clients) brew good coffee with you — list, create, delete, and share profiles on your Aiden through natural language, scrape coffee details from any roaster's product page, and apply Aiden-specific brewing heuristics to design a recipe.

Unofficial. Not affiliated with or endorsed by Fellow Industries. Uses the same private API the Fellow iOS app uses; could break without notice.

What it does

Tool Auth What
fetch_coffee_details none Scrape any Shopify roaster product page — Counter Culture, Onyx, Sey, Heart, Verve — and return structured data (varieties, process, elevation, notes, story)
flash_brew none Plan a Japanese iced coffee on the Aiden — computes the ice/water split and the dose workaround (the machine can't express a 1:9 concentrate, so you under-report the dose), grounded in the Counter Culture and Lance Hedrick flash brew recipes
brewing_guidelines none Return Aiden-specific brewing principles tailored to a coffee's roast, process, elevation, varietals, and your flavor goal. Temperature priors are derived from 69 Fellow Drops profiles, not folk wisdom. Supports basket mods (V60/Orea/Kalita drop-ins adjust grind and pulse pacing). Grind settings convert to your grinder (Encore, Encore ESP, Virtuoso+, Ode Gen 1/2, Ode + SSP burrs, Opus, Comandante C40, 1Zpresso J/JX, Timemore C2/C3, DF64, Niche Zero)
list_profiles OAuth List the brew profiles on your Aiden, grouped by category (custom / stock / shared)
create_profile OAuth Push a new profile, get back a brew.link URL
delete_profile OAuth Free up a slot (Aiden has a 14-profile cap)
share_profile OAuth Generate a brew.link for any existing profile
get_device_info OAuth Verify connection + show slot usage

Example session

You: I picked up this coffee from Counter Culture. My old profile tasted thin and sour — I want to actually taste the fig and strawberry. Make me a new profile and push it to my Aiden.

Claude calls:

  1. fetch_coffee_details(url) → returns { coffee_name: "Mpemba — Natural Sundried", process: "natural sundried", country: "Burundi", elevation: "1800–2000m", tasting_notes: ["fig", "strawberry", "bright"], … }
  2. brewing_guidelines({process: "natural sundried", elevation: "1800-2000m", flavor_goal: "more fruit"}) → returns principles ("naturals lose volatile aromatics above 93°C", "coarsen grind for aromatic clarity", "open ratio to 1:16") + a starting recipe
  3. create_profile({title: "Mpemba v3", ratio: 16, bloomTemperature: 92, …}) → pushes to Aiden, returns brew.link/p/o3nZ

Claude: I pushed Mpemba v3 to your Aiden. Three changes from your old profile: dropped temps ~4°C across the board (96/95/94 → 92/91/90 SS) to preserve the fig and strawberry esters that high heat was driving off, opened ratio from 1:15 → 1:16 to give the aromatics room, and went coarser on grind (Encore 13 → 17). brew.link: https://brew.link/p/o3nZ

Hosted endpoint

https://aidenmcp.ravenhoward.org/mcp

Or self-host (5 minutes, see below) — recommended if you'd rather not send your Fellow password to a server you don't run.

Setup

Claude.ai web / Claude iOS

  1. Open Claude.ai → Settings → ConnectorsAdd custom connector
  2. Fill in:
    • Name: Aiden
    • URL: https://aidenmcp.ravenhoward.org/mcp
    • Leave OAuth Client ID and OAuth Client Secret empty — Claude auto-registers via dynamic client registration
  3. Click Connect. Claude opens a sign-in page. Enter your Fellow email + password (the same ones you use for the Fellow iOS app). The page validates with Fellow and redirects you back.
  4. Try: "List my Aiden profiles."

Claude Desktop

Same as web — use Settings → Connectors. The OAuth flow opens in your browser.

If you'd rather skip OAuth and use header auth instead, edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or equivalent:

{
  "mcpServers": {
    "aiden": {
      "url": "https://aidenmcp.ravenhoward.org/mcp",
      "headers": {
        "X-Fellow-Email": "[email protected]",
        "X-Fellow-Password": "your-fellow-password"
      }
    }
  }
}

Other MCP clients

Streamable HTTP transport at /mcp. Auth via OAuth 2.0 (auth code + PKCE) or X-Fellow-Email / X-Fellow-Password headers.

How auth handles your Fellow password

Your password reaches the server exactly once during OAuth sign-in. The server:

  1. Receives your email + password on the /oauth/authorize page
  2. Calls Fellow's /auth/login to validate them — gets back a JWT
  3. Stores only the JWT in Cloudflare KV (encrypted at rest, 1-hour TTL)
  4. Discards the password

No persistent storage of credentials. No logging of credentials. The JWT is what the server uses to call Fellow's API on your behalf.

You can verify all of this by reading src/oauth/authorize.ts and src/auth.ts. If you'd rather not trust me as the operator, self-host.

Self-hosting

git clone https://github.com/ravenintheforrest/aiden-mcp
cd aiden-mcp
npm install
npx wrangler login

# Create the OAuth state KV namespace
npx wrangler kv namespace create AIDEN_OAUTH
# Copy the id from the output into wrangler.toml under [[kv_namespaces]]

# Deploy
npx wrangler deploy

Cloudflare's free tier covers 100k requests/day and 1k KV writes/day — plenty for personal or small-group use. The Worker is stateless beyond short-lived KV records, so no database to manage.

To attach a custom domain after deploy: CF dashboard → Workers & Pages → aiden-mcp → Settings → Domains & Routes → Add Custom Domain.

API-drift canary (optional)

Fellow's API is undocumented with no changelog — when they ship an app update, an endpoint can quietly change shape. Rather than finding out from a GitHub issue weeks later, the Worker can probe the API on a cron schedule (hourly, configured in wrangler.toml) and alert you within the hour of something drifting.

The canary logs into a dedicated Fellow account (make a spare — don't use your main one), exercises every endpoint the tools depend on, and checks three drift classes: response shapes against the contracts in src/fellow-schemas.ts, value plausibility (stored numbers must stay inside the ranges our own validation enforces on write — a unit migration leaves the band), and data at rest (nothing but the canary writes to that account, so its stored profiles must read back identical run over run; a change means the server re-scaled data underneath us). Findings are fingerprinted in KV, so the webhook fires once per change (new drift, or recovery) — not every hour forever.

npx wrangler secret put CANARY_FELLOW_EMAIL     # dedicated Fellow account
npx wrangler secret put CANARY_FELLOW_PASSWORD
npx wrangler secret put CANARY_WEBHOOK_URL      # Slack or Discord webhook
npx wrangler secret put CANARY_WRITE            # optional: "true" to also test
                                                # create→verify→delete round-trips

Skip all four and the canary no-ops — nothing else changes. The last report is always inspectable in KV under canary:last.

Local development

npx wrangler dev

Worker runs at http://localhost:8787. The /mcp endpoint, OAuth endpoints, and /health all work locally.

Profile schema

The Aiden brewer accepts profiles with these constraints:

Field Range Notes
ratio 14–20 Coffee:water ratio (e.g. 15 = 1:15)
bloomRatio 1–3 Water multiple for the bloom
bloomDuration 1–120 Seconds
bloomTemperature 50–99 °C
ssPulsesNumber 1–10 Single-serve pulses
ssPulsesInterval 5–60 Seconds between pulses
ssPulseTemperatures array of 50–99 Length must equal ssPulsesNumber
batchPulsesNumber 1–10 Same idea, batch mode
batchPulsesInterval 5–60
batchPulseTemperatures array of 50–99
title 1–50 chars Alphanumeric + basic punctuation

The MCP validates client-side before calling Fellow's API, so you'll get clear error messages instead of generic 400s.

Caveats

  • The 14-profile cap. Aiden hardware limits you to 14 custom profiles. create_profile will return a clear error if you're at the cap; use delete_profile first.
  • Fellow's API is private. Endpoints discovered from the iOS app's network traffic. Fellow could change them at any time and break this. Two defenses are built in: every create_profile/update_profile verifies Fellow's response echo against what was sent (so a silently-ignored field becomes a loud warning instead of a bad brew), and a scheduled canary strict-validates every endpoint's response shape so drift gets caught before users hit it. Open an issue if it catches you anyway.
  • One device per account assumed. If your Fellow account has multiple Aidens, the MCP currently picks the first returned. Open an issue if you need multi-device.
  • Re-auth is seamless. Access tokens are matched to the Fellow JWT lifetime; when one expires, the client refreshes via OAuth refresh tokens without you re-entering your Fellow password. Only Fellow-issued tokens are ever stored (encrypted, in KV) — never the password itself.

Architecture

  • Cloudflare Worker at aidenmcp.ravenhoward.org
  • Streamable HTTP MCP transport (web standards, works in Workers)
  • OAuth 2.0 authorization code grant with PKCE (RFC 6749 + RFC 7636)
  • Dynamic client registration (RFC 7591)
  • Discovery metadata at /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server (RFC 9728 + RFC 8414)
  • No persistent state beyond short-lived KV records (auth codes ≤10min, access tokens ≤1hr, client registrations ≤90 days)

License

MIT — fork it, ship it, change the brewing heuristics to match your taste.

Related

Contributing

PRs welcome — particularly for:

  • Roasters whose product pages don't parse cleanly via fetch_coffee_details (Sey, Heart, Tim Wendelboe pages I haven't tested)
  • Brewing heuristics in brewing_guidelines that disagree with what the tool currently returns
  • Multi-device Aiden support
  • Refresh token flow for OAuth so users don't re-auth every hour

Reviews (0)

No results found