# Sixteen Bridges
> Sixteen Bridges keeps a person's bubbles: saved notes and AI chat context in Markdown (up to 512 KB each, 20 on the free plan), so context can move between AI apps.
## Which way to connect
- **You can run shell commands** (Claude Code, Codex, Gemini CLI, Cursor's agent, Aider, a cloud sandbox): use the CLI, and sign in yourself. See "The CLI".
- **You are a desktop app that starts local MCP servers** (Claude Desktop, Cursor, VS Code, Windsurf): run the CLI as a local MCP server. See "Desktop apps".
- **You are writing code for the person** (a script, a bot, an app): use the REST API. See "The REST API".
- **You are a chat app** (ChatGPT, claude.ai, Gemini on gemini.google.com or in its phone app, Grok, Perplexity), even if you can run code in the chat: you can't connect by yourself. Tell the person the steps for adding it (a connector; in Gemini, a custom app). See "Chat apps".
## The CLI
### Sign in: do it yourself, the person only clicks Allow
1. Run `npx -y sixteenbridges whoami`. Exit code 0: already signed in, go on. Exit code 3: sign in.
2. Run `npx -y sixteenbridges login`. It opens the person's browser on sixteenbridges.com by itself. Tell them: "A Sixteen Bridges page just opened in your browser: click Allow." The command waits up to 5 minutes and prints "Signed in as …". Give it that long: don't stop it at a 2-minute timeout.
3. If it printed "Open this link" instead (no browser opened), open the link yourself: `open ""` on macOS, `xdg-open ""` on Linux, `start "" ""` on Windows. If you can't, show the link to the person.
4. If you can't keep a command running that long (a cloud sandbox, a remote machine, short timeouts), sign in in two steps:
- `npx -y sixteenbridges login --no-wait` prints the link (alone, on stdout) and exits.
- Give the person the link. They sign in and click Allow; sixteenbridges.com then shows a code.
- Ask them for the code, then run `npx -y sixteenbridges login --code ""` (within 15 minutes).
Never ask for their password, and never read or print the CLI's credentials file.
### Use it
```sh
npx -y sixteenbridges list # ids, titles, sources, one-line previews, usage
npx -y sixteenbridges search lisbon
npx -y sixteenbridges get # long bubbles come in pages; --raw for the exact text
npx -y sixteenbridges save "Title" notes.md --source claude --label "Claude Code"
cat notes.md | npx -y sixteenbridges save "Title" --source claude
npx -y sixteenbridges update --append "More text"
npx -y sixteenbridges delete # to the trash for 7 days
npx -y sixteenbridges trash # what's in the trash
npx -y sixteenbridges restore
npx -y sixteenbridges share --to sam@example.com # copies, into their account
npx -y sixteenbridges shares # what was sent and received
```
Every command takes --json (and --help). Exit codes: 0 done, 1 refused (the message says why and what to do), 2 wrong usage, 3 not signed in (sign in as above), 4 unavailable (try again in a minute).
## Desktop apps
These start the CLI as a local MCP server (`npx -y sixteenbridges mcp`), on the computer's own sign-in: no connector, no paid plan. Sign the computer in once first (`npx sixteenbridges login`).
### Claude Desktop
In Settings → Developer → Edit Config (claude_desktop_config.json):
```json
{
"mcpServers": {
"sixteen-bridges": {
"command": "npx",
"args": [
"-y",
"sixteenbridges",
"mcp"
]
}
}
}
```
1. First, sign this computer in once: npx sixteenbridges login
2. Add this to the config file, save, and restart Claude Desktop.
Note: On Windows, if it doesn't start, use "command": "cmd" with "args": ["/c", "npx", "-y", "sixteenbridges", "mcp"].
### Cursor
In ~/.cursor/mcp.json:
```json
{
"mcpServers": {
"sixteen-bridges": {
"command": "npx",
"args": [
"-y",
"sixteenbridges",
"mcp"
]
}
}
}
```
1. First, sign this computer in once: npx sixteenbridges login
2. Add this to ~/.cursor/mcp.json (or Settings → MCP → Add), then reload.
### VS Code
In .vscode/mcp.json:
```json
{
"servers": {
"sixteen-bridges": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"sixteenbridges",
"mcp"
]
}
}
}
```
1. First, sign this computer in once: npx sixteenbridges login
2. Add this to .vscode/mcp.json in your project (or your user MCP settings), then start the server.
### Windsurf
In ~/.codeium/windsurf/mcp_config.json:
```json
{
"mcpServers": {
"sixteen-bridges": {
"command": "npx",
"args": [
"-y",
"sixteenbridges",
"mcp"
]
}
}
}
```
1. First, sign this computer in once: npx sixteenbridges login
2. Add this to ~/.codeium/windsurf/mcp_config.json, then refresh its MCP servers.
## The REST API
For code you write for the person. Base URL: `https://api.sixteenbridges.com/v1`. Every request: `Authorization: Bearer `; bodies are JSON.
If the code runs where the CLI is signed in, the simplest way is to call the CLI with --json: it signs in, renews and retries for you, and prints the same payloads as below.
### Sign-in (OAuth 2.1, PKCE, the app registers itself)
1. `GET https://api.sixteenbridges.com/.well-known/oauth-protected-resource`: `authorization_servers[0]` is the sign-in server.
2. `GET /.well-known/oauth-authorization-server`: `authorization_endpoint`, `token_endpoint`, `registration_endpoint`.
3. Register once: `POST registration_endpoint` with `{"client_name": "My app", "redirect_uris": ["http://127.0.0.1:/callback"], "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "token_endpoint_auth_method": "none"}`. Keep the `client_id`.
4. Send the person to `authorization_endpoint?response_type=code&client_id=…&redirect_uri=…&code_challenge=&code_challenge_method=S256&state=`. They approve on sixteenbridges.com, and come back to your redirect URI with `code` and `state` (check the state).
5. `POST token_endpoint` (form): `grant_type=authorization_code&code=…&redirect_uri=…&client_id=…&code_verifier=…`. You get an `access_token` (about 1 hour) and a `refresh_token`.
6. Renew with `grant_type=refresh_token&refresh_token=…&client_id=…`. Each refresh token works once: save the new one every time.
Only tokens from this sign-in work; a sixteenbridges.com website session doesn't. The person can disconnect your app on their account page at any time: you then get 401, and must sign in again.
### Endpoints
| Request | Does |
|---|---|
| `GET /v1/me` | `{user_id}`: who the token belongs to |
| `GET /v1/bubbles?limit=20&cursor=…` | the bubbles, newest first, without content: `{bubbles, usage, next_cursor}` |
| `GET /v1/bubbles?q=words` | search titles and contents (2–100 characters) |
| `POST /v1/bubbles` | create: `{"title": "…", "content": "…", "source": {"kind": "claude", "label": "optional"}}` → 201 `{bubble}` |
| `GET /v1/bubbles/` | one bubble, with `content` |
| `PATCH /v1/bubbles/` | change `title` and/or `content` |
| `DELETE /v1/bubbles/` | to the trash: `{id, deleted, restorable_until}` |
| `GET /v1/bubbles/deleted` | the trash |
| `POST /v1/bubbles//restore` | back from the trash |
| `POST /v1/shares` | send copies: `{"email": "…", "bubble_ids": ["bub_…"]}` → 201 `{share}`; all of them or none |
| `GET /v1/shares?direction=received` | shares, newest first (direction optional: sent, received): `{shares, unseen, next_cursor}` |
| `POST /v1/logout` | ends this sign-in |
- Answers: `{"status": "SUCCESS", "payload": …}`, or `{"status": "ERROR", "status_code": 404, "error_info": {"error_type": "NOT_FOUND", "message": "…", "fields": [...]}}`.
- Error types: INVALID_INPUT, MISSING_MANDATORY_PARAMETER, INVALID_ENUM (400); AUTHENTICATION_FAILED (401: renew, or sign in again); BUBBLE_LIMIT_REACHED, RECIPIENT_LIMIT_REACHED (403: nothing was shared); NOT_FOUND (404, also for anyone else's bubble), RECIPIENT_NOT_FOUND (404); IDEMPOTENCY_CONFLICT (409); CONTENT_TOO_LARGE (413); SHARE_LIMIT_REACHED (429); SERVICE_UNAVAILABLE (503: try again).
- source.kind: claude, chatgpt, gemini, grok, perplexity, cli, api, other. Title 1–120 characters, unique (a repeat is saved as "Title (2)"); content up to 512 KB; label up to 200 characters.
- A save you may retry: send an `Idempotency-Key` header (1–64 of A–Z a–z 0–9 _ -). The same key returns the same bubble instead of a second one.
- Deleting for good is only on sixteenbridges.com: apps can only move bubbles to the trash.
## Chat apps
- MCP server: https://mcp.sixteenbridges.com/mcp
- Transport: Streamable HTTP
- Sign-in: OAuth 2.1. The app registers itself; the person approves once on sixteenbridges.com and stays connected until they disconnect it on their account page.
A chat app can't add a connector by itself. Tell the person the steps for the app they are using, briefly, and wait while they do it.
### Claude (claude.ai, Desktop)
1. Open Settings → Connectors and choose Add custom connector.
2. Name it Sixteen Bridges and paste the URL: https://mcp.sixteenbridges.com/mcp
3. Choose Connect, then Allow on sixteenbridges.com.
Note: Free plans can add one custom connector.
### ChatGPT
1. Turn on Developer mode: Settings → Apps (or Connectors) → Advanced settings.
2. Create an app or connector named Sixteen Bridges with the URL https://mcp.sixteenbridges.com/mcp and OAuth sign-in.
3. Allow it on sixteenbridges.com, then turn it on in the chat.
Note: Developer mode is on paid plans, and saving or editing bubbles from ChatGPT may need a Business or Enterprise plan. Workspace admins may need to allow custom apps first.
### Gemini (gemini.google.com)
1. On a computer, open gemini.google.com → Settings → Connected Apps. If it isn't there, open Personal Intelligence first.
2. Under Custom apps, choose Add a custom app.
3. Paste the URL https://mcp.sixteenbridges.com/mcp and choose Next. Leave Advanced features empty: it signs in by itself.
4. Follow the prompts (name it Sixteen Bridges if asked), then Allow on sixteenbridges.com.
5. In a chat, type @ and pick Sixteen Bridges.
Note: Custom apps are only for people 18 or over in the US, on a personal Google account (not work or school), in English, with Keep Activity on. Added on the web, they then work in the Gemini app too.
### Grok
1. Open grok.com/connectors, choose New Connector, then Custom.
2. Paste the URL: https://mcp.sixteenbridges.com/mcp
3. Allow it on sixteenbridges.com.
Note: Custom connectors are on paid Grok plans.
### Perplexity
1. Open Settings → Connectors and choose Custom connector, Remote.
2. Name it Sixteen Bridges, paste the URL https://mcp.sixteenbridges.com/mcp, and choose OAuth.
3. Allow it on sixteenbridges.com, then turn it on under a thread's sources.
Note: Custom connectors are on Pro, Max and Enterprise plans, and are added on the web.
## Terminal agents, as a connector instead of the CLI
### Claude Code
```sh
claude mcp add --transport http sixteen-bridges https://mcp.sixteenbridges.com/mcp
```
1. In Claude Code, run /mcp, pick sixteen-bridges and sign in. Allow it on sixteenbridges.com.
### Codex
```sh
codex mcp add sixteen-bridges --url https://mcp.sixteenbridges.com/mcp
codex mcp login sixteen-bridges
```
1. The login opens your browser: Allow it on sixteenbridges.com.
### Gemini CLI
```sh
gemini mcp add --transport http sixteen-bridges https://mcp.sixteenbridges.com/mcp
```
1. In Gemini CLI, run /mcp auth sixteen-bridges. Allow it on sixteenbridges.com.
## Using bubbles well
MCP tools: list_bubbles (with query to search), get_bubble (long bubbles come in pages), save_bubble, update_bubble (append adds to the end), delete_bubble (to the trash for 7 days), list_deleted_bubbles, restore_bubble, share_bubbles, list_shares. The CLI's commands and the API do the same.
- List first, then read only the bubbles you need.
- Show bubbles as a short numbered list: title, source, a one-line gist. Don't paste a whole bubble unless asked.
- When saving, set the source to the app you are (claude, chatgpt, gemini, grok, perplexity), with a short, specific title.
- Ask before deleting. Share only when the person asks, to the exact address they give.
## More
- Docs, with every endpoint and sign-in step: https://sixteenbridges.com/docs (CLI: /docs/cli, MCP: /docs/mcp, REST API: /docs/api)
- Steps for people: https://sixteenbridges.com/ai
- A person's bubbles and connected apps: https://sixteenbridges.com/dashboard