aicq-codex 0.1.0 → 0.1.1
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/mcp/server.js +46 -12
- package/package.json +1 -1
package/mcp/server.js
CHANGED
|
@@ -395,15 +395,46 @@ const TOOLS = [
|
|
|
395
395
|
|
|
396
396
|
// ── MCP plumbing ──────────────────────────────────────────────────────
|
|
397
397
|
|
|
398
|
+
// ── stdout protocol guard (MUST run before any lib import logs) ─────────
|
|
399
|
+
// The MCP stdio transport reserves stdout exclusively for JSON-RPC frames.
|
|
400
|
+
// Library modules still use console.log; route every such line to stderr so
|
|
401
|
+
// strict parsers (rmcp) never see non-protocol bytes on the wire.
|
|
402
|
+
const __stderrWrite = process.stderr.write.bind(process.stderr);
|
|
403
|
+
const __stdoutWrite = process.stdout.write.bind(process.stdout);
|
|
404
|
+
console.log = (...args) => {
|
|
405
|
+
const line = args.map((a) => (typeof a === "string" ? a : JSON.stringify(a))).join(" ");
|
|
406
|
+
__stderrWrite(`[AICQ MCP][out] ${line}\n`);
|
|
407
|
+
};
|
|
408
|
+
|
|
398
409
|
async function main() {
|
|
399
410
|
let ready = false;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
411
|
+
|
|
412
|
+
// Single-flight init lock: concurrent tool calls must not race the
|
|
413
|
+
// bootstrap sequence (module-level _db/_identity/_chat get assigned
|
|
414
|
+
// progressively; a second entrant sees _db set and skips ahead).
|
|
415
|
+
// Single-flight shared by BOTH the background bootstrap and every lazy
|
|
416
|
+
// tool call. Two independent entry points used to race each other: a tool
|
|
417
|
+
// could observe `_db` already set while `_chat` was still undefined and
|
|
418
|
+
// skip ahead ("Cannot read properties of undefined (sendMessage)").
|
|
419
|
+
let initPromise = null;
|
|
420
|
+
function startBootstrap() {
|
|
421
|
+
if (!initPromise) {
|
|
422
|
+
initPromise = (async () => {
|
|
423
|
+
try {
|
|
424
|
+
await ensureInitialized();
|
|
425
|
+
ready = true;
|
|
426
|
+
log(`Plugin runtime initialized (v${PLUGIN_VERSION})`);
|
|
427
|
+
} catch (e) {
|
|
428
|
+
initPromise = null; // allow retry on next tool call
|
|
429
|
+
log(`Initialization deferred (${e.message}); tools will retry lazily.`);
|
|
430
|
+
}
|
|
431
|
+
})();
|
|
432
|
+
}
|
|
433
|
+
return initPromise;
|
|
434
|
+
}
|
|
435
|
+
function ensureReadyOnce() {
|
|
436
|
+
if (ready && _connected) return Promise.resolve();
|
|
437
|
+
return startBootstrap();
|
|
407
438
|
}
|
|
408
439
|
|
|
409
440
|
const server = new Server(
|
|
@@ -411,6 +442,10 @@ async function main() {
|
|
|
411
442
|
{ capabilities: { tools: {} } }
|
|
412
443
|
);
|
|
413
444
|
|
|
445
|
+
// FIX (startup handshake race): handlers registered BEFORE connect, and
|
|
446
|
+
// connect happens BEFORE heavy E2EE/network bootstrap so the MCP client's
|
|
447
|
+
// `initialize` / `tools/list` are answered immediately. CallTool retries
|
|
448
|
+
// initialization lazily via the `ready` flag.
|
|
414
449
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
415
450
|
tools: TOOLS.map(({ name, description, inputSchema }) => ({
|
|
416
451
|
name, description, inputSchema,
|
|
@@ -427,10 +462,7 @@ async function main() {
|
|
|
427
462
|
};
|
|
428
463
|
}
|
|
429
464
|
try {
|
|
430
|
-
|
|
431
|
-
await ensureInitialized();
|
|
432
|
-
ready = true;
|
|
433
|
-
}
|
|
465
|
+
await ensureReadyOnce();
|
|
434
466
|
const result = await tool.run(req.params.arguments || {});
|
|
435
467
|
return {
|
|
436
468
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
@@ -446,7 +478,9 @@ async function main() {
|
|
|
446
478
|
|
|
447
479
|
const transport = new StdioServerTransport();
|
|
448
480
|
await server.connect(transport);
|
|
449
|
-
log(`stdio
|
|
481
|
+
log(`stdio transport attached; bootstrapping runtime in background`);
|
|
482
|
+
// fire-and-forget; failures reported via log()
|
|
483
|
+
void startBootstrap();
|
|
450
484
|
}
|
|
451
485
|
|
|
452
486
|
main().catch((e) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicq-codex",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "AICQ End-to-end Encrypted Chat plugin for OpenAI Codex — Agent Plugins v1 manifest + stdio MCP server exposing AICQ friend management, chat, file transfer, and group messaging tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./mcp/server.js",
|