Environment
- codebase-memory-mcp: 0.10.8 (macOS arm64 binary from GitHub releases; latest release at time of writing)
- Host agent: pi (@earendil-works/pi-coding-agent) 0.84.3
- OS: macOS 26.3 (arm64)
- Generated file:
~/.pi/agent/extensions/cbmem.ts (via codebase-memory-mcp install)
Summary
The pi bridge extension generated by codebase-memory-mcp install registers tools with a legacy shape (run: callback, no parameters schema). Current pi (0.84.3) is incompatible with that shape in two independent ways, so every one of the 15 graph tools fails on every invocation:
pi-ai's argument validation crashes with TypeError: Cannot read properties of undefined (reading 'properties')
- Even if validation passed, the tool body would never run
Re-running the installer (same latest version 0.10.8) regenerates a byte-identical file, so this is not local drift — the generator itself still emits the legacy API.
Root cause
1. Crash in pi-ai argument validation
Generated registration (all 15 tools):
pi.registerTool({
name: 'index_repository',
run: (args, ctx) => call('index_repository', args, ctx?.signal),
});
Two problems against pi 0.84.3:
- pi's
wrapToolDefinition() (dist/core/tools/tool-definition-wrapper.js) only calls definition.execute(toolCallId, params, signal, onUpdate, ctx) — a run property is never invoked.
pi-ai's validateToolArguments() (pi-ai/dist/utils/validation.js) calls normalizeOptionalNulls(args, tool.parameters), which reads schema.properties without guarding schema itself:
// validation.js:219
if (typeof value !== "object" || value === null || !schema.properties)
// ^^^^^^ tool.parameters is undefined here
With no parameters schema, tool.parameters is undefined, and any object-shaped arguments reach that line → the exact error seen in-session:
TypeError: Cannot read properties of undefined (reading 'properties')
2. Current pi API (docs/extensions.md)
Per the official extension docs, tools must be registered with a TypeBox parameters and an execute(toolCallId, params, signal, onUpdate, ctx):
import { Type } from "typebox";
pi.registerTool({
name: "greet",
parameters: Type.Object({ name: Type.String() }),
async execute(toolCallId, params, signal, onUpdate, ctx) { ... },
});
Minimal repro
Fresh install of codebase-memory-mcp 0.10.8 into pi 0.84.3, then in an interactive session invoke any generated tool (e.g. list_projects). Observe the TypeError above instead of tool output.
Fix that works (verified)
Rewriting the generated block to the current API makes all 15 tools work end-to-end:
import { Type } from 'typebox';
const ANY_ARGS = Type.Object({}, { additionalProperties: true });
pi.registerTool({
name,
description,
parameters: ANY_ARGS,
async execute(_toolCallId, params, signal, _onUpdate, _ctx) {
const result = await call(name, params ?? {}, signal);
return toToolResult(result); // normalize to { content: [{ type: 'text', text }] }
},
});
Details that mattered:
- Keep the args JSON piped via stdin (
cli <tool> accepts JSON on stdin) — arg-JSON deprecation warning is avoided and large payloads won't hit OS argv limits.
toToolResult must wrap the raw JSON into an AgentToolResult shape (content: [{ type: 'text', text }]).
- An empty-object schema with
additionalProperties: true survives pi-ai's validation and its strict-schema path.
Secondary finding: non-TTY CLI output defaults to tree for some tools
When scripting against the local CLI (as any bridge must), search_graph, trace_path, and detect_changes emit human-readable tree output by default instead of JSON, which breaks JSON parsing. They honor an explicit --format json. The other tools emit JSON by default. It would help bridge maintainers if JSON were the default on non-TTY stdout, or if this were documented where the cli <tool> '<json>' interface is described.
Suggested resolution
- Emit the current pi API (
parameters + execute) from the generator.
- Optionally add a smoke check at
install time: spawn the target agent ≥ required version, or embed a version probe, so future API drift fails loudly instead of silently.
Workaround (until fixed)
Take ownership of the generated file as its header permits: remove the codebase-memory-mcp:start/end markers and patch by hand. Downside: it will no longer be auto-regenerated on cbm install/update, so upsteam changes need manual re-porting.
Environment
~/.pi/agent/extensions/cbmem.ts(viacodebase-memory-mcp install)Summary
The pi bridge extension generated by
codebase-memory-mcp installregisters tools with a legacy shape (run:callback, noparametersschema). Current pi (0.84.3) is incompatible with that shape in two independent ways, so every one of the 15 graph tools fails on every invocation:pi-ai's argument validation crashes withTypeError: Cannot read properties of undefined (reading 'properties')Re-running the installer (same latest version 0.10.8) regenerates a byte-identical file, so this is not local drift — the generator itself still emits the legacy API.
Root cause
1. Crash in pi-ai argument validation
Generated registration (all 15 tools):
Two problems against pi 0.84.3:
wrapToolDefinition()(dist/core/tools/tool-definition-wrapper.js) only callsdefinition.execute(toolCallId, params, signal, onUpdate, ctx)— arunproperty is never invoked.pi-ai'svalidateToolArguments()(pi-ai/dist/utils/validation.js) callsnormalizeOptionalNulls(args, tool.parameters), which readsschema.propertieswithout guardingschemaitself:With no
parametersschema,tool.parametersisundefined, and any object-shaped arguments reach that line → the exact error seen in-session:2. Current pi API (docs/extensions.md)
Per the official extension docs, tools must be registered with a TypeBox
parametersand anexecute(toolCallId, params, signal, onUpdate, ctx):Minimal repro
Fresh install of codebase-memory-mcp 0.10.8 into pi 0.84.3, then in an interactive session invoke any generated tool (e.g.
list_projects). Observe the TypeError above instead of tool output.Fix that works (verified)
Rewriting the generated block to the current API makes all 15 tools work end-to-end:
Details that mattered:
cli <tool>accepts JSON on stdin) — arg-JSON deprecation warning is avoided and large payloads won't hit OS argv limits.toToolResultmust wrap the raw JSON into an AgentToolResult shape (content: [{ type: 'text', text }]).additionalProperties: truesurvives pi-ai's validation and its strict-schema path.Secondary finding: non-TTY CLI output defaults to
treefor some toolsWhen scripting against the local CLI (as any bridge must),
search_graph,trace_path, anddetect_changesemit human-readabletreeoutput by default instead of JSON, which breaks JSON parsing. They honor an explicit--format json. The other tools emit JSON by default. It would help bridge maintainers if JSON were the default on non-TTY stdout, or if this were documented where thecli <tool> '<json>'interface is described.Suggested resolution
parameters+execute) from the generator.installtime: spawn the target agent ≥ required version, or embed a version probe, so future API drift fails loudly instead of silently.Workaround (until fixed)
Take ownership of the generated file as its header permits: remove the
codebase-memory-mcp:start/endmarkers and patch by hand. Downside: it will no longer be auto-regenerated oncbm install/update, so upsteam changes need manual re-porting.