@uni-helper/mcp 0.0.2-beta.2 → 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,11 +1,5 @@
1
- import process from "node:process";
2
- import minimist from "minimist";
3
- import { searchForWorkspaceRoot } from "vite";
4
- import { serve } from "@hono/node-server";
5
- import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
6
- import fkill from "fkill";
7
- import { Hono } from "hono";
8
- import { cors } from "hono/cors";
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
4
  import { z } from "zod";
11
5
  import { dirname, join } from "node:path";
@@ -13,188 +7,9 @@ import { fileURLToPath } from "node:url";
13
7
  import { env } from "@huggingface/transformers";
14
8
  import { HuggingFaceTransformersEmbeddings } from "@langchain/community/embeddings/huggingface_transformers";
15
9
  import { HNSWLib } from "@langchain/community/vectorstores/hnswlib";
16
- import fs from "fs-extra";
17
- import { existsSync } from "node:fs";
18
- import { homedir } from "node:os";
19
- import consola from "consola";
20
- import { Buffer as Buffer$1 } from "node:buffer";
21
- import open from "open";
22
10
 
23
- //#region rolldown:runtime
24
- var __create = Object.create;
25
- var __defProp = Object.defineProperty;
26
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
27
- var __getOwnPropNames = Object.getOwnPropertyNames;
28
- var __getProtoOf = Object.getPrototypeOf;
29
- var __hasOwnProp = Object.prototype.hasOwnProperty;
30
- var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
31
- var __copyProps = (to, from, except, desc) => {
32
- if (from && typeof from === "object" || typeof from === "function") {
33
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
34
- key = keys[i];
35
- if (!__hasOwnProp.call(to, key) && key !== except) {
36
- __defProp(to, key, {
37
- get: ((k) => from[k]).bind(null, key),
38
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
39
- });
40
- }
41
- }
42
- }
43
- return to;
44
- };
45
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
46
- value: mod,
47
- enumerable: true
48
- }) : target, mod));
49
-
50
- //#endregion
51
- //#region node_modules/.pnpm/ansis@4.2.0/node_modules/ansis/index.cjs
52
- var require_ansis = /* @__PURE__ */ __commonJSMin(((exports, module) => {
53
- let e, t, r, { defineProperty: l, setPrototypeOf: n, create: o, keys: s } = Object, i = "", { round: c, max: a } = Math, p = (e) => {
54
- 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);
55
- return [
56
- l >> 16 & 255,
57
- l >> 8 & 255,
58
- 255 & l
59
- ];
60
- }, 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) => {
61
- let t, r, l, n, o;
62
- 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);
63
- }, f = (() => {
64
- let r = (e) => o.some(((t) => e.test(t))), l = globalThis, n = l.process ?? {}, o = n.argv ?? [], i = n.env ?? {}, c = -1;
65
- try {
66
- e = "," + s(i).join(",");
67
- } catch (e) {
68
- i = {}, c = 0;
69
- }
70
- let a$1 = "FORCE_COLOR", p = {
71
- false: 0,
72
- 0: 0,
73
- 1: 1,
74
- 2: 2,
75
- 3: 3
76
- }[i[a$1]] ?? -1, u = a$1 in i && p || r(/^--color=?(true|always)?$/);
77
- return u && (c = p), ~c || (c = ((r$1, l$1, n$1) => (t = r$1.TERM, {
78
- "24bit": 3,
79
- truecolor: 3,
80
- ansi256: 2,
81
- ansi: 1
82
- }[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;
83
- })(), g = {
84
- open: i,
85
- close: i
86
- }, h = 39, b = 49, O = {}, m = ({ p: e }, { open: t, close: l }) => {
87
- let o = (e$1, ...r) => {
88
- if (!e$1) {
89
- if (t && t === l) return t;
90
- if ((e$1 ?? i) === i) return i;
91
- }
92
- 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;
93
- if (s$1.includes("\x1B")) for (; c$1; c$1 = c$1.p) {
94
- let { open: e$2, close: t$1 } = c$1, r$1 = t$1.length, l$1 = i, o$1 = 0;
95
- 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;
96
- s$1 = l$1 + s$1.slice(o$1);
97
- }
98
- return a$1 + (s$1.includes("\n") ? s$1.replace(/(\r?\n)/g, p + "$1" + a$1) : s$1) + p;
99
- }, s = t, c = l;
100
- return e && (s = e.o + t, c = l + e.c), n(o, r), o.p = {
101
- open: t,
102
- close: l,
103
- o: s,
104
- c,
105
- p: e
106
- }, o.open = s, o.close = c, o;
107
- };
108
- const w = new function e(t = f) {
109
- let s = {
110
- Ansis: e,
111
- level: t,
112
- isSupported: () => a$1,
113
- strip: (e$1) => e$1.replace(/[›][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, i),
114
- extend(e$1) {
115
- for (let t$1 in e$1) {
116
- let r = e$1[t$1], l = (typeof r)[0];
117
- "s" === l ? (c(t$1, T(...p(r))), c(_(t$1), v(...p(r)))) : c(t$1, r, "f" === l);
118
- }
119
- return r = o({}, O), n(s, r), s;
120
- }
121
- }, c = (e$1, t$1, r) => {
122
- O[e$1] = { get() {
123
- let n = r ? (...e$2) => m(this, t$1(...e$2)) : m(this, t$1);
124
- return l(this, e$1, { value: n }), n;
125
- } };
126
- }, a$1 = t > 0, w = (e$1, t$1) => a$1 ? {
127
- open: `[${e$1}m`,
128
- close: `[${t$1}m`
129
- } : 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);
130
- 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));
131
- let M, I = {
132
- fg: C,
133
- bg: E,
134
- rgb: T,
135
- bgRgb: v,
136
- hex: y(T),
137
- bgHex: y(v),
138
- visible: g,
139
- reset: w(0, 0),
140
- bold: w(1, 22),
141
- dim: w(2, 22),
142
- italic: w(3, 23),
143
- underline: w(4, 24),
144
- inverse: w(7, 27),
145
- hidden: w(8, 28),
146
- strikethrough: w(9, 29)
147
- }, _ = (e$1) => "bg" + e$1[0].toUpperCase() + e$1.slice(1), k = "Bright";
148
- return "black,red,green,yellow,blue,magenta,cyan,white,gray".split(",").map(((e$1, t$1) => {
149
- 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);
150
- })), s.extend(I);
151
- }();
152
- module.exports = w, w.default = w;
153
- }));
154
-
155
- //#endregion
156
- //#region node_modules/.pnpm/ansis@4.2.0/node_modules/ansis/index.mjs
157
- var import_ansis = /* @__PURE__ */ __toESM(require_ansis(), 1);
158
- var ansis_default = import_ansis.default;
159
- 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;
160
-
161
- //#endregion
162
- //#region src/mcpServer/connect.ts
163
- function connectServer(server, options) {
164
- const { port = 2515, printUrl = true } = options;
165
- const transport = new WebStandardStreamableHTTPServerTransport();
166
- const app = new Hono();
167
- app.use("*", cors({
168
- origin: "*",
169
- allowMethods: [
170
- "GET",
171
- "POST",
172
- "DELETE",
173
- "OPTIONS"
174
- ],
175
- allowHeaders: [
176
- "Content-Type",
177
- "mcp-session-id",
178
- "Last-Event-ID",
179
- "mcp-protocol-version"
180
- ],
181
- exposeHeaders: ["mcp-session-id", "mcp-protocol-version"]
182
- }));
183
- app.all("/mcp", (c) => transport.handleRequest(c.req.raw));
184
- fkill(port, {
185
- force: true,
186
- silent: true
187
- }).then(() => {
188
- server.connect(transport).then(() => {
189
- if (printUrl) console.log(`${ansis_default.cyan` ➜ MCP: `}${ansis_default.gray(`server is running at ${ansis_default.green(`http://localhost:${port}/mcp`)}`)}`);
190
- serve({
191
- fetch: app.fetch,
192
- port
193
- });
194
- });
195
- });
196
- return `http://localhost:${port}/mcp`;
197
- }
11
+ //#region package.json
12
+ var version = "0.0.4";
198
13
 
