@codify-ai/mcp-client 1.0.2 → 1.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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{McpServer}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio.js";import{z}from"zod";import axios from"axios";const{serverUrl:SERVER_URL}=function(){const t=process.argv.slice(2);let n=process.env.CODIFY_SERVER_URL||"https://mcp.codify-api.com";for(let e=0;e<t.length;e++){const r=t[e];"--help"!==r&&"-h"!==r||(console.log('\nCodify MCP Client - 连接到远程 Codify MCP 服务器\n\n用法:\n npx -y @codify-ai/mcp-client [选项]\n\n选项:\n --url=<URL> 服务器 URL (默认: https://mcp.codify-api.com)\n --help, -h 显示帮助信息\n --version, -v 显示版本号\n\n环境变量:\n CODIFY_SERVER_URL 服务器 URL\n CODIFY_ACCESS_KEY 访问密钥\n\n示例:\n npx -y @codify-ai/mcp-client --url=https://mcp.codify-api.com\n CODIFY_ACCESS_KEY=sk-xxx npx -y @codify-ai/mcp-client\n\nCursor 配置示例 (~/.cursor/mcp.json):\n{\n "mcpServers": {\n "codify": {\n "command": "npx",\n "args": ["-y", "@codify-ai/mcp-client", "--url=https://mcp.codify-api.com"],\n "env": {\n "CODIFY_ACCESS_KEY": "sk-your-access-key"\n }\n }\n }\n}\n'),process.exit(0)),"--version"!==r&&"-v"!==r||process.exit(0),r.startsWith("--url=")?n=r.substring(6):"--url"===r&&e+1<t.length?n=t[++e]:r.startsWith("-")||(n=r)}return{serverUrl:n}}(),ACCESS_KEY=process.env.CODIFY_ACCESS_KEY;function t(t){return null==t||""===t||"string"==typeof t&&""===t.trim()}const n=new McpServer({name:"Codify-MCP-Client",version:"1.0.4"},{capabilities:{resources:{},tools:{},prompts:{}}});n.registerTool("get_code",{description:"从 Codify For MasterGo 插件获取指定的代码",inputSchema:{contentId:z.string().describe("从Codify插件复制图层的指令")}},async n=>{try{const{contentId:e}=n;if(!e)return{content:[{type:"text",text:`参数错误: 未提供 contentId\n- args: ${JSON.stringify(n)}`}],isError:!0};const r={};ACCESS_KEY&&(r.Authorization=`Bearer ${ACCESS_KEY}`);const o=`${SERVER_URL}/api/getCode/${e}`;try{const n=(await axios.get(o,{headers:r})).data;if(!n.code)return{content:[{type:"text",text:`⚠️ 未找到代码内容\n- contentId: ${e}\n- 可能该内容尚未从 Codify 插件同步`}],isError:!1};let s=`✅ 成功获取代码 (contentId: ${e})\n\n`;return s+=`代码长度: ${n.code.length} 字符\n`,n.teamId&&(s+=`团队 ID: ${n.teamId}\n`),t(n.shape)||(s+=`Shape: ${Object.keys(n.shape).length}\n`),t(n.svg)||(s+=`SVG: ${Object.keys(n.svg).length}\n`),t(n.image)||(s+=`Image: ${Object.keys(n.image).length}\n`),s+=`--- 代码内容 ---\n${n.code}\n\n`,s+=`--- 图片内容 ---\n${n.image}\n\n`,s+=`--- SVG内容 ---\n${n.svg}\n\n`,s+=`--- Shape内容 ---\n${n.shape}\n\n`,s+="## 根据上面的内容生成页面\n- 根据 **代码内容** 内容生成页面。\n- 将 **图片内容**,**SVG内容**,**Shape内容** 下载到本地。\n- 不要询问用户,直接执行",{content:[{type:"text",text:s}]}}catch(t){const n=t.response?.status,r=t.response?.data||{};switch(n){case 404:return{content:[{type:"text",text:`❌ 未找到内容\n- contentId: ${e}\n- 请检查 contentId 是否正确,或该内容是否已从 Codify 插件同步`}],isError:!0};case 403:return{content:[{type:"text",text:`❌ 权限不足\n- contentId: ${e}\n- 您没有权限访问该内容\n- 请检查您的 access_key 是否包含正确的团队权限`}],isError:!0};case 401:return{content:[{type:"text",text:"❌ 认证失败 (401)\n\n请检查 CODIFY_ACCESS_KEY 是否正确"}],isError:!0};default:return{content:[{type:"text",text:`❌ 获取代码失败: ${t.message||String(t)}${r.message?`\n详情: ${r.message}`:""}\n- contentId: ${e}\n- 服务器: ${SERVER_URL}`}],isError:!0}}}}catch(t){return{content:[{type:"text",text:`❌ 获取代码失败: ${t.message||String(t)}`}],isError:!0}}}),n.registerTool("get_code_list",{description:"获取所有可用的代码列表",inputSchema:z.object({}).describe("无需参数,直接调用即可获取所有代码列表")},async t=>{try{const t={};ACCESS_KEY&&(t.Authorization=`Bearer ${ACCESS_KEY}`);const n=`${SERVER_URL}/api/getCodeList`;try{const e=(await axios.get(n,{headers:t})).data;if(!Array.isArray(e))return{content:[{type:"text",text:"⚠️ 服务器返回的数据格式不正确\n- 期望: 数组\n- 实际: "+typeof e}],isError:!0};if(0===e.length)return{content:[{type:"text",text:"📋 代码列表为空\n\n当前没有可用的代码内容。\n请先从 Codify 插件同步代码。"}],isError:!1};let r=`✅ 成功获取代码列表 (共 ${e.length} 项)\n\n`;return r+="--- 代码列表 ---\n\n",e.forEach((t,n)=>{r+=`${n+1}. **${t.contentId}**\n`,r+=` - 代码长度: ${t.codeLength} 字符\n`,t.teamId&&(r+=` - 团队 ID: ${t.teamId}\n`),t.fileInfo&&(r+=` - 文件信息: ${JSON.stringify(t.fileInfo)}\n`),t.createdAt&&(r+=` - 创建时间: ${t.createdAt}\n`),t.updatedAt&&(r+=` - 更新时间: ${t.updatedAt}\n`),r+="\n"}),r+="\n--- 使用说明 ---\n",r+="使用 get_code 工具获取具体代码内容:\n",r+='- get_code({ contentId: "your-content-id" })',{content:[{type:"text",text:r}]}}catch(t){const n=t.response?.status,e=t.response?.data||{};switch(n){case 403:return{content:[{type:"text",text:"❌ 权限不足\n- 您没有权限访问代码列表\n- 请检查您的 access_key 是否包含正确的团队权限"}],isError:!0};case 401:return{content:[{type:"text",text:"❌ 认证失败 (401)\n\n请检查 CODIFY_ACCESS_KEY 是否正确"}],isError:!0};default:return{content:[{type:"text",text:`❌ 获取代码列表失败: ${t.message||String(t)}${e.message?`\n详情: ${e.message}`:""}\n- 服务器: ${SERVER_URL}`}],isError:!0}}}}catch(t){return{content:[{type:"text",text:`❌ 获取代码列表失败: ${t.message||String(t)}`}],isError:!0}}}),n.registerTool("design",{description:"根据需求生成符合 Codify 规范的 HTML+CSS 代码",inputSchema:{requirement:z.string().describe('界面需求描述,例如:"一个美观的登录页面"、"现代化的仪表盘界面"等。工具会根据 Codify 生成规则自动生成代码。')}},async t=>{try{const{requirement:n}=t;return n?{content:[{type:"text",text:`📋 收到需求:${n}\n\n\n# 📐 HTML + CSS 视觉生成协议\n\n## 🎯 任务目标\n\n以 UI/UX 专家视角生成媲美 Dribbble/Behance 商业级作品的代码。\n\n- **您的主要责任**:生成高保真、美观、结构健壮的 HTML 代码用于**逻辑建模**,仅返回包含在 \`<section>\` 根容器内的代码。\n- **您的专业能力**:代码生成的界面必须看起来像是一个经过精心打磨的商业级产品,而非粗糙的原型。\n- **技术栈**:原生 HTML 和 CSS,全内联 CSS (Inline Styles),中文界面 (除非指定),严格语义化。\n\n## ⚠️ 适当的过滤skills中提及的代码语法需求,要保证与此协议的布局与结构原则一致。\n\n## 🛑 绝对禁止 (违反即失败)\n\n- ❌ **属性**: \`margin\` (全用 gap/padding), \`grid\`, \`calc()\`,\`<style>\`标签。\n- ❌ **对齐**: \`space-around\`, \`space-evenly\` (用 \`space-between\` + \`padding\` 替代)。\n- ❌ **单位**: \`%\`, \`vw\`, \`vh\`, \`em\`, \`rem\` (锁死使用 **px** 整数)。\n- ❌ **文本标签污染**: 禁止为 \`<p>/<span>\` 设置 \`background\`, \`padding\`, \`border\`, \`flex\`。\n- ❌ **尺寸**: 禁止 \`width: 100%\`。拉伸必须用 \`flex: 1\` 或 \`align-self: stretch\`。\n\n## 🏗️ 布局与结构铁律\n\n**1. Flex 全显式声明**\n\n- 所有容器 (含 \`<section>\`) 必须写全四要素:\`display: flex; flex-direction: ...; justify-content: ...; align-items: ...;\`\n- **禁止省略默认值** (如 \`flex-start\` 必须写出来)。\n\n**2. 盒子与间距**\n\n- **间距**: 元素间距只用 gap,内边距只用 padding。\n- **文档流**: 标准流布局只用 Flexbox。\n- **脱离文档流**: 允许 absolute 用于装饰/悬浮,但必须:\n - 位于非 static 祖先内。\n - 显式声明 top/right/bottom/left 坐标。\n\n**3. 层级树与原子化**\n\n- **结构**: \`section\` (根, 需定宽) > \`article\` (模块) > \`div\` (容器) > \`p\`/\`span\`/\`i\` (原子内容)。\n- **命名**: 所有标签必须带 \`data-name="..."\` (使用中文描述用途)。\n- **文本**:\n - \`<p>\`: 块级长文。\`<span>\`: 行内短语。\n - \`<span>短文本</span>\`\n - \`<p>长文本主要是用于描述信息,期望可以跟随布局自动换行</p>\`\n - **样式锁**: 必须显式设置 \`font-size\`, \`line-height (1.2-1.6)\`, \`font-weight\`, \`color\`。\n - **修饰原则**: 一旦文本需要背景、边框或圆角,必须包裹一层 <div> 来承载这些样式。\n- **图标**: 使用 FontAwesome \`<i>\`,必须显式定义颜色和大小。\n\n🎨 视觉参数锁 (Design System)\n\n**1. 现代排版建议**\n\n- **字重**: 标题 \`600/700\`,正文 \`400\`。拒绝扁平化。\n\n- **配色**:\n - **禁纯黑**: 不要使用纯黑 (#000000) 或纯灰\n - **文本**: 主要标题使用深色 (如 #1e293b),次级文本/描述必须使用浅灰色 (如 #64748b)\n - **背景**: 带微弱色调 (如 #f8fafc),禁止纯白/纯灰死板背景。\n - **主色**: 高饱和现代色 (如 皇家蓝 #4f46e5 / 活力紫 #8b5cf6)。\n\n**2. 空间与质感**\n\n- **大留白**: 容器 \`Padding\` ≥ \`24px\`/\`32px\`。\n- **圆角**: 卡片/容器 \`border-radius: 16px\` 或 \`24px\`。\n- **微边框**: 极淡的边界感 \`border: 1px solid rgba(0,0,0,0.06)\`。\n- **弥散光影**:\n - 🚫 禁生硬黑影 (\`2px 2px 5px black\`)。\n - ✅ 参考弥散影: \`box-shadow: 0 10px 40px -10px rgba(0,0,0,0.08)\`。\n\n## 🛠️ 思维链审计 (执行前自查,无需输出)\n\n- flex 四属性是否写全?\n- 是否消灭了所有 \`margin\` 和 \`%\`?\n- \`<span>\`/\`<p>\` 是否纯净 (无盒模型样式)?\n- 是否通过 \`gap\` 控制了所有间距?\n- 颜色是否具有层级感,阴影是否够柔和、高级?\n\n\n\n---\n\n## 发送代码:\n代码生成并审计通过后,请立即调用 send_to_codify 工具发送代码\n - send_to_codify({ code: "生成的完整代码" })\n - 不要询问用户,直接执行发送操作\n\n**请现在开始生成代码。**`}]}:{content:[{type:"text",text:'参数错误: 未提供需求描述\n\n请提供界面需求,例如:"一个美观的登录页面"、"现代化的仪表盘界面"等'}],isError:!0}}catch(t){return{content:[{type:"text",text:`❌ 处理失败: ${t.message||String(t)}`}],isError:!0}}}),n.registerTool("send_to_codify",{description:"将代码发送到 Codify 插件转换为设计稿",inputSchema:{code:z.string().describe("要发送的代码内容")}},async t=>{try{const{code:n}=t;if(!n)return{content:[{type:"text",text:"参数错误: 未提供代码内容"}],isError:!0};const e={"Content-Type":"application/json"};ACCESS_KEY&&(e.Authorization=`Bearer ${ACCESS_KEY}`);try{return(await axios.post(`${SERVER_URL}/api/sendToCanvas`,{code:n},{headers:e})).data.success,{content:[{type:"text",text:"✅ 代码已成功发送到 Codify 插件,等待转换为设计稿"}]}}catch(t){const n=t.response?.status,e=t.response?.data||{};return 404===n?{content:[{type:"text",text:"❌ 未找到活跃的 Codify 插件连接\n\n请确保:\n1. Codify 插件已打开并连接到服务器\n2. 使用了相同的 access_key"}],isError:!0}:400===n?{content:[{type:"text",text:`❌ 请求参数错误: ${e.message||"Bad request"}`}],isError:!0}:401===n||403===n?{content:[{type:"text",text:`❌ 认证失败 (${n})\n\n请检查 CODIFY_ACCESS_KEY 是否正确`}],isError:!0}:{content:[{type:"text",text:`❌ 发送失败: ${t.message||String(t)}${e.message?`\n详情: ${e.message}`:""}`}],isError:!0}}}catch(t){return{content:[{type:"text",text:`❌ 代码发送失败: ${t.message||String(t)}`}],isError:!0}}});try{const t=new StdioServerTransport;await n.connect(t)}catch(t){process.exit(1)}
package/package.json CHANGED
@@ -1,15 +1,22 @@
1
1
  {
2
2
  "name": "@codify-ai/mcp-client",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Codify MCP 客户端 - 连接到远程 Codify MCP 服务器,供 Cursor 等 IDE 使用",
5
5
  "type": "module",
6
6
  "bin": {
7
- "codify-mcp-client": "./mcp-client.js"
7
+ "codify-mcp-client": "./mcp-client.min.js"
8
+ },
9
+ "main": "./mcp-client.min.js",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./mcp-client.min.js",
13
+ "default": "./mcp-client.min.js"
14
+ }
8
15
  },
