@kammcs/buildit-mcp 0.2.0 → 0.7.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/README.md +252 -32
  3. package/SECURITY.md +1 -1
  4. package/dist/api/client.js +5 -1
  5. package/dist/api/generated/operations.js +661 -4
  6. package/dist/api/generated/schemas.js +680 -2
  7. package/dist/api/generated/strict.js +799 -2
  8. package/dist/channel/api.js +128 -0
  9. package/dist/channel/approvals.js +259 -0
  10. package/dist/channel/item-events.js +138 -0
  11. package/dist/channel/lock.js +181 -0
  12. package/dist/channel/loop.js +776 -0
  13. package/dist/channel/mask.js +365 -0
  14. package/dist/channel/threads.js +60 -0
  15. package/dist/channel/tool-ring.js +124 -0
  16. package/dist/channel/typing.js +150 -0
  17. package/dist/channel/waiters.js +229 -0
  18. package/dist/channel/workers.js +66 -0
  19. package/dist/cli/claude-config.js +100 -0
  20. package/dist/cli/commands.js +410 -0
  21. package/dist/config.js +329 -6
  22. package/dist/errors.js +38 -0
  23. package/dist/index.js +122 -6
  24. package/dist/log.js +3 -2
  25. package/dist/secrets/keychain.js +273 -0
  26. package/dist/server.js +53 -5
  27. package/dist/tools/approve.js +791 -0
  28. package/dist/tools/ask.js +898 -0
  29. package/dist/tools/chat.js +98 -1
  30. package/dist/tools/items-read.js +5 -3
  31. package/dist/tools/items-write.js +66 -15
  32. package/dist/tools/plans.js +221 -14
  33. package/dist/tools/reply.js +138 -0
  34. package/dist/tools/shared.js +10 -1
  35. package/dist/tools/threads.js +123 -0
  36. package/dist/tools/whoami.js +17 -3
  37. package/dist/toolsets/catalog.js +3 -1
  38. package/dist/toolsets/registry.js +2 -0
  39. package/dist/transports/stdio.js +260 -6
  40. package/package.json +5 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@ An [MCP](https://modelcontextprotocol.io) server for [buildIt.Social](https://bu
4
4
 
5
5
  It runs on your own machine (stdio) or as a stateless HTTP server for a team. It holds no secrets of its own: each person's token stays in their own client.
6
6
 
7
- **Status:** 0.2.0, on npm as [`@kammcs/buildit-mcp`](https://www.npmjs.com/package/@kammcs/buildit-mcp). Built on the agent API's v1 contract: items and comments by default (15 tools), and planning, pages, chat, admin and destructive changes when you turn them on (41 tools in all).
7
+ **Status:** 0.7.0, not yet on npm ([`@kammcs/buildit-mcp`](https://www.npmjs.com/package/@kammcs/buildit-mcp) has 0.4.0). Built on the agent API's v1 contract: items and comments by default (15 tools), and planning, pages, chat, admin and destructive changes when you turn them on (43 tools in all). In [channel mode](#talk-to-claude-code-from-builditsocial) it also brings your messages to your agent in buildIt.Social into a Claude Code session, which answers with `reply`; with the [buildit plugin](#questions-and-approvals-in-builditsocial-plugin), its questions, approvals and [tool approvals](#tool-approvals-in-builditsocial) come to you there as cards, and you can [assign it work items](#work-items-for-your-agent).
8
8
 
9
9
  - [How it works](docs/design.md)
10
10
  - [Security policy](SECURITY.md)
@@ -23,11 +23,11 @@ It runs on your own machine (stdio) or as a stateless HTTP server for a team. It
23
23
  Nothing to install by hand: clients start the server with `npx`, which downloads it on first use.
24
24
 
25
25
  ```sh
26
- npx -y @kammcs/buildit-mcp@0 --help
26
+ npx -y @kammcs/buildit-mcp@latest --help
27
27
  ```
28
28
 
29
- - **Versions:** `@0` follows the 0.x releases, so you get fixes and new tools as they ship; `@0.2.0` pins one release. The server tells you when the API needs a newer one ([Versions](#versions)).
30
- - **Windows:** a client that starts `npx` directly fails there (`spawn npx ENOENT`: npx is a `.cmd` file), as Claude Code does. Use `cmd` as the command, with `/c`, `npx`, `-y` and `@kammcs/buildit-mcp@0` as its arguments (the Claude Code example below shows it).
29
+ - **Versions:** `@latest` gets the newest release each time the client starts the server, so you get fixes and new tools as they ship; `@0.4.0` pins one release. Don't use a range such as `@0`: npx keeps the copy it first installed for a range and never updates it. The server tells you when the API needs a newer one ([Versions](#versions)).
30
+ - **Windows:** a client that starts `npx` directly fails there (`spawn npx ENOENT`: npx is a `.cmd` file), as Claude Code does. Use `cmd` as the command, with `/c`, `npx`, `-y` and `@kammcs/buildit-mcp@latest` as its arguments (the Claude Code example below shows it).
31
31
  - Also available as a [container image](#container-image) and, for Claude Desktop, as a [bundle](#claude-desktop).
32
32
 
33
33
  ### From a clone (contributors)
@@ -39,32 +39,35 @@ npm ci
39
39
  npm run build
40
40
  ```
41
41
 
42
- The server is then `node /path/to/buildit-mcp/dist/index.js`: use that command and argument in place of `npx -y @kammcs/buildit-mcp@0` in the examples below. Inside the clone itself, `npx @kammcs/buildit-mcp` finds the clone's own `package.json` and fails (`buildit-mcp` is not recognized), so a client working in the clone needs `dist/index.js`; with Claude Code, add it there with `--scope local`, which wins over a user-scope entry in that folder only.
42
+ The server is then `node /path/to/buildit-mcp/dist/index.js`: use that command and argument in place of `npx -y @kammcs/buildit-mcp@latest` in the examples below. Inside the clone itself, `npx @kammcs/buildit-mcp` finds the clone's own `package.json` and fails (`buildit-mcp` is not recognized), so a client working in the clone needs `dist/index.js`; with Claude Code, add it there with `--scope local`, which wins over a user-scope entry in that folder only.
43
43
 
44
44
  ## Configuration
45
45
 
46
46
  Every setting is an environment variable, and also a flag (the flag wins). The token is the exception: it is only ever read from the environment, because other processes can see flags.
47
47
 
48
- | Variable | Flag | Default | Meaning |
49
- | ------------------------- | ------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
- | `BUILDIT_TOKEN` | none | | Your personal access token (stdio mode). Ignored in HTTP mode, where each request carries its own. |
51
- | `BUILDIT_API_URL` | `--api-url` | `https://api.buildit.social/functions/v1/agent-api` | The agent API. Must be `https://` (plain `http://` only for localhost). |
52
- | `BUILDIT_TOOLSETS` | `--toolsets` | `items,comments` | Comma-separated toolsets, or `all`. Known: `items`, `comments`, `planning`, `pages`, `chat`, `admin`, `destructive`. |
53
- | `BUILDIT_READ_ONLY` | `--read-only` | `false` | List only tools that change nothing. |
54
- | `BUILDIT_EXCLUDE_TOOLS` | `--exclude-tools` | | Comma-separated tool names to hide. |
55
- | `BUILDIT_LOG_LEVEL` | `--log-level` | `info` | `debug`, `info`, `warn` or `error`. Logs are JSON lines on stderr and never contain tokens or content. |
56
- | `BUILDIT_HTTP` | `--http` | `false` | Serve Streamable HTTP instead of stdio. |
57
- | `BUILDIT_HOST` | `--host` | `127.0.0.1` | HTTP bind address. |
58
- | `BUILDIT_PORT` | `--port` | `8765` | HTTP port. |
59
- | `BUILDIT_ALLOWED_HOSTS` | `--allowed-hosts` | localhost names on a loopback bind | Hostnames accepted in the `Host` header (DNS-rebinding protection). Required when binding off loopback, unless `BUILDIT_ALLOW_ANY_HOST` is set. |
60
- | `BUILDIT_ALLOWED_ORIGINS` | `--allowed-origins` | localhost names on a loopback bind | Hostnames accepted in the `Origin` header. Off loopback, requests with any other `Origin` are refused. `moz-extension://*`-style entries admit a browser extension. |
61
- | `BUILDIT_ALLOW_ANY_HOST` | `--allow-any-host` | `false` | Off loopback, serve without checking the `Host` header (for example behind a proxy that checks it). Without it, such a bind needs `BUILDIT_ALLOWED_HOSTS`. |
48
+ | Variable | Flag | Default | Meaning |
49
+ | ------------------------- | ------------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
+ | `BUILDIT_TOKEN` | none | | Your personal access token (stdio mode). Ignored in HTTP mode, where each request carries its own. |
51
+ | `BUILDIT_API_URL` | `--api-url` | `https://api.buildit.social/functions/v1/agent-api` | The agent API. Must be `https://` (plain `http://` only for localhost). |
52
+ | `BUILDIT_TOOLSETS` | `--toolsets` | `items,comments` | Comma-separated toolsets, or `all`. Known: `items`, `comments`, `planning`, `pages`, `chat`, `admin`, `destructive`. |
53
+ | `BUILDIT_READ_ONLY` | `--read-only` | `false` | List only tools that change nothing. |
54
+ | `BUILDIT_EXCLUDE_TOOLS` | `--exclude-tools` | | Comma-separated tool names to hide. |
55
+ | `BUILDIT_LOG_LEVEL` | `--log-level` | `info` | `debug`, `info`, `warn` or `error`. Logs are JSON lines on stderr and never contain tokens or content. |
56
+ | `BUILDIT_HTTP` | `--http` | `false` | Serve Streamable HTTP instead of stdio. |
57
+ | `BUILDIT_HOST` | `--host` | `127.0.0.1` | HTTP bind address. |
58
+ | `BUILDIT_PORT` | `--port` | `8765` | HTTP port. |
59
+ | `BUILDIT_ALLOWED_HOSTS` | `--allowed-hosts` | localhost names on a loopback bind | Hostnames accepted in the `Host` header (DNS-rebinding protection). Required when binding off loopback, unless `BUILDIT_ALLOW_ANY_HOST` is set. |
60
+ | `BUILDIT_ALLOWED_ORIGINS` | `--allowed-origins` | localhost names on a loopback bind | Hostnames accepted in the `Origin` header. Off loopback, requests with any other `Origin` are refused. `moz-extension://*`-style entries admit a browser extension. |
61
+ | `BUILDIT_ALLOW_ANY_HOST` | `--allow-any-host` | `false` | Off loopback, serve without checking the `Host` header (for example behind a proxy that checks it). Without it, such a bind needs `BUILDIT_ALLOWED_HOSTS`. |
62
+ | `BUILDIT_CHANNEL` | `--channel` | `false` | Claude Code channel mode (stdio): see [Talk to Claude Code from buildIt.Social](#talk-to-claude-code-from-builditsocial). The token then comes from the folder's saved session, or `BUILDIT_TOKEN`. |
63
+ | `BUILDIT_FOLDER` | `--folder` | the working directory | In channel mode, the folder whose saved session is used. |
64
+ | `BUILDIT_TOKEN_STORE` | none | the OS keychain | `file` keeps session tokens in a file readable only by you instead of the OS keychain. |
62
65
 
63
66
  The tools you see depend on the enabled toolsets, read-only mode, the exclude list, and your token's scopes: a token with only `projects:read` never sees write tools, and a token limited to some projects or channels doesn't see `create_channel` and `create_project`. If buildIt.Social refuses the token, only `whoami` is listed, so the agent can tell you why. If the scopes can't be read for a moment (a rate limit, the network), every tool your configuration allows is listed and buildIt.Social checks each call; the scopes are read again on the next list.
64
67
 
65
68
  ### Toolsets
66
69
 
67
- `items` and `comments` are on by default (15 tools). Turn others on with `BUILDIT_TOOLSETS` (or `--toolsets`), for example `BUILDIT_TOOLSETS=items,comments,planning,pages` or `BUILDIT_TOOLSETS=all` (41 tools). In HTTP mode, the `X-Buildit-Toolsets` header picks them per request, among the ones the server enables: it can narrow them, never add one.
70
+ `items` and `comments` are on by default (15 tools). Turn others on with `BUILDIT_TOOLSETS` (or `--toolsets`), for example `BUILDIT_TOOLSETS=items,comments,planning,pages` or `BUILDIT_TOOLSETS=all` (43 tools). In HTTP mode, the `X-Buildit-Toolsets` header picks them per request, among the ones the server enables: it can narrow them, never add one.
68
71
 
69
72
  **`admin` and `destructive` stay off unless you name them**, even when your token has `projects:admin` or `projects:delete`. Turn them on only for work that needs them, for example a separate client entry with `BUILDIT_TOOLSETS=items,admin` while you reorganize a workflow. Their changes always go through preview and confirm (below), except creating a channel or a project, which changes nothing that exists.
70
73
 
@@ -80,7 +83,7 @@ The tools you see depend on the enabled toolsets, read-only mode, the exclude li
80
83
  | | `get_item` | `projects:read` | read-only | One item: fields, description (long ones in windows), custom fields, children, links, latest comments, a Feedback report and, optionally, history and GitHub refs; the versions an update needs. |
81
84
  | | `create_item` | `projects:write` | | An epic, story, task, bug or subtask, under a parent or in a project, at a position; safe to retry with its idempotency key. |
82
85
  | | `update_item` | `projects:write` | idempotent | A field patch; the description appended to (safe) or replaced (with its version); `if_version` guards against concurrent edits. |
83
- | | `assign_item` | `projects:write` | idempotent | Assign to a person (`me`, an email or a name) or unassign. |
86
+ | | `assign_item` | `projects:write` | idempotent | Assign to a person (`me`, an email or a name), to your agent (`agent: "mine"`, working for you), or unassign. |
84
87
  | | `transition_item` | `projects:write` | idempotent | Move to a status by name, setting the fields the move needs and posting a comment; a refused move lists the moves allowed from where the item is. |
85
88
  | | `link_items` | `projects:write` | idempotent | Add a link: blocks, blocked by, relates, duplicates, duplicated by. |
86
89
  | | `unlink_items` | `projects:write` | destructive, idempotent | Remove a link, by kind and target or by its id. |
@@ -100,6 +103,8 @@ The tools you see depend on the enabled toolsets, read-only mode, the exclude li
100
103
  | `chat` | `list_channels` | `chat:read` | read-only, open-world | The channels you belong to (never direct messages). Paged. |
101
104
  | | `read_channel` | `chat:read` | read-only, open-world | A channel's messages, newest first, optionally `since` a time; says which come from an app (a bot of the org). Paged. |
102
105
  | | `read_thread` | `chat:read` | read-only, open-world | A message and its replies, oldest first. Paged. |
106
+ | | `list_pins` | `chat:read` | read-only, open-world | A channel's pinned messages, newest pinned first, with when and by whom. Paged. Messages say whether they're pinned in `read_channel` and `read_thread` too. |
107
+ | | `list_emoji` | `chat:read` | read-only | The org's custom emoji by name (messages show them as `:name:`); no images. |
103
108
  | `admin` (off) | `create_channel` | `projects:admin` | | A public or private channel, with members; safe to retry with its idempotency key. Needs a token without project or channel limits. |
104
109
  | | `create_project` | `projects:admin` | | Turn a channel into a project from a template, with its key (named after the channel); safe to retry. Needs a token without limits and Projects. |
105
110
  | | `get_workflow` | `projects:admin` | read-only | A workflow's statuses, moves and whole definition, to edit and propose. |
@@ -140,13 +145,13 @@ In every example the token comes from the `BUILDIT_TOKEN` environment variable;
140
145
  Single quotes keep `${BUILDIT_TOKEN}` literal, so the configuration stores the reference, not the token; Claude Code expands it when it starts the server.
141
146
 
142
147
  ```sh
143
- claude mcp add buildit --scope user -e 'BUILDIT_TOKEN=${BUILDIT_TOKEN}' -- npx -y @kammcs/buildit-mcp@0
148
+ claude mcp add buildit --scope user -e 'BUILDIT_TOKEN=${BUILDIT_TOKEN}' -- npx -y @kammcs/buildit-mcp@latest
144
149
  ```
145
150
 
146
151
  On Windows, from PowerShell (Git Bash would turn `/c` into a path):
147
152
 
148
153
  ```powershell
149
- claude mcp add buildit --scope user -e 'BUILDIT_TOKEN=${BUILDIT_TOKEN}' -- cmd /c npx -y "@kammcs/buildit-mcp@0"
154
+ claude mcp add buildit --scope user -e 'BUILDIT_TOKEN=${BUILDIT_TOKEN}' -- cmd /c npx -y "@kammcs/buildit-mcp@latest"
150
155
  ```
151
156
 
152
157
  Or share it with a project through `.mcp.json`, where each person's own `BUILDIT_TOKEN` is used:
@@ -156,7 +161,7 @@ Or share it with a project through `.mcp.json`, where each person's own `BUILDIT
156
161
  "mcpServers": {
157
162
  "buildit": {
158
163
  "command": "npx",
159
- "args": ["-y", "@kammcs/buildit-mcp@0"],
164
+ "args": ["-y", "@kammcs/buildit-mcp@latest"],
160
165
  "env": { "BUILDIT_TOKEN": "${BUILDIT_TOKEN}" }
161
166
  }
162
167
  }
@@ -174,7 +179,7 @@ In `~/.cursor/mcp.json` (or a project's `.cursor/mcp.json`), using Cursor's `${e
174
179
  "mcpServers": {
175
180
  "buildit": {
176
181
  "command": "npx",
177
- "args": ["-y", "@kammcs/buildit-mcp@0"],
182
+ "args": ["-y", "@kammcs/buildit-mcp@latest"],
178
183
  "env": { "BUILDIT_TOKEN": "${env:BUILDIT_TOKEN}" }
179
184
  }
180
185
  }
@@ -199,7 +204,7 @@ In `.vscode/mcp.json`. VS Code prompts for the token once and keeps it in its se
199
204
  "buildit": {
200
205
  "type": "stdio",
201
206
  "command": "npx",
202
- "args": ["-y", "@kammcs/buildit-mcp@0"],
207
+ "args": ["-y", "@kammcs/buildit-mcp@latest"],
203
208
  "env": { "BUILDIT_TOKEN": "${input:buildit-token}" }
204
209
  }
205
210
  }
@@ -222,16 +227,230 @@ Without the bundle, don't put a token in `claude_desktop_config.json`: it doesn'
222
227
  "mcpServers": {
223
228
  "buildit": {
224
229
  "command": "npx",
225
- "args": ["-y", "@kammcs/buildit-mcp@0"]
230
+ "args": ["-y", "@kammcs/buildit-mcp@latest"]
226
231
  }
227
232
  }
228
233
  }
229
234
  ```
230
235
 
236
+ ## Talk to Claude Code from buildIt.Social
237
+
238
+ With channel mode, the Claude Code session in a folder becomes a **session of your personal agent** in buildIt.Social. You write to the agent in the app, on your computer or your phone; the message arrives in the running Claude Code session, which works on it and answers you in the same thread. The session can also work on the items of the projects you connected it to, as you, labelled as done through the agent.
239
+
240
+ It works only with the **Claude Code CLI** (not Claude Desktop), because it uses Claude Code [channels](https://code.claude.com/docs/en/channels.md), a research preview whose flags and protocol may still change.
241
+
242
+ ### What you need
243
+
244
+ - A personal agent in buildIt.Social (Settings → Agents), in an org that hasn't turned agents in the app off (they are on by default).
245
+ - The Claude Code CLI, signed in with a **claude.ai account or a Claude Console API key**. Channels aren't available with Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry.
246
+ - On a **claude.ai Team or Enterprise** plan, an org Owner must turn channels on first: Organization settings → Claude Code → Channels (or `channelsEnabled: true` in managed settings). Until then Claude Code says the channel is "blocked by org policy".
247
+ - Node.js 20 or newer.
248
+
249
+ ### 1. Install or upgrade
250
+
251
+ Nothing to install by hand: `npx -y @kammcs/buildit-mcp@latest` downloads the newest release when it runs, and again whenever a new one ships. Check the version with `npx -y @kammcs/buildit-mcp@latest --version`; channel mode needs 0.4.0 or newer, the [plugin](#questions-and-approvals-in-builditsocial-plugin) 0.5.0, [work items for your agent](#work-items-for-your-agent) 0.6.0, and [tool approvals](#tool-approvals-in-builditsocial) 0.7.0.
252
+
253
+ > **Until 0.4.0 is on npm**, `@latest` is an older release without channel mode, so use a local build: `git clone https://github.com/kammcs/buildit-mcp.git`, then `npm ci && npm run build` in it, and use `node /path/to/buildit-mcp/dist/index.js` wherever the steps below say `npx -y @kammcs/buildit-mcp@latest`. `connect` run that way prints the matching `claude mcp add` line.
254
+
255
+ ### 2. Connect the folder
256
+
257
+ In a terminal, in the folder where you run Claude Code (the project or repository), connect it to the projects it may work on:
258
+
259
+ ```sh
260
+ npx -y @kammcs/buildit-mcp@latest connect --project DEMO
261
+ ```
262
+
263
+ It prints a link and a code. Open the link, sign in to buildIt.Social if you need to, and check that the app shows the same code. The approval screen says what is connecting ("Claude Code on your computer's name"), as which of your agents and to which projects. The scopes are chosen there, not by the CLI: the screen pre-checks the usual ones, and you can untick any you don't want to give. Then approve. Approve only a code you started yourself. The code works for 10 minutes.
264
+
265
+ Once it is approved, the command says who approved it and for which projects, as approved: `Connected as Claude (your name) in your org, project DEMO; session "your-folder".`, and asks **"Is this you? [y/N]"**. Whoever approves a code gets the session, so check the name: only `y` saves the token, in your OS keychain for this folder. Any other answer (or no answer, without a terminal) saves nothing and cancels the session at once, since someone else may have approved your code; run `connect` again for a new code.
266
+
267
+ - `--project` takes up to 10 project keys (repeat it, or separate keys with commas). The session reaches only those projects, and never more than you can.
268
+ - `--label <name>` names the session in buildIt.Social (1 to 40 characters; the folder's name by default). The agent's messages show as "agent · label".
269
+ - `--folder <path>` connects another folder than the working directory. `--api-url <url>` connects to another buildIt.Social deployment: its agent API's address, such as `https://buildit.example.com/functions/v1/agent-api`; a bare host such as `https://buildit.example.com` gets `/functions/v1/agent-api` added (the command says so).
270
+ - `--yes` saves without asking. It is for scripts only, and unsafe whenever anyone else could have seen the code.
271
+ - No personal access token is involved: the session has a token of its own (`buildit_ags_...`), which the CLI keeps and never prints. It expires after 30 days unused.
272
+
273
+ `npx -y @kammcs/buildit-mcp@latest status` shows the folder's session and whether buildIt.Social still accepts it; `disconnect` cancels the session in buildIt.Social and forgets the folder's token (if it can't reach buildIt.Social, it forgets the token anyway and says to revoke the session in the app).
274
+
275
+ ### 3. Add the server to Claude Code, with `--channel`
276
+
277
+ `connect` ends by printing the exact line for this step: copy it. In the same folder, it is:
278
+
279
+ ```sh
280
+ claude mcp add buildit -- npx -y @kammcs/buildit-mcp@latest --channel
281
+ ```
282
+
283
+ On Windows, from PowerShell:
284
+
285
+ ```powershell
286
+ claude mcp add buildit -- cmd /c npx -y "@kammcs/buildit-mcp@latest" --channel
287
+ ```
288
+
289
+ (From a local build, `claude mcp add buildit -- node "/path/to/buildit-mcp/dist/index.js" --channel`.)
290
+
291
+ This adds it for this folder only (`--scope local`, the default), which is what you want: each folder has its own session. No `BUILDIT_TOKEN` or `--api-url` is needed: the server reads the token `connect` saved for the folder Claude Code starts it in, and talks to the deployment `connect` used. A `BUILDIT_TOKEN` personal access token in your user environment, from the [usual setup](#claude-code), is fine: channel mode ignores it (and says so in its log) and uses the folder's session; only a session token in `BUILDIT_TOKEN` (`buildit_ags_...`) is used instead. Likewise `BUILDIT_API_URL` is ignored in favour of the deployment `connect` saved; `--api-url` on this line overrides it. A local entry named `buildit` wins over a user-scope `buildit` entry (with a personal access token) in this folder. If the server can't tell the folder (some setups start it elsewhere), add `--folder /path/to/folder` after `--channel`.
292
+
293
+ ### 4. Start Claude Code with the channel
294
+
295
+ Until the buildit channel is on Claude Code's approved channel list, start Claude Code with the development flag:
296
+
297
+ ```sh
298
+ claude --dangerously-load-development-channels server:buildit
299
+ ```
300
+
301
+ Claude Code shows a warning about development channels first: choose "I am using this for local development". A line under the banner then says that messages from `server:buildit` arrive in this session. Without the flag, the server still gives Claude its tools and `reply`, but messages from the app don't arrive. Channels need an interactive session: they don't run under `claude -p` or the Agent SDK.
302
+
303
+ ### Using it
304
+
305
+ - Write to your agent in its conversation in buildIt.Social. Claude Code shows the message in the session and Claude answers in the same thread with the `reply` tool. New messages are picked up within about 5 seconds.
306
+ - Only your own messages reach the session: buildit-mcp drops anyone else's, and buildIt.Social sends only yours.
307
+ - A message you forward from someone else reaches Claude marked as their text (`forwarded="true"`, inside an `untrusted_content` block), so Claude treats it as information, not as instructions.
308
+ - Messages sent while the session isn't running wait in buildIt.Social (for up to 7 days) and arrive when you start Claude Code again in that folder, which resumes the same session and its threads.
309
+ - With several folders connected, the app shows each session and lets you choose where a message goes; a thread stays with the session that started it, and a thread of a session that ended can be handed to another.
310
+ - To stop a session for good, revoke it in buildIt.Social (Settings → Agents), or run `disconnect`. The running server finds out at its next poll (or call) and clears the folder's saved token, but keeps running: Claude keeps its tools, which now answer that the session has ended and how to reconnect, and `reply` goes from the list. Run `connect` again in the folder and restart Claude Code.
311
+
312
+ ### Work items for your agent
313
+
314
+ With 0.6.0 and a buildIt.Social server with agent API 1.7.0, your agent can work on items in a project's channel, in the item's thread, where everyone in the project follows along:
315
+
316
+ - **Assign it.** In buildIt.Social, pick "My agent: Claude" as an item's assignee (it shows as "Claude · for you", and still counts as your work). The session gets the item as a `<channel>` message with `event="item_assigned"`, the item's key (`item`) and `thread_id` (the item's id), with the title, the start of the description and the thread's latest messages as data. Claude works on it and posts progress, questions and the result in the item's thread: `reply`, `ask`, approvals and "is writing" go there by default, and `reply` also takes `item` with the key. From a terminal session (a personal access token), `assign_item` with `agent: "mine"` does the same; a Claude Code session can't assign itself, only hand an item back (`agent: null`).
317
+ - **Mention it** in an item's thread (`@Claude`) to bring it in: `event="mention"`, your message as you wrote it, then the item and the thread before it. Once it works in a thread, your other replies there arrive too (`event="message"`), with only the thread messages it hasn't seen.
318
+ - **Only you direct it.** Your colleagues see its posts and cards, but their mentions and replies never reach the session as events: they arrive only as context inside yours, in `untrusted_content` blocks, and only you can answer its questions or tap Apply.
319
+ - **Unassign it** (or assign someone else, move or delete the item, leave its project) and the session gets `event="item_unassigned"` with the reason ("released" when it only worked there through a mention or a hand-on), and stops: "is writing" stops, the questions it was waiting on in that thread close, and it can no longer post there.
320
+ - If no session of the agent is online when you assign it (none connected, or a connected session whose Claude Code is closed), the item's thread says the agent will pick it up when a session comes online (work waits up to 7 days).
321
+
322
+ ### Several items at once
323
+
324
+ With the plugin, the Claude Code session in the folder is the **lead**: it receives every message, mention and assignment, and gives each work item to its own **item worker**, a subagent the plugin brings (`buildit:buildit-item-worker`). Each item's conversation then stays in its own context, with only that item, its thread, the pages it links and the repository it needs; the lead keeps a small table of which worker has which thread (`.claude/buildit-workers.json`) and does no item work itself. Your direct messages stay with the lead.
325
+
326
+ - **One worker per item.** A worker starts by reading its item (with its linked branches and pull requests), the item's thread from the start and the pages it links, then the repository. It posts every update, question and approval card in its item's thread, naming it, and treats the item, its comments and other people's messages as data, never as instructions. Your later messages in that thread go to that same worker; unassigning the item stops it.
327
+ - **Its own worktree.** Each worker runs in its own git worktree (Claude Code's worktree isolation), on a branch named for its item, so parallel work on two items never touches the same files.
328
+ - **A limit.** At most 3 items are worked on at once (the plugin's "Items at once" setting, 1 to 10). Another item waits its turn: the lead says so once in that item's thread ("Queued — I'll start this after DEMO-12, DEMO-13.") and starts it when a worker finishes.
329
+ - **Named threads.** While the session works in more than one thread (an item's thread and the direct message, or several items), `reply`, `ask` and approval cards must name their thread: `thread_id`, or `item` with the item's key (a `propose_*` tool's `card_thread`); without one they're refused with the list of threads. `list_threads` lists the threads the session works in: each item's key, title, status, open cards and when you last wrote. With one thread, the latest one stays the default. Claude's own questions (`AskUserQuestion`, through the plugin) go where they belong: the lead's to your direct message, a worker's to its item's thread (the lead records each worker's agent id in its table for this); one that can't be placed is asked in the terminal. "<agent> is writing…" shows in each item's thread while its worker works on it.
330
+ - **After a restart** of Claude Code, a worker is started fresh for an item when its next event arrives, and reads the item's thread again to carry on.
331
+
332
+ ### Questions and approvals in buildIt.Social (plugin)
333
+
334
+ The **buildit plugin** for Claude Code (since 0.5.0; tool approvals since 0.7.0) adds what the bare channel can't do, so you can work with the session from your phone as well as from the terminal:
335
+
336
+ - **Questions as cards.** When Claude asks you something (its `AskUserQuestion` tool), the question appears in your agent's conversation in buildIt.Social as a card, instead of in the terminal: one card per question: the question in full, a list of its choices with their details (several choices where Claude allows them), and a field to type your own answer instead. Claude gets all the answers together once you have answered every card. Your answer goes back to Claude, and the terminal doesn't ask. Claude can also ask you with the `ask` tool while it works on a message from the app.
337
+ - **Approvals as cards.** A destructive or configuration change (a `propose_*` tool) is posted as a card with **Apply** and **Cancel**. buildIt.Social words the card from its own preview and applies the change itself when you tap Apply, as you through your agent; an agent session can never apply a change itself (`apply_plan` answers `plan_card_required`), so only your tap applies it. Claude learns the outcome (applied, cancelled, not applied because the items changed, failed, expired after 60 minutes, or unknown, when buildIt.Social couldn't confirm it, and then Claude checks the items) as a channel message.
338
+ - **Tool approvals as cards** (0.7.0). When Claude Code would ask you whether a tool may run (a command, a file edit, another tool), it asks in buildIt.Social too, and the first answer wins: see [Tool approvals in buildIt.Social](#tool-approvals-in-builditsocial).
339
+ - **"<agent> is writing…"** shows in the thread while Claude works on your message, and stops when it answers, asks, posts an approval, or ends its turn.
340
+
341
+ If nobody answers a question in time (60 minutes by default), the card closes and Claude is told nobody answered, so it makes a safe assumption and says which, or stops and says what it needs; it doesn't fall back to the terminal. The same goes when you dismiss the card in the app ("Dismiss question"), or when the session ends while it waits. Pressing Esc in the terminal closes the card. Without the plugin, or with its questions setting off, Claude asks in the terminal as usual.
342
+
343
+ **Install it.** The plugin replaces the `claude mcp add` server of step 3: it starts buildit-mcp in channel mode itself. So **remove that server first**, in the same folder:
344
+
345
+ ```sh
346
+ claude mcp remove buildit
347
+ ```
348
+
349
+ Then add this repository as a plugin marketplace and install the plugin (in Claude Code, or from a terminal with `claude plugin ...`):
350
+
351
+ ```text
352
+ /plugin marketplace add kammcs/buildit-mcp
353
+ /plugin install buildit@buildit-mcp
354
+ ```
355
+
356
+ (On Claude Code 2.1.275 or later, `/plugin install buildit --marketplace kammcs/buildit-mcp` does both in one step.) Connect the folder as in step 2 if you haven't, then start Claude Code with the plugin's channel:
357
+
358
+ ```sh
359
+ claude --dangerously-load-development-channels plugin:buildit@buildit-mcp
360
+ ```
361
+
362
+ `buildit-mcp status` names the buildit servers set up for the folder (the plugin, and any `buildit-mcp --channel` server in `~/.claude.json` or the folder's `.mcp.json`, by name), warns when both kinds are, and says which running one receives the folder's messages. If both run anyway, the plugin's server is the folder's channel, since Claude Code shows channel messages only from a server it registered as one: the plugin passes `--from-plugin`, and a server without it stops polling as soon as the plugin's holds the folder (both keep a lock next to the session file). Of two plugin servers, the first to start wins. A server that isn't the channel serves its tools without it, and its `reply`, `ask` and `whoami` say another buildIt server receives the messages; remove the extra one with `claude mcp remove <name>`.
363
+
364
+ **Settings** (`/plugin`, the buildit plugin's options):
365
+
366
+ | Setting | Default | What it does |
367
+ | -------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------- |
368
+ | Question wait (minutes) | 60 | How long a question card waits for an answer, 1 to 60. The card closes a minute before the hook's one-hour limit at most. |
369
+ | Questions in buildIt.Social | on | Off: Claude's `AskUserQuestion` questions stay in the terminal. Approvals and "is writing" are unaffected. |
370
+ | Items at once | 3 | How many work items assigned to your agent are worked on at once, 1 to 10, each by its own subagent; the rest wait. |
371
+ | Tool approvals in buildIt.Social | on | Off: Claude Code asks for tool approvals in the terminal only. |
372
+ | Approval wait (minutes) | 60 | How long a tool approval card waits, 1 to 60, before Claude is told no. At most a minute under the hook's one-hour limit. |
373
+
374
+ The plugin passes them to the server as `BUILDIT_ASK_TIMEOUT_MINUTES`, `BUILDIT_QUESTIONS_IN_APP`, `BUILDIT_MAX_PARALLEL_ITEMS`, `BUILDIT_APPROVALS_IN_APP` and `BUILDIT_APPROVAL_TIMEOUT_MINUTES`, and turns every toolset on (`BUILDIT_TOOLSETS=all`), since approvals need the `destructive` and `admin` tools; `--channel` does the same when `BUILDIT_TOOLSETS` isn't set. The session's own scopes and projects still limit what works. It hooks `AskUserQuestion` (`PreToolUse`, an `mcp_tool` hook calling the server's `ask` tool with a one-hour timeout), Claude's turn ending (`Stop`, calling `turn_ended`, which stops "is writing"), and the hooks of [tool approvals](#tool-approvals-in-builditsocial): `PermissionRequest` (`approve`, a one-hour timeout), `PreToolUse` on every tool (`tool_seen`), `PostToolUse` and `PostToolUseFailure` (`tool_done`), `SubagentStop` (`agent_done`) and `UserPromptSubmit` (`prompt_typed`). None of these is a tool for Claude. Tested with Claude Code 2.1.312, where a hook of this kind waited more than ten minutes (a `PermissionRequest` hook 700 seconds) as it should.
375
+
376
+ #### Tool approvals in buildIt.Social
377
+
378
+ With the plugin (0.7.0, and a buildIt.Social server with agent API 1.8.0), when Claude Code would ask you whether a tool may run, it asks in buildIt.Social too, as a card:
379
+
380
+ - **What the card shows.** Everyone who can read the thread sees only which tool Claude wants to use and who asks ("Claude wants to use Bash", and the subagent when one asks), in buildIt.Social's own words, and that only you can answer. Only you see the details: Claude's description of the call, and each part of its input (the command, the file and its new content, the text an edit replaces), as plain text.
381
+ - **Where it goes.** The main session's approvals go to your direct message with the agent; an item worker's (the plugin's own `buildit-item-worker`, by that exact name) to its work item's thread; any other subagent's to the direct message, with the subagent named (a background subagent's terminal prompt may be seen by nobody). When the item's thread refuses the card, it goes to the direct message instead.
382
+ - **The answers.** **Approve** runs the call. **Allow for this session** appears when Claude Code suggests a rule for the rest of the session for the tool that asks (such as `Bash(npm test:*)`, or accepting file edits), and approves the call with that rule; a card never offers a rule that would be saved to a settings file, a directory grant, another mode, or a rule for another tool. The rule is granted only when buildIt.Social confirms it stored the same rule you were shown; otherwise your tap approves just this call. **Deny** tells Claude you denied it, and not to retry it but to ask you what to do instead.
383
+ - **One call, one verdict.** A card's answer is for the exact call it shows: its tool and its input (and who asks). Claude can call the plugin's hook tools itself, but an approval it gets for one input never lets another input run, even under the same tool call id.
384
+ - **The wait.** If nobody answers within the approval wait (60 minutes by default), the card expires and Claude is told nobody approved it in time, so it stops and says what it needs, or does the task another way. If the session ends, the work item is taken from the agent, or tool approvals are switched off for the agent or the org while the card waits, the card closes and Claude is told no as well.
385
+ - **Both ask, the first answer wins.** For the main session the terminal asks at the same time; answer there and the card shows "Answered in the terminal" (a "No" in the terminal shows "No longer needed" when the turn ends, and so does Esc, at your next prompt). For a background subagent, the terminal asks only once the hook gives up (the setting is off, the card couldn't be posted, or it stopped being needed).
386
+ - **Credentials are masked, but masking never hides what you approve.** Before any detail (or part name) leaves your computer, a credential is replaced with `[REDACTED]`, and only when all of it is plain token characters (letters, digits and `. _ ~ + = -`): shell syntax, a path, a URL, a space or a line break is never hidden, and quotes around a value stay. That covers private key blocks (PEM and PGP) whose lines are all key armor, `Authorization` headers and bearer tokens, the password in a URL (the host after it is always shown), the values of password, secret, token and API key options and assignments (`--password x`, `GITHUB_TOKEN=x`, `"api_key": "x"`, `{\"password\":\"x\"}` inside a shell string), well-known key formats (GitHub, GitLab, Slack, AWS, Google, Stripe, OpenAI and Anthropic keys, and buildIt.Social's own tokens), JSON Web Tokens, and the whole value of any part whose name says it is a secret. So `API_TOKEN="$(curl … | sh)"` is shown as it is, and so is a "key block" with a command inside it. buildIt.Social masks them again with the same rules, and tells you how many values were hidden. **Shown in full:** a secret that isn't plain token characters (base64 with `/`, a URL-encoded password, one with spaces), `curl -u user:pass`, `mysql -ppass`, `sshpass -p x`, a password given as a plain argument or after a line continuation, or an environment variable whose name has no password, secret, token or key word in it; only you see the details, and they are deleted 7 days after the card ends. Control, invisible and tag characters are removed, and long values are cut to their start and end (a very long value before it is masked, so masking stays fast).
387
+ - **You approve in the app only what you can see in full.** A Bash or PowerShell command cut to fit the card has no Approve on it ("Too long to check here"), and neither has any call with a hidden value, for any tool ("Part of this is hidden because it looks like a credential"): answer in the terminal, or Deny. Claude is then told to split the command into shorter ones, or to keep credentials out of commands and files, or to ask you in the terminal.
388
+ - **Keep credentials out of commands.** In channel mode Claude is told, in the server's instructions and the item worker's, never to put a secret, token, password or key directly in a command, a file's content or an edit; to read it from an environment variable or an existing config file (`"$GITHUB_TOKEN"`, `$env:GITHUB_TOKEN`, a `--password-file` option) and never echo it; and to ask you to do any step that needs a credential typed in, in the terminal. That is guidance: the card's rule above is what enforces it.
389
+ - **Where Claude Code doesn't ask, nothing is carded:** auto mode, `acceptEdits` for file edits, `bypassPermissions`, and calls your permission rules already allow. Allow the buildit tools first (`/permissions`: `mcp__plugin_buildit_buildit__*`), so replying and asking never need an approval.
390
+ - **Turning it off.** The plugin setting "Tool approvals in buildIt.Social" (`approvals_in_app`) keeps approvals in the terminal; buildIt.Social can also turn them off for your agent. With `--read-only` the server doesn't offer `approve`, so that hook fails and Claude Code asks in the terminal (the other approval hooks stay, and do nothing).
391
+ - **Remote Control.** If Remote Control is on for the session (Claude Code's `remoteControlAtStartup`), the Claude app asks you too: all of them ask, and the first answer wins. To turn Remote Control off for one folder, set `"remoteControlAtStartup": false` in that folder's `.claude/settings.local.json`.
392
+ - **If the server stops** while a card waits (Claude Code cancels the waiting call first when it shuts down), or a post's answer was lost (the card may exist anyway), the card is closed ("Closed."), by the next buildit server in the folder if need be, so you never approve a call nobody waits for.
393
+
394
+ Tested with Claude Code 2.1.312.
395
+
396
+ #### Try it from a checkout
397
+
398
+ Until 0.7.0 is on npm, the plugin's server (`npx -y @kammcs/buildit-mcp@0.7.0 --channel`) can't be downloaded. A checkout can make a local plugin marketplace whose buildit plugin runs the checkout's own build:
399
+
400
+ ```sh
401
+ git clone https://github.com/kammcs/buildit-mcp.git
402
+ cd buildit-mcp
403
+ npm ci && npm run build
404
+ npm run dev-marketplace
405
+ ```
406
+
407
+ `npm run dev-marketplace` writes the marketplace `buildit-dev` to `.dev-marketplace/` in the checkout (git ignores it; `-- --out <dir>` writes it elsewhere): the plugin of `plugin/`, with the same name, hooks and settings, whose server is `node <checkout>/dist/index.js --channel --from-plugin` (an absolute path, since Claude Code copies an installed plugin into its plugin cache), and the version `<version>-local`. It prints the commands; once:
408
+
409
+ ```sh
410
+ claude plugin marketplace add /path/to/buildit-mcp/.dev-marketplace
411
+ claude plugin install buildit@buildit-dev
412
+ ```
413
+
414
+ Then, in the folder you work in (connected as in step 2, with the local build: `node /path/to/buildit-mcp/dist/index.js connect --project DEMO`, which prints these steps too):
415
+
416
+ ```sh
417
+ claude mcp remove buildit
418
+ claude --dangerously-load-development-channels plugin:buildit@buildit-dev
419
+ ```
420
+
421
+ - `claude mcp remove buildit` is only needed when the server of step 3 is set up in that folder (it says so when there is none).
422
+ - Check the line under the banner: it should say that messages from `plugin:buildit@buildit-dev` arrive in this session.
423
+ - `--plugin-dir` alone doesn't do: it loads the plugin's hooks and server, but Claude Code registers a plugin's channel only for an installed plugin, so messages from buildIt.Social wouldn't arrive.
424
+ - Run `npm run dev-marketplace` again after rebuilding or pulling, then `claude plugin marketplace update buildit-dev` and `claude plugin update buildit@buildit-dev`, so Claude Code takes the new copy; restart Claude Code. `claude plugin validate .dev-marketplace` checks it.
425
+
426
+ On Windows, Claude Code starts the plugin's `npx` itself; if `/mcp` shows the plugin's server as failed, check that `npx -y @kammcs/buildit-mcp@0.7.0 --version` works in a terminal (Node.js 20 or newer on `PATH`).
427
+
428
+ ### Where the token is kept
429
+
430
+ | System | Store |
431
+ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
432
+ | Windows | Windows Credential Manager: generic credentials named `<hash>.buildit-mcp` |
433
+ | macOS | The login keychain (service `buildit-mcp`). macOS may ask once whether Node.js may read it, and again after Node.js is updated: choose Always Allow. |
434
+ | Linux | The Secret Service (GNOME Keyring, KWallet), which needs a desktop session |
435
+
436
+ Each folder and deployment has its own entry, named by a hash of the folder's real path and the API's address. The keychain is reached through the optional `@napi-rs/keyring` package, which npm installs with buildit-mcp where it has a build for the system. When there is no usable keychain (a headless Linux, WSL, a system without a build), the token goes to a file readable only by you, and the CLI says so: `%APPDATA%\buildit-mcp\sessions.json` on Windows, `~/Library/Application Support/buildit-mcp/sessions.json` on macOS, `~/.config/buildit-mcp/sessions.json` elsewhere (`$XDG_CONFIG_HOME` if set). Set `BUILDIT_TOKEN_STORE=file` to use the file directly. `BUILDIT_TOKEN` set to a session token overrides the store. Next to each token, `connect` records which deployment the folder's session belongs to (an `api-<hash>` entry, not a secret).
437
+
438
+ ### Troubleshooting
439
+
440
+ - **"No buildIt.Social session is saved for ..."**: the server looked for a session for that folder and found none. Run `connect` in that folder, or point the server at the right one with `--folder`. A folder reached through another path (a symbolic link, another drive letter) is the same folder only if its real path is the same.
441
+ - **Messages don't arrive:** check that Claude Code was started with `--dangerously-load-development-channels server:buildit`, and that `/mcp` shows `buildit` connected. "Blocked by org policy" means your Team or Enterprise org hasn't turned channels on. Sessions signed in through Bedrock, Agent Platform or Foundry can't use channels. For details, start Claude Code with `--debug` and read `~/.claude/debug/<session-id>.txt`; add `-e BUILDIT_LOG_LEVEL=debug` to the `claude mcp add` command for the server's own logs (they never contain tokens or message text).
442
+ - **The code expired, or the connection was denied:** run `connect` again for a new code. "Denied" also covers an agent turned off or deleted, or an owner who left the org, after the approval.
443
+ - **"Too many connections ... waiting for approval"** or **"... started from this network in the last hour"**: `connect` waits out a short pause by itself; for a longer one, approve or deny the codes already shown (or let them expire after 10 minutes), then try again when it says.
444
+ - **"This buildIt.Social session has ended"** from every tool, or "the session was revoked or has expired" in the logs: the session ended (revoked in the app, disconnected, or unused for 30 days), and its saved token was cleared. Claude gets one last channel message saying so, and the server stays up so Claude can tell you. Run `connect --project <KEY>` again in the folder, approve it, then restart Claude Code.
445
+ - **The session is paused:** the org turned agents in the app off, or your membership was suspended. The server keeps trying every minute and resumes when it is allowed again.
446
+ - **macOS keeps asking for the keychain:** choose Always Allow; it asks again when the Node.js binary changes.
447
+ - **WSL:** it can't reach Windows Credential Manager, so the token goes to the file in your Linux home. Run `connect` inside WSL if Claude Code runs there.
448
+ - **`spawn npx ENOENT` on Windows:** use `cmd /c npx` as above.
449
+
231
450
  ## HTTP mode
232
451
 
233
452
  ```sh
234
- npx -y @kammcs/buildit-mcp@0 --http # http://127.0.0.1:8765/mcp
453
+ npx -y @kammcs/buildit-mcp@latest --http # http://127.0.0.1:8765/mcp
235
454
  ```
236
455
 
237
456
  - Every request must carry `Authorization: Bearer <token>`; the server uses that request's token for its API calls and keeps nothing afterwards. A token is required even on localhost.
@@ -251,7 +470,7 @@ claude mcp add buildit --transport http --header 'Authorization: Bearer ${BUILDI
251
470
  One server can serve a whole team: each member connects with the team URL and their own token, and the server forwards each request with that member's token. It holds no buildIt.Social secret and stores nothing, so it can run as several replicas behind any load balancer.
252
471
 
253
472
  ```sh
254
- npx -y @kammcs/buildit-mcp@0 --http --host 0.0.0.0 --port 8765
473
+ npx -y @kammcs/buildit-mcp@latest --http --host 0.0.0.0 --port 8765
255
474
  # with BUILDIT_ALLOWED_HOSTS=mcp.example.com
256
475
  ```
257
476
 
@@ -259,7 +478,7 @@ Bound to anything but loopback, the server refuses to start without `BUILDIT_ALL
259
478
 
260
479
  ### Container image
261
480
 
262
- `ghcr.io/kammcs/buildit-mcp` runs the server in HTTP mode on port 8765, as a non-root user, with a health check on `/healthz`. Each release is tagged with its version (`0.2.0`) and its major version (`0`), for amd64 and arm64. No token is in the image: each request brings its own.
481
+ `ghcr.io/kammcs/buildit-mcp` runs the server in HTTP mode on port 8765, as a non-root user, with a health check on `/healthz`. Each release is tagged with its version (`0.4.0`) and its major version (`0`), for amd64 and arm64. No token is in the image: each request brings its own.
263
482
 
264
483
  ```sh
265
484
  docker run -d -p 8765:8765 -e BUILDIT_ALLOWED_HOSTS=mcp.example.com ghcr.io/kammcs/buildit-mcp:0
@@ -281,7 +500,8 @@ docker run -i --rm -e BUILDIT_HTTP=false -e BUILDIT_TOKEN ghcr.io/kammcs/buildit
281
500
  - **The agent acts as you.** Everything it does is done with your permissions and is labelled in buildIt.Social as done through your agent.
282
501
  - **People-written content is marked.** Titles, descriptions, comments, pages and messages, the names of people, projects, channels and the like (and GitHub titles, branch names and authors) come back inside `<untrusted_content>` blocks, and the server tells the agent to treat them as data, never instructions. Each block carries a random id, repeated in its closing tag, and only that closing tag ends it. This reduces, but cannot remove, the risk of prompt injection, so prefer narrow scopes and review what an agent proposes.
283
502
  - **Destructive and admin changes are previewed and need your confirmation** ([above](#preview-then-confirm)), and their toolsets are off unless you turn them on. Read the preview before you say yes: it is what will happen.
284
- - **Chat is read only**, and never reaches direct messages.
503
+ - **Chat is read only**, and never reaches direct messages. The one exception is channel mode (`reply`, `ask`'s question cards and the approval cards), which writes only in your agent's own conversation with you. Only you can answer its cards; an answer is passed to Claude as your words inside an `untrusted_content` block, and an approval card is applied by buildIt.Social on your tap, never by the session.
504
+ - **Channel mode passes on only your own messages**, because whoever can write into a Claude Code session can steer it. A session token reaches only the projects you approved, never more than you can, and only your agent's conversation with you; revoke it in the app when you no longer need it.
285
505
  - **Logs** are JSON on stderr and never contain tokens or content.
286
506
 
287
507
  ### Hardening
@@ -304,7 +524,7 @@ buildit-mcp follows [semantic versioning](https://semver.org), and every release
304
524
  - **The API says when to update.** buildIt.Social's agent API publishes the oldest buildit-mcp release it supports (`min_mcp_version`, from `GET /v1/meta`). When this server is older, `whoami` reports `update_required: true` and asks the agent to tell you to update, and in stdio mode the server also logs a warning when it starts. It doesn't stop working by itself: calls go on as far as the API accepts them.
305
525
  - **The API says what it serves.** From API 1.1.0, `GET /v1/meta` also lists the operations the deployment serves. Once the server has read it (in stdio mode at startup, and whenever `whoami` runs), a call the deployment doesn't serve yet, such as a newer `plan_release` action, is refused with a clear message instead of reaching the API, `whoami` lists those operations (`not_served`), and arguments that need a newer API (such as `description_offset`) are refused the same way.
306
526
 
307
- To update: `npx` with `@0` picks up the newest 0.x release when the client next starts the server (run `npx -y @kammcs/buildit-mcp@0 --version` to check); with a pinned version, change the pin. From a clone, pull and rebuild.
527
+ To update: with `@latest`, npx checks for the newest release whenever the client starts the server (run `npx -y @kammcs/buildit-mcp@latest --version` to check); with a pinned version, change the pin. If a client was set up with a range such as `@0`, switch it to `@latest`: npx keeps a range's first install. From a clone, pull and rebuild. The container image's `0` tag moves with each 0.x release; `docker pull` (or `docker compose pull`) fetches it.
308
528
 
309
529
  ## Development
310
530
 
package/SECURITY.md CHANGED
@@ -37,7 +37,7 @@ Security fixes go into the latest minor release on npm, as a patch release, and
37
37
 
38
38
  | Version | Supported |
39
39
  | -------------------------------- | --------- |
40
- | The latest minor release (0.2.x) | Yes |
40
+ | The latest minor release (0.4.x) | Yes |
41
41
  | Older minor releases | No |
42
42
  | Unreleased commits on `main` | No |
43
43
 
@@ -161,6 +161,10 @@ export class ApiClient {
161
161
  * deployment, not the caller.
162
162
  */
163
163
  served;
164
+ /** Whether this client's token is an agent session token (it is refused for good once the session ends). */
165
+ get sessionToken() {
166
+ return this.token?.startsWith('buildit_ags_') === true;
167
+ }
164
168
  constructor(options) {
165
169
  this.baseUrl = options.baseUrl.replace(/\/+$/, '');
166
170
  this.token = options.token;
@@ -254,7 +258,7 @@ export class ApiClient {
254
258
  ...(options.tool ? { tool: options.tool } : {}),
255
259
  };
256
260
  const headers = {
257
- Authorization: `Bearer ${this.token}`,
261
+ ...(this.token === undefined ? {} : { Authorization: `Bearer ${this.token}` }),
258
262
  Accept: 'application/json',
259
263
  'User-Agent': USER_AGENT,
260
264
  'X-Request-Id': requestId,