199
14
  //#endregion
200
15
  //#region src/docs/index.ts
@@ -214,211 +29,33 @@ async function loadVectorStore(vectorName, _embeddings) {
214
29
  }
215
30
 
216
31
  //#endregion
217
- //#region package.json
218
- var version = "0.0.2-beta.2";
219
-
220
- //#endregion
221
- //#region src/mcpServer/projectAnalyzer.ts
222
- async function readFileIfExists(path) {
223
- const content = await fs.readFile(path, "utf-8").catch(() => void 0);
224
- return {
225
- exists: !!content,
226
- path,
227
- content
228
- };
229
- }
230
- async function analyzeProject(rootPath) {
231
- const [pagesJson, manifestJson] = await Promise.all([readFileIfExists(join(rootPath, "src/pages.json")), readFileIfExists(join(rootPath, "src/manifest.json"))]);
232
- return {
233
- pagesJson,
234
- manifestJson
235
- };
236
- }
237
-
238
- //#endregion
239
- //#region src/mcpServer/server.ts
240
- async function createMcpServer(config, options) {
32
+ //#region src/server/index.ts
33
+ async function createMcpServer() {
241
34
  const server = new McpServer({
242
35
  name: "uni",
243
36
  version
244
37
  });
245
- server.registerTool("get-vite-config", {
246
- title: "获取 Vite 配置",
247
- description: "获取 Vite 配置摘要,包括根目录、解析配置、插件和环境名称。"
248
- }, () => ({ content: [{
249
- type: "text",
250
- text: JSON.stringify({
251
- root: config.root,
252
- resolve: config.resolve,
253
- plugins: config.plugins.map((p) => p.name).filter(Boolean),
254
- environmentNames: Object.keys(config.environments)
255
- })
256
- }] }));
257
38
  server.registerTool("search-docs-by-Uniapp-official", {
258
39
  title: "搜索 Uniapp 官方文档",
259
40
  description: "在 Uniapp 文档知识库中进行搜索,可查找相关信息、代码示例、API参考文档和操作指南。当您需要解答关于Uniapp文档的问题、查找特定文档内容、了解功能运作原理或定位实现细节时,可使用此工具。搜索结果将返回带有标题的上下文相关内容,并附有直达文档页面的链接。",
260
41
  inputSchema: { query: z.string().describe("用于搜索内容的查询语句") }
261
42
  }, async ({ query }) => {
262
- 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) => ({
263
44
  type: "text",
264
45
  text: JSON.stringify(doc)
265
46
  })) };
266
47
  });
