@bastani/atomic 0.9.25-alpha.2 → 0.9.25-alpha.4

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 (274) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/builtin/intercom/package.json +2 -2
  3. package/dist/builtin/mcp/CHANGELOG.md +43 -0
  4. package/dist/builtin/mcp/OAUTH.md +59 -269
  5. package/dist/builtin/mcp/README.md +58 -345
  6. package/dist/builtin/mcp/index.bundle.mjs +4 -27792
  7. package/dist/builtin/mcp/native-client-licenses/LICENSES/modelcontextprotocol-typescript-sdk.txt +21 -0
  8. package/dist/builtin/mcp/native-client-licenses/NOTICE +30 -0
  9. package/dist/builtin/mcp/package.json +4 -25
  10. package/dist/builtin/subagents/package.json +3 -3
  11. package/dist/builtin/web-access/package.json +2 -2
  12. package/dist/builtin/workflows/CHANGELOG.md +12 -0
  13. package/dist/builtin/workflows/builtin/{chunk-e1254zvd.js → chunk-kfsnh3w7.js} +40 -12
  14. package/dist/builtin/workflows/builtin/{chunk-cpw5gtzg.js → chunk-rqmasd3d.js} +1 -1
  15. package/dist/builtin/workflows/builtin/{chunk-qy6g0baf.js → chunk-wz783pvd.js} +1 -1
  16. package/dist/builtin/workflows/builtin/goal.js +2 -2
  17. package/dist/builtin/workflows/builtin/index.js +3 -3
  18. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  19. package/dist/builtin/workflows/package.json +2 -2
  20. package/dist/builtin/workflows/src/extension/index.bundle.mjs +472 -88
  21. package/dist/builtin/workflows/src/index.js +65 -28
  22. package/dist/cli/args.d.ts.map +1 -1
  23. package/dist/cli/args.js +2 -1
  24. package/dist/cli/args.js.map +1 -1
  25. package/dist/core/agent-session-accessors.d.ts.map +1 -1
  26. package/dist/core/agent-session-accessors.js +7 -0
  27. package/dist/core/agent-session-accessors.js.map +1 -1
  28. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  29. package/dist/core/agent-session-extension-bindings.js +103 -7
  30. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  31. package/dist/core/agent-session-methods.d.ts +7 -1
  32. package/dist/core/agent-session-methods.d.ts.map +1 -1
  33. package/dist/core/agent-session-methods.js.map +1 -1
  34. package/dist/core/agent-session-state.d.ts.map +1 -1
  35. package/dist/core/agent-session-state.js +3 -2
  36. package/dist/core/agent-session-state.js.map +1 -1
  37. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  38. package/dist/core/agent-session-tool-registry.js +6 -3
  39. package/dist/core/agent-session-tool-registry.js.map +1 -1
  40. package/dist/core/agent-session-types.d.ts +1 -0
  41. package/dist/core/agent-session-types.d.ts.map +1 -1
  42. package/dist/core/agent-session-types.js.map +1 -1
  43. package/dist/core/agent-session.d.ts +3 -0
  44. package/dist/core/agent-session.d.ts.map +1 -1
  45. package/dist/core/agent-session.js +6 -0
  46. package/dist/core/agent-session.js.map +1 -1
  47. package/dist/core/extensions/api-types.d.ts +3 -0
  48. package/dist/core/extensions/api-types.d.ts.map +1 -1
  49. package/dist/core/extensions/api-types.js.map +1 -1
  50. package/dist/core/extensions/context-types.d.ts +3 -1
  51. package/dist/core/extensions/context-types.d.ts.map +1 -1
  52. package/dist/core/extensions/context-types.js.map +1 -1
  53. package/dist/core/extensions/index.d.ts +2 -0
  54. package/dist/core/extensions/index.d.ts.map +1 -1
  55. package/dist/core/extensions/index.js +1 -0
  56. package/dist/core/extensions/index.js.map +1 -1
  57. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  58. package/dist/core/extensions/loader-api.js +15 -0
  59. package/dist/core/extensions/loader-api.js.map +1 -1
  60. package/dist/core/extensions/loader-runtime.d.ts.map +1 -1
  61. package/dist/core/extensions/loader-runtime.js +3 -0
  62. package/dist/core/extensions/loader-runtime.js.map +1 -1
  63. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  64. package/dist/core/extensions/loader-virtual-modules.js +3 -0
  65. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  66. package/dist/core/extensions/mcp-server-registry.d.ts.map +1 -1
  67. package/dist/core/extensions/mcp-server-registry.js +4 -0
  68. package/dist/core/extensions/mcp-server-registry.js.map +1 -1
  69. package/dist/core/extensions/runner.d.ts +3 -0
  70. package/dist/core/extensions/runner.d.ts.map +1 -1
  71. package/dist/core/extensions/runner.js +4 -0
  72. package/dist/core/extensions/runner.js.map +1 -1
  73. package/dist/core/extensions/runtime-types.d.ts +3 -0
  74. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  75. package/dist/core/extensions/runtime-types.js.map +1 -1
  76. package/dist/core/extensions/tool-types.d.ts +1 -0
  77. package/dist/core/extensions/tool-types.d.ts.map +1 -1
  78. package/dist/core/extensions/tool-types.js.map +1 -1
  79. package/dist/core/extensions/workflow-run-control-hub.d.ts +23 -0
  80. package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -0
  81. package/dist/core/extensions/workflow-run-control-hub.js +57 -0
  82. package/dist/core/extensions/workflow-run-control-hub.js.map +1 -0
  83. package/dist/core/extensions/workflow-run-control.d.ts +163 -0
  84. package/dist/core/extensions/workflow-run-control.d.ts.map +1 -0
  85. package/dist/core/extensions/workflow-run-control.js +73 -0
  86. package/dist/core/extensions/workflow-run-control.js.map +1 -0
  87. package/dist/core/mcp-child-policy.d.ts +11 -0
  88. package/dist/core/mcp-child-policy.d.ts.map +1 -0
  89. package/dist/core/mcp-child-policy.js +31 -0
  90. package/dist/core/mcp-child-policy.js.map +1 -0
  91. package/dist/core/mcp-servers.d.ts +34 -25
  92. package/dist/core/mcp-servers.d.ts.map +1 -1
  93. package/dist/core/mcp-servers.js +148 -1
  94. package/dist/core/mcp-servers.js.map +1 -1
  95. package/dist/core/package-manager-manifest.js.map +1 -1
  96. package/dist/core/package-manager-mcp-servers.js +1 -1
  97. package/dist/core/package-manager-mcp-servers.js.map +1 -1
  98. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  99. package/dist/core/remote-catalog-provider.js +4 -9
  100. package/dist/core/remote-catalog-provider.js.map +1 -1
  101. package/dist/core/sdk.js +11 -1
  102. package/dist/core/sdk.js.map +1 -1
  103. package/dist/core/tool-loadout.d.ts +1 -0
  104. package/dist/core/tool-loadout.d.ts.map +1 -1
  105. package/dist/core/tool-loadout.js +3 -0
  106. package/dist/core/tool-loadout.js.map +1 -1
  107. package/dist/core/tools/bash.d.ts.map +1 -1
  108. package/dist/core/tools/bash.js +11 -30
  109. package/dist/core/tools/bash.js.map +1 -1
  110. package/dist/core/tools/truncate.d.ts +8 -0
  111. package/dist/core/tools/truncate.d.ts.map +1 -1
  112. package/dist/core/tools/truncate.js +24 -0
  113. package/dist/core/tools/truncate.js.map +1 -1
  114. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  115. package/dist/extensions/codemode/execute.js +26 -0
  116. package/dist/extensions/codemode/execute.js.map +1 -1
  117. package/dist/extensions/codemode/renderer.d.ts.map +1 -1
  118. package/dist/extensions/codemode/renderer.js +38 -23
  119. package/dist/extensions/codemode/renderer.js.map +1 -1
  120. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  121. package/dist/extensions/codemode/tool.js +22 -10
  122. package/dist/extensions/codemode/tool.js.map +1 -1
  123. package/dist/extensions/mcp/cli.d.ts +21 -0
  124. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  125. package/dist/extensions/mcp/cli.js +500 -0
  126. package/dist/extensions/mcp/cli.js.map +1 -0
  127. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  128. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  129. package/dist/extensions/mcp/cli.lazy.js +3 -0
  130. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  131. package/dist/extensions/mcp/client/auth-provider.d.ts +15 -0
  132. package/dist/extensions/mcp/client/auth-provider.d.ts.map +1 -0
  133. package/dist/extensions/mcp/client/auth-provider.js +2 -0
  134. package/dist/extensions/mcp/client/auth-provider.js.map +1 -0
  135. package/dist/extensions/mcp/client/client.d.ts +89 -0
  136. package/dist/extensions/mcp/client/client.d.ts.map +1 -0
  137. package/dist/extensions/mcp/client/client.js +457 -0
  138. package/dist/extensions/mcp/client/client.js.map +1 -0
  139. package/dist/extensions/mcp/client/index.d.ts +9 -0
  140. package/dist/extensions/mcp/client/index.d.ts.map +1 -0
  141. package/dist/extensions/mcp/client/index.js +7 -0
  142. package/dist/extensions/mcp/client/index.js.map +1 -0
  143. package/dist/extensions/mcp/client/oauth/callback.d.ts +42 -0
  144. package/dist/extensions/mcp/client/oauth/callback.d.ts.map +1 -0
  145. package/dist/extensions/mcp/client/oauth/callback.js +106 -0
  146. package/dist/extensions/mcp/client/oauth/callback.js.map +1 -0
  147. package/dist/extensions/mcp/client/oauth/discovery.d.ts +27 -0
  148. package/dist/extensions/mcp/client/oauth/discovery.d.ts.map +1 -0
  149. package/dist/extensions/mcp/client/oauth/discovery.js +153 -0
  150. package/dist/extensions/mcp/client/oauth/discovery.js.map +1 -0
  151. package/dist/extensions/mcp/client/oauth/errors.d.ts +24 -0
  152. package/dist/extensions/mcp/client/oauth/errors.d.ts.map +1 -0
  153. package/dist/extensions/mcp/client/oauth/errors.js +46 -0
  154. package/dist/extensions/mcp/client/oauth/errors.js.map +1 -0
  155. package/dist/extensions/mcp/client/oauth/flow.d.ts +82 -0
  156. package/dist/extensions/mcp/client/oauth/flow.d.ts.map +1 -0
  157. package/dist/extensions/mcp/client/oauth/flow.js +292 -0
  158. package/dist/extensions/mcp/client/oauth/flow.js.map +1 -0
  159. package/dist/extensions/mcp/client/oauth/index.d.ts +7 -0
  160. package/dist/extensions/mcp/client/oauth/index.d.ts.map +1 -0
  161. package/dist/extensions/mcp/client/oauth/index.js +6 -0
  162. package/dist/extensions/mcp/client/oauth/index.js.map +1 -0
  163. package/dist/extensions/mcp/client/oauth/provider.d.ts +59 -0
  164. package/dist/extensions/mcp/client/oauth/provider.d.ts.map +1 -0
  165. package/dist/extensions/mcp/client/oauth/provider.js +116 -0
  166. package/dist/extensions/mcp/client/oauth/provider.js.map +1 -0
  167. package/dist/extensions/mcp/client/oauth/types.d.ts +77 -0
  168. package/dist/extensions/mcp/client/oauth/types.d.ts.map +1 -0
  169. package/dist/extensions/mcp/client/oauth/types.js +109 -0
  170. package/dist/extensions/mcp/client/oauth/types.js.map +1 -0
  171. package/dist/extensions/mcp/client/protocol/content.d.ts +82 -0
  172. package/dist/extensions/mcp/client/protocol/content.d.ts.map +1 -0
  173. package/dist/extensions/mcp/client/protocol/content.js +41 -0
  174. package/dist/extensions/mcp/client/protocol/content.js.map +1 -0
  175. package/dist/extensions/mcp/client/protocol/jsonrpc.d.ts +59 -0
  176. package/dist/extensions/mcp/client/protocol/jsonrpc.d.ts.map +1 -0
  177. package/dist/extensions/mcp/client/protocol/jsonrpc.js +67 -0
  178. package/dist/extensions/mcp/client/protocol/jsonrpc.js.map +1 -0
  179. package/dist/extensions/mcp/client/protocol/types.d.ts +123 -0
  180. package/dist/extensions/mcp/client/protocol/types.d.ts.map +1 -0
  181. package/dist/extensions/mcp/client/protocol/types.js +7 -0
  182. package/dist/extensions/mcp/client/protocol/types.js.map +1 -0
  183. package/dist/extensions/mcp/client/testing/index.d.ts +2 -0
  184. package/dist/extensions/mcp/client/testing/index.d.ts.map +1 -0
  185. package/dist/extensions/mcp/client/testing/index.js +2 -0
  186. package/dist/extensions/mcp/client/testing/index.js.map +1 -0
  187. package/dist/extensions/mcp/client/transports/in-memory.d.ts +19 -0
  188. package/dist/extensions/mcp/client/transports/in-memory.d.ts.map +1 -0
  189. package/dist/extensions/mcp/client/transports/in-memory.js +50 -0
  190. package/dist/extensions/mcp/client/transports/in-memory.js.map +1 -0
  191. package/dist/extensions/mcp/client/transports/stdio.d.ts +32 -0
  192. package/dist/extensions/mcp/client/transports/stdio.d.ts.map +1 -0
  193. package/dist/extensions/mcp/client/transports/stdio.js +201 -0
  194. package/dist/extensions/mcp/client/transports/stdio.js.map +1 -0
  195. package/dist/extensions/mcp/client/transports/streamable-http.d.ts +96 -0
  196. package/dist/extensions/mcp/client/transports/streamable-http.d.ts.map +1 -0
  197. package/dist/extensions/mcp/client/transports/streamable-http.js +456 -0
  198. package/dist/extensions/mcp/client/transports/streamable-http.js.map +1 -0
  199. package/dist/extensions/mcp/client/transports/transport.d.ts +28 -0
  200. package/dist/extensions/mcp/client/transports/transport.d.ts.map +1 -0
  201. package/dist/extensions/mcp/client/transports/transport.js +38 -0
  202. package/dist/extensions/mcp/client/transports/transport.js.map +1 -0
  203. package/dist/extensions/mcp/config.d.ts +72 -0
  204. package/dist/extensions/mcp/config.d.ts.map +1 -0
  205. package/dist/extensions/mcp/config.js +158 -0
  206. package/dist/extensions/mcp/config.js.map +1 -0
  207. package/dist/extensions/mcp/index.d.ts +76 -0
  208. package/dist/extensions/mcp/index.d.ts.map +1 -0
  209. package/dist/extensions/mcp/index.js +1119 -0
  210. package/dist/extensions/mcp/index.js.map +1 -0
  211. package/dist/extensions/mcp/log.d.ts +16 -0
  212. package/dist/extensions/mcp/log.d.ts.map +1 -0
  213. package/dist/extensions/mcp/log.js +66 -0
  214. package/dist/extensions/mcp/log.js.map +1 -0
  215. package/dist/extensions/mcp/oauth.d.ts +103 -0
  216. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  217. package/dist/extensions/mcp/oauth.js +382 -0
  218. package/dist/extensions/mcp/oauth.js.map +1 -0
  219. package/dist/extensions/mcp/resources.d.ts +43 -0
  220. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  221. package/dist/extensions/mcp/resources.js +262 -0
  222. package/dist/extensions/mcp/resources.js.map +1 -0
  223. package/dist/extensions/mcp/runtime.d.ts +104 -0
  224. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  225. package/dist/extensions/mcp/runtime.js +546 -0
  226. package/dist/extensions/mcp/runtime.js.map +1 -0
  227. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  228. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  229. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  230. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  231. package/dist/extensions/mcp/tools.d.ts +84 -0
  232. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  233. package/dist/extensions/mcp/tools.js +251 -0
  234. package/dist/extensions/mcp/tools.js.map +1 -0
  235. package/dist/extensions/mcp/ui.d.ts +60 -0
  236. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  237. package/dist/extensions/mcp/ui.js +175 -0
  238. package/dist/extensions/mcp/ui.js.map +1 -0
  239. package/dist/extensions/tool-search/tool.d.ts +1 -1
  240. package/dist/extensions/tool-search/tool.d.ts.map +1 -1
  241. package/dist/extensions/tool-search/tool.js +3 -13
  242. package/dist/extensions/tool-search/tool.js.map +1 -1
  243. package/dist/index-extensions.d.ts +2 -1
  244. package/dist/index-extensions.d.ts.map +1 -1
  245. package/dist/index-extensions.js +1 -1
  246. package/dist/index-extensions.js.map +1 -1
  247. package/dist/index.d.ts +5 -1
  248. package/dist/index.d.ts.map +1 -1
  249. package/dist/index.js +5 -0
  250. package/dist/index.js.map +1 -1
  251. package/dist/main.d.ts.map +1 -1
  252. package/dist/main.js +7 -0
  253. package/dist/main.js.map +1 -1
  254. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  255. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  256. package/dist/modes/interactive/components/visual-truncate.js +39 -6
  257. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  258. package/docs/extensions/api-reference.md +3 -3
  259. package/docs/extensions/events.md +2 -0
  260. package/docs/extensions.md +8 -8
  261. package/docs/mcp-servers.md +171 -50
  262. package/docs/packages/authoring.md +2 -2
  263. package/docs/providers.md +8 -0
  264. package/docs/sdk/reference.md +16 -0
  265. package/docs/sdk.md +67 -1
  266. package/docs/settings.md +2 -0
  267. package/docs/tools.md +6 -0
  268. package/docs/workflows/operations.md +3 -1
  269. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  270. package/examples/extensions/minimal-mode.ts +28 -108
  271. package/npm-shrinkwrap.json +69 -69
  272. package/package.json +8 -8
  273. package/dist/builtin/mcp/app-bridge.bundle.js +0 -67
  274. package/dist/builtin/mcp/xdg-open +0 -1267
