@@ -6,6 +6,104 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
66
77## [ Unreleased]
88
9+ ### Added — ` manage_daemon ` tool and the ` Daemon Control ` category (2026-07-30)
10+
11+ - ** New MCP tool ` manage_daemon ` in a new ` daemon ` category.** Tool counts move
12+ ** 71 → 72** (` read-only ` 12 and ` safe-write ` 54 are unchanged; only ` full `
13+ grows), categories 15 → 16. ` action="status" ` is a read-only diagnostic that
14+ reports daemon liveness/holder/transport/uptime/tunnel plus the live session
15+ state — ` sessionDead ` , the last circuit-breaker trip including Airtable's own
16+ captured response body, and the browser busy queue — which is what lets an AI
17+ agent tell * daemon gone* from * session dead* from * browser busy* . The remaining
18+ actions (` start ` , ` restart ` , ` stop ` , ` tunnel_enable ` , ` tunnel_disable ` ,
19+ ` token_rotate ` ) administer the daemon process itself.
20+ - ** New setting ` airtableFormula.mcp.categories.daemon ` , defaulting to ` false ` .**
21+ For a ` custom ` -profile user that one value is the whole decision, and this tool
22+ can stop or restart the very server the agent is talking through — so it is off
23+ until explicitly enabled. It is included in the ` full ` profile only.
24+
25+ ### Fixed — "Toggle MCP Tool Categories" showed 8 of 16 categories (2026-07-30)
26+
27+ - ** The command-palette category picker had its own hand-written list of 8
28+ categories** , so Record Read/Write/Destructive, View Sections (both), Form
29+ Metadata, Sync and Daemon Control were simply unreachable from it — and a newly
30+ shipped category was invisible until someone noticed. It now enumerates
31+ ` SETTINGS_TO_CATEGORY ` from ` tool-profile.ts ` (the table ` check:tool-sync `
32+ already guards) instead of a second copy, so the picker cannot fall behind the
33+ category list again.
34+
35+ ### Fixed — ` check:tool-sync ` can no longer pass while a tool is uncallable (2026-07-30)
36+
37+ - ** The tool-sync guard now cross-checks ` mcp-server/src/index.js ` against
38+ ` tool-config.js ` in both directions.** ` manage_daemon ` shipped with a definition
39+ and a handler in ` index.js ` but ** no entry in ` TOOL_CATEGORIES ` ** — and because
40+ ` enabledToolNames() ` iterates that map, a tool absent from it is yielded by
41+ nothing and ` isToolEnabled() ` returns ` false ` in * every* profile, ` full `
42+ included. It was registered and permanently uncallable. ` check:tool-sync `
43+ nevertheless printed green, because every check it performed walked
44+ ` tool-config.js ` and its mirrors — comparing the map against copies of itself,
45+ which cannot see a tool that belongs to no category. The guard now also asserts
46+ that every tool defined or handled in ` index.js ` is categorized, and that every
47+ categorized tool has both a definition and a handler. It fails loudly if either
48+ extraction yields zero tools, so a reformat degrades to a failure rather than to
49+ a silent pass.
50+
51+ ### Changed — the shared daemon now starts when an MCP tool call needs it (2026-07-30)
52+
53+ - ** You no longer have to open the dashboard for the daemon to start.** MCP tool
54+ calls now start it themselves. Before this, the extension only * looked* for a
55+ running daemon, so unless you had opened the Airtable dashboard (or run a formula
56+ command) that session quietly fell back to a per-window server — and ** each VS
57+ Code window then drove its own Chromium against the same browser profile** . That
58+ collision is the failure this extension has historically shown you as "session
59+ dead". One shared daemon is the configuration that avoids it.
60+ - ** What you will notice:** one Airtable browser session shared by every window
61+ instead of one per window, fewer spurious "session dead" errors, and the daemon
62+ appearing in the dashboard without you starting it.
63+ - ** Stop still means stop.** A daemon you stop from the dashboard is not
64+ resurrected by the next tool call.
65+ - ** If the daemon cannot start, the extension falls back to the old per-window
66+ server** rather than leaving you with no MCP tools.
67+ - ** Fixed alongside it:** on ` Bring your own cookie ` / ` Direct login ` , a failed or
68+ stopped daemon used to leave the fallback server with no credentials at all —
69+ every tool call failed with a missing-credentials error. The fallback is now
70+ given credentials exactly when it is the one actually serving you.
71+
72+ ### Fixed — login could report success when you were not signed in (issue #21 ) (2026-07-30)
73+
74+ - ** Login declared success as soon as Airtable answered, and showed
75+ ` User: undefined ` even when it had worked.** The endpoint being polled
76+ (` getUserProperties ` ) turns out to carry ** no identity whatsoever** — its
77+ signed-in response is a list of feature flags — so the user id being read had
78+ never existed, and any successful HTTP response counted as "logged in". In
79+ practice the login window could close about two seconds after opening, before an
80+ SSO redirect or a typed 2FA code could finish, and still report success.
81+ - ** Login now waits for Airtable to actually say who you are** , reading the signed-in
82+ user from the page itself, and every login path (dashboard login, CLI login,
83+ manual login) waits the same ** 5 minutes** — enough for SSO plus a hand-typed 2FA
84+ code. Previously these paths disagreed, one waiting 1 minute and the others 5.
85+ - ** The dashboard shows your user id only when it genuinely knows it** , and never
86+ carries one over from a previous session. In ` Bring your own cookie ` mode, where
87+ there is no page to read it from, it says so instead of showing a stale or made-up
88+ id. A missing user id is no longer treated as "signed out" — it is not evidence of
89+ anything, and treating it as such would have logged out working sessions.
90+ - ** ` Direct login ` now fails loudly with ` DIRECT_LOGIN_UNVERIFIED ` ** when the login
91+ flow finishes and a session cookie exists but Airtable still serves no signed-in
92+ user — the same false success as above, on the browser-free path. It usually means
93+ an incomplete SSO or 2FA step: check your email/password/TOTP secret, or switch
94+ Auth Mode back to ` browser ` .
95+ - ** Session health checks retry before declaring a session expired.** The signed-in
96+ marker arrives with the page, so a single slow render used to read as "signed out"
97+ — and the extension answers that by relaunching the browser, so a false alarm cost
98+ a full browser launch. Login is also no longer killed at 2 minutes while it is
99+ still legitimately waiting for you to finish signing in.
100+ - ** CLI ` doctor ` and ` status ` now tell you different, true things.** ` doctor `
101+ actually probes the session (` Session: signed in as usr… ` / `NOT signed in —
102+ <reason >`) and reuses the running daemon's browser rather than opening a second one
103+ against the same profile. ` status ` reports only what is on disk and no longer
104+ claims anything about your session — it used to print ` Session: not found ` on
105+ perfectly healthy installs by looking for a file nothing writes any more.
106+
9107### Pre-merge hardening pass — tool profiles, sync safety, packaging, transport, proxies, session recovery, logout (2026-07-25)
10108
11109Pre-merge hardening pass on ` feat/base-to-base-sync ` before merging base-to-base
0 commit comments