Toggling Package Extension Tools
Overview
Use Pi's active tool list as the switch. It removes the target tool definitions from later prompts, but leaves the package loaded.
Pattern
- Persist your own enabled flag. Do not try to mutate the upstream package.
- Call
pi.getAllTools()and collect names whosesourceInfo.sourcematches the package, for examplenpm:pi-mcp-adapter. - On
session_start, apply the saved state withpi.setActiveTools(...). The prompt is built from the active tool list, so waiting until later is too late. - When disabling, remove only the matching tool names.
- When re-enabling, merge the matching tool names back in without dropping other active tools or adding duplicates.
- If footer or widget state depends on the toggle, emit a companion event such as
mcp-adapter:state-changed.
What This Does Not Do
This does not unload the package. Its commands, runtime initialization, or status handlers may still run. It only removes tools from the active prompt surface.
Minimal Example
const source = "npm:pi-mcp-adapter";
function getPackageToolNames(pi: Pick<ExtensionAPI, "getAllTools">): string[] {
return pi
.getAllTools()
.filter((tool) => tool.sourceInfo.source === source)
.map((tool) => tool.name);
}
function applyEnabledState(
pi: Pick<
ExtensionAPI,
"getAllTools" | "getActiveTools" | "setActiveTools" | "events"
>,
enabled: boolean,
) {
const packageToolNames = getPackageToolNames(pi);
const current = pi.getActiveTools();
const packageTools = new Set(packageToolNames);
const next = enabled
? [...current, ...packageToolNames.filter((name) => !current.includes(name))]
: current.filter((name) => !packageTools.has(name));
pi.setActiveTools(next);
pi.events.emit("package-tools:state-changed", enabled);
}
Verify
- Saved disabled state removes the package tools on
session_start - Toggle off removes every matching tool
- Toggle on restores them
- Slash commands still work because
setActiveTools(...)only affects tools - Footer or widget state updates on the companion event