@jdzhang225gmail/fontend-prompt 0.1.1 → 0.2.0

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,104 +1,79 @@
1
- # 前端提示词 Skills & MCP Server
1
+ # 前端提示词 Skills (CLI)
2
2
 
3
- 这是一个**前端开发辅助工具库**,它既可以作为 **Skills (CLI 工具)** 使用(零 Token 消耗,适合 Agent 直接调用),也可以作为标准的 **MCP Server** 使用。
3
+ 这是一个**前端开发辅助 CLI 工具**。它通过**零 Token 消耗**的本地分析,将模糊的需求转化为**专业、结构化、带审批流的前端开发方案**,供 Agent 或开发者直接使用。
4
4
 
5
- 它致力于把模糊的需求转化为**专业、结构化、带审批流的前端开发方案**。
5
+ ## 🌟 核心特性
6
6
 
7
- ## 🌟 核心理念:Skills vs MCP
8
-
9
- - **Skills (CLI 模式)**: 🚀 **推荐!** Agent 通过命令行直接运行工具。 **优点**:无需在 Prompt 中挂载巨量的工具定义,极大节省 Token;运行速度快;无常驻进程。
10
- - **MCP Server 模式**: 经典模式,适合 Claude Desktop 等标准 MCP 客户端。
7
+ - **纯 CLI 工具**: 无需常驻服务,即用即走。
8
+ - **节省 Token**: 本地扫描项目结构,无需将整个文件树塞入 Context。
9
+ - **结构化输出**: 生成包含文件变更、审批关口、校验步骤的标准 Prompt
11
10
 
12
11
  ---
13
12
 
14
- ## 🚀 快速开始 (CLI / Skills)
13
+ ## 🚀 安装 (推荐)
14
+
15
+ 为了获得极速体验(避免每次 `npx` 下载),请**全局安装**:
16
+
17
+ ```bash
18
+ npm install -g @jdzhang225gmail/fontend-prompt
19
+ ```
15
20
 
16
- 无需安装,直接使用 `npx` 运行:
21
+ 安装后,即可使用 `fontend-prompt` 命令。
22
+
23
+ ---
24
+
25
+ ## 📖 使用指南
17
26
 
18
27
  ### 1. 扫描项目 (Scan)
19
28
  快速了解项目架构、技术栈与关键文件。
20
29
 
21
30
  ```bash
22
- npx @jdzhang225gmail/fontend-prompt scan
31
+ fontend-prompt scan
23
32
  # 或指定目录
24
- npx @jdzhang225gmail/fontend-prompt scan --depth 2
33
+ fontend-prompt scan --depth 2
25
34
  ```
26
35
 
27
36
  ### 2. 优化需求 (Optimize)
28
- 将你的“一句话需求”转化为详细的开发方案(包含文件变更、审批关口等)。
37
+ 将你的“一句话需求”转化为详细的开发方案。
29
38
 
30
39
  ```bash
31
- npx @jdzhang225gmail/fontend-prompt optimize "给后台增加一个用户管理页面"
40
+ fontend-prompt optimize "给后台增加一个用户管理页面"
32
41
  ```
33
42
 
34
43
  ### 3. 评分 (Score)
35
44
  看看你的 Prompt 写得好不好,缺什么信息。
36
45
 
37
46
  ```bash
38
- npx @jdzhang225gmail/fontend-prompt score "帮我写个页面"
47
+ fontend-prompt score "帮我写个页面"
39
48
  ```
40
49
 
41
50
  ---
42
51
 
43
52
  ## 🤖 在 Agent 中使用 (Antigravity / Claude Code)
44
53
 
45
- ### 方式一:作为 CLI 工具(最省 Token)
46
-
47
- 告诉你的 Agent(或者写在 `.cursorrules` / `.agent/workflows` 中):
48
-
49
- > "当需要理解项目结构时,请运行命令 `npx @jdzhang225gmail/fontend-prompt scan`。"
50
- > "当需要规划新功能时,请运行命令 `npx @jdzhang225gmail/fontend-prompt optimize '<需求>'`,并根据输出结果执行。"
51
-
52
- ### 方式二:作为库集成
54
+ 为了让 Agent 更流畅地调用本工具,请告诉它直接使用命令行。
53
55
 
