{
  "markdown": "# untappd-mcp-server\n\n[![npm version](https://img.shields.io/npm/v/untappd-mcp-server)](https://www.npmjs.com/package/untappd-mcp-server)\n[![npm downloads](https://img.shields.io/npm/dt/untappd-mcp-server)](https://www.npmjs.com/package/untappd-mcp-server)\n[![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)\n\nA Model Context Protocol (MCP) server that exposes the Untappd API as tools for AI agents — **27 tools** covering the full Untappd v4 read API, plus built-in interactive OAuth authentication. Search venues, breweries, and beers; check what's on tap via check-in feeds; explore user badges, friends, wish lists, and drinking history; and aggregate stats — all from any MCP-compatible client.\n\n## Prerequisites\n\n- Node.js 20+\n- Untappd API credentials (`client_id` and `client_secret`) from [untappd.com/api](https://untappd.com/api)\n- Optional: an Untappd OAuth access token to unlock authenticated tools — obtainable in-chat via the `authenticate_untappd` tool or `npx untappd-mcp-server auth` (see [Interactive Authentication](#interactive-authentication))\n\n## Quick Start\n\n### Via npx (zero install)\n\n```bash\nUNTAPPD_CLIENT_ID=xxx UNTAPPD_CLIENT_SECRET=yyy npx untappd-mcp-server\n```\n\n### PowerShell\n\n```powershell\n$env:UNTAPPD_CLIENT_ID = \"your_client_id\"\n$env:UNTAPPD_CLIENT_SECRET = \"your_client_secret\"\nnpx untappd-mcp-server\n```\n\n### Claude Desktop\n\nAdd to your Claude Desktop config (`claude_desktop_config.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"untappd\": {\n      \"command\": \"npx\",\n      \"args\": [\"untappd-mcp-server\"],\n      \"env\": {\n        \"UNTAPPD_CLIENT_ID\": \"your_client_id\",\n        \"UNTAPPD_CLIENT_SECRET\": \"your_client_secret\",\n        \"UNTAPPD_ACCESS_TOKEN\": \"optional_oauth_token\",\n        \"UNTAPPD_USERNAME\": \"optional_default_username\"\n      }\n    }\n  }\n}\n```\n\n## Tools\n\nTools marked **🔑 token** require an access token (`UNTAPPD_ACCESS_TOKEN` env var or interactive authentication).\n\n### Authentication Tools\n\n#### authenticate_untappd\n\nInteractively authenticate with Untappd via OAuth: opens your browser to Untappd's approve page, captures the redirect on a temporary localhost listener, and saves the access token — the 🔑 tools work immediately, no restart. **Prerequisite:** your Untappd app's Callback URL must be set to exactly `http://localhost:8737/callback` (or your `UNTAPPD_REDIRECT_URL`).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `timeout_seconds` | integer | No | How long to wait for browser approval (default 180, max 600) |\n\n#### get_auth_status\n\nReport authentication status: token presence, source (env var or token file), file path, and whether the 🔑 tools are unlocked. Free by default; `validate: true` verifies the token with one API call.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `validate` | boolean | No | Verify the token against the API with one call (default false) |\n\n### Search & Lookup\n\n#### venue_search\n\nSearch for venues (breweries, bars, restaurants) by name with optional location awareness.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `q` | string | Yes | Search query (venue name) |\n| `lat` | number | No | Latitude for location-aware results |\n| `lng` | number | No | Longitude for location-aware results |\n\n#### search_brewery\n\nSearch for breweries by name.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `q` | string | Yes | Brewery name search query |\n| `offset` | integer | No | Offset for pagination |\n\n#### search_beer\n\nSearch for beers by name.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `q` | string | Yes | Beer name search query |\n| `offset` | integer | No | Pagination offset |\n| `sort` | string | No | Sort order: `checkin` (default), `name`, `count` |\n\n### Venue\n\n#### get_venue_info\n\nRetrieve detailed information and recent check-ins for a venue.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `venue_id` | integer | Yes | Untappd venue ID |\n| `compact` | boolean | No | If true, returns venue info only (no checkins, media, top beers) |\n\n#### get_venue_checkins\n\nRetrieve the recent check-in feed for a venue. This is the primary tool for determining what's currently on tap — recent check-ins act as a live signal for available beers.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `venue_id` | integer | Yes | Untappd venue ID |\n| `limit` | integer | No | Number of results (max 25, default 25) |\n| `max_id` | integer | No | Return results older than this checkin ID |\n| `min_id` | integer | No | Return only checkins newer than this ID |\n\n#### get_venue_foursquare_lookup\n\nResolve a Foursquare venue ID to its Untappd venue — the bridge between Foursquare/location data and Untappd venue tools.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `foursquare_id` | string | Yes | Foursquare venue ID in v2 MD5-hash format (v3 numeric IDs will not work) |\n\n### Beer\n\n#### get_beer_info\n\nRetrieve detailed information for a specific beer.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `bid` | integer | Yes | Untappd beer ID |\n| `compact` | boolean | No | If true, returns beer info only |\n\n#### get_beer_checkins\n\nRetrieve the recent public check-in feed for a specific beer — what people are saying about it right now, and where they're drinking it.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `bid` | integer | Yes | Untappd beer ID |\n| `limit` | integer | No | Results per page (max 50, default 25) |\n| `max_id` | integer | No | Return results older than this checkin ID |\n| `min_id` | integer | No | Return only checkins newer than this ID |\n\n#### get_trending_beers\n\nRetrieve globally trending beers (macro and micro brew lists, by recent check-in velocity). No parameters.\n\n### Brewery\n\n#### get_brewery_info\n\nRetrieve detailed information, beer list, and recent check-ins for a brewery.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `brewery_id` | integer | Yes | Untappd brewery ID |\n| `compact` | boolean | No | If true, returns brewery info only |\n\n#### get_brewery_checkins\n\nRetrieve the recent public check-in feed for a brewery — all its beers being checked in globally.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `brewery_id` | integer | Yes | Untappd brewery ID |\n| `limit` | integer | No | Results per page (max 50, default 25) |\n| `max_id` | integer | No | Return results older than this checkin ID |\n| `min_id` | integer | No | Return only checkins newer than this ID |\n\n### User\n\n#### get_user_info\n\nRetrieve profile and stats for an Untappd user.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `username` | string | Yes | Untappd username |\n| `compact` | boolean | No | If true, returns user info only (no checkins, media, recent brews) |\n\n#### get_user_activity\n\nRetrieve the recent check-in activity feed for a user.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `username` | string | Yes | Untappd username |\n| `limit` | integer | No | Number of results (max 25, default 25) |\n| `max_id` | integer | No | Return results older than this checkin ID |\n| `min_id` | integer | No | Return only checkins newer than this ID |\n\n#### get_user_distinct_beers\n\nRetrieve the unique beers a user has checked in, with flexible sort ordering. `sort=checkin` with `limit=1` is the single-call pattern for \"most-checked-in beer\".\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `username` | string | Yes | Untappd username |\n| `offset` | integer | No | Pagination offset |\n| `limit` | integer | No | Results per page (max 50, default 25) |\n| `sort` | string | No | `date` (default), `checkin`, `highest_rated`, `lowest_rated`, `highest_rated_you`, `lowest_rated_you` |\n\n#### get_user_wishlist\n\nRetrieve beers on a user's wish list.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `username` | string | Yes | Untappd username |\n| `offset` | integer | No | Pagination offset |\n| `limit` | integer | No | Results per page (max 50, default 25) |\n| `sort` | string | No | `date` (default), `checkin`, `highest_rated`, `lowest_rated` |\n\n#### get_user_badges\n\nRetrieve a user's earned badges (pages of 50, most recent first).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `username` | string | Yes | Untappd username |\n| `offset` | integer | No | Pagination offset (pages of 50) |\n\n#### get_user_friends\n\nRetrieve a user's friend list (public accounts only).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `username` | string | Yes | Untappd username |\n| `offset` | integer | No | Pagination offset |\n| `limit` | integer | No | Results per page (max 50, default 25) |\n\n### Activity Feeds\n\n#### get_global_feed\n\nRetrieve the global public check-in feed (The Pub). High rate-limit cost for the data returned — prefer `min_id` polling to fetch only new check-ins. **Note:** standard API keys are typically not authorized for `/thepub` — Untappd returns *\"You are not authorized to call this method from this key\"* unless your key has elevated access (`get_local_feed` is not restricted).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `limit` | integer | No | Results per page (max 50, default 25) |\n| `max_id` | integer | No | Return results older than this checkin ID |\n| `min_id` | integer | No | Return only checkins newer than this ID |\n\n#### get_local_feed\n\nRetrieve the public check-in feed near a geographic point.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `lat` | number | Yes | Latitude |\n| `lng` | number | Yes | Longitude |\n| `radius` | integer | No | Radius in **miles** (default 25, max 50) |\n| `limit` | integer | No | Results per page (max 50, default 25) |\n| `max_id` | integer | No | Return results older than this checkin ID |\n| `min_id` | integer | No | Return only checkins newer than this ID |\n\n#### get_friend_feed 🔑 token\n\nRetrieve the friend check-in feed for the authenticated user.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `limit` | integer | No | Results per page (max 50, default 25) |\n| `max_id` | integer | No | Return results older than this checkin ID |\n| `min_id` | integer | No | Return only checkins newer than this ID |\n\n### Checkin\n\n#### get_checkin_info\n\nRetrieve extended details for a specific check-in, including badges earned, toasts, and comments.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `checkin_id` | integer | Yes | Untappd check-in ID |\n\n### Composite / Aggregation\n\nThese tools make multiple API calls (1 per page scanned — 50 beers/badges, 25 check-ins). They pre-check the remaining rate limit before starting and stop early — setting `truncated: true` in the response — if the budget runs low.\n\n#### get_user_stats_at_venue\n\nGet a user's check-in stats at a specific venue — visit count, last visit, average rating, top beers — by scanning their recent check-in feed. Untappd's API has no venue-history endpoint, so the stats cover the scanned window (`max_pages` × 25 check-ins), not all time.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `venue_id` | integer | Yes | Untappd venue ID |\n| `username` | string | No | Untappd username (defaults to `UNTAPPD_USERNAME`) |\n| `max_pages` | integer | No | Max feed pages to scan at 25 check-ins/page (default 5 = 125 check-ins) |\n\n#### search_venue_then_get_user_stats\n\nSearch for a venue by name, then get the user's check-in stats at the top match.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `q` | string | Yes | Venue search query |\n| `username` | string | No | Untappd username (defaults to `UNTAPPD_USERNAME`) |\n| `lat` | number | No | Latitude for location-aware search |\n| `lng` | number | No | Longitude for location-aware search |\n| `max_pages` | integer | No | Max feed pages to scan at 25 check-ins/page (default 5 = 125 check-ins) |\n\n#### get_user_beer_stats\n\nAggregate a user's distinct beer history into style, brewery, and rating breakdowns — top styles, top breweries, average personal vs global ratings, highest-rated, and most-checked-in.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `username` | string | Yes | Untappd username |\n| `max_pages` | integer | No | Max pages to scan at 50 beers/page (default 10 = 500 beers) |\n\n#### get_user_badge_summary\n\nRetrieve all badges for a user (paginating to completion) with a structured summary.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `username` | string | Yes | Untappd username |\n| `max_pages` | integer | No | Max pages to scan at 50 badges/page (default 10 = 500 badges) |\n\n## Rate Limiting\n\nThe Untappd API allows **100 calls per hour** per API key (per access token when authenticated). Every tool response includes the current rate limit status:\n\n```json\n{\n  \"rateLimit\": {\n    \"limit\": 100,\n    \"remaining\": 97\n  }\n}\n```\n\nComposite tools call `assertRateLimitSufficient` before starting pagination and stop early with `truncated: true` rather than exhausting the budget. If the limit is exceeded, the Untappd API returns a 429 error which is surfaced as: `Rate limit exceeded. Limit: 100, Remaining: 0. Resets hourly.`\n\n## Authentication\n\n| Mode | Env Vars | Unlocks |\n|------|----------|---------|\n| Public | `UNTAPPD_CLIENT_ID` + `UNTAPPD_CLIENT_SECRET` | All public tools |\n| Authenticated | + `UNTAPPD_ACCESS_TOKEN` (+ optional `UNTAPPD_USERNAME`) | `get_friend_feed`, user-scoped rate limits, richer `/user` data |\n\nWhen an access token is configured (env var or saved token file), the server prefers it for **all** calls — rate limits become user-scoped and `/user` endpoints return richer data. `UNTAPPD_USERNAME` provides a default username for authenticated user tools.\n\nThe server exits on startup if neither a client id/secret pair nor an access token is configured.\n\n## Interactive Authentication\n\nYou don't need to obtain an access token manually — the server can run Untappd's OAuth flow for you.\n\n**One-time prerequisite:** in your Untappd app settings at [untappd.com/api](https://untappd.com/api), set the **Callback URL** to exactly:\n\n```\nhttp://localhost:8737/callback\n```\n\n(or the value of `UNTAPPD_REDIRECT_URL` if you override it — it must be a localhost http URL, and the two must match exactly or Untappd rejects the flow).\n\n**In chat:** ask your agent to run the `authenticate_untappd` tool. Your browser opens to Untappd's approve page; once you approve, the token is saved and the 🔑 tools work immediately — no restart needed.\n\n**In a terminal:**\n\n```bash\nnpx untappd-mcp-server auth            # run the interactive flow\nnpx untappd-mcp-server auth --status   # show current auth status\nnpx untappd-mcp-server auth --clear    # delete the saved token\n```\n\n(In the repo: `npm run auth`.)\n\n**Storage & precedence:** the token is saved to `~/.untappd-mcp-server/token.json` (override with `UNTAPPD_TOKEN_PATH`). If `UNTAPPD_ACCESS_TOKEN` is set it always wins over the file. Untappd tokens do not expire.\n\n**Security note:** the token is stored in plaintext with `0600` permissions on macOS/Linux; on Windows protection relies on your user-profile ACLs. Delete it any time with `auth --clear`. Tool outputs only ever include a masked form of the token.\n\n## Development\n\n```bash\nnpm install\nnpm run build\nnpm test          # unit tests (mocked API — no rate limit cost)\nnpm run smoke     # live smoke test against the real API (~25 calls, ~26 with a token)\n```\n\nThe smoke test uses your `UNTAPPD_*` env vars, skips authenticated tools when no access token is set, and aborts if the remaining rate limit drops below 5. Filter to a single tool with `npm run smoke -- --only=tool_name`.\n\n### Testing with MCP Inspector\n\n```bash\nnpx @modelcontextprotocol/inspector node dist/index.js\n```\n\n## Known Limitations\n\n- **No tap list data** — actual tap lists require an Untappd for Business subscription. Venue check-in feeds serve as a real-time proxy.\n- **No venue events** — Untappd's public API has no events endpoint, and the Eventbrite search API that could have bridged the gap was discontinued; deferred to v3.\n- **No venue-history endpoint** — the v4 API has no per-user venue history; `get_user_stats_at_venue` scans the recent check-in feed instead, so its stats cover a window (`max_pages` × 25 check-ins), not all time.\n- **Rate limit: 100/hour** — minimise redundant calls; every response surfaces `rateLimit.remaining`.\n- **Feed limit caps** — tools accept `limit` up to 50, but the API caps some feeds at 25 server-side.\n- **Global feed requires an elevated key** — `/thepub` (`get_global_feed`) is not authorized for standard API keys; the local feed works with any key.\n- **Foursquare lookup requires v2 IDs** — the MD5-hash format; Foursquare v3 numeric IDs will not work.\n- **Venue IDs required** — use `venue_search` first to resolve a venue name to an ID.\n- **Public check-ins only** — private user accounts are not visible.\n- **Read-only** — write operations (check-in, toast, comment, wish-list management) are deferred to v3.\n- **MCP client timeouts** — some MCP clients cap tool-call duration below the `authenticate_untappd` default of 180s; pass a smaller `timeout_seconds` if your client times out first, or use `npx untappd-mcp-server auth` in a terminal instead.\n\n## License\n\nMIT\n",
  "bytes": 18106,
  "sha": "5239596b879275d4ae2a45928f4d74773fb0bd927912d5d4c36d4a4b077933eb",
  "repo_slug": "darrenjrobinson/untappd-mcp-server",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_darrenjrobinson_untappd_9f0679f3/readme"
}