mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 08:35:57 +00:00
fix: route Exa and CodeGraph through shared mcp adapter
This commit is contained in:
@@ -15,10 +15,9 @@
|
||||
- `extensions/fff-override.ts`:强制使用 FFF 官方 `override` 模式,统一接管 `find`、`grep`、`multi_grep` 和 FFF 的 `@` 补全;显式 CLI flag 仍遵循 FFF 官方优先级。
|
||||
- `extensions/tavily-override.ts`:加载 `@tavily/pi-extension`,把上游工具重命名为 `tavily_web_search` / `tavily_web_fetch`,并同步改写 label 与工具提示中的内部名称。
|
||||
- `@keenable/pi-search`:加载 `keenable_search` / `keenable_fetch` 及其 skill,默认 keyless,`KEENABLE_API_KEY` 仅用于提高速率限制。
|
||||
- `extensions/exa.ts`:通过隔离的 `pi-mcp-adapter` 配置连接 Exa 托管 MCP,把原始工具名映射为统一的来源前缀形式 `exa_web_search`、`exa_web_fetch` 和 `exa_web_search_advanced`。
|
||||
- `extensions/mcp.ts`:通过单个共享 `pi-mcp-adapter` 实例同时连接 Exa 托管 MCP 与机器现有的 `codegraph serve --mcp`,避免重复注册 Pi 的全局 MCP flag 与命令;Exa 原始工具映射为统一的来源前缀形式 `exa_web_search`、`exa_web_fetch` 和 `exa_web_search_advanced`,CodeGraph 只暴露 `codegraph_explore`。
|
||||
- `context-mode`:加载上游 Pi adapter 与 skills,提供 `ctx_*` 工具、隔离式大输出处理和会话连续性。
|
||||
- `extensions/hashline.ts`:部署组合包权威 `config/pi-hashline-edit.json` 后加载 `pi-hashline-edit`,以行哈希锚点覆盖内置 `read` / `edit`;Hashline 自带 `grep` 强制关闭。
|
||||
- `extensions/codegraph.ts`:通过隔离的 `pi-mcp-adapter` 配置连接机器现有的 `codegraph serve --mcp`,只暴露 `codegraph_explore`。
|
||||
- `extensions/permission-system.ts`:在权限扩展注册前,将 `config/pi-permission-system.json` 同步为全局权威配置。
|
||||
- `extensions/lsp.ts`:把组合包内 TypeScript Language Server CLI 物化为绝对命令路径,部署 TypeScript/Kotlin/JDT LS 全局配置并加载 `pi-lsp`。
|
||||
- `extensions/tool-routing.ts`:保留 Pi 默认系统提示词,在每轮开始前按激活工具追加简短路由规则,并提供 `/dump-system-prompt` 将扩展所见的有效提示词写入 `.pi-debug/effective-system-prompt.md`。
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
- `context-mode@1.0.169`:通过 Pi adapter 提供 `ctx_*` 工具、上下文隔离和会话连续性。
|
||||
- `@tavily/pi-extension@0.1.2`:提供 Tavily 广泛搜索与页面提取;通过本地 override 暴露为 `tavily_web_search` / `tavily_web_fetch`。
|
||||
- `@keenable/pi-search@0.1.2`:提供紧凑的 `keenable_search` / `keenable_fetch`,并加载其搜索 skill;API key 可选。
|
||||
- `pi-mcp-adapter@2.26.0`:分别用隔离配置接入机器现有的 CodeGraph 和 Exa 托管 MCP。
|
||||
- `pi-mcp-adapter@2.26.0`:通过单个共享 adapter 实例接入机器现有的 CodeGraph 和 Exa 托管 MCP,避免重复注册 Pi 的全局 MCP flag 与命令。
|
||||
- `pi-context-view@0.4.2`:查看上下文占用。
|
||||
- `@firstpick/pi-extension-codex-fast-mode@0.1.1`:为 Codex provider 提供会话级 `/fast-mode`。
|
||||
- `pi-lsp@0.1.7`:为 TypeScript/JavaScript、Kotlin 和 Java 提供 LSP 诊断、跳转与符号工具;TypeScript 后端由组合包内置。
|
||||
@@ -159,11 +159,11 @@ Tavily 通过 `extensions/tavily-override.ts` 加载官方扩展。override 只
|
||||
|
||||
Keenable 直接加载 npm 包的扩展和 skill,默认无需 key;设置 `KEENABLE_API_KEY` 可提高速率限制。它适合中文内容、`site` 限定和发布日期筛选。搜索结果保持紧凑,只对选中的 URL 调用 `keenable_fetch`。
|
||||
|
||||
`extensions/exa.ts` 通过已有的 `pi-mcp-adapter` 连接 `https://mcp.exa.ai/mcp`,把 MCP 原始工具映射为统一的来源前缀形式:`exa_web_search`、`exa_web_fetch` 和 `exa_web_search_advanced`。Exa 适合官方文档、技术资料、版本信息和论文;高级搜索必须显式限制结果数量与返回文本长度,避免响应过大。
|
||||
`extensions/mcp.ts` 通过单个 `pi-mcp-adapter` 实例同时连接 Exa 与 CodeGraph,避免两个 adapter 重复注册 `--mcp-config`、`/mcp` 和 `/mcp-auth`。其中 Exa 连接 `https://mcp.exa.ai/mcp`,并把 MCP 原始工具映射为统一的来源前缀形式:`exa_web_search`、`exa_web_fetch` 和 `exa_web_search_advanced`。Exa 适合官方文档、技术资料、版本信息和论文;高级搜索必须显式限制结果数量与返回文本长度,避免响应过大。
|
||||
|
||||
### CodeGraph 只负责连接
|
||||
|
||||
`extensions/codegraph.ts` 使用隔离的 `pi-mcp-adapter` 配置启动
|
||||
同一个 `extensions/mcp.ts` adapter 配置启动
|
||||
`codegraph serve --mcp`,不会读取或覆盖用户已有的 MCP 配置。连接采用
|
||||
`keep-alive`,并只把官方当前主工具 `codegraph_explore` 作为同名 Pi 工具暴露;
|
||||
CodeGraph 的文件 watcher 由该 MCP 进程自身维护。
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { createMcpAdapter } from "pi-mcp-adapter";
|
||||
|
||||
/** Connect Pi to the CodeGraph MCP server provided by the host machine. */
|
||||
export default createMcpAdapter({
|
||||
config: {
|
||||
settings: {
|
||||
disableProxyTool: true,
|
||||
scriptMode: false,
|
||||
},
|
||||
mcpServers: {
|
||||
codegraph: {
|
||||
command: "codegraph",
|
||||
args: ["serve", "--mcp"],
|
||||
lifecycle: "keep-alive",
|
||||
directTools: ["codegraph_explore"],
|
||||
includeTools: ["codegraph_explore"],
|
||||
toolPrefix: "none",
|
||||
approveTools: false,
|
||||
exposeResources: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,32 +0,0 @@
|
||||
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||
import { createMcpAdapter } from "pi-mcp-adapter";
|
||||
import { createExaToolApiOverride } from "./exa-tool-prefix.ts";
|
||||
|
||||
const EXA_TOOLS = ["web_search_exa", "web_fetch_exa", "web_search_advanced_exa"];
|
||||
const EXA_MCP_URL = `https://mcp.exa.ai/mcp?tools=${EXA_TOOLS.join(",")}`;
|
||||
|
||||
const exaAdapter = createMcpAdapter({
|
||||
config: {
|
||||
settings: {
|
||||
disableProxyTool: true,
|
||||
scriptMode: false,
|
||||
},
|
||||
mcpServers: {
|
||||
exa: {
|
||||
url: EXA_MCP_URL,
|
||||
protocolVersion: "auto",
|
||||
lifecycle: "eager",
|
||||
directTools: EXA_TOOLS,
|
||||
includeTools: EXA_TOOLS,
|
||||
toolPrefix: "none",
|
||||
approveTools: false,
|
||||
exposeResources: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/** Connect Pi to Exa while exposing every direct tool as `exa_<original-name>`. */
|
||||
export default function exaExtension(pi: ExtensionAPI): void {
|
||||
exaAdapter(createExaToolApiOverride(pi));
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { McpConfig } from "pi-mcp-adapter";
|
||||
|
||||
export const EXA_TOOLS = ["web_search_exa", "web_fetch_exa", "web_search_advanced_exa"];
|
||||
const EXA_MCP_URL = `https://mcp.exa.ai/mcp?tools=${EXA_TOOLS.join(",")}`;
|
||||
|
||||
export const MCP_CONFIG: McpConfig = {
|
||||
settings: {
|
||||
disableProxyTool: true,
|
||||
scriptMode: false,
|
||||
},
|
||||
mcpServers: {
|
||||
exa: {
|
||||
url: EXA_MCP_URL,
|
||||
protocolVersion: "auto",
|
||||
lifecycle: "eager",
|
||||
directTools: EXA_TOOLS,
|
||||
includeTools: EXA_TOOLS,
|
||||
toolPrefix: "none",
|
||||
approveTools: false,
|
||||
exposeResources: false,
|
||||
},
|
||||
codegraph: {
|
||||
command: "codegraph",
|
||||
args: ["serve", "--mcp"],
|
||||
lifecycle: "keep-alive",
|
||||
directTools: ["codegraph_explore"],
|
||||
includeTools: ["codegraph_explore"],
|
||||
toolPrefix: "none",
|
||||
approveTools: false,
|
||||
exposeResources: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||
import { createMcpAdapter } from "pi-mcp-adapter";
|
||||
import { createExaToolApiOverride } from "./exa-tool-prefix.ts";
|
||||
import { MCP_CONFIG } from "./mcp-config.ts";
|
||||
|
||||
const mcpAdapter = createMcpAdapter({
|
||||
config: MCP_CONFIG,
|
||||
});
|
||||
|
||||
/** Connect Pi to Exa and CodeGraph through one shared MCP adapter instance. */
|
||||
export default function mcpExtension(pi: ExtensionAPI): void {
|
||||
mcpAdapter(createExaToolApiOverride(pi));
|
||||
}
|
||||
+1
-2
@@ -25,11 +25,10 @@
|
||||
"./extensions/fff-override.ts",
|
||||
"./extensions/tavily-override.ts",
|
||||
"./node_modules/@keenable/pi-search/src/index.ts",
|
||||
"./extensions/exa.ts",
|
||||
"./extensions/mcp.ts",
|
||||
"./pi-rtk-optimizer/index.ts",
|
||||
"./extensions/hashline.ts",
|
||||
"./node_modules/context-mode/build/adapters/pi/extension.js",
|
||||
"./extensions/codegraph.ts",
|
||||
"./extensions/lsp.ts",
|
||||
"./node_modules/pi-context-view/src/index.ts",
|
||||
"./node_modules/@firstpick/pi-extension-codex-fast-mode/index.ts",
|
||||
|
||||
@@ -32,11 +32,14 @@ test("Exa API override keeps registered and active tool names aligned", () => {
|
||||
});
|
||||
|
||||
api.registerTool({ name: "web_fetch_exa", label: "MCP: web_fetch_exa" });
|
||||
api.setActiveTools(["read", "web_fetch_exa", "web_fetch_exa"]);
|
||||
api.registerTool({ name: "codegraph_explore", label: "MCP: codegraph_explore" });
|
||||
api.setActiveTools(["read", "web_fetch_exa", "web_fetch_exa", "codegraph_explore"]);
|
||||
api.unregisterTool("web_fetch_exa");
|
||||
api.unregisterTool("codegraph_explore");
|
||||
|
||||
assert.equal(registered[0]?.name, "exa_web_fetch");
|
||||
assert.equal(registered[0]?.label, "Exa Web Fetch");
|
||||
assert.deepEqual(active, ["read", "exa_web_fetch"]);
|
||||
assert.deepEqual(unregistered, ["exa_web_fetch"]);
|
||||
assert.equal(registered[1]?.name, "codegraph_explore");
|
||||
assert.deepEqual(active, ["read", "exa_web_fetch", "codegraph_explore"]);
|
||||
assert.deepEqual(unregistered, ["exa_web_fetch", "codegraph_explore"]);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import test from "node:test";
|
||||
|
||||
import { EXA_TOOLS, MCP_CONFIG } from "../extensions/mcp-config.ts";
|
||||
|
||||
test("one MCP adapter config contains both Exa and CodeGraph", () => {
|
||||
assert.deepEqual(MCP_CONFIG, {
|
||||
settings: {
|
||||
disableProxyTool: true,
|
||||
scriptMode: false,
|
||||
},
|
||||
mcpServers: {
|
||||
exa: {
|
||||
url: `https://mcp.exa.ai/mcp?tools=${EXA_TOOLS.join(",")}`,
|
||||
protocolVersion: "auto",
|
||||
lifecycle: "eager",
|
||||
directTools: EXA_TOOLS,
|
||||
includeTools: EXA_TOOLS,
|
||||
toolPrefix: "none",
|
||||
approveTools: false,
|
||||
exposeResources: false,
|
||||
},
|
||||
codegraph: {
|
||||
command: "codegraph",
|
||||
args: ["serve", "--mcp"],
|
||||
lifecycle: "keep-alive",
|
||||
directTools: ["codegraph_explore"],
|
||||
includeTools: ["codegraph_explore"],
|
||||
toolPrefix: "none",
|
||||
approveTools: false,
|
||||
exposeResources: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("the package loads only the shared MCP extension entry", async () => {
|
||||
const packageJson = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")) as {
|
||||
pi: { extensions: string[] };
|
||||
};
|
||||
const localMcpEntries = packageJson.pi.extensions.filter((entry) =>
|
||||
entry === "./extensions/mcp.ts" || entry === "./extensions/exa.ts" || entry === "./extensions/codegraph.ts"
|
||||
);
|
||||
|
||||
assert.deepEqual(localMcpEntries, ["./extensions/mcp.ts"]);
|
||||
});
|
||||
Reference in New Issue
Block a user