267
- server.registerTool("get-project-overview", {
268
- title: "获取项目概览",
269
- description: "返回 Uniapp 项目的 pages.json 和 manifest.json 配置文件。"
270
- }, async () => {
271
- const overview = await analyzeProject(config.root);
272
- return { content: [{
273
- type: "text",
274
- text: JSON.stringify(overview, null, 2)
275
- }] };
276
- });
277
48
  return server;
278
49
  }
279
50
 
280
- //#endregion
281
- //#region src/updateConfigs/claude.ts
282
- async function updateClaudeConfig(root, sseUrl, _options) {
283
- const mcp = existsSync(join(root, ".mcp.json")) ? JSON.parse(await fs.readFile(join(root, ".mcp.json"), "utf-8") || "{}") : {};
284
- mcp.mcpServers ||= {};
285
- mcp.mcpServers.uni = {
286
- type: "http",
287
- url: sseUrl
288
- };
289
- await fs.writeFile(join(root, ".mcp.json"), `${JSON.stringify(mcp, null, 2)}\n`);
290
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`Updated config file ${join(root, ".mcp.json")}`)}`);
291
- }
292
-
293
- //#endregion
294
- //#region src/updateConfigs/cursor.ts
295
- async function updateCursorConfig(root, sseUrl, _options) {
296
- await fs.mkdir(join(root, ".cursor"), { recursive: true });
297
- const mcp = existsSync(join(root, ".cursor/mcp.json")) ? JSON.parse(await fs.readFile(join(root, ".cursor/mcp.json"), "utf-8") || "{}") : {};
298
- mcp.mcpServers ||= {};
299
- mcp.mcpServers.uni = { url: sseUrl };
300
- await fs.writeFile(join(root, ".cursor/mcp.json"), `${JSON.stringify(mcp, null, 2)}\n`);
301
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`Updated config file ${join(root, ".cursor/mcp.json")}`)}`);
302
- }
303
-
304
- //#endregion
305
- //#region src/updateConfigs/print.ts
306
- function mcpServersConfig(sseUrl) {
307
- const code = ansis_default.rgb(206, 145, 120);
308
- const purple = ansis_default.rgb(218, 112, 214);
309
- return `
310
- ${ansis_default.yellow`{`}
311
- ${code`"mcpServers"`}${ansis_default.white`:`} ${purple`{`}
312
- ${code`"uni"`}${ansis_default.white`:`} ${ansis_default.blue`{`}
313
- ${code`"url"`}${ansis_default.white`:`} ${code`"${sseUrl}"`}
314
- ${ansis_default.blue`}`}
315
- ${purple`}`}
316
- ${ansis_default.yellow`}`}
317
- `;
318
- }
319
-
320
- //#endregion
321
- //#region src/updateConfigs/trae.ts
322
- async function updateTraeConfig(sseUrl, _options) {
323
- await open(`trae://trae.ai-ide/mcp-import?type=http&name=uni&config=${Buffer$1.from(JSON.stringify({ url: sseUrl })).toString("base64")}`);
324
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`自动配置了trae链接,请在trae中确认`)}`);
325
- }
326
-
327
- //#endregion
328
- //#region src/updateConfigs/trae-cn.ts
329
- async function updateTraeCNConfig(sseUrl, _options) {
330
- await open(`trae-cn://trae.ai-ide/mcp-import?type=http&name=uni&config=${Buffer$1.from(JSON.stringify({ url: sseUrl })).toString("base64")}`);
331
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`自动配置了trae-cn链接,请在trae-cn中确认`)}`);
332
- }
333
-
334
- //#endregion
335
- //#region src/updateConfigs/vscode.ts
336
- async function updateVSCodeConfig(root, sseUrl, _options) {
337
- await fs.mkdir(join(root, ".vscode"), { recursive: true });
338
- const mcp = existsSync(join(root, ".vscode/mcp.json")) ? JSON.parse(await fs.readFile(join(root, ".vscode/mcp.json"), "utf-8") || "{}") : {};
339
- mcp.servers ||= {};
340
- mcp.servers.uni = {
341
- type: "http",
342
- url: sseUrl
343
- };
344
- await fs.writeFile(join(root, ".vscode/mcp.json"), `${JSON.stringify(mcp, null, 2)}\n`);
345
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`Updated config file ${join(root, ".vscode/mcp.json")}`)}`);
346
- }
347
-
348
- //#endregion
349
- //#region src/updateConfigs/windsurf.ts
350
- async function updateWindsurfConfig(sseUrl, _options) {
351
- const windsurfDir = join(homedir(), ".codeium", "windsurf");
352
- const windsurfConfigPath = join(windsurfDir, "mcp_config.json");
353
- try {
354
- await fs.mkdir(windsurfDir, { recursive: true });
355
- const config = existsSync(windsurfConfigPath) ? JSON.parse(await fs.readFile(windsurfConfigPath, "utf-8").catch(() => "{}") || "{}") : {};
356
- config.mcpServers ||= {};
357
- config.mcpServers.uni = { serverUrl: sseUrl };
358
- await fs.writeFile(windsurfConfigPath, `${JSON.stringify(config, null, 2)}\n`);
359
- consola.log(`${CONSOLE_LOG_PREFIX}${ansis_default.gray(`Updated config file ${windsurfConfigPath}`)}`);
360
- } catch (e) {
361
- consola.error(`${CONSOLE_LOG_PREFIX}${ansis_default.red(`Failed to update ${windsurfConfigPath}`)}${e}`);
362
- }
363
- }
364
-
365
- //#endregion
366
- //#region src/updateConfigs/index.ts
367
- const CONSOLE_LOG_PREFIX = ansis_default.cyan.bold`[MCP] `;
368
- async function updateConfigs(root, sseUrl, options) {
369
- const { updateConfig = false } = options;
370
- if (updateConfig === false) {
371
- consola.log(`${CONSOLE_LOG_PREFIX}请手动配置mcpServers`);
372
- consola.box(mcpServersConfig(sseUrl));
373
- }
374
- const configPromises = (updateConfig === "auto" ? [
375
- existsSync(join(root, ".cursor")) ? "cursor" : null,
376
- existsSync(join(root, ".vscode")) ? "vscode" : null,
377
- existsSync(join(homedir(), ".codeium", "windsurf")) ? "windsurf" : null,
378
- existsSync(join(root, ".mcp.json")) ? "claude-code" : null,
379
- existsSync(join(homedir(), ".trae-cn")) ? "trae-cn" : null,
380
- existsSync(join(homedir(), ".trae")) ? "trae" : null
381
- ].filter((x) => x !== null) : Array.isArray(updateConfig) ? updateConfig : []).map(async (config) => {
382
- switch (config) {
383
- case "cursor":
384
- await updateCursorConfig(root, sseUrl, options);
385
- break;
386
- case "vscode":
387
- await updateVSCodeConfig(root, sseUrl, options);
388
- break;
389
- case "windsurf":
390
- await updateWindsurfConfig(sseUrl, options);
391
- break;
392
- case "claude-code":
393
- await updateClaudeConfig(root, sseUrl, options);
394
- break;
395
- case "trae-cn":
396
- await updateTraeCNConfig(sseUrl, options);
397
- break;
398
- case "trae":
399
- await updateTraeConfig(sseUrl, options);
400
- break;
401
- }
402
- });
403
- await Promise.all(configPromises);
404
- }
405
-
406
51
  //#endregion