54
- 如果你在编写 TS 脚本或 Agent 插件:
56
+ **添加到 `.cursorrules` Agent 系统提示词:**
55
57
 
56
- ```typescript
57
- import { scanProject, optimizeFrontendPrompt } from "@jdzhang225gmail/fontend-prompt";
58
-
59
- const tree = await scanProject({ rootDir: "." });
60
- const plan = optimizeFrontendPrompt({ userPrompt: "..." });
61
- ```
58
+ > "当需要理解项目结构时,请运行命令 `fontend-prompt scan`。"
59
+ > "当需要规划新功能时,请运行命令 `fontend-prompt optimize '<需求>'`,并根据输出结果执行。"
62
60
 
63
61
  ---
64
62
 
65
- ## 📦 安装与构建
63
+ ## 📦 本地开发与构建
66
64
 
67
- 如果你想本地部署或二次开发:
65
+ 如果你想二次开发:
68
66
 
69
67
  ```bash
70
68
  npm install
71
69
  npm run build
72
70
 
73
- # 本地运行 CLI
74
- npm run skill -- --help
75
- ```
76
-
77
- ---
78
-
79
- ## 🛠️ MCP Server 配置
80
-
81
- 如果你仍希望在 Claude Desktop 中作为常驻服务使用:
82
-
83
- ```json
84
- {
85
- "mcpServers": {
86
- "frontend-helper": {
87
- "command": "npx",
88
- "args": ["-y", "@jdzhang225gmail/fontend-prompt"]
89
- }
90
- }
91
- }
71
+ # 本地测试
72
+ node dist/cli.js --help
92
73
  ```
93
74
 
94
75
  ---
95
76
 
96
- ## 功能特性
97
-
98
- - **中文优先**: 所有输出、文档、注释默认均为中文。
99
- - **Gate 机制**: 在关键节点(设计/计划/验收)生成审批关口,防止 AI 一条路走到黑。
100
- - **安全扫描**: 自动识别项目目录,但严格限制在 CWD 下访问。
101
-
102
77
  ## 许可
103
78
 
104
79
  MIT
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import * as fs from "fs/promises";
7
7
  // 读取 package.json 获取版本号
8
8
  // const pkg = JSON.parse(await fs.readFile(new URL("../package.json", import.meta.url), "utf-8"));
9
9
  // 为了避免 ESM 路径问题,暂时硬编码,或者用 simple import
10
- const version = "0.1.0";
10
+ const version = "0.2.0";
11
11
  const cli = cac("fontend-skill");
12
12
  cli
13
13
  .command("scan [root]", "扫描项目目录结构与关键文件")
package/dist/index.js CHANGED
@@ -1,181 +1,5 @@
1
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
- import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
- import { scanProject } from "./skills/scan.js";
5
- import { buildOptimizedPromptPackage } from "./skills/optimize.js";
6
- import { scoreFrontendPrompt } from "./skills/score.js";
7
- import { asNonEmptyString } from "./utils.js";
8
- // === 导出 Skills (作为库使用) ===
9
1
  export * from "./types.js";
10
2
  export * from "./utils.js";
11
3
  export { scanProject } from "./skills/scan.js";
12
4
  export { buildOptimizedPromptPackage as optimizeFrontendPrompt } from "./skills/optimize.js";
13
5
  export { scoreFrontendPrompt } from "./skills/score.js";
