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
|
-
|
|
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
|
|
102
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
},
|