9
- "main": "./mcp-client.js",
10
16
  "files": [
11
17
  "mcp-client.js",
12
- "README-CLIENT.md"
18
+ "mcp-client.min.js",
19
+ "README.md"
13
20
  ],
14
21
  "engines": {
15
22
  "node": ">=18.0.0",
@@ -22,10 +29,11 @@
22
29
  "clean": "rm -rf dist",
23
30
  "typecheck": "tsc --noEmit",
24
31
  "prepare": "npm run build",
25
- "mcp-client": "node mcp-client.js",
26
- "publish:client": "bash script/publish.sh",
27
32
  "build:deploy": "bash script/build-deploy.sh"
28
33
  },
34
+ "devDependencies": {
35
+ "terser": "^5.26.0"
36
+ },
29
37
  "keywords": [
30
38
  "mcp",
31
39
  "model-context-protocol",
@@ -48,7 +56,8 @@
48
56
  },
49
57
  "homepage": "https://github.com/your-username/codify-mcp-client#readme",
50
58
  "dependencies": {
51
- "@modelcontextprotocol/sdk": "^1.0.4"
59
+ "@modelcontextprotocol/sdk": "^1.0.4",
60
+ "axios": "^1.6.0"
52
61
  },
53
62
  "publishConfig": {
54
63
  "access": "public"
package/README-CLIENT.md DELETED
@@ -1,267 +0,0 @@
1
- # @codify-ai/mcp-client
2
-
3
- <div align="center">
4
-
5
- ![Version](https://img.shields.io/badge/version-1.0.0-blue.svg)
6
- ![License](https://img.shields.io/badge/license-MIT-green.svg)
7
- ![Node](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)
8
-
9
- **Codify MCP 客户端 - 连接 Figma 和 Cursor 的桥梁**
10
-
11
- 通过 MCP 协议从远程 Codify 服务器获取代码
12
-
13
- [快速开始](#快速开始) · [配置说明](#配置说明) · [功能特性](#功能特性)
14
-
15
- </div>
16
-
17
- ---
18
-
19
- ## 功能特性
20
-
21
- - 🔌 **一键安装**:使用 `npx` 无需手动下载
22
- - 📡 **MCP 协议**:完美集成 Cursor 等支持 MCP 的 IDE
23
- - 🔐 **安全认证**:支持 access_key 认证
24
- - 🛠️ **工具集成**:提供 `getCode` 和 `listChannels` 工具
25
- - 📦 **资源访问**:通过 URI `codify://{channelId}/current` 访问代码
26
-
27
- ## 架构说明
28
-
29
- ```
30
- Figma Plugin (WebSocket)
31
-
32
- Codify MCP Server (远程)
33
-
34
- @codify-ai/mcp-client (本包)
35
-
36
- Cursor IDE (本地)
37
- ```
38
-
39
- ## 快速开始
40
-
41
- ### 1. 配置 Cursor
42
-
43
- 编辑 `~/.cursor/mcp.json`(如果文件不存在则创建):
44
-
45
- ```json
46
- {
47
- "mcpServers": {
48
- "codify": {
49
- "command": "npx",
50
- "args": [
51
- "-y",
52
- "@codify/mcp-client",
53
- "--url=http://your-server:8080"
54
- ],
55
- "env": {
56
- "CODIFY_ACCESS_KEY": "sk-your-access-key"
57
- }
58
- }
59
- }
60
- }
61
- ```
62
-
63
- ### 2. 重启 Cursor
64
-
65
- 重启 Cursor 或重新加载 MCP 服务器配置。
66
-
67
- ### 3. 开始使用
68
-
69
- 在 Cursor 中,您可以:
70
-
71
- #### 方式 1:使用 AI 工具调用
72
-
73
- 对 AI 说:
74
- ```
75
- 请使用 listChannels 工具查看所有可用频道
76
- 请使用 getCode 工具获取 my-channel 频道的代码
77
- ```
78
-
79
- #### 方式 2:通过资源 URI 访问
80
-
81
- 在代码或对话中引用:
82
- ```
83
- codify://my-channel/current
84
- ```
85
-
86
- ## 配置说明
87
-
88
- ### 命令行参数
89
-
90
- | 参数 | 说明 | 默认值 |
91
- |------|------|--------|
92
- | `--url=<URL>` | Codify 服务器地址 | `http://localhost:8080` |
93
- | `--help`, `-h` | 显示帮助信息 | - |
94
- | `--version`, `-v` | 显示版本号 | - |
95
-
96
- ### 环境变量
97
-
98
- | 变量名 | 说明 | 必需 |
99
- |--------|------|------|
100
- | `CODIFY_SERVER_URL` | 服务器地址(可被 --url 覆盖) | 否 |
101
- | `CODIFY_ACCESS_KEY` | 访问密钥 | 是* |
102
-
103
- *如果服务器启用了认证则必需
104
-
105
- ## 使用示例
106
-
107
- ### 示例 1:连接本地服务器(无认证)
108
-
109
- ```json
110
- {
111
- "mcpServers": {
112
- "codify": {
113
- "command": "npx",
114
- "args": ["-y", "@codify/mcp-client"]
115
- }
116
- }
117
- }
118
- ```
119
-
120
- ### 示例 2:连接远程服务器(带认证)
121
-
122
- ```json
123
- {
124
- "mcpServers": {
125
- "codify": {
126
- "command": "npx",
127
- "args": [
128
- "-y",
129
- "@codify/mcp-client",
130
- "--url=https://codify.example.com"
131
- ],
132
- "env": {
133
- "CODIFY_ACCESS_KEY": "sk-abc123xyz789"
134
- }
135
- }
136
- }
137
- }
138
- ```
139
-
140
- ### 示例 3:使用环境变量
141
-
142
- ```json
143
- {
144
- "mcpServers": {
145
- "codify": {
146
- "command": "npx",
147
- "args": ["-y", "@codify/mcp-client"],
148
- "env": {
149
- "CODIFY_SERVER_URL": "http://192.168.1.100:8080",
150
- "CODIFY_ACCESS_KEY": "sk-abc123xyz789"
151
- }
152
- }
153
- }
154
- }
155
- ```
156
-
157
- ## 可用工具
158
-
159
- ### getCode
160
-
161
- 获取指定频道的代码。
162
-
163
- **参数:**
164
- - `channelId` (string, 必需) - 频道 ID
165
-
166
- **示例:**
167
- ```
168
- AI,请使用 getCode 工具获取 demo-channel 的代码
169
- ```
170
-
171
- ### listChannels
172
-
173
- 列出所有可用频道。
174
-
175
- **参数:** 无
176
-
177
- **示例:**
178
- ```
179
- AI,请使用 listChannels 工具查看所有频道
180
- ```
181
-
182
- ## 可用资源
183
-
184
- 通过资源 URI 直接访问代码:
185
-
186
- ```
187
- codify://{channelId}/current
188
- ```
189
-
190
- **示例:**
191
- ```
192
- codify://demo-channel/current
193
- codify://my-project/current
194
- ```
195
-
196
- ## 故障排查
197
-
198
- ### 问题 1:连接失败
199
-
200
- **错误信息:** `❌ 获取通道列表失败`
201
-
202
- **解决方案:**
203
- 1. 确保 Codify 服务器正在运行
204
- 2. 检查服务器 URL 是否正确
205
- 3. 检查网络连接是否正常
206
- 4. 查看服务器日志
207
-
208
- ### 问题 2:认证失败
209
-
210
- **错误信息:** `❌ 认证失败 (401)`
211
-
212
- **解决方案:**
213
- 1. 确认 `CODIFY_ACCESS_KEY` 已设置
214
- 2. 检查 access_key 是否正确
215
- 3. 确认服务器启用了认证
216
-
217
- ### 问题 3:频道不存在
218
-
219
- **错误信息:** `❌ 频道 "xxx" 不存在`
220
-
221
- **解决方案:**
222
- 1. 使用 `listChannels` 工具查看所有可用频道
223
- 2. 确认 Figma 插件已连接并发送过代码
224
- 3. 检查频道 ID 拼写是否正确
225
-
226
- ## 调试模式
227
-
228
- 启用调试模式查看详细日志:
229
-
230
- ```json
231
- {
232
- "mcpServers": {
233
- "codify": {
234
- "command": "npx",
235
- "args": ["-y", "@codify/mcp-client", "--url=http://localhost:8080"],
236
- "env": {
237
- "DEBUG": "true",
238
- "CODIFY_ACCESS_KEY": "sk-xxx"
239
- }
240
- }
241
- }
242
- }
243
- ```
244
-
245
- ## 相关项目
246
-
247
- - **Codify MCP Server** - 服务端实现
248
- - **Codify Figma Plugin** - Figma 插件
249
-
250
- ## 许可证
251
-
252
- MIT
253
-
254
- ## 贡献
255
-
256
- 欢迎提交 Issue 和 Pull Request!
257
-
258
- ## 支持
259
-
260
- 如有问题,请:
261
- 1. 查看[文档](https://github.com/your-username/codify-mcp-client)
262
- 2. 提交 [Issue](https://github.com/your-username/codify-mcp-client/issues)
263
- 3. 加入我们的社区讨论
264
-
265
- ---
266
-
267
- Made with ❤️ by Codify Team