Add AT Protocol (lexicon/XRPC) support and one-command install#8
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a new atproto protocol adapter (AT Protocol / lexicon / XRPC) so search/execute can interact with AT Protocol services (e.g. Bluesky) via a typed XRPC client, and streamlines setup by expanding anyapi-mcp install plus making the website/installer emphasize “one-command” onboarding.
Changes:
- Introduces
kind: "atproto": builds an operation index and a typed NSID→types map from@atproto/apilexicons; adds parent-side session mint/refresh via app passwords. - Extends CLI/MCP server flows (
add,add_api,list,login,logout,serve) to support atproto registration, status reporting, and session handling. - Expands installation automation to also register with OpenCode; updates docs/site messaging accordingly.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/registry.ts | Adds AtprotoAuth and extends ApiKind/Auth unions to include atproto. |
| src/register.ts | Adds atproto registration logic, keystore key management, and unregister secret cleanup. |
| src/commands/serve.ts | Extends MCP server tool descriptions, add_api schema/flow, execute auth handling, and list_apis auth status for atproto. |
| src/commands/logout.ts | Adds atproto session/app-password logout behavior (reusing --forget-client). |
| src/commands/login.ts | Adds atproto app-password login path alongside existing OAuth browser login. |
| src/commands/list.ts | Reports atproto auth status in CLI list. |
| src/commands/install.ts | Adds OpenCode config merge/install support; expands --client options. |
| src/commands/add.ts | Adds atproto flags (--identifier, --app-password) and validation; passes through new register options. |
| src/atproto.ts | New atproto adapter: builds ops index + generates NSID→official type map; provides XRPC execute harness. |
| src/atproto-auth.ts | New parent-side atproto auth module: app-password storage + session mint/refresh/self-heal. |
| src/atproto_test.ts | New tests covering lexicon indexing and method-map generation behavior. |
| src/adapters.ts | Registers the new atprotoAdapter. |
| site/install.sh | Installer now runs anyapi-mcp install by default (best-effort) with opt-out env var. |
| site/index.html | Landing page copy updated to emphasize multi-API support and one-server messaging (incl. atproto). |
| README.md | Documents atproto adapter usage and updated install flow including OpenCode registration. |
| deno.lock | Adds pinned npm:@atproto/api@0.20.9 and transitive dependencies. |
| CLAUDE.md | Updates repo architecture/docs to include atproto adapter/auth and OpenCode install behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+246
to
+255
| if (kind === "atproto") { | ||
| const passwordKey = `anyapi-mcp:${id}:apppass`; | ||
| const sessionKey = `anyapi-mcp:${id}:session`; | ||
| if (opts.appPassword) await setSecret(passwordKey, opts.appPassword); | ||
| auth = { | ||
| kind: "atproto", | ||
| identifier: opts.identifier ?? "", | ||
| passwordKey, | ||
| sessionKey, | ||
| }; |
| } from "../oauth.ts"; | ||
| import { loginWithAppPassword } from "../atproto-auth.ts"; | ||
|
|
||
| const HELP = `anyapi-mcp login - authenticate an OAuth 2.0 API in the browser |
Comment on lines
+9
to
12
| # ANYAPI_MCP_REF git ref (branch or tag) to install (default: main) | ||
| # ANYAPI_MCP_BIN_DIR directory to install the binary into (default: ~/.local/bin) | ||
| # ANYAPI_MCP_NO_INSTALL set to any value to skip registering with Claude clients | ||
| set -eu |
Comment on lines
+295
to
+301
| const headers: Record<string, string> = {}; | ||
| if (token) headers["authorization"] = \`Bearer \${token}\`; | ||
| let body: string | undefined; | ||
| if (method === "POST" && input !== undefined) { | ||
| headers["content-type"] = "application/json"; | ||
| body = JSON.stringify(input); | ||
| } |
Add an `atproto` adapter kind: search/execute against any AT Protocol service
(e.g. Bluesky) via a thin, typed XRPC client. Types are reused from @atproto/api
with a type-only import, so none of the SDK runs in the execute sandbox;
writeTypes emits only an NSID -> {params,input,output} map, letting
client.query/procedure infer from the NSID string literal. The operation index
is built from the package's runtime `schemas`, and NSID -> namespace names come
from its `ids` export (never derived) so a type reference can't drift and break
the whole-program check.
Auth runs in the parent like OAuth: app-password sessions
(createSession/refreshSession), injecting only a short-lived access JWT into the
sandbox. Registering without an identifier is anonymous (public reads, no
token); with one, the parent mints/refreshes a session and guides to `login`
when needed.
install.sh now runs `anyapi-mcp install` after building (best-effort; opt out
with ANYAPI_MCP_NO_INSTALL), and `install` also registers with OpenCode by
merging an `mcp` entry into its config (its `mcp add` is interactive-only).
Docs and the landing page updated throughout.
a4f2abd to
2f3de1a
Compare
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.
Summary
Adds an
atprotoadapter kind (AT Protocol / lexicon / XRPC — e.g. Bluesky) and streamlines install so one command sets everything up.atproto kind
kind: "atproto":search/executeagainst any AT Protocol service via a thin, typed XRPC client (client.query(nsid, params)/client.procedure(nsid, input)).import * as Lex from "npm:@atproto/api@…", so nothing from the SDK runs in the sandbox.writeTypesemits only anXrpcMethodsmap (NSID →{type, params, input, output}) pointing at the per-method namespaces, so calls infer params + result from the NSID string literal.schemas; NSID → namespace names come from itsidsexport (never derived), so aLex.*reference can't drift and break the whole-program type-checkexecuteruns.OutputSchemais referenced only when the lexicon declares one (elseunknown).Auth (parent-side, like OAuth)
com.atproto.server.createSession/refreshSessionrun in the parent; only the short-lived access JWT reaches the sandbox (never the app password or refresh JWT). Self-heals from the stored app password — no browser.identifieris the intent signal: none → anonymous (public reads, no token — replaces pointing an OpenAPI entry at the public AppView); set → authenticated, minting/refreshing a session and guiding toanyapi-mcp loginwhen needed.anyapi-mcp login, oradd --app-password); no MCP tool accepts secrets. NewAuthvariantatproto; keystore accounts…:apppass/…:session.Install
install.shnow runsanyapi-mcp installafter building (best-effort underset -e; opt out withANYAPI_MCP_NO_INSTALL).anyapi-mcp installadds OpenCode alongside Claude Code/Desktop, by merging anmcpentry into~/.config/opencode/opencode.json(itsopencode mcp addis an interactive wizard with no flags). Same safe read-modify-write as the Claude Desktop path: preserves other servers/keys, refuses to clobber an unparseable.jsonc.Docs & site
Testing
deno task check/lint/fmtclean;deno test16 passing (incl. newsrc/atproto_test.tscovering index/map generation).@atproto/apitypes; an anonymous public read (app.bsky.actor.getProfileviapublic.api.bsky.app) runs through the sandbox.