407
52
  //#region src/index.ts
408
- function isBuild() {
409
- return minimist(process.argv.slice(2))._.includes("build");
410
- }
411
- function uniMcp(options = {}) {
412
- if (isBuild()) return;
413
- return {
414
- name: "uni-mcp",
415
- enforce: "post",
416
- async configResolved(config) {
417
- const url = connectServer(await createMcpServer(config, options), options);
418
- await updateConfigs(searchForWorkspaceRoot(config.root), url, options);
419
- }
420
- };
53
+ async function main() {
54
+ const server = await createMcpServer();
55
+ const transport = new StdioServerTransport();
56
+ await server.connect(transport);
421
57
  }
58
+ main().catch(console.error);
422
59
 
423
60
  //#endregion
424
- export { uniMcp as default, isBuild };
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.2",
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,31 +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
- "fkill": "^10.0.3",
48
48
  "fs-extra": "^11.3.3",
49
49
  "hnswlib-node": "^3.0.0",
50
- "hono": "^4.11.4",
51
50
  "langchain": "^1.2.8",
52
51
  "local-pkg": "^1.1.2",
53
52
  "minimist": "^1.2.8",
54
53
  "open": "^11.0.0",
55
54
  "pathe": "^2.0.3",
55
+ "which": "^6.0.0",
56
56
  "zod": "^4.3.5"
57
57
  },
