Repository navigation
Batch 2026-10-08: 19 PRs combined - #2153
Merged
Merged
Conversation
`@tomic/mcp` (browser/mcp) is a stdio MCP server for Claude Code, Claude Desktop, Cursor and other clients. It runs locally and signs every edit with the user's own Agent key, so writes are ordinary signed commits. Tools: list_drives, get_resource (documents and meetings include their text), search, semantic_search, query, get_user_classes, get_schema, create_resource, edit_resource and delete_resource (never a whole drive). The data verbs behind those tools now live in @tomic/lib (assistant-tools.ts), and the in-app assistant calls the same functions, so there is one implementation behind both surfaces. The compact JSON-AD dialect, short subject refs and class helpers move from the data-browser to @tomic/lib for the same reason. Reads no longer include the genesis certificate, which is long and tells a model nothing. This is steps 1 and 2 of planning/mcp-endpoint.md; a hosted endpoint with OAuth (for claude.ai connectors) is not part of this change.
atomic-mcp now makes a key on the machine it runs on and prints a link. In the app (/app/connect-agent) the person picks which drives it may reach and whether it may edit, then clicks Allow. Account settings lists connected apps with a Revoke button. Only an agent may edit its own Agent resource, so the grant is not recorded there: the ACLs on the shared drives are the record. The app adds the key to read (and write), the MCP finds its access by searching for resources that list it, and revoking removes it everywhere, including from what it created. The app remembers which apps were connected on the private drive, so settings can list them. ATOMIC_AGENT_SECRET still works for scripts and CI.
Any app that makes its own key (a CLI, a script, the MCP server) can now ask for access the same way: connectAgentUrl builds the approval link, optionally asking for edit rights or specific resources, waitForGrant polls until the person clicks Allow, and publishAgentName sets the name shown under Connected apps. The approval page honours the write and target hints as preselections; the person still decides. The MCP server now uses these instead of its own copies.
atomic-cli connect makes a key on this machine, prints the approval link (/app/connect-agent), waits for Allow and writes the config. Without a config the CLI now points there instead of asking for the secret. ad-generate connect does the same for the codegen CLI, so private ontologies no longer need an agent secret in atomic.config.json, which often ends up in a repository. The key file helper moves from the MCP server into @tomic/lib/node (loadOrCreateLocalAgent), shared by both. Also adds the new screens' strings to the translation catalogs.
POST /mcp (Streamable HTTP) for clients that cannot run a local process. The node is the OAuth 2.1 authorization server (dynamic client registration, PKCE S256, RFC 9728 and 8414 metadata) with stateless signed tokens derived from the node key. The person approves in the app at /app/authorize-mcp, which gives a fresh issued agent read rights on the drives they pick, so revoking is removing it under Connected apps. The node never signs as the person. Tools: list_drives, get_resource (with document text) and search.
…writes signed as the issued agent The hosted /mcp endpoint now has every tool, including create, edit and delete when the person allowed editing; the node signs those commits as the issued agent behind the token and sends them through the normal commit pipeline. The local atomic-mcp is a stdio bridge to it with a token from an OAuth connect. The consent page only accepts the node the person is signed in to, and only redirects to exactly the registered redirect URI.
The consent page needs the identity the desktop app holds, which a browser on the same machine does not. connect --desktop opens atomic://authorize-mcp, the app routes it to the consent page, and after Allow it tells the loopback listener and stays in the app instead of navigating away.
…imports its bridge
…d rebuild old indexes in resumable slices
…en if the PR list is unreadable Before: the dispatch token cannot list atomic-saas pull requests (403), so the open-PR check always failed and Downstream paired with any same-named saas branch, including a stale one left after its PR merged. Its old Cargo.lock then failed cargo --locked and turned the Main check red for a change that had nothing to do with it (#2114). After: when the PR list is unreadable, the commit's own PR list is asked next, which a token that can read the branch may also read. Only when both fail does the step pair with the namesake, as before, with the same warning.
When the app shows the account's sign-in card it now carries 'Sign in with secret' like the portal's, instead of a separate field below it. The separate field stays for builds without an account to sign in to.
A freshly installed PWA has empty storage, so a drive opens with no name and no profile. Show 'Drive' instead of the raw atomic:/did: id, 'Signed in' instead of 'User' once the profile has loaded empty, a plain message instead of the ClientDb leader timeout in the vault restore offer, and fail point reads against a silent leader after 10s instead of 30s.
…ions A leader tab whose worker died without an error event kept answering leader-ping, so its own reads and every follower's waited out the timeout. Point reads now give up after 10s in the leader too. Format AccountMenu and add the two new strings to the catalogs.
…ew message Panel headers, the user row and the bottom nav buttons share one calmer sizing. Long-press or right-click on a panel header offers to hide it, and every panel can be toggled in settings. The new message dialog lists people from the current drive and narrows them as you type.
The plain ring spinner and the bare "Loading..." text give way to the boot splash's orbiting mark, centered when it fills a page. Long-press now opens the panel menu on release so the click that follows does not close it.
server/src/forms.rs include_str!s browser/form-renderer/shared/validation-cases.json, which the Dagger Rust containers did not mount, so the lib and bin test builds failed to compile.
This was referenced Oct 8, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Before: nineteen open PRs each waited for their own Mancave run, and most of those runs ended in runner losses or load flakes.
After: one tested commit with #2123 (pair Downstream with a saas namesake only when a PR of it is open), #2127 (readable names and errors on a drive that isn't on this device), #2133 (Sentry context), #2134 (simpler form answer validation), #2135 (parallel hosted search and loading states), #2136 (faster /search on large drives), #2138 (@mention of resources in chat), #2140 (self-hosting behind a reverse proxy, owner-mode drive refusals), #2141 (usage limit on invite links), #2142 (no misleading failed toast when the node refuses a drive), #2143 (Sync page: plan facts up top, one card per device), #2147 (Last day focus and mention replacing), #2149 (fewer success toasts), #2132 (sidebar balance and panel toggles), #2121 (0 for an empty dashboard Count), #2117 (shorter atom index keys), #2129 (local identity sign-in free of optional account errors), #2146 (share an Atomic drive skill) and #1870 (MCP server).
Left out: #2125 (agent secret in account sign-in; its own tests fail, 11 in GettingStartedFlow), #2130 (vault recovery and inbox sync; its own useInbox test fails), #2120 (first upload of a cached drive; real conflict in the sync probe logic), #2128 (pairs with atomic-saas 202), #2148, #2150 and #2151 (still in design or CI), and the plugin-host stack waiting on Joep's answers.
How: merged into develop, changelog and catalog conflicts kept on both sides, catalogs re-extracted with wuchale, lint,
tsc,cargo fmtand the lib and data-browser unit tests are clean locally. The e2e change of #2149 intest-utils.tsis not carried over, because the batch already has the Share dialog flow there.Generated by Claude Code