@uni-helper/mcp 0.0.2-beta.1 → 0.0.4

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/README.md CHANGED
@@ -1,4 +1,8 @@
1
- # [WIP]uniapp MCP plugin
1
+ # UniAPP MCP
2
+
3
+ > 访问[uni-helper/skills](https://github.com/uni-helper/skills)获取`skills`。
4
+
5
+ 使用 `MCP + RAG` 方案来查询 uniapp 文档。
2
6
 
3
7
  ## 安装
4
8
 
@@ -6,16 +10,21 @@
6
10
  pnpm add @uni-helper/mcp -D
7
11
  ```
8
12
 
9
- ## 配置
10
-
11
- 在 `vite.config.ts` 中添加如下配置:
12
-
13
- ```ts
14
- import mcp from '@uni-helper/mcp'
15
- import uni from '@uni-helper/plugin-uni'
16
- import { defineConfig } from 'vite'
13
+ ## 配置 MCP 服务器
14
+ ```json
15
+ {
16
+ "mcpServers": {
17
+ "uni-doc": {
18
+ "command": "uni-mcp"
19
+ }
20
+ }
21
+ }
22
+ ```
17
23
 
18
- export default defineConfig({
19
- plugins: [uni(), mcp()],
20
- })
24
+ ## 注意如果使用pnpm,请在`pnpm-workspace.yaml`中添加如下配置:
25
+ 确保能正确构建`@uni-helper/mcp`插件
26
+ ```yaml
27
+ onlyBuiltDependencies:
28
+ - hnswlib-node
29
+ - '@uni-helper/mcp'
21
30
  ```
package/dist/index.mjs CHANGED
@@ -1,8 +1,5 @@
1
- import { searchForWorkspaceRoot } from "vite";
2
- import { serve } from "@hono/node-server";
3
- import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
4
- import { Hono } from "hono";
5
- import { cors } from "hono/cors";
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
4
  import { z } from "zod";
8
5
  import { dirname, join } from "node:path";
@@ -10,190 +7,17 @@ import { fileURLToPath } from "node:url";
10
7
  import { env } from "@huggingface/transformers";
11
8
  import { HuggingFaceTransformersEmbeddings } from "@langchain/community/embeddings/huggingface_transformers";
12
9
  import { HNSWLib } from "@langchain/community/vectorstores/hnswlib";
13
- import fs from "fs-extra";
14
- import { existsSync } from "node:fs";
15
- import { homedir } from "node:os";
16
- import consola from "consola";
17
- import { Buffer as Buffer$1 } from "node:buffer";
18
- import open from "open";
19
10
 
20
- //#region rolldown:runtime
21
- var __create = Object.create;
22
- var __defProp = Object.defineProperty;
23
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
24
- var __getOwnPropNames = Object.getOwnPropertyNames;
25
- var __getProtoOf = Object.getPrototypeOf;
26
- var __hasOwnProp = Object.prototype.hasOwnProperty;
27
- var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
28
- var __copyProps = (to, from, except, desc) => {
29
- if (from && typeof from === "object" || typeof from === "function") {
30
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
31
- key = keys[i];
32
- if (!__hasOwnProp.call(to, key) && key !== except) {
33
- __defProp(to, key, {
34
- get: ((k) => from[k]).bind(null, key),
35
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
36
- });
37
- }
38
- }
39
- }
40
- return to;
41
- };
42
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
43
- value: mod,
44
- enumerable: true
45
- }) : target, mod));
46
-
47
- //#endregion
48
- //#region node_modules/.pnpm/ansis@4.2.0/node_modules/ansis/index.cjs
49
- var require_ansis = /* @__PURE__ */ __commonJSMin(((exports, module) => {
50
- let e, t, r, { defineProperty: l, setPrototypeOf: n, create: o, keys: s } = Object, i = "", { round: c, max: a } = Math, p = (e) => {
51
- let t = /([a-f\d]{3,6})/i.exec(e)?.[1], r = t?.length, l = parseInt(6 ^ r ? 3 ^ r ? "0" : t[0] + t[0] + t[1] + t[1] + t[2] + t[2] : t, 16);
52
- return [
53
- l >> 16 & 255,
54
- l >> 8 & 255,
55
- 255 & l
56
- ];
57
- }, u = (e, t, r) => e ^ t || t ^ r ? 16 + 36 * c(e / 51) + 6 * c(t / 51) + c(r / 51) : 8 > e ? 16 : e > 248 ? 231 : c(24 * (e - 8) / 247) + 232, d = (e) => {
58
- let t, r, l, n, o;
59
- return 8 > e ? 30 + e : 16 > e ? e - 8 + 90 : (232 > e ? (o = (e -= 16) % 36, t = (e / 36 | 0) / 5, r = (o / 6 | 0) / 5, l = o % 6 / 5) : t = r = l = (10 * (e - 232) + 8) / 255, n = 2 * a(t, r, l), n ? 30 + (c(l) << 2 | c(r) << 1 | c(t)) + (2 ^ n ? 0 : 60) : 30);
60
- }, f = (() => {
61
- let r = (e) => o.some(((t) => e.test(t))), l = globalThis, n = l.process ?? {}, o = n.argv ?? [], i = n.env ?? {}, c = -1;
62
- try {
63
- e = "," + s(i).join(",");
64
- } catch (e) {
65
- i = {}, c = 0;
66
- }
67
- let a$1 = "FORCE_COLOR", p = {
68
- false: 0,
69
- 0: 0,
70
- 1: 1,
71
- 2: 2,
72
- 3: 3
73
- }[i[a$1]] ?? -1, u = a$1 in i && p || r(/^--color=?(true|always)?$/);
74
- return u && (c = p), ~c || (c = ((r$1, l$1, n$1) => (t = r$1.TERM, {
75
- "24bit": 3,
76
- truecolor: 3,
77
- ansi256: 2,
78
- ansi: 1
79
- }[r$1.COLORTERM] || (r$1.CI ? /,GITHUB/.test(e) ? 3 : 1 : l$1 && "dumb" !== t ? n$1 ? 3 : /-256/.test(t) ? 2 : 1 : 0)))(i, !!i.PM2_HOME || i.NEXT_RUNTIME?.includes("edge") || !!n.stdout?.isTTY, "win32" === n.platform)), !p || i.NO_COLOR || r(/^--(no-color|color=(false|never))$/) ? 0 : l.window?.chrome || u && !c ? 3 : c;
80
- })(), g = {
81
- open: i,
82
- close: i
83
- }, h = 39, b = 49, O = {}, m = ({ p: e }, { open: t, close: l }) => {
84
- let o = (e$1, ...r) => {
85
- if (!e$1) {
86
- if (t && t === l) return t;
87
- if ((e$1 ?? i) === i) return i;
88
- }
89
- let n, s$1 = e$1.raw ? String.raw({ raw: e$1 }, ...r) : i + e$1, c$1 = o.p, a$1 = c$1.o, p = c$1.c;
90
- if (s$1.includes("\x1B")) for (; c$1; c$1 = c$1.p) {
91
- let { open: e$2, close: t$1 } = c$1, r$1 = t$1.length, l$1 = i, o$1 = 0;
92
- if (r$1) for (; ~(n = s$1.indexOf(t$1, o$1)); o$1 = n + r$1) l$1 += s$1.slice(o$1, n) + e$2;
93
- s$1 = l$1 + s$1.slice(o$1);
94
- }
95
- return a$1 + (s$1.includes("\n") ? s$1.replace(/(\r?\n)/g, p + "$1" + a$1) : s$1) + p;
96
- }, s = t, c = l;
97
- return e && (s = e.o + t, c = l + e.c), n(o, r), o.p = {
98
- open: t,
99
- close: l,
100
- o: s,
101
- c,
102
- p: e
103
- }, o.open = s, o.close = c, o;
104
- };
105
- const w = new function e(t = f) {
106
- let s = {
107
- Ansis: e,
108
- level: t,
109
- isSupported: () => a$1,
110
- strip: (e$1) => e$1.replace(/[›][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, i),
111
- extend(e$1) {
112
- for (let t$1 in e$1) {
113
- let r = e$1[t$1], l = (typeof r)[0];
114
- "s" === l ? (c(t$1, T(...p(r))), c(_(t$1), v(...p(r)))) : c(t$1, r, "f" === l);
115
- }
116
- return r = o({}, O), n(s, r), s;
117
- }
118
- }, c = (e$1, t$1, r) => {
119
- O[e$1] = { get() {
120
- let n = r ? (...e$2) => m(this, t$1(...e$2)) : m(this, t$1);
121
- return l(this, e$1, { value: n }), n;
122
- } };
123
- }, a$1 = t > 0, w = (e$1, t$1) => a$1 ? {
124
- open: `[${e$1}m`,
125
- close: `[${t$1}m`
126
- } : g, y = (e$1) => (t$1) => e$1(...p(t$1)), R = (e$1, t$1) => (r, l, n) => w(`${e$1}8;2;${r};${l};${n}`, t$1), $ = (e$1, t$1) => (r, l, n) => w(((e$2, t$2, r$1) => d(u(e$2, t$2, r$1)))(r, l, n) + e$1, t$1), x = (e$1) => (t$1, r, l) => e$1(u(t$1, r, l)), T = R(3, h), v = R(4, b), C = (e$1) => w("38;5;" + e$1, h), E = (e$1) => w("48;5;" + e$1, b);
127
- 2 === t ? (T = x(C), v = x(E)) : 1 === t && (T = $(0, h), v = $(10, b), C = (e$1) => w(d(e$1), h), E = (e$1) => w(d(e$1) + 10, b));
128
- let M, I = {
129
- fg: C,
130
- bg: E,
131
- rgb: T,
132
- bgRgb: v,
133
- hex: y(T),
134
- bgHex: y(v),
135
- visible: g,
136
- reset: w(0, 0),
137
- bold: w(1, 22),
138
- dim: w(2, 22),
139
- italic: w(3, 23),
140
- underline: w(4, 24),
141
- inverse: w(7, 27),
142
- hidden: w(8, 28),
143
- strikethrough: w(9, 29)
144
- }, _ = (e$1) => "bg" + e$1[0].toUpperCase() + e$1.slice(1), k = "Bright";
145
- return "black,red,green,yellow,blue,magenta,cyan,white,gray".split(",").map(((e$1, t$1) => {
146
- M = _(e$1), 8 > t$1 ? (I[e$1 + k] = w(90 + t$1, h), I[M + k] = w(100 + t$1, b)) : t$1 = 60, I[e$1] = w(30 + t$1, h), I[M] = w(40 + t$1, b);
147
- })), s.extend(I);
148
- }();
149
- module.exports = w, w.default = w;
150
- }));
151
-
152
- //#endregion
153
- //#region node_modules/.pnpm/ansis@4.2.0/node_modules/ansis/index.mjs
154
- var import_ansis = /* @__PURE__ */ __toESM(require_ansis(), 1);
155
- var ansis_default = import_ansis.default;
156
- const { Ansis, fg, bg, rgb, bgRgb, hex, bgHex, reset, inverse, hidden, visible, bold, dim, italic, underline, strikethrough, black, red, green, yellow, blue, magenta, cyan, white, gray, redBright, greenBright, yellowBright, blueBright, magentaBright, cyanBright, whiteBright, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bgGray, bgRedBright, bgGreenBright, bgYellowBright, bgBlueBright, bgMagentaBright, bgCyanBright, bgWhiteBright } = import_ansis.default;
157
-
158
- //#endregion
159
- //#region src/mcpServer/connect.ts
160
- function connectServer(server, options) {
161
- const { port = 2515, printUrl = true } = options;
162
- const transport = new WebStandardStreamableHTTPServerTransport();
163
- const app = new Hono();
164
- app.use("*", cors({
165
- origin: "*",
166
- allowMethods: [
167
- "GET",
168
- "POST",
169
- "DELETE",
170
- "OPTIONS"
171
- ],
172
- allowHeaders: [
173
- "Content-Type",
174
- "mcp-session-id",
175
- "Last-Event-ID",
176
- "mcp-protocol-version"
177
- ],
178
- exposeHeaders: ["mcp-session-id", "mcp-protocol-version"]
179
- }));
180
- app.all("/mcp", (c) => transport.handleRequest(c.req.raw));
181
- server.connect(transport).then(() => {
182
- if (printUrl) console.log(`${ansis_default.cyan` ➜ MCP: `}${ansis_default.gray(`server is running at ${ansis_default.green(`http://localhost:${port}/mcp`)}`)}`);
183
- serve({
184
- fetch: app.fetch,
185
- port
186
- });
187
- });
188
- return `http://localhost:${port}/mcp`;
189
- }
11
+ //#region package.json
12
+ var version = "0.0.4";
190
13
 
191
14
  //#endregion
192
15
  //#region src/docs/index.ts
193
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
194
17
  async function loadVectorStore(vectorName, _embeddings) {
195
18
  const vectorDirMap = { uniapp: join(__dirname, "../", "vectorStore", "uniapp") };
196
- env.remoteHost = "https://hf-mirror.com";
19
+ env.version = "master";
20
+ env.remoteHost = "https://www.modelscope.cn/models";
197
21
  const embeddings = _embeddings ?? new HuggingFaceTransformersEmbeddings({
198
22
  model: "onnx-community/Qwen3-Embedding-0.6B-ONNX",
199
23
  pretrainedOptions: {
@@ -205,207 +29,33 @@ async function loadVectorStore(vectorName, _embeddings) {
205
29
  }
206
30
 
207
31
  //#endregion
208
- //#region package.json
209
- var version = "0.0.2-beta.1";
210
-
211
- //#endregion
212
- //#region src/mcpServer/projectAnalyzer.ts
213
- async function readFileIfExists(path) {
214
- const content = await fs.readFile(path, "utf-8").catch(() => void 0);
215
- return {
216
- exists: !!content,
217
- path,
218
- content
219
- };
220
- }
221
- async function analyzeProject(rootPath) {
222
- const [pagesJson, manifestJson] = await Promise.all([readFileIfExists(join(rootPath, "src/pages.json")), readFileIfExists(join(rootPath, "src/manifest.json"))]);
223
- return {
224
- pagesJson,
225
- manifestJson
226
- };
227
- }
228
-
229
- //#endregion
230
- //#region src/mcpServer/server.ts
231
- async function createMcpServer(config, options) {
32
+ //#region src/server/index.ts
33
+ async function createMcpServer() {
232
34
  const server = new McpServer({
233
35
  name: "uni",
234
36
  version
235
37
  });
236
- server.registerTool("get-vite-config", {
237
- title: "获取 Vite 配置",
238
- description: "获取 Vite 配置摘要,包括根目录、解析配置、插件和环境名称。"
239
- }, () => ({ content: [{
240
- type: "text",
241
- text: JSON.stringify({
242
- root: config.root,
243
- resolve: config.resolve,
244
- plugins: config.plugins.map((p) => p.name).filter(Boolean),
245
- environmentNames: Object.keys(config.environments)
246
- })
247
- }] }));
248
38
  server.registerTool("search-docs-by-Uniapp-official", {
249
39
  title: "搜索 Uniapp 官方文档",
250
40
  description: "在 Uniapp 文档知识库中进行搜索,可查找相关信息、代码示例、API参考文档和操作指南。当您需要解答关于Uniapp文档的问题、查找特定文档内容、了解功能运作原理或定位实现细节时,可使用此工具。搜索结果将返回带有标题的上下文相关内容,并附有直达文档页面的链接。",
251
41
  inputSchema: { query: z.string().describe("用于搜索内容的查询语句") }
252
42
  }, async ({ query }) => {
253
- return { content: (await (await loadVectorStore("uniapp", options.embeddings)).similaritySearch(query, 3)).map((doc) => ({
43
+ return { content: (await (await loadVectorStore("uniapp")).similaritySearch(query, 3)).map((doc) => ({
254
44
  type: "text",
255
45
  text: JSON.stringify(doc)
256
46
  })) };
257
47
  });
258
- server.registerTool("get-project-overview", {
259
- title: "获取项目概览",
260
- description: "返回 Uniapp 项目的 pages.json 和 manifest.json 配置文件。"
261
- }, async () => {
262
- const overview = await analyzeProject(config.root);
263
- return { content: [{
264
- type: "text",
265
- text: JSON.stringify(overview, null, 2)
266
- }] };
267
- });
268
48
  return server;
269
49
  }
270
50
 
271
- //#endregion
272
- //#region src/updateConfigs/claude.ts
273
- async function updateClaudeConfig(root, sseUrl, _options) {
274
- const mcp = existsSync(join(root, ".mcp.json")) ? JSON.parse(await fs.readFile(join(root, ".mcp.json"), "utf-8") || "{}") : {};
275
- mcp.mcpServers ||= {};
276
- mcp.mcpServers.uni = {
277
- type: "http",
278
- url: sseUrl
279
- };
280
- await fs.writeFile(join(root, ".mcp.json"), `${JSON.stringify(mcp, null, 2)}\n`);
281
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`Updated config file ${join(root, ".mcp.json")}`)}`);
282
- }
283
-
284
- //#endregion
285
- //#region src/updateConfigs/cursor.ts
286
- async function updateCursorConfig(root, sseUrl, _options) {
287
- await fs.mkdir(join(root, ".cursor"), { recursive: true });
288
- const mcp = existsSync(join(root, ".cursor/mcp.json")) ? JSON.parse(await fs.readFile(join(root, ".cursor/mcp.json"), "utf-8") || "{}") : {};
289
- mcp.mcpServers ||= {};
290
- mcp.mcpServers.uni = { url: sseUrl };
291
- await fs.writeFile(join(root, ".cursor/mcp.json"), `${JSON.stringify(mcp, null, 2)}\n`);
292
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`Updated config file ${join(root, ".cursor/mcp.json")}`)}`);
293
- }
294
-
295
- //#endregion
296
- //#region src/updateConfigs/print.ts
297
- function mcpServersConfig(sseUrl) {
298
- const code = ansis_default.rgb(206, 145, 120);
299
- const purple = ansis_default.rgb(218, 112, 214);
300
- return `
301
- ${ansis_default.yellow`{`}
302
- ${code`"mcpServers"`}${ansis_default.white`:`} ${purple`{`}
303
- ${code`"uni"`}${ansis_default.white`:`} ${ansis_default.blue`{`}
304
- ${code`"url"`}${ansis_default.white`:`} ${code`"${sseUrl}"`}
305
- ${ansis_default.blue`}`}
306
- ${purple`}`}
307
- ${ansis_default.yellow`}`}
308
- `;
309
- }
310
-
311
- //#endregion
312
- //#region src/updateConfigs/trae.ts
313
- async function updateTraeConfig(sseUrl, _options) {
314
- await open(`trae://trae.ai-ide/mcp-import?type=http&name=uni&config=${Buffer$1.from(JSON.stringify({ url: sseUrl })).toString("base64")}`);
315
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`自动配置了trae链接,请在trae中确认`)}`);
316
- }
317
-
318
- //#endregion
319
- //#region src/updateConfigs/trae-cn.ts
320
- async function updateTraeCNConfig(sseUrl, _options) {
321
- await open(`trae-cn://trae.ai-ide/mcp-import?type=http&name=uni&config=${Buffer$1.from(JSON.stringify({ url: sseUrl })).toString("base64")}`);
322
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`自动配置了trae-cn链接,请在trae-cn中确认`)}`);
323
- }
324
-
325
- //#endregion
326
- //#region src/updateConfigs/vscode.ts
327
- async function updateVSCodeConfig(root, sseUrl, _options) {
328
- await fs.mkdir(join(root, ".vscode"), { recursive: true });
329
- const mcp = existsSync(join(root, ".vscode/mcp.json")) ? JSON.parse(await fs.readFile(join(root, ".vscode/mcp.json"), "utf-8") || "{}") : {};
330
- mcp.servers ||= {};
331
- mcp.servers.uni = {
332
- type: "http",
333
- url: sseUrl
334
- };
335
- await fs.writeFile(join(root, ".vscode/mcp.json"), `${JSON.stringify(mcp, null, 2)}\n`);
336
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`Updated config file ${join(root, ".vscode/mcp.json")}`)}`);
337
- }
338
-
339
- //#endregion
340
- //#region src/updateConfigs/windsurf.ts
341
- async function updateWindsurfConfig(sseUrl, _options) {
342
- const windsurfDir = join(homedir(), ".codeium", "windsurf");
343
- const windsurfConfigPath = join(windsurfDir, "mcp_config.json");
344
- try {
345
- await fs.mkdir(windsurfDir, { recursive: true });
346
- const config = existsSync(windsurfConfigPath) ? JSON.parse(await fs.readFile(windsurfConfigPath, "utf-8").catch(() => "{}") || "{}") : {};
347
- config.mcpServers ||= {};
348
- config.mcpServers.uni = { serverUrl: sseUrl };
349
- await fs.writeFile(windsurfConfigPath, `${JSON.stringify(config, null, 2)}\n`);
350
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`Updated config file ${windsurfConfigPath}`)}`);
351
- } catch (e) {
352
- consola.error(`${CONSOLE_LOG_PREFIX}${ansis_default.red(`Failed to update ${windsurfConfigPath}`)}${e}`);
353
- }
354
- }
355
-
356
- //#endregion
357
- //#region src/updateConfigs/index.ts
358
- const CONSOLE_LOG_PREFIX = ansis_default.cyan.bold`[MCP] `;
359
- async function updateConfigs(root, sseUrl, options) {
360
- const { updateConfig = false } = options;
361
- if (updateConfig === false) {
362
- consola.log(`${CONSOLE_LOG_PREFIX}请手动配置mcpServers`);
363
- consola.box(mcpServersConfig(sseUrl));
364
- }
365
- const configPromises = (updateConfig === "auto" ? [
366
- existsSync(join(root, ".cursor")) ? "cursor" : null,
367
- existsSync(join(root, ".vscode")) ? "vscode" : null,
368
- existsSync(join(homedir(), ".codeium", "windsurf")) ? "windsurf" : null,
369
- existsSync(join(root, ".mcp.json")) ? "claude-code" : null,
370
- existsSync(join(homedir(), ".trae-cn")) ? "trae-cn" : null,
371
- existsSync(join(homedir(), ".trae")) ? "trae" : null
372
- ].filter((x) => x !== null) : Array.isArray(updateConfig) ? updateConfig : []).map(async (config) => {
373
- switch (config) {
374
- case "cursor":
375
- await updateCursorConfig(root, sseUrl, options);
376
- break;
377
- case "vscode":
378
- await updateVSCodeConfig(root, sseUrl, options);
379
- break;
380
- case "windsurf":
381
- await updateWindsurfConfig(sseUrl, options);
382
- break;
383
- case "claude-code":
384
- await updateClaudeConfig(root, sseUrl, options);
385
- break;
386
- case "trae-cn":
387
- await updateTraeCNConfig(sseUrl, options);
388
- break;
389
- case "trae":
390
- await updateTraeConfig(sseUrl, options);
391
- break;
392
- }
393
- });
394
- await Promise.all(configPromises);
395
- }
396
-
397
51
  //#endregion
398
52
  //#region src/index.ts
399
- function uniMcp(options = {}) {
400
- return {
401
- name: "uni-mcp",
402
- enforce: "post",
403
- async configResolved(config) {
404
- const url = connectServer(await createMcpServer(config, options), options);
405
- await updateConfigs(searchForWorkspaceRoot(config.root), url, options);
406
- }
407
- };
53
+ async function main() {
54
+ const server = await createMcpServer();
55
+ const transport = new StdioServerTransport();
56
+ await server.connect(transport);
408
57
  }
58
+ main().catch(console.error);
409
59
 
410
60
  //#endregion
411
- export { uniMcp as default };
61
+ export { };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@uni-helper/mcp",
3
3
  "type": "module",
4
- "version": "0.0.2-beta.1",
5
- "description": "mcp - uniapp也得有ai开发体验",
4
+ "version": "0.0.4",
5
+ "description": "uniapp提供ai开发体验",
6
6
  "author": "FliPPeDround <flippedround@qq.com>",
7
7
  "license": "MIT",
8
8
  "funding": "https://afdian.com/a/flippedround",
@@ -17,6 +17,8 @@
17
17
  "uni-app",
18
18
  "uni-helper",
19
19
  "mcp",
20
+ "ai",
21
+ "agent",
20
22
  "miniapp"
21
23
  ],
22
24
  "sideEffects": false,
@@ -28,29 +30,29 @@
28
30
  },
29
31
  "main": "./dist/index.mjs",
30
32
  "module": "./dist/index.mjs",
31
- "types": "./dist/index.d.mts",
33
+ "bin": {
34
+ "uni-mcp": "./dist/index.mjs"
35
+ },
32
36
  "files": [
33
37
  "dist",
34
38
  "scripts",
35
39
  "vectorStore"
36
40
  ],
37
- "peerDependencies": {
38
- "uniapp": "*",
39
- "vite": ">=3.1.0"
40
- },
41
41
  "dependencies": {
42
- "@hono/node-server": "^1.19.9",
43
42
  "@huggingface/transformers": "^3.8.1",
44
43
  "@langchain/community": "^1.1.4",
45
44
  "@modelcontextprotocol/sdk": "^1.25.2",
45
+ "cac": "^6.7.14",
46
+ "commander": "^14.0.2",
46
47
  "consola": "^3.2.3",
47
48
  "fs-extra": "^11.3.3",
48
49
  "hnswlib-node": "^3.0.0",
49
- "hono": "^4.11.4",
50
50
  "langchain": "^1.2.8",
51
51
  "local-pkg": "^1.1.2",
52
+ "minimist": "^1.2.8",
52
53
  "open": "^11.0.0",
53
54
  "pathe": "^2.0.3",
55
+ "which": "^6.0.0",
54
56
  "zod": "^4.3.5"
55
57
  },
56
58
  "devDependencies": {
@@ -62,6 +64,7 @@
62
64
  "@modelcontextprotocol/inspector": "^0.18.0",
63
65
  "@types/debug": "^4.1.12",
64
66
  "@types/fs-extra": "^11.0.4",
67
+ "@types/minimist": "^1.2.5",
65
68
  "@types/node": "^25.0.8",
66
69
  "@types/turndown": "^5.0.6",
67
70
  "ansis": "^4.2.0",
@@ -76,7 +79,6 @@
76
79
  "tsx": "^4.21.0",
77
80
  "turndown": "^7.2.2",
78
81
  "typescript": "^5.9.3",
79
- "vite": "^7.3.1",
80
82
  "vitest": "^4.0.17",
81
83
  "vitest-package-exports": "^1.1.2"
82
84
  },
@@ -90,12 +92,13 @@
90
92
  "build": "tsdown",
91
93
  "dev": "tsdown --watch ./src",
92
94
  "lint": "eslint",
93
- "task": "tsx ./tasks/uniappDocs/index.ts",
95
+ "task": "node ./tasks/uniappDocs/index.ts",
94
96
  "play": "cd playground && pnpm dev",
95
97
  "lint:fix": "eslint --fix",
96
98
  "inspect": "mcp-inspector",
97
99
  "release": "bumpp",
100
+ "pull:repo": "node scripts/cli.ts",
98
101
  "test": "vitest",
99
- "postinstall": "node scripts/download-model.cjs"
102
+ "postinstall": "node scripts/download-model.mjs && node scripts/link-global.mjs"
100
103
  }
101
104
  }
@@ -1,10 +1,14 @@
1
- const process = require('node:process')
2
- const { env } = require('@huggingface/transformers')
3
- const { HuggingFaceTransformersEmbeddings } = require('@langchain/community/embeddings/huggingface_transformers')
1
+ import process from 'node:process'
2
+ import { env } from '@huggingface/transformers'
3
+ import { HuggingFaceTransformersEmbeddings } from '@langchain/community/embeddings/huggingface_transformers'
4
4
 
5
- async function downloadModel() {
6
- env.remoteHost = 'https://hf-mirror.com'
5
+ if (process.env.CI) {
6
+ process.exit(0)
7
+ }
7
8
 
9
+ async function downloadModel() {
10
+ env.version = 'master'
11
+ env.remoteHost = 'https://www.modelscope.cn/models'
8
12
  const embeddings = new HuggingFaceTransformersEmbeddings({
9
13
  model: 'onnx-community/Qwen3-Embedding-0.6B-ONNX',
10
14
  pretrainedOptions: {
@@ -0,0 +1,38 @@
1
+ import { execSync } from 'node:child_process'
2
+ import { dirname, join } from 'node:path'
3
+ import process from 'node:process'
4
+ import { fileURLToPath } from 'node:url'
5
+ import which from 'which'
6
+
7
+ if (process.env.CI) {
8
+ process.exit(0)
9
+ }
10
+
11
+ const __filename = fileURLToPath(import.meta.url)
12
+ const __dirname = dirname(__filename)
13
+
14
+ async function linkGlobal() {
15
+ const resolvedOrNull = await which('uni-mcp', { nothrow: true })
16
+ if (resolvedOrNull) {
17
+ return
18
+ }
19
+
20
+ const rootDir = join(__dirname, '..')
21
+
22
+ console.log('🔧 正在将 uni-mcp 链接到全局...')
23
+
24
+ try {
25
+ execSync('npm link -y', {
26
+ cwd: rootDir,
27
+ stdio: 'inherit',
28
+ shell: true,
29
+ })
30
+ console.log('✅ uni-mcp 已成功链接到全局')
31
+ }
32
+ catch (err) {
33
+ console.error('❌ 全局链接失败:', err.message)
34
+ process.exit(1)
35
+ }
36
+ }
37
+
38
+ linkGlobal()
package/dist/index.d.mts DELETED
@@ -1,79 +0,0 @@
1
- import { Plugin } from "vite";
2
-
3
- //#region node_modules/.pnpm/@langchain+core@1.1.15_openai@6.16.0_ws@8.19.0_zod@4.3.5_/node_modules/@langchain/core/dist/embeddings.d.cts
4
- interface EmbeddingsInterface<TOutput = number[]> {
5
- /**
6
- * An abstract method that takes an array of documents as input and
7
- * returns a promise that resolves to an array of vectors for each
8
- * document.
9
- * @param documents An array of documents to be embedded.
10
- * @returns A promise that resolves to an array of vectors for each document.
11
- */
12
- embedDocuments(documents: string[]): Promise<TOutput[]>;
13
- /**
14
- * An abstract method that takes a single document as input and returns a
15
- * promise that resolves to a vector for the query document.
16
- * @param document A single document to be embedded.
17
- * @returns A promise that resolves to a vector for the query document.
18
- */
19
- embedQuery(document: string): Promise<TOutput>;
20
- }
21
- /**
22
- * An abstract class that provides methods for embedding documents and
23
- * queries using LangChain.
24
- */
25
- //#endregion
26
- //#region src/types.d.ts
27
- type SupportedUpdateConfigType = 'cursor' | 'vscode' | 'windsurf' | 'claude-code' | 'trae-cn' | 'trae';
28
- type MaybeArray<T> = T | T[];
29
- interface UniMcpOptions {
30
- /**
31
- * 监听的端口,默认为 Vite 开发服务器的端口
32
- */
33
- port?: number;
34
- /**
35
- * 在控制台打印 MCP 服务器 URL
36
- *
37
- * @default true
38
- */
39
- printUrl?: boolean;
40
- /**
41
- * 自定义的 Embeddings 模型
42
- *
43
- * 内置模型为 Qwen3-Embedding-0.6B-ONNX
44
- *
45
- * 如果本地运行效率低,可自定义模型
46
- * - 确保模型支持 1024 维
47
- * - 支持 langchain 的 Embeddings 格式
48
- * @default
49
- * ```ts
50
- * new HuggingFaceTransformersEmbeddings({
51
- * model: 'onnx-community/Qwen3-Embedding-0.6B-ONNX',
52
- * pretrainedOptions: {
53
- * dtype: 'int8',
54
- * device: 'cpu',
55
- * },
56
- * })
57
- * ```
58
- */
59
- embeddings?: EmbeddingsInterface;
60
- /**
61
- * 要更新的配置类型
62
- *
63
- * - `auto` - 如果配置文件存在则自动更新
64
- * - `cursor` - 更新 Cursor 配置文件 `.cursor/mcp.json`
65
- * - `vscode` - 更新 VSCode 配置文件 `.vscode/settings.json`
66
- * - `windsurf` - 更新 Windsurf 配置文件 `~/.codeium/windsurf/mcp_config.json`
67
- * - `claude-code` - 更新 Claude Code 配置文件 `.mcp.json`
68
- * - `trae-cn` - 更新 Trae 配置文件 `~/trae CN/mcp.json`
69
- * - `trae` - 更新 Trae 配置文件 `.trae/mcp.json`
70
- *
71
- * @default false
72
- */
73
- updateConfig?: 'auto' | false | MaybeArray<SupportedUpdateConfigType>;
74
- }
75
- //#endregion
76
- //#region src/index.d.ts
77
- declare function uniMcp(options?: UniMcpOptions): Plugin;
78
- //#endregion
79
- export { uniMcp as default };