@@ -1,111 +1,232 @@
1
1
  ---
2
2
  title: "MCP Servers"
3
- description: "Configure MCP servers, discover tools, and authenticate connections."
3
+ description: "Configure MCP servers, discover tools and resources, and authenticate connections."
4
4
  ---
5
5
 
6
6
  # MCP Servers
7
7
 
8
- Atomic includes MCP support in both npm and binary installations. No separate extension install is needed. Use `/mcp` to inspect servers or `/mcp setup` to configure them.
8
+ Atomic includes [Model Context Protocol](https://modelcontextprotocol.io) support in npm and binary installations. It connects to servers over stdio or streamable HTTP. No separate extension install is needed.
9
9
 
10
- ## Configure a server
10
+ ## Quick setup
11
11
 
12
- Put shared project configuration in `.mcp.json` at your project root:
12
+ Add a local server, check the connection, then start Atomic:
13
+
14
+ ```sh
15
+ atomic mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem .
16
+ atomic mcp list
17
+ atomic
18
+ ```
19
+
20
+ For a remote server:
21
+
22
+ ```sh
23
+ atomic mcp add docs --url https://example.com/mcp --bearer-token-env-var DOCS_TOKEN
24
+ ```
25
+
26
+ Commands write user-level configuration by default. Add `--local` or `-l` to write `.atomic/mcp.json` in the current project instead. Start Atomic and grant project trust before using project servers.
27
+
28
+ Use `/mcp` to inspect connections and manage servers. After changing configuration outside the session, run `/reload` or restart Atomic.
29
+
30
+ ## Configure servers
31
+
32
+ Atomic reads user-level servers from `~/.atomic/agent/mcp.json` and project servers from `.atomic/mcp.json`. Project configuration is read only after [project trust](/security) is granted. A project entry replaces a user-level entry with the same name.
33
+
34
+ Both files use a top-level `mcpServers` object. Keep personal servers and credentials in the user-level file. `ATOMIC_CODING_AGENT_DIR` relocates the Atomic agent directory.
35
+
36
+ Stdio servers use `command`, `args`, `env`, and `cwd`. `command` is one executable, not a shell command string. Relative `cwd` values resolve against the session directory.
37
+
38
+ HTTP servers use `url`, optional `headers`, and optional `oauth`. For bearer authentication:
13
39
 
14
40
  ```json
15
41
  {
16
42
  "mcpServers": {
17
- "my-server": {
18
- "command": "path/to/mcp-server",
19
- "args": []
43
+ "docs": {
44
+ "url": "https://example.com/mcp",
45
+ "headers": { "Authorization": "Bearer ${DOCS_TOKEN}" },
46
+ "description": "Search and read the product documentation"
20
47
  }
21
48
  }
22
49
  }
23
50
  ```
24
51
 
25
- Replace `command` and `args` with your server's launch instructions. For a remote HTTP server, use `url` instead:
52
+ URLs support `${NAME}` and `$env:NAME` environment references. Atomic resolves them in memory before validating the URL, without rewriting configuration files. `env`, `headers`, and `oauth.clientSecret` support `${NAME}` environment references and whole-value `!command` expressions, for example `"Authorization": "!echo Bearer $(gh auth token)"`. Only use commands from configuration you trust.
53
+
54
+ Both transports support:
55
+
56
+ - `timeout`: per-request inactivity timeout in seconds, default 60. Progress notifications reset it; it is not a total execution deadline.
57
+ - `enabled: false`: keep a server listed without connecting to it.
58
+ - `exposure` and `toolExposure`: control how tools reach the model.
59
+ - `description`: a short server summary for the system prompt, tool search, and `describeNamespace()`. Without it, Atomic uses the first line of server instructions once connected.
60
+
61
+ Server names may contain letters, digits, `_`, and `-`. Names that differ only in `-` and `_` identify the same namespace. Invalid entries are reported and skipped without preventing other servers from connecting.
62
+
63
+ `type` is optional: `command` selects stdio and `url` selects streamable HTTP. If present, it must be `stdio`, `http`, or `streamable-http`. SSE is not supported; use the server's streamable HTTP endpoint, commonly `/mcp` rather than `/sse`.
64
+
65
+ ### Servers from packages and extensions
66
+
67
+ Installed [packages](/packages/authoring#mcp-servers) and extensions can contribute servers with the same configuration shape. File-configured servers take precedence over contributions with the same normalized name. Project packages load only after the project is trusted.
68
+
69
+ `/mcp` shows each server's source. Enabled-state and exposure changes for file-configured servers are saved without replacing unrelated configuration. Changes to extension-contributed servers apply to the current session.
70
+
71
+ ## Manage servers
72
+
73
+ `/mcp` opens a server manager with connection state, tool count, exposure, and source. Select a server to inspect tools and connection details, sign in or out, reconnect, enable or disable it, or change exposure. Servers that need attention appear first.
74
+
75
+ | Command | Action |
76
+ | --- | --- |
77
+ | `/mcp` | Open the manager in the TUI, or show status outside it. |
78
+ | `/mcp login [server]` | Sign in with OAuth. |
79
+ | `/mcp logout [server]` | Remove stored OAuth credentials. |
80
+ | `/mcp reconnect [server]` | Reconnect a server and refresh its tools. |
81
+
82
+ Command completion suggests actions and eligible server names. When a server name is omitted, Atomic selects an eligible server when the choice is unambiguous; otherwise it asks you to choose. Session login requires an interactive UI. Shell login opens the browser without starting a session; authenticate before unattended work.
83
+
84
+ Enabled servers connect in the background when a session starts. The first prompt waits up to 10 seconds for servers with `direct` tools. Codemode, tool search, and resource calls wait for the servers they need. A dropped connection reconnects on the next call. Changes announced by a server update the available tools; withdrawn tools become unreachable.
85
+
86
+ ### Shell commands
87
+
88
+ Shell commands use file-configured servers and do not load extensions:
89
+
90
+ ```sh
91
+ atomic mcp add <server> [options] -- <command> [args...]
92
+ atomic mcp add <server> [options] --url <url>
93
+ atomic mcp remove <server> [-l]
94
+ atomic mcp list [--json]
95
+ atomic mcp login <server> [--timeout <seconds>]
96
+ atomic mcp logout <server>
97
+ ```
98
+
99
+ `add` replaces an existing entry of the same name. `add` and `remove` accept `--local` (`-l`) for the project file. For stdio, use repeatable `--env KEY=VALUE` and `--cwd`. For HTTP, use repeatable `--header KEY=VALUE`, `--bearer-token-env-var NAME`, and `--oauth-client-id`, `--oauth-client-secret`, `--oauth-callback-port`, or `--oauth-client-name`. Both transports accept `--exposure` and `--description`. Run `atomic mcp --help` for usage.
100
+
101
+ `list` connects to enabled servers and reports state, tools, and errors; it exits with status 1 for invalid configuration or an enabled server that is not connected. `--json` produces a machine-readable report. Login waits up to 300 seconds by default; `--timeout` changes that browser-login budget, not the server request timeout. A running session uses new credentials on its next turn.
102
+
103
+ ## Find and call tools
104
+
105
+ Tools are named `mcp__<server>__<tool>`, with punctuation replaced by `_`. Names that collide after normalization receive deterministic hash suffixes. Use names returned by discovery rather than constructing them yourself.
106
+
107
+ ### Control tool exposure
108
+
109
+ | Exposure | Behavior |
110
+ | --- | --- |
111
+ | `codemode`, the default | Callable from codemode scripts, but not declared to the model or listed in the codemode description. Discover with `searchTools()`, `describeTool()`, or `ALL_TOOLS`. |
112
+ | `deferred` | Not declared until `tool_search` loads a matching tool for the next model call. |
113
+ | `direct` | Declared like a built-in tool and also callable from codemode. |
114
+ | `hidden` | Unreachable. |
115
+
116
+ `codemode-deferred` is accepted as an alias for `codemode`. Atomic activates `codemode` for codemode servers and `tool_search` for deferred servers. Set `"autoEnableCodemode": false` beside `mcpServers` to prevent automatic codemode activation. A project value overrides a user-level value.
117
+
118
+ `toolExposure` overrides individual tools. Keys are original server tool names or patterns where `*` matches any characters. Exact names win; among patterns, the first match wins:
26
119
 
27
120
  ```json
28
121
  {
29
122
  "mcpServers": {
30
- "my-server": {
31
- "url": "https://example.com/mcp"
123
+ "github": {
124
+ "url": "https://api.githubcopilot.com/mcp/",
125
+ "exposure": "deferred",
126
+ "toolExposure": {
127
+ "search_code": "direct",
128
+ "get_*": "codemode",
129
+ "delete_*": "hidden"
130
+ }
32
131
  }
33
132
  }
34
133
  }
35
134
  ```
36
135
 
37
- Remote `url` values support `${VAR}` and `$env:VAR` environment variable interpolation in both project and user configuration. For example, commit this server entry and set `MY_SERVICE_URL` and `MY_SERVICE_TOKEN` in the environment that launches Atomic:
136
+ Codemode and deferred tools can be reached through either indirect mechanism. Server summaries appear in the `mcp_servers` system prompt section. Scripts can read instructions and tool names with `describeNamespace("mcp__github")`.
38
137
 
39
- ```json
40
- { "url": "${MY_SERVICE_URL}/mcp", "auth": "bearer", "bearerTokenEnv": "MY_SERVICE_TOKEN" }
41
- ```
138
+ Codemode receives the complete MCP result, including `content`, `structuredContent`, and `isError`. Text over 20 KB is shortened for the model, with the complete text saved to a temporary file named in the result. Every MCP call passes through Atomic's tool pipeline, including permission hooks.
42
139
 
43
- With `MY_SERVICE_URL=https://example.com`, the endpoint is `https://example.com/mcp`. Unset variables become empty strings.
140
+ ## Use resources
44
141
 
45
- The resolved endpoint must be a non-empty HTTP(S) URL. If Atomic reports a configuration error before connecting, check the variables in its environment and the URL suffix. Restart Atomic after changing its environment.
142
+ When a connected server offers resources, Atomic registers:
46
143
 
47
- Atomic reads configuration in this order, with later files overriding earlier settings:
144
+ - `list_mcp_resources`, to list resources. Use `server` for one server and `cursor` for its next page; without `server`, it lists resources across servers.
145
+ - `list_mcp_resource_templates`, to list URI templates.
146
+ - `read_mcp_resource`, to read by `server` and `uri`. Text and images reach the model directly; other binary content is saved to a temporary file.
48
147
 
49
- 1. `~/.config/mcp/mcp.json`, shared user-global configuration.
50
- 2. `~/.atomic/agent/mcp.json`, Atomic user-global overrides.
51
- 3. `.mcp.json`, shared project configuration.
52
- 4. `.atomic/mcp.json`, Atomic project overrides.
148
+ These tools reach enabled, non-hidden resource servers. Their exposure is the widest exposure among those servers. Resource links in tool results identify the server and `read_mcp_resource`.
53
149
 
54
- The Atomic agent directory can be relocated with `ATOMIC_CODING_AGENT_DIR`. Use `/mcp setup` to inspect detected configuration and preview imports from other hosts before writing changes.
150
+ MCP Apps resources (`ui://` URIs or `text/html;profile=mcp-app`) are omitted because Atomic does not render them.
55
151
 
56
- Servers connect lazily by default. Adding a server does not require an immediate connection at startup.
152
+ ## Authentication
153
+
154
+ For a remote OAuth server, configure its URL and run `/mcp login my-server`, or select **Sign in** in `/mcp`. Atomic opens the authorization page and displays a clickable URL. If the browser runs on another machine, paste the complete URL it was redirected to into the sign-in prompt. Treat authorization and redirect URLs as sensitive.
57
155
 
58
- ## Servers from packages and extensions
156
+ Atomic registers OAuth clients as `atomic`, stores credentials in `~/.atomic/agent/mcp-auth.json`, and refreshes tokens when they expire or are rejected. A successful sign-in reconnects the server. If additional scope is required, sign in again. `/mcp logout my-server` or `atomic mcp logout my-server` deletes stored credentials. Old adapter credential files are not imported; sign in through the native client.
59
157
 
60
- Installed [packages](/packages/authoring#mcp-servers) and extensions can contribute MCP servers. Contributed servers sit below all four configuration files: a server with the same name in any of them replaces the contributed entry completely. To turn a contributed server off, give its name an entry with only `disabled`:
158
+ OAuth applies to HTTP servers without an `Authorization` header or provider-token configuration. For a pre-registered client:
61
159
 
62
160
  ```json
63
161
  {
64
162
  "mcpServers": {
65
- "acme-search": { "disabled": true }
163
+ "example": {
164
+ "url": "https://mcp.example.com/mcp",
165
+ "oauth": {
166
+ "clientId": "my-client",
167
+ "clientSecret": "${EXAMPLE_SECRET}",
168
+ "callbackPort": 8765,
169
+ "scope": "read write"
170
+ }
171
+ }
66
172
  }
67
173
  }
68
174
  ```
69
175
 
70
- `"disabled": true` removes any server from the effective configuration, contributed or not.
176
+ `clientSecret` is optional. `callbackPort` uses `http://127.0.0.1:<port>/callback`. For another registered redirect URI, set `callbackUrl`; it must use HTTP on `localhost`, `127.0.0.1`, or `[::1]`. Atomic sends it as written. If it has no port, Atomic adds `callbackPort` or a free port. The URI must match the client's registration.
71
177
 
72
- `/mcp` shows where each contributed server came from next to its name: `(package npm:@acme/tools)` for a package manifest, `(extension from package npm:@acme/tools)` for a package's extension, or `(extension /path/to/extension.ts)` for a local extension. Connection errors name the same source. Turning on direct tools for a contributed server in `/mcp` copies its definition into `~/.atomic/agent/mcp.json`, where it then overrides the contributed version.
178
+ Use `oauth.clientName` when a server requires a known registration name. Sign out before signing in again to register with a changed name. Use `oauth.scope` for servers that do not advertise their required scopes; later scope requests are added to it.
73
179
 
74
- To choose which servers one package contributes, add `mcpServers` patterns to its [package filter](/packages/reference#package-filtering). Project packages contribute servers only after the project is trusted. Workflow stages see the same contributed servers as the session that starts them.
180
+ ### Override OAuth authorization server discovery
75
181
 
76
- ## Find and call tools
182
+ If a server advertises the wrong authorization server or none, set `oauth.authServerMetadataUrl` to a trusted RFC 8414 or OpenID Connect metadata document:
183
+
184
+ ```json
185
+ {
186
+ "mcpServers": {
187
+ "example": {
188
+ "url": "https://mcp.example.com/mcp",
189
+ "oauth": { "authServerMetadataUrl": "https://example.okta.com/.well-known/openid-configuration" }
190
+ }
191
+ }
192
+ }
193
+ ```
194
+
195
+ Atomic uses the document instead of authorization server discovery and trusts its issuer as configured. Point it only at a document you trust. The URL must use HTTPS, except for HTTP on `localhost`, `127.0.0.1`, or `[::1]`.
196
+
197
+ Atomic rejects authorization responses whose `iss` names another issuer, before exchanging the code. If the server promises the RFC 9207 issuer parameter, the response must include it. Empty or null optional token and registration fields count as absent. An empty refresh token does not replace a previously stored one, and `expires_in: null` does not immediately expire the access token.
77
198
 
78
- The `mcp` gateway discovers tools without adding every server's full tool definitions to the session:
199
+ ### Authenticate with a provider login
79
200
 
80
- ```js
81
- mcp({ server: "my-server" })
82
- mcp({ search: "search" })
83
- mcp({ describe: "my_server_search" })
84
- mcp({ tool: "my_server_search", args: '{"query":"example"}' })
201
+ An HTTP server can use your current provider login token instead of MCP OAuth:
202
+
203
+ ```json
204
+ { "mcpServers": { "radius": { "url": "https://radius.example/mcp", "auth": { "provider": "radius" } } } }
85
205
  ```
86
206
 
87
- Use the tool names returned by discovery. `args` is a JSON string, not an object. Search may connect configured servers when their metadata has not yet been cached.
207
+ Atomic reads the current token for every request and does not copy it into MCP credential storage. If the token is missing or rejected, run `/login <provider>` and retry the MCP call.
88
208
 
89
- To expose a server's tools directly in the agent's tool list, add `"directTools": true` to that server's configuration. To expose only selected tools, set `directTools` to an array of the original MCP tool names. The default is gateway-only access.
209
+ Because the credential goes to the configured server, provider-token authentication has these limits:
90
210
 
91
- In a headless SDK session, cached direct tools are available at startup, but discovery does not connect uncached lazy servers. Call the `mcp` gateway when you need them. Set the server's `lifecycle` to `"eager"` or `"keep-alive"` if it must connect during startup.
211
+ - It is accepted only from global configuration and extension registrations, not project configuration or package manifests.
212
+ - The URL must use HTTPS, except for HTTP on `localhost`, `127.0.0.1`, or `[::1]`.
213
+ - Tokens are sent only to the server's origin. Only same-origin `307` and `308` redirects are followed.
92
214
 
93
- ## Authentication
215
+ ## Native configuration only
94
216
 
95
- For an OAuth server, run `/mcp-auth my-server` in an interactive session. You can also select the server in `/mcp` and press Enter or `Ctrl+A`. Run `/mcp logout my-server` to remove stored OAuth credentials and disconnect.
217
+ The old adapter has been replaced by the native client. Only `~/.atomic/agent/mcp.json` and trusted `.atomic/mcp.json` files are read; shared configuration files and client imports are not supported. Use the native fields documented above. Old adapter fields are not translated, and old OAuth credential files are not imported.
96
218
 
97
- Automatic OAuth is opt-in through `settings.autoAuth`. Browser-based authorization requires an interactive session; authenticate before running unattended work.
219
+ Tools use `mcp__<server>__<tool>` names and default to `codemode` exposure. The old gateway tool, configurable prefixes, lazy/idle lifecycle settings, metadata cache, SSE transport, MCP Apps rendering, and setup command are not available. All enabled servers connect in the background.
98
220
 
99
221
  ## Troubleshooting
100
222
 
101
- - Run `/mcp` to check server status and `/mcp tools` to list available tools.
102
- - After editing configuration manually, restart Atomic to load it. Use `/mcp reconnect my-server` to reconnect a configured server and refresh its tools.
103
- - If Atomic cannot open the authorization browser, use the complete URL it displays for manual login. **Treat it as sensitive**: it includes all paths, parameters, and any credentials. Login instructions are not redacted; transport and RPC error diagnostics are.
104
- Browser-launch failure cancels the pending attempt, so its callback cannot complete authentication. Check your default browser and retry `/mcp-auth my-server`.
105
- - If a local server cannot start, check its executable, arguments, working directory, and required environment variables. Server configuration supports `cwd` and `env`.
106
- - If authorization fails, run `/mcp-auth my-server` again. Check the remote server's URL and authentication requirements.
107
- - For slow tools, a server's `timeoutMs` controls the inactivity timeout. Progress notifications reset it; it is not a total execution deadline.
223
+ - Run `/mcp` to inspect connection errors, server tools, and the tail of a failed stdio server's stderr.
224
+ - After editing configuration, run `/reload` or restart Atomic. Use `/mcp reconnect my-server` to retry a connection and refresh tools.
225
+ - For a missing tool, check server and per-tool exposure. `hidden` tools cannot be called; codemode or deferred tools need an active discovery tool.
226
+ - For OAuth redirect failures, check `callbackPort` and `callbackUrl` against the registered URI. Over SSH, paste the complete redirected URL into the waiting sign-in prompt.
227
+ - For an issuer mismatch, check the authorization server's metadata and callback configuration before retrying. Do not disable issuer checks to accept an unexpected response.
228
+ - For slow calls, adjust `timeout` in seconds. Progress resets this inactivity timer.
108
229
 
109
230
  ## Local documentation
110
231
 
111
- This guide is available at `docs/mcp-servers.md` under Atomic's installation root in both npm and binary installations. The session's documentation instructions provide the absolute docs directory. Read this guide there rather than looking inside the bundled extension directory.
232
+ This guide is available at `docs/mcp-servers.md` under Atomic's installation root in npm and binary installations. The session's documentation instructions provide the absolute docs directory.
@@ -41,14 +41,14 @@ A package can contribute [MCP servers](/mcp-servers) with `mcpServers`. Point it
41
41
  {
42
42
  "atomic": {
43
43
  "mcpServers": {
44
- "acme-search": { "url": "https://mcp.acme.dev", "auth": "bearer", "bearerTokenEnv": "ACME_TOKEN" },
44
+ "acme-search": { "url": "https://mcp.acme.dev", "headers": { "Authorization": "Bearer ${ACME_TOKEN}" } },
45
45
  "acme-local": { "command": "node", "args": ["./dist/server.js"], "cwd": "." }
46
46
  }
47
47
  }
48
48
  }
49
49
  ```
50
50
 
51
- Entries use the same schema as `mcp.json`, including `${VAR}` interpolation, `lifecycle`, and `timeoutMs`. A relative `cwd` is resolved against the package root, so `"cwd": "."` lets a stdio server run files shipped in the package. MCP servers are only read from the manifest, never from a convention directory.
51
+ Entries use the same schema as `mcp.json`, including URL environment-variable interpolation, tool `exposure`, per-tool `toolExposure`, and request `timeout` in seconds. A relative `cwd` is resolved against the package root, so `"cwd": "."` lets a stdio server run files shipped in the package. MCP servers are only read from the manifest, never from a convention directory. Package manifests cannot select provider login credentials with `auth.provider`.
52
52
 
53
53
  Contributed servers have the lowest precedence: users can replace or disable one by name in their own MCP configuration, and filter them with `mcpServers` patterns in settings. Project packages contribute servers only in trusted projects. For a server whose configuration is computed at runtime, call [`pi.registerMcpServer()`](/extensions/api-reference#pi-registermcpserver-name-config) from an extension.
54
54
 
package/docs/providers.md CHANGED
@@ -124,12 +124,20 @@ Anthropic fast mode delivers up to 2.5x higher output tokens per second at twice
124
124
 
125
125
  Anthropic subscription auth is active for Claude Pro/Max accounts. Third-party harness usage draws from [extra usage](https://claude.ai/settings/usage) and is billed per token, not against Claude plan limits.
126
126
 
127
+ Run `/login anthropic` and choose subscription authentication. **Browser login (default)** uses a local callback and still accepts a pasted redirect URL. Choose **Copy code login (headless)** when your browser runs on another machine: complete sign-in in that browser, then paste the `code#state` value Anthropic displays into Atomic. This method does not need a reachable local callback.
128
+
127
129
  For gateway-issued Anthropic bearer credentials, set `ANTHROPIC_AUTH_TOKEN` without `ANTHROPIC_API_KEY` or `ANTHROPIC_OAUTH_TOKEN`. A populated bearer token counts as configured Anthropic authentication, so `/model`, saved/default selection, cycling, RPC catalogs, and isolated model pickers keep Anthropic models available. Atomic sends it as `Authorization: Bearer …` for normal turns, branch summaries, and Verbatim Compaction without replacing caller-supplied custom headers.
128
130
 
129
131
  Claude Opus 5 is available from the bundled/dynamic Anthropic and Amazon Bedrock catalogs. With bearer-only Anthropic auth, select the exact `anthropic/claude-opus-5-*` entry through `/model`; Bedrock uses its catalog-advertised inference profile. `xhigh` appears only when the chosen entry advertises it. Bedrock requests retain adaptive thinking, prompt caching, and AWS validation/error details from the provider runtime.
130
132
 
131
133
  `ANTHROPIC_AUTH_TOKEN` is specifically for Anthropic-compatible gateways that require a bearer header. It does not synthesize an API key or `x-api-key`, and callers may still add independent custom headers/base URLs through `models.json` or an extension. Empty environment variables do not count as configured. If token and API-key sources are both configured, normal credential resolution rules apply; avoid setting both accidentally.
132
134
 
135
+ ### Anthropic workload identity federation
136
+
137
+ With no Anthropic key, bearer token, or login configured, Atomic uses workload identity federation when `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, and `ANTHROPIC_IDENTITY_TOKEN_FILE` are all set. The Anthropic SDK exchanges the identity token for a short-lived access token and refreshes it, re-reading the token file each time, so keep that file fresh in long sessions. `ANTHROPIC_SERVICE_ACCOUNT_ID` and `ANTHROPIC_WORKSPACE_ID` are sent when set.
138
+
139
+ Keys, `ANTHROPIC_AUTH_TOKEN`, and custom authorization headers take precedence. Federation applies only to the `anthropic` provider, not to other Anthropic-compatible providers.
140
+
133
141
  ### GitHub Copilot
134
142
 
135
143
  - Press Enter for github.com, or enter your GitHub Enterprise Server domain
@@ -849,6 +849,22 @@ type EditDiffResult
849
849
  SessionManager
850
850
  SettingsManager
851
851
 
852
+ // Workflow run control (session.workflows)
853
+ type SessionWorkflows
854
+ type WorkflowRunSummary
855
+ type WorkflowRunDetail
856
+ type WorkflowRunControlOutcome
857
+ type WorkflowRunControlFailedRun
858
+ WorkflowRunControlError
859
+ WorkflowRunNotFoundError
860
+ WorkflowRunOwnershipError
861
+ WorkflowRunNotResumableError
862
+ WorkflowStageNotFoundError
863
+ WorkflowStageAmbiguousError
864
+ WorkflowStageResumeUnsupportedError
865
+ WorkflowRunDatabaseError
866
+ WorkflowRunControlUnavailableError
867
+
852
868
  // Tool factories
853
869
  createCodingTools
854
870
  createReadOnlyTools
package/docs/sdk.md CHANGED
@@ -210,7 +210,7 @@ To continue a saved run in another session:
210
210
 
211
211
  1. Keep its definition and durable storage available.
212
212
  2. Bind the new host.
213
- 3. Use `/workflow resume <run-id>` or the workflow tool's `resume` action.
213
+ 3. Use `session.workflows.resume(runId)` ([Workflow run control](#workflow-run-control)), `/workflow resume <run-id>`, or the workflow tool's `resume` action.
214
214
 
215
215
  Rebinding alone does not reopen a saved run. See [workflow operations](/workflows/operations) for inspection, graceful quit, and resume.
216
216
 
@@ -226,6 +226,69 @@ Rebinding host callbacks preserves pending MCP OAuth ownership. Authorization st
226
226
 
227
227
  Web provider configuration caches are session-local. Configuration discovery and environment keys are unchanged; create a new session to pick up changed cached settings. GitHub extraction returns the owned clone path for use with file tools, so callers need not predict its directory.
228
228
 
229
+ ### Workflow run control
230
+
231
+ `session.workflows` manages the workflow runs that this session owns, without slash commands or the model-facing `workflow` tool. It uses the same run-control service as the tool, so ownership and durability rules are identical: a run owned by another session, or executing in another live Atomic process, stays read-only here.
232
+
233
+ ```typescript
234
+ interface SessionWorkflows {
235
+ listRuns(filter?: { status?: WorkflowRunFilterStatus }): Promise<readonly WorkflowRunSummary[]>;
236
+ getRun(runId: string): Promise<WorkflowRunDetail>;
237
+ getStages(runId: string, filter?: { status?: WorkflowStageStatus }): Promise<readonly WorkflowRunStageSummary[]>;
238
+ pause(runId: string, options?: { stageId?: string }): Promise<WorkflowRunControlOutcome>;
239
+ pause(target: { all: true }): Promise<WorkflowRunControlOutcome>;
240
+ quit(target: string | { all: true }): Promise<WorkflowRunControlOutcome>;
241
+ resume(runId: string, options?: { stageId?: string; message?: string }): Promise<WorkflowRunControlOutcome>;
242
+ }
243
+ ```
244
+
245
+ `listRuns()` returns the same per-run data as `workflow status`: id, workflow name, status, active stages, and unanswered prompts (`awaitingInput`). Run IDs accept the full UUID or a unique 8-character prefix. `getRun()`, `getStages()`, `pause()` and `quit()` resolve a prefix against the runs this session holds and reject it at once when none matches, so pass the full UUID for a run recorded by an earlier process. `pause`, `quit` and `resume` resolve with the tool's acknowledged outcome: `action`, `runId` (`--all` for a batch), a `status` of `ok`, `running`, `paused`, `partial`, `noop` or `cancelled`, and a human-readable `message`. A `noop` means the request was understood and found nothing to change, such as pausing a run that already ended. A `partial` outcome means part of the request took effect. For `pause({ all: true })` and `quit({ all: true })`, `partial` means this call stopped at least one run and others are still active: `failedRuns` lists each run that is still active with its `runId`, a `reason` (for example `pause_failed` or `no_active_stages`) and a `message`, so check `outcome.status === "partial"` before treating a batch stop as complete. If active runs could not be stopped and this call stopped none, the call rejects with `WorkflowRunControlError` (`WORKFLOW_RUN_CONTROL_FAILED`) whose `failedRuns` carries the same list, even when other runs were already paused. Runs that are already paused or already ended are not failures, and a batch with no active run left to stop resolves as a `noop`. Call `getRun()` before retrying.
246
+
247
+ Pausing a run doesn't park a stage that is waiting on a prompt. Such a run reports `paused` and counts as already paused, because nothing in it advances on its own. If your host then answers that prompt, the stage can continue its turn before you call `resume`. To keep a paused run fully stopped, hold prompt answers until you resume it.
248
+
249
+ Requests that cannot be carried out reject with a subclass of `WorkflowRunControlError`. Branch on `code` or use `instanceof`:
250
+
251
+ | Class | `code` | Meaning |
252
+ | --- | --- | --- |
253
+ | `WorkflowRunNotFoundError` | `WORKFLOW_RUN_NOT_FOUND` | The run ID is unknown or malformed, or a prefix is ambiguous or matches no run in this session. |
254
+ | `WorkflowRunOwnershipError` | `WORKFLOW_RUN_OWNED_ELSEWHERE` | The run belongs to another session, or is running in another live Atomic process. Control it from its owner. |
255
+ | `WorkflowRunNotResumableError` | `WORKFLOW_RUN_NOT_RESUMABLE` | The run completed, was killed, or has no durable progress to resume. |
256
+ | `WorkflowStageNotFoundError` | `WORKFLOW_STAGE_NOT_FOUND` | `stageId` matches no stage of the run, or the stage has no control to pause. |
257
+ | `WorkflowStageAmbiguousError` | `WORKFLOW_STAGE_AMBIGUOUS` | `stageId` matches more than one stage; pass a more specific identifier. |
258
+ | `WorkflowStageResumeUnsupportedError` | `WORKFLOW_STAGE_RESUME_UNSUPPORTED` | A durable run resumes as a whole; call `resume()` without `stageId`. |
259
+ | `WorkflowRunDatabaseError` | `WORKFLOW_RUN_DATABASE` | Workflow durability is unavailable, including when the database cannot be inspected to check a run's owner during `pause()` or `quit()`. Restore the database, then inspect the run before retrying. |
260
+ | `WorkflowRunControlError` | `WORKFLOW_RUN_CONTROL_FAILED` | Another failure; `message` explains it. |
261
+ | `WorkflowRunControlUnavailableError` | `WORKFLOW_RUN_CONTROL_UNAVAILABLE` | The workflows package is disabled, or the session was disposed. |
262
+
263
+ Each error carries the `runId` when one applies. A refused batch also carries `failedRuns`.
264
+
265
+ A host with a stop button can pause its session's runs and resume the same runs later:
266
+
267
+ ```typescript
268
+ import { createAgentSession, WorkflowRunControlError } from "@bastani/atomic";
269
+
270
+ const { session } = await createAgentSession();
271
+
272
+ async function onStopClicked() {
273
+ const outcome = await session.workflows.pause({ all: true });
274
+ showStatus(outcome.message);
275
+ }
276
+
277
+ async function onResumeClicked() {
278
+ for (const run of await session.workflows.listRuns({ status: "paused" })) {
279
+ try {
280
+ const outcome = await session.workflows.resume(run.runId);
281
+ showStatus(`${run.name}: ${outcome.message}`);
282
+ } catch (error) {
283
+ if (!(error instanceof WorkflowRunControlError)) throw error;
284
+ showStatus(`${run.name}: ${error.code}: ${error.message}`);
285
+ }
286
+ }
287
+ }
288
+ ```
289
+
290
+ `pause` holds the live run and keeps it resumable in this process; `quit` retires the executor at a durability boundary so a later process can resume it. After `quit`, or when resuming a run from a previous process, `resume` follows the durable resume path: keep the workflow definition and durable storage available. See [pausing, quitting, and resuming](/workflows/operations#pausing-quitting-and-resuming) for what each action guarantees. To watch runs change instead of polling `listRuns()`, use the observation contract in [Workflow activity and lifecycle hooks](/extensions/events#workflow-activity-and-lifecycle-hooks).
291
+
229
292
  ### Workflow and subagent children
230
293
 
231
294
  Children inherit the invoking session's model/auth runtime, settings, agent directory, human-input callbacks, and diagnostic sink. Choosing a child model or fallback does not switch to global credentials.
@@ -275,6 +338,9 @@ interface AgentSession {
275
338
  sessionFile: string | undefined;
276
339
  sessionId: string;
277
340
 
341
+ // Typed control of the workflow runs this session owns
342
+ readonly workflows: SessionWorkflows;
343
+
278
344
  // Model and thinking control
279
345
  setModel(model: Model): Promise<void>;
280
346
  setThinkingLevel(level: ThinkingLevel): void;
package/docs/settings.md CHANGED
@@ -476,6 +476,8 @@ A list containing only modifiers starts from Atomic's standard defaults. Modifie
476
476
 
477
477
  Plain names establish a replacement list before its modifiers apply. A project list of only modifiers layers over the global selection. A project list with plain names, or an empty list, replaces the global selection. For example, global `["read", "bash"]` plus project `["-bash", "+ls"]` resolves to `["read", "ls"]`.
478
478
 
479
+ `/reload` enables tools newly added to `defaultTools`. It does not disable removed tools or re-enable unchanged tools you turned off during the session. Explicit `--tools`, `--no-tools`, and `--no-builtin-tools` choices override the setting on reload too; excluded tools remain excluded.
480
+
479
481
  `codemode` and `tool_search` are built-in extension tools registered inactive. Add `"+codemode"` or `"+tool_search"` to `defaultTools` to activate them alongside ordinary defaults. See [codemode](/tools#codemode) and [tool search](/tools#tool_search) for usage and safety boundaries.
480
482
 
481
483
  ### Sessions
package/docs/tools.md CHANGED
@@ -41,16 +41,22 @@ Use `text(value)`, `image(dataUrlOrImageContent)`, `console.log(...)`, or a top-
41
41
  return await tools.read({ path: "README.md" });
42
42
  ```
43
43
 
44
+ `image()` accepts base64 PNG, JPEG, GIF, or WebP data URLs and MCP image content. It detects the MIME type from the data, ignores an incorrect supplied type, and rejects malformed base64 or unsupported formats before returning an image. Remote HTTP image URLs are not supported; fetch the image through a permitted tool first.
45
+
44
46
  There is no default deadline. Text output defaults to 10,000 estimated tokens; longer output keeps its start and end and, when saving succeeds, names a temporary file containing the full text. Failed scripts retain partial output and report the error. Unawaited calls are cancelled when a script ends; await work you need to finish.
45
47
 
46
48
  Tools with `outputSchema` return their `structuredContent` to scripts, including structured error results. Other tools return text and throw on errors. Completed `bash` calls provide structured output as described in the [SDK reference](/sdk/reference#bash-tool-behavior).
47
49
 
48
50
  `ALL_TOOLS`, `searchTools(query, { limit, namespace })`, and `describeTool(name)` discover the currently permitted tools. `store(key, value)` and `load(key)` preserve JSON values across successful calls on the current session branch, including after resume. Failed scripts discard store writes, not tool side effects. `models.getModelsOfType`, `getAvailableOfType`, and `getModelOfType` expose public catalog metadata; `models.classify(model, context)` calls a registered classifier with host-resolved credentials, at most four concurrently. Reported classifier usage contributes to the script's session cost.
49
51
 
52
+ Use `await describeNamespace(name)` to retrieve a callable tool namespace's `{ name, description?, instructions?, tools }`, or `undefined` when it is unavailable. Namespace instructions are returned on request rather than included in inline listings. `searchTools()` also searches those instructions; pass `{ namespace: name }` to restrict the search.
53
+
50
54
  Set [codemode settings](/settings#tools) to control inline declaration size and whether ordinary direct tool declarations remain visible. Atomic's existing [MCP host](/mcp-servers) remains the only MCP connection/configuration owner: codemode calls the permitted gateway or direct tools, not a second MCP host. Use MCP discovery for server tools not yet registered in the session.
51
55
 
52
56
  ## `tool_search`
53
57
 
58
+ Deferred tools and their namespaces are omitted from codemode's inline catalog. Discover them with `searchTools()`, `describeNamespace()`, or `ALL_TOOLS`; `tool_search` can load matching registered tools for direct calls.
59
+
54
60
  `tool_search` is inactive by default. Enable it with `"defaultTools": ["+tool_search"]` or include it in `--tools`. It ranks currently registered `codemode` and `deferred` tools by their metadata and activates matching tools for the next model call. It does not bypass session tool restrictions or replace MCP server discovery.
55
61
 
56
62
  ## `code_search`
@@ -372,6 +372,8 @@ This reopens only the conversation. The workflow DAG and terminal stage snapshot
372
372
 
373
373
  Workflow stages and their subagent transcripts are excluded from ordinary `/resume`, `atomic -r`, `--continue`, and global history. Use workflow inspection and resume commands for stages; terminal subagents remain transcript artifacts, not resumable children. An explicit `--session` file path can still open a stage transcript. Older unmarked workflow sessions may remain in ordinary history.
374
374
 
375
+ Embedding hosts can run the same pause, quit, and resume actions programmatically with `session.workflows`; see [Workflow run control](/sdk#workflow-run-control).
376
+
375
377
  ## Workflow activity for extensions
376
378
 
377
379
  Extensions can subscribe with `ctx.observeWorkflowActivity(observer)` and use the typed `workflow_lifecycle`, `workflow_activity_changed`, `workflow_stage_completed`, and `workflow_heartbeat` hooks. See [Workflow activity and lifecycle hooks](/extensions/events#workflow-activity-and-lifecycle-hooks) for the public types and subscription example.
@@ -470,7 +472,7 @@ If a resume continuation reports `cleanup skipped: database admission unavailabl
470
472
 
471
473
  While root registration is pending, status shows `pending` with phase `starting`, not healthy execution. Status listing and exact-run detail include `phase`, `phaseAgeMs`, `dependencyError`, and `lastProgressAt`. Last progress records admission or a tracked node starting/settling, not polling or a heartbeat. Database failures report `blocked_dependency`; a paused run still reports `paused`. Starting and dependency-blocked runs do not emit "still running" heartbeats.
472
474
 
473
- For an admitted live executor with no active stage or tool, pause installs a local barrier immediately and acknowledges within 500ms of starting database settlement. The acknowledgement and status distinguish `observed` from `durable` control persistence. If confirmation is still pending at acknowledgement, settlement continues in the background for up to 10 seconds total. Status becomes `durable` on success; only a settlement failure or deadline reports `blocked_dependency`. `observed` is not proof of a saved pause and does not guarantee cross-process resume. During registration, pause acknowledges immediately while database settlement continues in the background. After registration, resume allows up to 10 seconds for database confirmation before releasing the barrier. A failed resume leaves the executor paused; restore database availability and retry the same run. These limits do not cover stage cancellation or arbitrary external I/O.
475
+ For an admitted live executor with no active stage or tool, pause installs a local barrier immediately and acknowledges within 500ms of starting database settlement. The acknowledgement and status distinguish `observed` from `durable` control persistence. If confirmation is still pending at acknowledgement, settlement continues in the background for up to 10 seconds total. Status becomes `durable` on success; only a settlement failure or deadline reports `blocked_dependency`. `observed` is not proof of a saved pause and does not guarantee cross-process resume. During registration, pause acknowledges immediately while database settlement continues in the background. After registration, resume allows up to 10 seconds for database confirmation before releasing the barrier, and a resume requested while the pause's confirmation is still pending waits for it within that same 10 seconds instead of cancelling it. A failed resume leaves the executor paused; restore database availability and retry the same run. These limits do not cover stage cancellation or arbitrary external I/O.
474
476
 
475
477
  If registration times out or reports an unavailable database while the run is paused, restore the existing database without resetting data, then resume that same run in the same Atomic process. Resume retries registration with the original identity and releases the existing executor once; repeated concurrent resume requests share the retry and do not start another executor. If the run was not paused, admission failure ends the attempt. A non-retryable admission rejection, such as a permission error, is reported on resume instead of retrying the live executor. Retain the full run ID and inspect it before retrying. Completed checkpoints remain reusable, but an external side effect whose checkpoint was never confirmed can still repeat after a crash; make such operations idempotent.
476
478
 
@@ -12,8 +12,8 @@
12
12
  *
13
13
  * How it works:
14
14
  * - registerTool() with the same name as a built-in replaces it entirely
15
- * - We create instances of the original tools via createReadTool(), etc.
16
- * and delegate execute() to them
15
+ * - We create the original definitions via createReadToolDefinition(), etc.
16
+ * and override only their renderers
17
17
  * - renderCall() controls what's shown when the tool is invoked
18
18
  * - renderResult() controls what's shown after execution completes
19
19
  * - renderShell: "self" lets a tool render its own outer shell instead of
@@ -26,23 +26,21 @@
26
26
  */
27
27
 
28
28
  import type { BashToolDetails, EditToolDetails, ExtensionAPI, ReadToolDetails } from "@bastani/atomic";
29
- import { createBashTool, createEditTool, createReadTool, createWriteTool } from "@bastani/atomic";
29
+ import {
30
+ createBashToolDefinition,
31
+ createEditToolDefinition,
32
+ createReadToolDefinition,
33
+ createWriteToolDefinition,
34
+ } from "@bastani/atomic";
30
35
  import { Text } from "@earendil-works/pi-tui";
31
36
 
32
37
  export default function (pi: ExtensionAPI) {
33
38
  const cwd = process.cwd();
34
39
 
35
40
  // --- Read tool: show path and line count ---
36
- const originalRead = createReadTool(cwd);
41
+ const originalRead = createReadToolDefinition(cwd);
37
42
  pi.registerTool({
38
- name: "read",
39
- label: "read",
40
- description: originalRead.description,
41
- parameters: originalRead.parameters,
42
-
43
- async execute(toolCallId, params, signal, onUpdate) {
44
- return originalRead.execute(toolCallId, params, signal, onUpdate);
45
- },
43
+ ...originalRead,
46
44
 
47
45
  renderCall(args, theme, _context) {
48
46
  let text = theme.fg("toolTitle", theme.bold("read "));
@@ -92,16 +90,9 @@ export default function (pi: ExtensionAPI) {
92
90
  });
93
91
 
94
92
  // --- Bash tool: show command and exit code ---
95
- const originalBash = createBashTool(cwd);
93
+ const originalBash = createBashToolDefinition(cwd);
96
94
  pi.registerTool({
97
- name: "bash",
98
- label: "bash",
99
- description: originalBash.description,
100
- parameters: originalBash.parameters,
101
-
102
- async execute(toolCallId, params, signal, onUpdate) {
103
- return originalBash.execute(toolCallId, params, signal, onUpdate);
104
- },
95
+ ...originalBash,
105
96
 
106
97
  renderCall(args, theme, _context) {
107
98
  let text = theme.fg("toolTitle", theme.bold("$ "));
@@ -151,17 +142,9 @@ export default function (pi: ExtensionAPI) {
151
142
  });
152
143
 
153
144
  // --- Edit tool: show path and diff stats ---
154
- const originalEdit = createEditTool(cwd);
145
+ const originalEdit = createEditToolDefinition(cwd);
155
146
  pi.registerTool({
156
- name: "edit",
157
- label: "edit",
158
- description: originalEdit.description,
159
- parameters: originalEdit.parameters,
160
- renderShell: "self",
161
-
162
- async execute(toolCallId, params, signal, onUpdate) {
163
- return originalEdit.execute(toolCallId, params, signal, onUpdate);
164
- },
147
+ ...originalEdit,
165
148
 
166
149
  renderCall(args, theme, _context) {
167
150
  let text = theme.fg("toolTitle", theme.bold("edit "));
@@ -216,16 +199,9 @@ export default function (pi: ExtensionAPI) {
216
199
  });
217
200
 
218
201
  // --- Write tool: show path and size ---
219
- const originalWrite = createWriteTool(cwd);
202
+ const originalWrite = createWriteToolDefinition(cwd);
220
203
  pi.registerTool({
221
- name: "write",
222
- label: "write",
223
- description: originalWrite.description,
224
- parameters: originalWrite.parameters,
225
-
226
- async execute(toolCallId, params, signal, onUpdate) {
227
- return originalWrite.execute(toolCallId, params, signal, onUpdate);
228
- },
204
+ ...originalWrite,
229
205
 
230
206
  renderCall(args, theme, _context) {
231
207
  let text = theme.fg("toolTitle", theme.bold("write "));