58
58
  "devDependencies": {
@@ -79,7 +79,6 @@
79
79
  "tsx": "^4.21.0",
80
80
  "turndown": "^7.2.2",
81
81
  "typescript": "^5.9.3",
82
- "vite": "^7.3.1",
83
82
  "vitest": "^4.0.17",
84
83
  "vitest-package-exports": "^1.1.2"
85
84
  },
@@ -93,12 +92,13 @@
93
92
  "build": "tsdown",
94
93
  "dev": "tsdown --watch ./src",
95
94
  "lint": "eslint",
96
- "task": "tsx ./tasks/uniappDocs/index.ts",
95
+ "task": "node ./tasks/uniappDocs/index.ts",
97
96
  "play": "cd playground && pnpm dev",
98
97
  "lint:fix": "eslint --fix",
99
98
  "inspect": "mcp-inspector",
100
99
  "release": "bumpp",
100
+ "pull:repo": "node scripts/cli.ts",
101
101
  "test": "vitest",
102
- "postinstall": "node scripts/download-model.mjs"
102
+ "postinstall": "node scripts/download-model.mjs && node scripts/link-global.mjs"
103
103
  }
104
104
  }
@@ -2,10 +2,13 @@ import process from 'node:process'
2
2
  import { env } from '@huggingface/transformers'
3
3
  import { HuggingFaceTransformersEmbeddings } from '@langchain/community/embeddings/huggingface_transformers'
4
4
 
5
+ if (process.env.CI) {
6
+ process.exit(0)
7
+ }
8
+
5
9
  async function downloadModel() {
6
10
  env.version = 'master'
7
11
  env.remoteHost = 'https://www.modelscope.cn/models'
8
- await new Promise(resolve => setTimeout(resolve, 1000))
9
12
  const embeddings = new HuggingFaceTransformersEmbeddings({
10
13
  model: 'onnx-community/Qwen3-Embedding-0.6B-ONNX',
11
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,80 +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 isBuild(): boolean;
78
- declare function uniMcp(options?: UniMcpOptions): Plugin | undefined;
79
- //#endregion
80
- export { uniMcp as default, isBuild };