antechamber 1.0.26 → 1.0.27

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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project uses [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.27] - 2026-10-28
11
+
12
+ ### Fixed
13
+
14
+ - Find OmO's builtin `/mcp` command when an extension such as `pi-mcp-adapter` also registers `mcp` and OmO renames
15
+ the builtin to `mcp:1`. MCP sign-in used to fail there with "Unknown command /mcp".
16
+
10
17
  ## [1.0.26] - 2026-10-28
11
18
 
12
19
  ### Fixed
package/dist/mcp.d.ts CHANGED
@@ -17,6 +17,8 @@
17
17
  * Commands are sent straight to the agent, outside the conversation queue: they neither
18
18
  * wait behind a running turn nor create a user message, and the session is held active so
19
19
  * the reaper cannot stop the process (and its listener or pending state) mid-flow.
20
+ * An extension that registers its own `mcp` command makes OmO rename the builtin (`mcp:1`),
21
+ * so the builtin is found by its source, not by name.
20
22
  */
21
23
  import type { RouteServices } from "./route-services.js";
22
24
  type OCMcpStatus = {
package/dist/mcp.js CHANGED
@@ -17,6 +17,8 @@
17
17
  * Commands are sent straight to the agent, outside the conversation queue: they neither
18
18
  * wait behind a running turn nor create a user message, and the session is held active so
19
19
  * the reaper cannot stop the process (and its listener or pending state) mid-flow.
20
+ * An extension that registers its own `mcp` command makes OmO rename the builtin (`mcp:1`),
21
+ * so the builtin is found by its source, not by name.
20
22
  */
21
23
  import { randomUUID } from "node:crypto";
22
24
  import { errorBody } from "./http.js";
@@ -32,6 +34,7 @@ const MCP_AUTH_ATTEMPT_TTL_MS = 10 * 60_000;
32
34
  const SERVER_NAME = /^[^\s"'\\]+$/;
33
35
  const INTEGRATION_PREFIX = "mcp_";
34
36
  const OAUTH_METHOD_ID = "oauth";
37
+ const BUILTIN_MCP_PATH = "<builtin:mcp>";
35
38
  const flows = new Map();
36
39
  const admissions = new Map();
37
40
  function isRecord(value) {
@@ -95,11 +98,15 @@ async function directoryServers(sessions, directory) {
95
98
  const live = liveSession(sessions, directory) ?? (fallback === undefined ? undefined : { pi: fallback });
96
99
  return live === undefined ? [] : loadedServers(live.pi).catch(() => []);
97
100
  }
98
- async function hasMcpCommand(pi) {
101
+ /** The builtin MCP command's name in this agent; builds without `sourceInfo` only know it as `mcp`. */
102
+ async function mcpCommandName(pi) {
99
103
  const response = await pi.probe({ type: "get_commands" }, undefined, AbortSignal.timeout(MCP_READ_WAIT_MS));
100
104
  if (!response.success || !isRecord(response.data) || !Array.isArray(response.data.commands))
101
- return false;
102
- return response.data.commands.some((command) => isRecord(command) && command.name === "mcp" && command.source === "extension");
105
+ return undefined;
106
+ const commands = response.data.commands.flatMap((command) => isRecord(command) && command.source === "extension" && typeof command.name === "string"
107
+ ? [{ name: command.name, builtin: isRecord(command.sourceInfo) && command.sourceInfo.path === BUILTIN_MCP_PATH }]
108
+ : []);
109
+ return (commands.find((command) => command.builtin) ?? commands.find((command) => command.name === "mcp"))?.name;
103
110
  }
104
111
  /** The URL OmO prints on its own line after naming the server (`auth` and `auth-start` both do). */
105
112
  export function authorizationUrl(text, name) {
@@ -151,7 +158,7 @@ function sameCallback(target, authorization) {
151
158
  const expected = new URL(announced);
152
159
  return target.origin === expected.origin && target.pathname === expected.pathname;
153
160
  }
154
- function runMcpCommand(sessions, s, pi, name, args, observe = {}) {
161
+ function runMcpCommand(sessions, s, pi, name, commandName, args, observe = {}) {
155
162
  const errors = [];
156
163
  const onEvent = (event) => {
157
164
  const entry = event.entry;
@@ -175,7 +182,7 @@ function runMcpCommand(sessions, s, pi, name, args, observe = {}) {
175
182
  pi.onEvent(onEvent);
176
183
  pi.onExtensionUI(onNotify);
177
184
  return sessions.lifecycle
178
- .use(s, () => pi.command({ type: "prompt", message: `/mcp ${args}`, expandPromptTemplates: true }, MCP_AUTH_COMMAND_TIMEOUT_MS))
185
+ .use(s, () => pi.command({ type: "prompt", message: `/${commandName} ${args}`, expandPromptTemplates: true }, MCP_AUTH_COMMAND_TIMEOUT_MS))
179
186
  .then((response) => {
180
187
  if (!response.success)
181
188
  throw new Error(response.error ?? "OmO rejected the /mcp command");
@@ -233,12 +240,14 @@ async function startFlow(services, directory, name, command) {
233
240
  const servers = await loadedServers(pi);
234
241
  if (!servers.some((server) => server.name === name))
235
242
  return { error: { status: 404, body: errorBody("McpServerNotFoundError", `MCP server not found: ${name}`) } };
236
- if (!(await hasMcpCommand(pi)))
243
+ const commandName = await mcpCommandName(pi);
244
+ if (commandName === undefined)
237
245
  return { error: { status: 400, body: errorBody("UnsupportedError", "This OmO build has no /mcp command") } };
238
246
  const url = Promise.withResolvers();
239
247
  const flow = {
240
248
  s,
241
249
  pi,
250
+ commandName,
242
251
  command,
243
252
  attemptID: randomUUID(),
244
253
  created: Date.now(),
@@ -247,7 +256,7 @@ async function startFlow(services, directory, name, command) {
247
256
  running: true,
248
257
  authorized: false,
249
258
  };
250
- flow.done = runMcpCommand(services.sessions, s, pi, name, `${command} ${name}`, {
259
+ flow.done = runMcpCommand(services.sessions, s, pi, name, commandName, `${command} ${name}`, {
251
260
  url: (found) => {
252
261
  flow.authorizationUrl ??= found;
253
262
  url.resolve(found);
@@ -326,7 +335,7 @@ async function completeFlow(services, directory, name, input) {
326
335
  await flow.done;
327
336
  }
328
337
  else {
329
- await runMcpCommand(services.sessions, flow.s, flow.pi, name, `auth-complete ${name} ${redirect}`, {
338
+ await runMcpCommand(services.sessions, flow.s, flow.pi, name, flow.commandName, `auth-complete ${name} ${redirect}`, {
330
339
  authorized: () => {
331
340
  flow.authorized = true;
332
341
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-compat",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "OpenChamber extension: displays OmO tool calls the way OmO means them when OpenChamber runs on antechamber",
5
5
  "private": true,
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-graph",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "OpenChamber extension: live, interactive graph of the OmO sub-agents behind the current session",
5
5
  "private": true,
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-work",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "OpenChamber 2.x Work Status section: OmO todo phases, monitors, eval cells and background work of the current session",
5
5
  "private": true,
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "OpenCode-compatible HTTP/SSE server that lets OpenChamber drive the pi coding agent (and OmO) over RPC",
5
5
  "type": "module",
6
6
  "license": "MIT",