Untappd MCP
Provides tools for searching beers, retrieving beer details, accessing user profile, wishlist, and beer history, and performing check-ins with ratings and messages via the Untappd API.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Untappd MCPShow me my recent Untappd check-ins"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Untappd MCP
A multi-user Model Context Protocol server for Untappd. It keeps Untappd credentials on the server and exposes a small, explicit tool surface for beer search, profiles and beer history (your own and other users'), wishlists, "has this user had that beer?" lookups, and check-ins.
Current capabilities
Streamable HTTP endpoint:
POST /mcpOAuth 2.1 authorization-code flow with mandatory PKCE S256; Claude and ChatGPT both connect through it
OAuth protected-resource and authorization-server metadata
Client ID Metadata Document (CIMD) support, Dynamic Client Registration, and a pre-registered public Claude client
Short-lived, audience-bound opaque access tokens and rotating refresh tokens
Firebase Auth Google sign-in and a secure server-side browser session
Revocable, time-limited personal access tokens as a header-auth alternative to the OAuth flow
search_beers(via Untappd's public search index — no shared-quota cost) andget_beerget_my_profile,get_my_wishlist,get_my_beers,get_my_recent_venues, andget_my_friend_feedget_user_profile,get_user_beers,get_user_checkins, andget_user_friendsfor any Untappd usernamecheck_i_had_beer— "have I checked in this beer?" for the connected account, in one API callcheck_user_had_beer— "has USERNAME ever checked in this beer?", with their rating and first/last datesget_untappd_api_usage— the shared Untappd hourly rate-limit budget and how much is leftcheck_in, with 0–5 quarter-step (0.25) ratings, an optional venue (foursquareId+ coordinates fromget_my_recent_venues), and message validationtoast_checkin— toggle a toast on someone's check-incomment_checkin— post a comment to a check-inUntappd authorization-code connect flow:
GET /connect/untappdAES-256-GCM encryption at rest for credentials in Firestore collection
untappd_credentialsFirebase ID-token verification on every authenticated server request
The server never returns an Untappd access token to an MCP client.
Related MCP server: colacloud-mcp
Identity and authorization
There are three separate credentials. They must never be substituted for one another:
Firebase browser sign-in ──> MCP OAuth server ── MCP access token ──> /mcp
└─ encrypted Untappd access token ──> Untappd APIFirebase Auth identifies the person in the browser and creates a secure HTTP-only session. The MCP authorization server then issues its own access token whose owner is that Firebase uid, whose audience is exactly this server’s /mcp URL, and whose scopes are untappd:read and untappd:write.
As a header-auth alternative to the OAuth flow, the server also issues personal access tokens. They are created only from an authenticated Firebase browser session, are shown once, stored only as SHA-256 hashes, bound to the Firebase uid, expire automatically, and can be revoked at any time. They use the same bearer-token MCP transport.
Endpoint | Purpose |
| Streamable HTTP MCP; accepts MCP OAuth bearer tokens and personal access tokens. |
| Unauthenticated liveness endpoint. |
| Protected-resource metadata. The |
| OAuth authorization-server metadata. The |
| Dynamic Client Registration, for MCP clients that do not support CIMD. |
| Authorization request, Firebase browser sign-in, then consent. |
| Authorization-code and refresh-token grants. |
| Firebase-authenticated personal access-token management page. |
| Creates a personal access token and shows it once. |
| Revokes one of the signed-in user’s personal access tokens. |
| Starts the separate Untappd authorization flow for the signed-in Firebase user. |
The server keeps only hashes of MCP access, authorization-code, and refresh tokens in Firestore. Refresh tokens rotate; a reused refresh token revokes its whole token family. Untappd access tokens use AES-256-GCM encryption before storage.
Legacy degustation-app migration
When a user opens /tokens, the server first checks for an existing encrypted credential. If none exists, it imports users/{uid}.untappdAccessToken from the old degustation app. When Firebase UID differs, it falls back only to one exact match of the user’s verified Firebase email. The token is validated with Untappd before being encrypted into untappd_credentials/{uid}. Legacy Firestore documents are read-only during this migration and their plaintext token is not deleted.
Untappd connection flow
The user opens
/connect/untappdand signs in with Firebase if no browser session exists.The server creates a signed, ten-minute Untappd OAuth
statebound to that Firebaseuid, then redirects the user to Untappd.Untappd redirects to
/connect/untappd/callback.The server exchanges the code, fetches the profile, and stores the encrypted token under
untappd_credentials/{firebaseUid}.
Connecting a client
Claude and ChatGPT both connect to https://YOUR_CLOUD_RUN_OR_CUSTOM_DOMAIN/mcp over OAuth:
Add a custom connector pointing at
.../mcpand choose OAuth. Both clients discover this server's client metadata automatically (CIMD); Dynamic Client Registration also works.On first use the client opens this server's authorization page. Sign in with the Google account whose Untappd data the client should use, then approve the
untappd:read/untappd:writescopes.
That Google account must already have Untappd connected — if not, open https://YOUR_CLOUD_RUN_OR_CUSTOM_DOMAIN/connect/untappd first and connect it.
Personal access token (alternative)
For header-only auth, or a client that cannot run the OAuth flow:
Open
https://YOUR_CLOUD_RUN_OR_CUSTOM_DOMAIN/tokensand sign in with the Google account whose Untappd data you want to use.Select Create token for Claude, then copy the displayed header value — shown once only.
In the connector settings use
.../mcp, set Authentication: None, and add this request header:
Authorization: Bearer pat_…Use the Revoke button on /tokens immediately if the token is exposed. A token carries the same read/write Untappd scope as an OAuth connection, so the client must still confirm before check-ins.
Local development
Prerequisites: Node.js 22+, Firebase Application Default Credentials, a Firebase project with Google sign-in enabled, and a registered Untappd application.
cp .env.example .env
npm ci
npm test
npm run build
npm startConfigure the values in .env; never commit it. Generate the encryption key with:
openssl rand -base64 32For local callback testing, register the exact UNTAPPD_REDIRECT_URI with Untappd. Untappd requires HTTPS for API calls, and it expects a non-standard User-Agent for every request.
Deployment
The included Dockerfile is suitable for Cloud Run. Configure these values through Secret Manager:
UNTAPPD_CLIENT_SECRETUNTAPPD_TOKEN_ENCRYPTION_KEYCONNECT_STATE_SECRET
Grant the Cloud Run service account Firestore access for untappd_credentials, Secret Manager access for the three runtime secrets, and only firebaseauth.users.createSession plus firebaseauth.users.get for secure Firebase session handling. Keep Firebase service-account credentials and Untappd credentials out of the image and repository.
Set these non-secret runtime variables:
PUBLIC_BASE_URL=https://YOUR_CLOUD_RUN_OR_CUSTOM_DOMAIN
FIREBASE_PROJECT_ID=beer-degustation
FIREBASE_WEB_API_KEY=...
FIREBASE_AUTH_DOMAIN=beer-degustation.firebaseapp.com
FIREBASE_WEB_APP_ID=...
UNTAPPD_CLIENT_ID=...
UNTAPPD_REDIRECT_URI=https://YOUR_CLOUD_RUN_OR_CUSTOM_DOMAIN/connect/untappd/callback
UNTAPPD_USER_AGENT=untappd-mcp/0.1 (support@example.com)
MCP_ALLOWED_ORIGINS=https://claude.ai,https://chatgpt.com
MCP_PERSONAL_ACCESS_TOKEN_TTL_SECONDS=15552000
# Optional: override Untappd's public Algolia search keys only if they rotate.
# Set both or neither; low-sensitivity, plain env is fine.
UNTAPPD_ALGOLIA_APP_ID=
UNTAPPD_ALGOLIA_SEARCH_KEY=PUBLIC_BASE_URL and UNTAPPD_REDIRECT_URI must use the exact final HTTPS origin. Add that hostname to Firebase Console → Authentication → Settings → Authorized domains before using the OAuth browser login. The browser config fields are Firebase public configuration, not credentials.
Create Firestore TTL policies for expiresAt in these collection groups: mcp_oauth_transactions, mcp_oauth_authorization_codes, mcp_oauth_access_tokens, mcp_oauth_refresh_tokens, and mcp_personal_access_tokens. TTL reduces retained metadata; server-side expiry checks remain mandatory.
Untappd API rate limit
Untappd rate-limits authenticated calls per access token — 100 per rolling hour (unauthenticated client-credential calls share a separate pool). To stay within it:
search_beersruns against Untappd's public Algolia beer index and does not spend the quota. It falls back to the Untappdsearch/beerAPI (which does) only when Algolia returns an error; every fallback logs"message":"algolia_search_fallback".Every real Untappd API response is recorded from its
X-RateLimit-*headers, keyed by the access token that made the call, and emitted as a structured"message":"untappd_api_call"log line (tokenPool,rateLimitRemaining, per-instance counters).get_untappd_api_usagereturnslastSeen— theX-RateLimit-Remainingfor the connected account's own token (null until this server process has called Untappd with it) — plusinstance.*counters that cover every account served by this process. Makes no API call.check_i_had_beer, andcheck_user_had_beerwhen the target is another connected user, answer in a singlebeer/infocall. Otherwisecheck_user_had_beerpages the target's distinct beers (up tomaxRequests× 50) and aborts early withstoppedForRateLimit: trueonce the scanning token's remaining budget drops to ~10.
The single-call path for check_user_had_beer uses the target user's own Untappd token, so a connected user can see another connected user's had-status for a specific beer even if that user's Untappd profile is private and they are not friends. It is limited to accounts connected to this server.
Cloud Run runs several instances, each keeping its own in-memory rate-limit state, so lastSeen is only populated on instances that have recently made a call with that token.
Security notes
Close Firestore Rules before deployment. Cloud Run uses the Admin SDK, so it continues to work after browser access is denied. With open rules, an attacker could forge an OAuth token record.
Untappd tokens are encrypted before reaching Firestore, but rotate the encryption key with a planned re-encryption migration.
The OAuth callback uses a signed and expiring
statevalue to prevent CSRF.OAuth authorization codes are one-time, expire after one minute, and require PKCE S256. Redirect URIs are exact-match registered values.
MCP access tokens are short-lived and audience-bound to this server. Untappd tokens are never accepted at
/mcp.Personal access tokens are displayed only once, stored as hashes, expire after 180 days by default, and can be revoked from
/tokens.check_in,toast_checkin, andcomment_checkinare intentionally marked non-idempotent (toast_checkintoggles). The calling model must get user confirmation before invoking them.untappd:writeis required forcheck_in,toast_checkin, andcomment_checkin; all other current tools (includingget_untappd_api_usage) requireuntappd:read.
This server cannot be deployed
Maintenance
Related MCP Connectors
Yelp business search, place details and the full review feed, as structured JSON.
Search books, authors and series, get recommendations, and manage your own reading shelves.
- OutstandOAuthso.outstand
Publish and schedule social media posts and read analytics across 12 networks through one API.
Search books and authors, fetch editions, browse subjects, and resolve cover images.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides access to the Open Brewery DB API, allowing AI assistants to search for breweries and retrieve detailed information like location, type, and contact details. It enables interactive exploration of a global database containing over 40,000 breweries.6 npm1MIT
- AlicenseAqualityNot gradedmaintenanceProvides access to over 2.5 million US alcohol label records from the TTB via the COLA Cloud API. It enables users to search for labels by brand, barcode, or permit holder and retrieve detailed product information including label images and ABV.6MIT
- AlicenseAqualityAmaintenanceAn MCP server that interfaces with Untappd's mobile API to search beers, breweries, venues, and user data, and to post check-ins, toasts, and comments using your own account.45669 npmMIT
- AlicenseNot gradedqualityAmaintenanceMCP server for Untappd connectivity, enabling beer search with optional limit, offset, and sorting.MIT