@reus-able/frontend-helper-mcp 1.1.1 → 1.1.3

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/dist/index.js CHANGED
@@ -1,115 +1,115 @@
1
1
  #!/usr/bin/env node
2
- import { McpServer as R } from "@modelcontextprotocol/sdk/server/mcp.js";
3
- import { StdioServerTransport as F } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import c from "fs/promises";
2
+ import { McpServer as F } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport as x } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import m from "fs/promises";
5
5
  import a from "path";
6
- import { fileURLToPath as p } from "url";
7
- import { ListPromptsRequestSchema as P, GetPromptRequestSchema as x, ListResourcesRequestSchema as $, ReadResourceRequestSchema as M, ListToolsRequestSchema as C, CallToolRequestSchema as L } from "@modelcontextprotocol/sdk/types.js";
8
- import N from "fs";
9
- function T(e) {
6
+ import { fileURLToPath as f } from "url";
7
+ import { ListPromptsRequestSchema as $, GetPromptRequestSchema as P, ListResourcesRequestSchema as E, ReadResourceRequestSchema as L, ListToolsRequestSchema as M, CallToolRequestSchema as T } from "@modelcontextprotocol/sdk/types.js";
8
+ import C from "fs";
9
+ function _(e) {
10
10
  try {
11
- return N.statSync(e).isDirectory();
11
+ return C.statSync(e).isDirectory();
12
12
  } catch {
13
13
  return !1;
14
14
  }
15
15
  }
16
- function u(e, t, o = 8) {
16
+ function p(e, n, s = 8) {
17
17
  let r = e;
18
- for (let n = 0; n <= o; n++) {
19
- const s = a.resolve(r, t);
20
- if (T(s)) return s;
18
+ for (let t = 0; t <= s; t++) {
19
+ const o = a.resolve(r, n);
20
+ if (_(o)) return o;
21
21
  const i = a.dirname(r);
22
22
  if (i === r) break;
23
23
  r = i;
24
24
  }
25
25
  }
26
- function y() {
26
+ function k() {
27
27
  const e = process.env.MCP_COMMAND_PROMPTS_DIR ?? process.env.MCP_PROMPTS_DIR;
28
28
  if (e) return e;
29
- const t = a.dirname(p(import.meta.url)), o = u(
30
- t,
29
+ const n = a.dirname(f(import.meta.url)), s = p(
30
+ n,
31
31
  "resources/command-prompts"
32
32
  );
33
- if (o) return o;
34
- const r = u(
33
+ if (s) return s;
34
+ const r = p(
35
35
  process.cwd(),
36
36
  "resources/command-prompts"
37
37
  );
38
38
  return r || a.resolve(process.cwd(), "resources/command-prompts");
39
39
  }
40
- function _() {
40
+ function h() {
41
41
  const e = process.env.MCP_SKILLS_DIR;
42
42
  if (e) return e;
43
- const t = a.dirname(p(import.meta.url)), o = u(t, "resources/skills");
44
- if (o) return o;
45
- const r = u(process.cwd(), "resources/skills");
43
+ const n = a.dirname(f(import.meta.url)), s = p(n, "resources/skills");
44
+ if (s) return s;
45
+ const r = p(process.cwd(), "resources/skills");
46
46
  return r || a.resolve(process.cwd(), "resources/skills");
47
47
  }
48
- async function d(e) {
48
+ async function w(e) {
49
49
  try {
50
- return await c.access(e), (await c.readdir(e)).filter(
51
- (o) => [".txt", ".md", ".json"].includes(a.extname(o).toLowerCase())
50
+ return await m.access(e), (await m.readdir(e)).filter(
51
+ (s) => [".txt", ".md", ".json"].includes(a.extname(s).toLowerCase())
52
52
  );
53
- } catch (t) {
54
- return console.error(`Error accessing prompts directory ${e}:`, t), [];
53
+ } catch (n) {
54
+ return console.error(`Error accessing prompts directory ${e}:`, n), [];
55
55
  }
56
56
  }
57
57
  function D(e) {
58
58
  return !(!e || e.includes("..") || e.includes("/") || e.includes("\\"));
59
59
  }
60
- function q(e) {
61
- const t = e.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
62
- if (!t) return {};
63
- const o = {};
64
- for (const r of t[1].split(`
60
+ function N(e) {
61
+ const n = e.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
62
+ if (!n) return {};
63
+ const s = {};
64
+ for (const r of n[1].split(`
65
65
  `)) {
66
- const n = r.trim();
67
- if (!n) continue;
68
- const s = n.match(/^([A-Za-z0-9_-]+):\s*(.*)\s*$/);
69
- if (!s) continue;
70
- const i = s[1], m = s[2];
71
- i === "name" && (o.name = m), i === "description" && (o.description = m);
66
+ const t = r.trim();
67
+ if (!t) continue;
68
+ const o = t.match(/^([A-Za-z0-9_-]+):\s*(.*)\s*$/);
69
+ if (!o) continue;
70
+ const i = o[1], c = o[2];
71
+ i === "name" && (s.name = c), i === "description" && (s.description = c);
72
72
  }
73
- return o;
73
+ return s;
74
74
  }
75
- async function w(e) {
75
+ async function v(e) {
76
76
  try {
77
- await c.access(e);
78
- const o = (await c.readdir(e, { withFileTypes: !0 })).filter((n) => n.isDirectory()).map((n) => n.name), r = [];
79
- for (const n of o) {
80
- const s = a.join(e, n, "SKILL.md");
77
+ await m.access(e);
78
+ const s = (await m.readdir(e, { withFileTypes: !0 })).filter((t) => t.isDirectory()).map((t) => t.name), r = [];
79
+ for (const t of s) {
80
+ const o = a.join(e, t, "SKILL.md");
81
81
  try {
82
- const i = await c.readFile(s, "utf-8"), m = q(i);
82
+ const i = await m.readFile(o, "utf-8"), c = N(i);
83
83
  r.push({
84
- dirName: n,
85
- name: m.name,
86
- description: m.description,
87
- filePath: s
84
+ dirName: t,
85
+ name: c.name,
86
+ description: c.description,
87
+ filePath: o
88
88
  });
89
89
  } catch {
90
90
  continue;
91
91
  }
92
92
  }
93
- return r.sort((n, s) => n.dirName.localeCompare(s.dirName)), r;
94
- } catch (t) {
95
- return console.error(`Error accessing skills directory ${e}:`, t), [];
93
+ return r.sort((t, o) => t.dirName.localeCompare(o.dirName)), r;
94
+ } catch (n) {
95
+ return console.error(`Error accessing skills directory ${e}:`, n), [];
96
96
  }
97
97
  }
98
- async function E(e, t) {
99
- if (!D(t)) return;
100
- const r = (await w(e)).find((s) => s.dirName === t || s.name === t);
98
+ async function I(e, n) {
99
+ if (!D(n)) return;
100
+ const r = (await v(e)).find((o) => o.dirName === n || o.name === n);
101
101
  if (!r) return;
102
- const n = await c.readFile(r.filePath, "utf-8");
103
- return { entry: r, markdown: n };
102
+ const t = await m.readFile(r.filePath, "utf-8");
103
+ return { entry: r, markdown: t };
104
104
  }
105
- async function v(e, t) {
106
- return (await d(e)).find((r) => a.parse(r).name === t);
105
+ async function S(e, n) {
106
+ return (await w(e)).find((r) => a.parse(r).name === n);
107
107
  }
108
- function f(e) {
109
- const t = a.extname(e).toLowerCase();
110
- return t === ".md" ? "text/markdown" : t === ".json" ? "application/json" : "text/plain";
108
+ function y(e) {
109
+ const n = a.extname(e).toLowerCase();
110
+ return n === ".md" ? "text/markdown" : n === ".json" ? "application/json" : "text/plain";
111
111
  }
112
- const S = {
112
+ const R = {
113
113
  "code-refactor": {
114
114
  name: "代码重构",
115
115
  description: "对代码进行结构调整,不改变功能逻辑"
@@ -126,26 +126,35 @@ const S = {
126
126
  name: "安装技能",
127
127
  description: "安装mcp中定义的技能"
128
128
  }
129
+ }, j = {
130
+ "vue-components": {
131
+ name: "Vue组件编写规范",
132
+ description: "对于Vue组件的编写规范"
133
+ },
134
+ "vue-hooks": {
135
+ name: "Vue钩子函数编写规范",
136
+ description: "对于Vue组件中的钩子函数的编写规范"
137
+ }
129
138
  };
130
- function j(e) {
131
- const t = y();
132
- e.server.setRequestHandler(P, async () => {
139
+ function q(e) {
140
+ const n = k();
141
+ e.server.setRequestHandler($, async () => {
133
142
  try {
134
- return { prompts: (await d(t)).map((n) => {
135
- const s = a.parse(n).name;
143
+ return { prompts: (await w(n)).map((t) => {
144
+ const o = a.parse(t).name;
136
145
  return {
137
- name: s,
138
- description: S[s]?.description || `Content of ${n}`
146
+ name: o,
147
+ description: R[o]?.description || `Content of ${t}`
139
148
  };
140
149
  }) };
141
- } catch (o) {
142
- return console.error("Error listing prompts:", o), { prompts: [] };
150
+ } catch (s) {
151
+ return console.error("Error listing prompts:", s), { prompts: [] };
143
152
  }
144
- }), e.server.setRequestHandler(x, async (o) => {
145
- const r = o.params.name;
153
+ }), e.server.setRequestHandler(P, async (s) => {
154
+ const r = s.params.name;
146
155
  try {
147
- const n = await v(t, r);
148
- if (!n)
156
+ const t = await S(n, r);
157
+ if (!t)
149
158
  throw new Error(`Prompt not found: ${r}`);
150
159
  return {
151
160
  messages: [
@@ -153,58 +162,104 @@ function j(e) {
153
162
  role: "user",
154
163
  content: {
155
164
  type: "text",
156
- text: await c.readFile(a.join(t, n), "utf-8")
165
+ text: await m.readFile(a.join(n, t), "utf-8")
157
166
  }
158
167
  }
159
168
  ]
160
169
  };
161
- } catch (n) {
162
- throw new Error(`Failed to load prompt ${r}: ${n}`);
170
+ } catch (t) {
171
+ throw new Error(`Failed to load prompt ${r}: ${t}`);
163
172
  }
164
173
  });
165
174
  }
166
175
  function H(e) {
167
- const t = y();
168
- e.server.setRequestHandler($, async () => {
176
+ const n = k(), s = h();
177
+ e.server.setRequestHandler(E, async () => {
169
178
  try {
170
- return { resources: (await d(t)).map((n) => {
171
- const s = a.parse(n).name, i = f(n);
179
+ const t = (await w(n)).map((i) => {
180
+ const c = a.parse(i).name, l = y(i);
172
181
  return {
173
- uri: `prompt://${s}`,
174
- name: s,
175
- mimeType: i,
176
- description: S[s]?.description || `Content of ${n}`
182
+ uri: `prompt://${c}`,
183
+ name: c,
184
+ mimeType: l,
185
+ description: R[c]?.description || `Content of ${i}`
177
186
  };
178
- }) };
179
- } catch (o) {
180
- return console.error("Error listing resources:", o), { resources: [] };
187
+ });
188
+ let o = [];
189
+ try {
190
+ o = (await m.readdir(s, { withFileTypes: !0 })).filter((c) => c.isDirectory()).map((c) => {
191
+ const l = c.name;
192
+ return {
193
+ uri: `skill://skill-${l}`,
194
+ name: l,
195
+ mimeType: "text/markdown",
196
+ description: j[l]?.description || `Skill ${l}`
197
+ };
198
+ });
199
+ } catch (i) {
200
+ console.error("Error listing skills:", i);
201
+ }
202
+ return { resources: [...t, ...o] };
203
+ } catch (r) {
204
+ return console.error("Error listing resources:", r), { resources: [] };
181
205
  }
182
206
  }), e.server.setRequestHandler(
183
- M,
184
- async (o) => {
185
- const r = o.params.uri, n = r.replace(/^prompt:\/\//, "");
207
+ L,
208
+ async (r) => {
209
+ const t = r.params.uri;
186
210
  try {
187
- const s = await v(t, n);
188
- if (!s)
189
- throw new Error(`Resource not found: ${r}`);
190
- const i = await c.readFile(a.join(t, s), "utf-8"), m = f(s);
191
- return {
192
- contents: [
193
- {
194
- uri: r,
195
- mimeType: m,
196
- text: i
211
+ const o = t.indexOf("://");
212
+ if (o === -1)
213
+ throw new Error(`Invalid URI format: ${t}`);
214
+ const i = t.substring(0, o), c = t.substring(o + 3);
215
+ switch (i) {
216
+ case "skill": {
217
+ const l = a.join(s, c.replace("skill-", ""), "SKILL.md");
218
+ try {
219
+ await m.access(l);
220
+ } catch {
221
+ throw new Error(`Resource not found: ${t}`);
197
222
  }
198
- ]
199
- };
200
- } catch (s) {
201
- throw new Error(`Failed to read resource ${r}: ${s}`);
223
+ const u = await m.readFile(l, "utf-8");
224
+ return {
225
+ contents: [
226
+ {
227
+ uri: t,
228
+ mimeType: "text/markdown",
229
+ text: u
230
+ }
231
+ ]
232
+ };
233
+ }
234
+ case "prompt": {
235
+ const l = await S(n, c);
236
+ if (!l)
237
+ throw new Error(`Resource not found: ${t}`);
238
+ const u = await m.readFile(
239
+ a.join(n, l),
240
+ "utf-8"
241
+ ), d = y(l);
242
+ return {
243
+ contents: [
244
+ {
245
+ uri: t,
246
+ mimeType: d,
247
+ text: u
248
+ }
249
+ ]
250
+ };
251
+ }
252
+ default:
253
+ throw new Error(`Unsupported resource protocol: ${i}`);
254
+ }
255
+ } catch (o) {
256
+ throw new Error(`Failed to read resource ${t}: ${o}`);
202
257
  }
203
258
  }
204
259
  );
205
260
  }
206
- function I(e) {
207
- const t = _(), o = {
261
+ function O(e) {
262
+ const n = h(), s = {
208
263
  name: "get_skill",
209
264
  description: "按名称获取 resources/skills 下的 SKILL.md 内容",
210
265
  inputSchema: {
@@ -219,10 +274,10 @@ function I(e) {
219
274
  },
220
275
  annotations: { readOnlyHint: !0, idempotentHint: !0 }
221
276
  };
222
- e.server.setRequestHandler(C, async () => ({ tools: [o] })), e.server.setRequestHandler(L, async (r) => {
277
+ e.server.setRequestHandler(M, async () => ({ tools: [s] })), e.server.setRequestHandler(T, async (r) => {
223
278
  if (r.params.name === "get_skill") {
224
- const n = r.params.arguments, s = n && typeof n == "object" && typeof n.name == "string" ? n.name : void 0;
225
- if (!s)
279
+ const t = r.params.arguments, o = t && typeof t == "object" && typeof t.name == "string" ? t.name : void 0;
280
+ if (!o)
226
281
  return {
227
282
  content: [
228
283
  {
@@ -233,21 +288,21 @@ function I(e) {
233
288
  isError: !0
234
289
  };
235
290
  try {
236
- const i = await E(t, s);
291
+ const i = await I(n, o);
237
292
  if (!i) {
238
- const h = (await w(t)).map((l) => {
239
- const k = [l.dirName, l.name].filter(Boolean).join(", "), g = l.description ? ` - ${l.description}` : "";
240
- return `- ${k}${g}`;
293
+ const l = (await v(n)).map((u) => {
294
+ const d = [u.dirName, u.name].filter(Boolean).join(", "), g = u.description ? ` - ${u.description}` : "";
295
+ return `- ${d}${g}`;
241
296
  }).join(`
242
297
  `);
243
298
  return {
244
299
  content: [
245
300
  {
246
301
  type: "text",
247
- text: `Skill not found: ${s}
302
+ text: `Skill not found: ${o}
248
303
 
249
304
  Available skills:
250
- ` + (h || "- (none)")
305
+ ` + (l || "- (none)")
251
306
  }
252
307
  ],
253
308
  isError: !0
@@ -284,11 +339,11 @@ Available skills:
284
339
  };
285
340
  });
286
341
  }
287
- async function O() {
288
- const e = a.dirname(p(import.meta.url)), t = a.resolve(e, "../package.json"), o = JSON.parse(await c.readFile(t, "utf-8")), r = new R(
342
+ async function b() {
343
+ const e = a.dirname(f(import.meta.url)), n = a.resolve(e, "../package.json"), s = JSON.parse(await m.readFile(n, "utf-8")), r = new F(
289
344
  {
290
- name: o.name,
291
- version: o.version
345
+ name: s.name,
346
+ version: s.version
292
347
  },
293
348
  {
294
349
  capabilities: {
@@ -298,13 +353,13 @@ async function O() {
298
353
  }
299
354
  }
300
355
  );
301
- return j(r), H(r), I(r), r;
356
+ return q(r), H(r), O(r), r;
302
357
  }
303
- async function b() {
358
+ async function K() {
304
359
  console.error("Starting MCP server serving...");
305
- const e = await O(), t = new F();
306
- await e.connect(t);
360
+ const e = await b(), n = new x();
361
+ await e.connect(n);
307
362
  }
308
- b().catch((e) => {
363
+ K().catch((e) => {
309
364
  console.error("Fatal error:", e), process.exit(1);
310
365
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "前端开发的一些cursor mcp工具集",
3
3
  "name": "@reus-able/frontend-helper-mcp",
4
- "version": "1.1.1",
4
+ "version": "1.1.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -0,0 +1,12 @@
1
+ ## 组件编写
2
+ 你需要帮助用户进行组件结构重构
3
+
4
+ ### 1. 确认组件重构要求
5
+
6
+ 首先,查看是否存在 `skill-vue-components` 资源。
7
+ **如果有,则按照该资源的要求进行组件结构重构。**
8
+
9
+ **否则,立即终止并告知用户:“组件编写规范获取失败”**
10
+
11
+ ### 2. 实施组件编写
12
+ 根据以上要求,实施组件编写。
@@ -1,6 +1,13 @@
1
1
  ## 组件结构重构
2
- 你需要帮助用户进行组件结构重构,要求如下
2
+ 你需要帮助用户进行组件结构重构
3
3
 
4
+ ### 1. 确认组件重构要求
5
+
6
+ 首先,查看是否存在 `skill-vue-components` 资源。
7
+ **如果有,则按照该资源的要求进行组件结构重构。**
8
+
9
+ **否则,遵循以下要求:**
10
+ ```
4
11
  1. 视图层与逻辑层分离,即SFC中只负责视图渲染,逻辑抽离到hook中。
5
12
  1.1. 完善定义组件的常量、类型,将props,emit等类型也提取出来。
6
13
  1.2. 组件中的主要逻辑需要放在对应的useXXX.ts文件中,入参为组件的props,并导出useXXX hook。
@@ -18,5 +25,15 @@
18
25
  ** 不要设计逻辑的变更 **
19
26
  ** 不要修改类名或者html结构 **
20
27
  ** 注意不要破坏变量的响应式 **
28
+ ```
21
29
 
22
- 在实施前请在计划中列举你的改动点并严格遵守注意点。
30
+ ### 2. 列出重构计划
31
+ 根据以上要求,列出组件结构重构的计划。
32
+ 计划大纲如下:
33
+ 1. 重构基准
34
+ 如果存在 `/helper/vue-components` 资源则输出 `/helper/vue-components`;
35
+ 否则输出 `备用组件结构重构规范`
36
+ 2. 当前组件分析
37
+ 3. 重构改动点以及修改后的文件结构
38
+ 4. 注意事项
39
+ 5. 实施步骤