untappd-mcp 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "MCP server for Untappd — beers, breweries, venues, check-ins, wishlists, and your friend feed",
10
- "version": "1.3.0"
10
+ "version": "1.4.0"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "Untappd",
16
16
  "source": "./",
17
17
  "description": "MCP server for Untappd — search beers/breweries/venues, read profiles/check-ins/wishlists, and post check-ins, toasts, and comments",
18
- "version": "1.3.0",
18
+ "version": "1.4.0",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "untappd-mcp",
3
3
  "displayName": "Untappd",
4
- "version": "1.3.0",
4
+ "version": "1.4.0",
5
5
  "description": "MCP server for Untappd — search beers/breweries/venues, read check-ins and wishlists, and post check-ins, toasts, and comments",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/README.md CHANGED
@@ -33,6 +33,7 @@ it goes stale.
33
33
  | `UNTAPPD_DEVICE_ID` | no | Stable device UUID the token is keyed to (a default is provided). |
34
34
  | `UNTAPPD_UTV` | no | API version param (default `4.0.0`). |
35
35
  | `UNTAPPD_USER_AGENT` | no | Override the User-Agent (default mimics the app). |
36
+ | `UNTAPPD_CACHE_DB` | no | Path to the local check-in cache SQLite file (default `~/.untappd-mcp/checkins.db`). Local/stdio only. |
36
37
 
37
38
  Copy `.env.example` to `.env` and fill it in for local use.
38
39
 
@@ -81,6 +82,59 @@ Writes (confirm-gated — return a dry-run preview unless called with
81
82
  `untappd_wishlist_add`, `untappd_wishlist_remove`, `untappd_delete_checkin`,
82
83
  `untappd_add_friend`, `untappd_accept_friend`, `untappd_reject_friend`, `untappd_remove_friend`.
83
84
 
85
+ Check-in cache: `untappd_sync_checkins`, `untappd_cache_has_had`,
86
+ `untappd_cache_has_had_many`, `untappd_cache_query`.
87
+
88
+ ## Check-in cache
89
+
90
+ The Untappd API only exposes paged, most-recent-first check-in lists (50 per
91
+ page) and has **no** "has this user ever had beer X?" lookup — answering that
92
+ from the API alone means paging an entire history (often 11k+ check-ins) against
93
+ a tight ~100-calls/hour rate limit. These tools maintain a SQLite mirror of a
94
+ user's check-ins so the question is answered instantly, offline, with zero API
95
+ calls. The mirror is a local file on the stdio/desktop server (`node:sqlite`,
96
+ path via `UNTAPPD_CACHE_DB`) and a per-user Durable Object on the remote
97
+ connector — the tools and behaviour are identical either way.
98
+
99
+ **Recommended workflow — sync first, then query:**
100
+
101
+ 1. **Sync** with `untappd_sync_checkins` (omit `username` for your own account).
102
+ It is incremental (stops as soon as it reaches already-cached check-ins) and
103
+ resumable: while the initial backfill is incomplete it pages backwards up to
104
+ `max_pages` per call (default 10) and **persists progress after every page**,
105
+ so an interrupted run never loses data. The summary reports `rows_added`,
106
+ `pages_fetched`, a `backfill_percent` estimate, and `another_run_needed` — if
107
+ that is `true`, just call it again (and again) until it is `false`. That
108
+ covers both extending the backfill downwards and catching up a burst of new
109
+ check-ins too large for one run (`catchup_in_progress`). Spreading the work
110
+ across several runs keeps you under the rate limit.
111
+ 2. **Query** the cache with no further API calls:
112
+ - `untappd_cache_has_had` — has the user had a beer, by exact `bid` or a
113
+ case-insensitive `beer_name` substring; returns count, best rating, last
114
+ date, and the matching check-ins.
115
+ - `untappd_cache_has_had_many` — cross-check a whole list of `bids` in one
116
+ call (e.g. a venue's menu) → had/not-had per beer.
117
+ - `untappd_cache_query` — filter cached check-ins by brewery, style,
118
+ `min_rating`, venue, and/or date range, with sorting and a limit.
119
+
120
+ Every read result carries a `freshness` block (`last_synced_at`,
121
+ `backfill_complete`, `backfill_percent`) and, when the backfill is
122
+ incomplete, a `caveat` — so a "not found" can be reported as possibly a false
123
+ negative for older history until the sync finishes.
124
+
125
+ Syncing **another** user goes through the same authed endpoint as
126
+ `untappd_user_checkins`, so Untappd's privacy rules apply: it only works if that
127
+ account is public or your friend. Otherwise the sync returns a clear error
128
+ telling you to add them as a friend first.
129
+
130
+ On the remote connector each logged-in user gets their **own** durable cache
131
+ (keyed by their account), holding only the check-ins their account was allowed
132
+ to fetch — one user can never read another's cache. See
133
+ [`docs/DEPLOY-CONNECTOR.md`](docs/DEPLOY-CONNECTOR.md) for the one-time deploy
134
+ step this adds. `untappd_healthcheck` reports the running version and the exact
135
+ tool set (count + names + a stable hash), so you can confirm which build a
136
+ connector is serving.
137
+
84
138
  ## Development
85
139
 
86
140
  ```sh
package/SKILL.md CHANGED
@@ -45,3 +45,32 @@ Each returns a dry-run preview and makes NO network call unless called with
45
45
  `untappd_search_beer`; optional `rating` 0–5 in 0.25 steps, `shout`, venue).
46
46
 
47
47
  Photo attachment and wishlist add/remove are not yet supported.
48
+
49
+ ## Check-in cache
50
+
51
+ The API can't answer "has this user ever had beer X?" without paging their whole
52
+ history (50/page, rate-limited). These tools keep a SQLite mirror so that
53
+ question is answered instantly with **no** API calls. On the stdio server the
54
+ mirror is a local file (`UNTAPPD_CACHE_DB`, default `~/.untappd-mcp/checkins.db`);
55
+ on the remote connector it's a per-user Durable Object. Same tools either way.
56
+
57
+ **Sync first, then query:**
58
+
59
+ - `untappd_sync_checkins` — fetch check-ins into the cache. Incremental (stops at
60
+ already-cached check-ins) and resumable: while the backfill is incomplete it
61
+ pages backwards up to `max_pages` per call (default 10) and saves progress
62
+ after every page. If the returned `another_run_needed` is true, call it again
63
+ until it is false (covers both the backfill and catching up large bursts of
64
+ new check-ins). Omit `username` for your own account;
65
+ syncing another user needs their account public or a friend (friends-only, same
66
+ as `untappd_user_checkins`).
67
+ - `untappd_cache_has_had` — has the user had a beer? By exact `bid` or a
68
+ case-insensitive `beer_name` substring.
69
+ - `untappd_cache_has_had_many` — batch had/not-had for a list of `bids` in one
70
+ call (venue-menu cross-check).
71
+ - `untappd_cache_query` — filter cached check-ins by brewery, style, `min_rating`,
72
+ venue, and date range, with sort + limit.
73
+
74
+ Every cache read returns a `freshness` block (and a `caveat` when the backfill is
75
+ incomplete) so you can flag that a "not found" may be a false negative until the
76
+ sync finishes.