bfi-cli 0.1.81 → 0.1.82
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.
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import module from 'node:module';
|
|
4
|
+
|
|
5
|
+
if (module.enableCompileCache && !process.env.NODE_DISABLE_COMPILE_CACHE) {
|
|
6
|
+
try {
|
|
7
|
+
module.enableCompileCache();
|
|
8
|
+
} catch {
|
|
9
|
+
// Ignore errors
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
await import('../dist/mcp-codesearch/main.mjs');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { CallToolRequestSchema, CallToolResultSchema, ListToolsRequestSchema, ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import os from "node:os";
|
|
9
|
+
var BcsError = class extends Error {
|
|
10
|
+
errorKind;
|
|
11
|
+
constructor(errorKind, message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.errorKind = errorKind;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var BcsRemote = class {
|
|
17
|
+
url;
|
|
18
|
+
token;
|
|
19
|
+
fetchImpl;
|
|
20
|
+
client = null;
|
|
21
|
+
constructor(url, token, fetchImpl) {
|
|
22
|
+
this.url = url;
|
|
23
|
+
this.token = token;
|
|
24
|
+
this.fetchImpl = fetchImpl;
|
|
25
|
+
}
|
|
26
|
+
async listTools() {
|
|
27
|
+
const client = await this.ensure();
|
|
28
|
+
try {
|
|
29
|
+
return (await client.request({ method: "tools/list" }, ListToolsResultSchema)).tools;
|
|
30
|
+
} catch (e) {
|
|
31
|
+
return this.handleRemoteFailure(e);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async callTool(name, args) {
|
|
35
|
+
if (!this.token()) throw new BcsError("unauthorized", this.loginHint());
|
|
36
|
+
const client = await this.ensure();
|
|
37
|
+
try {
|
|
38
|
+
return await client.request({
|
|
39
|
+
method: "tools/call",
|
|
40
|
+
params: {
|
|
41
|
+
name,
|
|
42
|
+
arguments: args ?? {}
|
|
43
|
+
}
|
|
44
|
+
}, CallToolResultSchema);
|
|
45
|
+
} catch (e) {
|
|
46
|
+
return this.handleRemoteFailure(e);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async ensure() {
|
|
50
|
+
if (this.client) return this.client;
|
|
51
|
+
const token = this.token();
|
|
52
|
+
if (!token) throw new BcsError("unauthorized", this.loginHint());
|
|
53
|
+
const client = new Client({
|
|
54
|
+
name: "bfi-codesearch-mcp",
|
|
55
|
+
version: "0.1.0"
|
|
56
|
+
});
|
|
57
|
+
const transport = new StreamableHTTPClientTransport(this.url, {
|
|
58
|
+
requestInit: { headers: { Authorization: `Bearer ${token}` } },
|
|
59
|
+
fetchImpl: this.fetchImpl
|
|
60
|
+
});
|
|
61
|
+
try {
|
|
62
|
+
await client.connect(transport);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
throw new BcsError("bcs_unreachable", `bfi-code-search 服务不可达(${this.url}): ${e instanceof Error ? e.message : String(e)}`);
|
|
65
|
+
}
|
|
66
|
+
this.client = client;
|
|
67
|
+
return client;
|
|
68
|
+
}
|
|
69
|
+
handleRemoteFailure(e) {
|
|
70
|
+
this.client = null;
|
|
71
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
72
|
+
if (/401|unauthorized|Unauthorized/i.test(message)) throw new BcsError("unauthorized", `bfi-code-search token 无效或过期。${this.loginHint()}`);
|
|
73
|
+
throw new BcsError("bcs_error", `bfi-code-search 远端调用失败: ${message}`);
|
|
74
|
+
}
|
|
75
|
+
loginHint() {
|
|
76
|
+
return "未找到 bfi token:请先执行 `bfi auth login --token <sk-token>`(token 获取地址 https://bfi.yyuap.com/user/profile),或设置 BFI_TOKEN 环境变量";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".bfi");
|
|
80
|
+
const GLOBAL_CONFIG_FILE = path.join(GLOBAL_CONFIG_DIR, "config.json");
|
|
81
|
+
path.join(".bfi", "lock.json");
|
|
82
|
+
function loadGlobalConfig() {
|
|
83
|
+
try {
|
|
84
|
+
if (fs.existsSync(GLOBAL_CONFIG_FILE)) {
|
|
85
|
+
const content = fs.readFileSync(GLOBAL_CONFIG_FILE, "utf8");
|
|
86
|
+
return JSON.parse(content);
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.warn(`Warning: Failed to load global config: ${error.message}`);
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function resolveToken() {
|
|
94
|
+
if (process.env.BFI_TOKEN) return process.env.BFI_TOKEN;
|
|
95
|
+
return loadGlobalConfig()?.token ?? null;
|
|
96
|
+
}
|
|
97
|
+
function textResult(payload, isError = false) {
|
|
98
|
+
return {
|
|
99
|
+
content: [{
|
|
100
|
+
type: "text",
|
|
101
|
+
text: JSON.stringify(payload, null, 2)
|
|
102
|
+
}],
|
|
103
|
+
isError
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function buildServer(remote) {
|
|
107
|
+
const bcs = remote ?? new BcsRemote(process.env.BFI_BCS_URL || "https://bfi.yyuap.com:8443/bcs/mcp", resolveToken);
|
|
108
|
+
const server = new Server({
|
|
109
|
+
name: "bfi-code-search",
|
|
110
|
+
version: "0.1.0"
|
|
111
|
+
}, {
|
|
112
|
+
capabilities: { tools: {} },
|
|
113
|
+
instructions: [
|
|
114
|
+
"代码图谱/规则链/跨仓检索通道(bfi cli 登录态鉴权,零配置):",
|
|
115
|
+
"· 结构化查询:query(BM25+语义混合检索)/ context(符号360度)/ trace(最短调用路径)/ impact(影响面)/ cypher(图谱直查)",
|
|
116
|
+
"· 规则链三件套:rule_chain(单据动作有效规则链)/ rule_impact(规则被哪些链使用)/ rule_search(模糊搜规则/单据)",
|
|
117
|
+
"· 内容检索:zoekt_search(309 仓跨仓文本/正则/行级,毫秒级——搜字面量/URL/配置值/报错文案)",
|
|
118
|
+
"· 佐证纪律:多候选必须让用户确认;trace 结果校验仓库归属;检索结果不是完整源码,结合行号取源码片段引用"
|
|
119
|
+
].join("\n")
|
|
120
|
+
});
|
|
121
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
122
|
+
return { tools: await bcs.listTools() };
|
|
123
|
+
});
|
|
124
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
125
|
+
const { name, arguments: args } = request.params;
|
|
126
|
+
try {
|
|
127
|
+
return await bcs.callTool(name, args);
|
|
128
|
+
} catch (e) {
|
|
129
|
+
return textResult({
|
|
130
|
+
ok: false,
|
|
131
|
+
error_kind: e instanceof BcsError ? e.errorKind : "internal_error",
|
|
132
|
+
message: e instanceof Error ? e.message : String(e)
|
|
133
|
+
}, true);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return server;
|
|
137
|
+
}
|
|
138
|
+
async function main() {
|
|
139
|
+
await buildServer().connect(new StdioServerTransport());
|
|
140
|
+
}
|
|
141
|
+
main().catch((e) => {
|
|
142
|
+
console.error("[bfi-codesearch-mcp] 启动失败:", e);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
});
|
|
145
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bfi-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.82",
|
|
4
4
|
"description": "用友大业财BFI统一命令行工具,支持技能,技能包,元数据,UI元数据等",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"bfi": "bin/bfi.js",
|
|
8
|
-
"bfi-db-mcp": "bin/bfi-db-mcp.js"
|
|
8
|
+
"bfi-db-mcp": "bin/bfi-db-mcp.js",
|
|
9
|
+
"bfi-codesearch-mcp": "bin/bfi-codesearch-mcp.js"
|
|
9
10
|
},
|
|
10
11
|
"files": [
|
|
11
12
|
"dist",
|
|
@@ -54,4 +55,4 @@
|
|
|
54
55
|
"yaml": "^2.8.3",
|
|
55
56
|
"zod": "^3.25.0"
|
|
56
57
|
}
|
|
57
|
-
}
|
|
58
|
+
}
|