14
- // === MCP Server 实现 ===
15
- // 只有当文件被直接运行时才启动 Server
16
- // 简单的判断方式:看是否通过 import 导入
17
- // 在 Node.js 中,如果 entry point 是此文件,则启动
18
- const isMainModule = import.meta.url.endsWith(process.argv[1]) || (process.argv[1] && import.meta.url.includes(process.argv[1]));
19
- // 注意:ESM 中判断 isMain 比较麻烦,这里我们简化处理:
20
- // 如果是通过 `node dist/index.js` 启动,我们假设它是为了跑 server。
21
- // 如果作为库被 import,通常不会立即执行 await server.connect。
22
- // 但 MCP SDK 的 connect 是阻塞的吗?StdioServerTransport 是基于 stdio 的。
23
- // 为了安全起见,我们把 Server 启动逻辑封装在一个函数里,如果用户想跑 Server 可以显示调用,或者我们检测命令行参数。
24
- // 或者,为了兼容旧的 `npm start`,我们保留默认启动行为,但如果用户只想用库,可能会有副作用。
25
- // 更好的做法是:把 Server 逻辑拆分到 `src/server.ts`,`index.ts` 只做导出。
26
- // 但根据计划,我们尽量保持 index.ts 为入口。
27
- // 让我们依然默认启动 Server,因为这对 MCP 是标准行为。
28
- // 使用者如果只是 import { scanProject } from '...', 只要不执行到最后的 connect 就行。
29
- // 但顶层的代码会执行。
30
- // 修正方案:将 Server 逻辑包裹在 IIFE 或判断中。
31
- // 更加稳妥的方式:不做判断,假设这个文件就是 Server 入口。
32
- // 库的使用者应该 import from './skills/scan.js' 而不是 './index.js' 以避免副作用,或者我们把 index.js 变成纯导出,把 server 移到 server.ts。
33
- // 鉴于我不想改变 `dist/index.js` 的既定路径(README 里写了),我将保持 `index.ts` 为 Server。
34
- // 并新建 `src/lib.ts` 或直接让用户 import 子路径。
35
- // 为了完成任务 "Reorganized Structure",我会把 Server 逻辑保留在 index.ts,但极其精简。
36
- const server = new Server({
37
- name: "frontend-prompt-workflow-mcp",
38
- version: "0.1.0",
39
- }, {
40
- capabilities: {
41
- tools: {},
42
- },
43
- });
44
- server.setRequestHandler(ListToolsRequestSchema, async () => {
45
- return {
46
- tools: [
47
- {
48
- name: "scan_project",
49
- description: "Scan project directory tree (read-only) and detect claude.md/CLAUDE.md. Intended for initial architecture understanding.",
50
- inputSchema: {
51
- type: "object",
52
- properties: {
53
- rootDir: { type: "string" },
54
- maxDepth: { type: "number" },
55
- maxEntries: { type: "number" },
56
- },
57
- },
58
- },
59
- {
60
- name: "optimize_frontend_prompt",
61
- description: "Standardize/optimize a raw user question into a frontend-dev prompt package (messages + guardrails + clarifying questions).",
62
- inputSchema: {
63
- type: "object",
64
- properties: {
65
- userPrompt: { type: "string" },
66
- projectContext: { type: "string" },
67
- techStack: { type: "string" },
68
- framework: { type: "string" },
69
- language: { type: "string", enum: ["ts", "js"] },
70
- styling: { type: "string" },
71
- stateManagement: { type: "string" },
72
- router: { type: "string" },
73
- constraints: { type: "array", items: { type: "string" } },
74
- taskType: {
75
- type: "string",
76
- enum: [
77
- "new_feature",
78
- "optimize_existing",
79
- "refactor",
80
- "bugfix",
81
- "performance",
82
- "ui_polish",
83
- "dependency_upgrade",
84
- "test_addition",
85
- ],
86
- },
87
- outputLanguage: { type: "string", enum: ["zh", "en"] },
88
- outputFormat: { type: "string", enum: ["step_by_step", "direct", "both"] },
89
- codeStyle: { type: "string", enum: ["diff", "full_files", "snippets"] },
90
- mustAskClarifyingQuestions: { type: "boolean" },
91
- requireApprovalGates: { type: "boolean" },
92
- },
93
- required: ["userPrompt"],
94
- },
95
- },
96
- {
97
- name: "score_frontend_prompt",
98
- description: "Score a frontend prompt quality and suggest missing info / improvements.",
99
- inputSchema: {
100
- type: "object",
101
- properties: {
102
- prompt: { type: "string" },
103
- },
104
- required: ["prompt"],
105
- },
106
- },
107
- ],
108
- };
109
- });
110
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
111
- if (request.params.name === "scan_project") {
112
- const rawArgs = (request.params.arguments ?? {});
113
- const rootDir = asNonEmptyString(rawArgs.rootDir);
114
- const maxDepth = typeof rawArgs.maxDepth === "number" ? rawArgs.maxDepth : undefined;
115
- const maxEntries = typeof rawArgs.maxEntries === "number" ? rawArgs.maxEntries : undefined;
116
- const result = await scanProject({ rootDir, maxDepth, maxEntries });
117
- return {
118
- content: [
119
- {
120
- type: "text",
121
- text: JSON.stringify(result, null, 2),
122
- },
123
- ],
124
- };
125
- }
126
- if (request.params.name === "optimize_frontend_prompt") {
127
- const rawArgs = (request.params.arguments ?? {});
128
- const userPrompt = asNonEmptyString(rawArgs.userPrompt);
129
- if (!userPrompt) {
130
- throw new Error("optimize_frontend_prompt: missing required argument 'userPrompt'");
131
- }
132
- const args = {
133
- userPrompt,
134
- projectContext: asNonEmptyString(rawArgs.projectContext),
135
- techStack: asNonEmptyString(rawArgs.techStack),
136
- framework: asNonEmptyString(rawArgs.framework),
137
- language: asNonEmptyString(rawArgs.language) ?? undefined,
138
- styling: asNonEmptyString(rawArgs.styling),
139
- stateManagement: asNonEmptyString(rawArgs.stateManagement),
140
- router: asNonEmptyString(rawArgs.router),
141
- constraints: Array.isArray(rawArgs.constraints)
142
- ? rawArgs.constraints.map((x) => String(x)).filter((x) => x.trim().length)
143
- : undefined,
144
- taskType: asNonEmptyString(rawArgs.taskType) ?? undefined,
145
- outputLanguage: asNonEmptyString(rawArgs.outputLanguage) ?? undefined,
146
- outputFormat: asNonEmptyString(rawArgs.outputFormat) ?? undefined,
147
- codeStyle: asNonEmptyString(rawArgs.codeStyle) ?? undefined,
148
- mustAskClarifyingQuestions: typeof rawArgs.mustAskClarifyingQuestions === "boolean" ? rawArgs.mustAskClarifyingQuestions : undefined,
149
- requireApprovalGates: typeof rawArgs.requireApprovalGates === "boolean" ? rawArgs.requireApprovalGates : undefined,
150
- };
151
- const result = buildOptimizedPromptPackage(args);
152
- return {
153
- content: [
154
- {
155
- type: "text",
156
- text: JSON.stringify(result, null, 2),
157
- },
158
- ],
159
- };
160
- }
161
- if (request.params.name === "score_frontend_prompt") {
162
- const rawArgs = (request.params.arguments ?? {});
163
- const prompt = asNonEmptyString(rawArgs.prompt);
164
- if (!prompt) {
165
- throw new Error("score_frontend_prompt: missing required argument 'prompt'");
166
- }
167
- const result = scoreFrontendPrompt({ prompt });
168
- return {
169
- content: [
170
- {
171
- type: "text",
172
- text: JSON.stringify(result, null, 2),
173
- },
174
- ],
175
- };
176
- }
177
- throw new Error(`Unknown tool: ${request.params.name}`);
178
- });
179
- // 启动 Server
180
- const transport = new StdioServerTransport();
181
- await server.connect(transport);
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@jdzhang225gmail/fontend-prompt",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
7
- "fontend-prompt": "./dist/index.js",
8
- "fontend-skill": "./dist/cli.js"
7
+ "fontend-prompt": "./dist/cli.js"
9
8
  },
10
9
  "files": [
11
10
  "dist",
@@ -17,11 +16,10 @@
17
16
  "scripts": {
18
17
  "dev": "tsx watch src/index.ts",
19
18
  "build": "tsc -p tsconfig.json",
20
- "start": "node dist/index.js",
19
+ "start": "node dist/cli.js",
21
20
  "prepublishOnly": "npm run build"
22
21
  },
23
22
  "dependencies": {
24
- "@modelcontextprotocol/sdk": "^1.0.0",
25
23
  "cac": "^6.7.14",
26
24
  "npm": "^11.7.0"
27
25
  },