├── .github
└── workflows
│ ├── ci.yml
│ └── publish.yml
├── .gitignore
├── .npmignore
├── .npmrc
├── README.md
├── README.zh-CN.md
├── bin
└── cli.js
├── build.js
├── images
├── image-20250507174245589.png
├── image-20250507174511910.png
├── image-20250507174840456.png
├── image-20250507175005364.png
└── image-20250507175107044.png
├── package.json
├── src
├── http-util.ts
├── index.ts
├── markdown
│ ├── component-workflow.md
│ └── meta.md
├── tools
│ ├── base-tool.ts
│ ├── get-component-link.ts
│ ├── get-component-workflow.ts
│ ├── get-dsl.ts
│ ├── get-meta.ts
│ └── get-version.ts
└── types.d.ts
└── tsconfig.json
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v4
15 |
16 | - name: Use Node.js 18.x
17 | uses: actions/setup-node@v4
18 | with:
19 | node-version: 18.x
20 |
21 | - name: Install dependencies
22 | run: npm install
23 |
24 | - name: Build
25 | run: npm run build
26 |
27 | - name: Upload build artifacts
28 | uses: actions/upload-artifact@v4
29 | with:
30 | name: build-artifacts
31 | path: dist/
32 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish to NPM
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | release-type:
7 | description: "Release type"
8 | required: true
9 | default: "patch"
10 | type: "choice"
11 | options:
12 | - "patch"
13 | - "minor"
14 | - "major"
15 | - "beta"
16 | - "alpha"
17 | version-increment:
18 | description: "Version increment (beta and alpha)"
19 | required: false
20 | default: "0"
21 | type: "choice"
22 | options:
23 | - "0"
24 | - "1"
25 | - "2"
26 | - "3"
27 | - "4"
28 | - "5"
29 |
30 | # Add permission configuration
31 | permissions:
32 | contents: write
33 |
34 | jobs:
35 | publish:
36 | runs-on: ubuntu-latest
37 | steps:
38 | - uses: actions/checkout@v4
39 | with:
40 | ref: main
41 |
42 | - name: Set up Node.js
43 | uses: actions/setup-node@v4
44 | with:
45 | node-version: "18.x"
46 | registry-url: "https://registry.npmjs.org"
47 |
48 | - name: Install dependencies
49 | run: npm install
50 |
51 | - name: Build project
52 | run: npm run build
53 |
54 | - name: Get current version
55 | id: get-current-version
56 | run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
57 |
58 | - name: Version update (official version)
59 | if: ${{ github.event.inputs.release-type == 'patch' || github.event.inputs.release-type == 'minor' || github.event.inputs.release-type == 'major' }}
60 | run: npm version ${{ github.event.inputs.release-type }} --no-git-tag-version
61 |
62 | - name: Version update (Beta version - first time)
63 | if: ${{ github.event.inputs.release-type == 'beta' && !contains(steps.get-current-version.outputs.version, 'beta') }}
64 | run: |
65 | npm --no-git-tag-version version prerelease --preid=beta
66 | # If a specific increment number is needed, execute additional increments
67 | if [ "${{ github.event.inputs.version-increment }}" != "0" ]; then
68 | for i in $(seq 1 ${{ github.event.inputs.version-increment }}); do
69 | npm --no-git-tag-version version prerelease --preid=beta
70 | done
71 | fi
72 |
73 | - name: Version update (Beta version - increment)
74 | if: ${{ github.event.inputs.release-type == 'beta' && contains(steps.get-current-version.outputs.version, 'beta') }}
75 | run: |
76 | # For versions with existing beta tags, directly increment the pre-release version number
77 | for i in $(seq 1 $((${{ github.event.inputs.version-increment }} + 1))); do
78 | npm --no-git-tag-version version prerelease --preid=beta
79 | done
80 |
81 | - name: Version update (Alpha version - first time)
82 | if: ${{ github.event.inputs.release-type == 'alpha' && !contains(steps.get-current-version.outputs.version, 'alpha') }}
83 | run: |
84 | npm --no-git-tag-version version prerelease --preid=alpha
85 | # If a specific increment number is needed, execute additional increments
86 | if [ "${{ github.event.inputs.version-increment }}" != "0" ]; then
87 | for i in $(seq 1 ${{ github.event.inputs.version-increment }}); do
88 | npm --no-git-tag-version version prerelease --preid=alpha
89 | done
90 | fi
91 |
92 | - name: Version update (Alpha version - increment)
93 | if: ${{ github.event.inputs.release-type == 'alpha' && contains(steps.get-current-version.outputs.version, 'alpha') }}
94 | run: |
95 | # For versions with existing alpha tags, directly increment the pre-release version number
96 | for i in $(seq 1 $((${{ github.event.inputs.version-increment }} + 1))); do
97 | npm --no-git-tag-version version prerelease --preid=alpha
98 | done
99 |
100 | - name: Publish to NPM
101 | run: npm publish
102 | env:
103 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
104 |
105 | - name: Get new version number
106 | id: get-version
107 | run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
108 |
109 | - name: Commit version change
110 | run: |
111 | git config --local user.email "github-actions[bot]@users.noreply.github.com"
112 | git config --local user.name "github-actions[bot]"
113 | git add package.json
114 | git commit -m "chore: publish v${{ steps.get-version.outputs.version }}"
115 | git tag v${{ steps.get-version.outputs.version }}
116 | git push
117 | git push --tags
118 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | package-lock.json
3 | yarn.lock
4 | pnpm-lock.yaml
5 |
6 | dist/
7 | build/
8 | out/
9 |
10 | .cursorrules
11 |
12 | logs/
13 | *.log
14 | npm-debug.log*
15 | yarn-debug.log*
16 | yarn-error.log*
17 |
18 | .env
19 | .env.local
20 | .env.development.local
21 | .env.test.local
22 | .env.production.local
23 |
24 | .idea/
25 | .vscode/
26 | *.swp
27 | *.swo
28 |
29 | .DS_Store
30 | Thumbs.db
31 |
32 | .specstory
33 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | node_modules
3 | **/node_modules/
4 | **/node_modules
5 | src/
6 | .git/
7 | .gitignore
8 | *.log
9 | .eslintrc
10 | .prettierrc
11 | tsconfig.json
12 | build.js
13 | smithery.yaml
14 | Dockerfile
15 | README.md
16 | **/.DS_Store
17 | **/.idea
18 | **/.vscode
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 | node_modules=false
3 | @mastergo:registry=https://registry.npmjs.org/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MasterGo Magic MCP
2 |
3 | [](https://deepwiki.com/mastergo-design/mastergo-magic-mcp)
4 |
5 | MasterGo Magic MCP is a standalone MCP (Model Context Protocol) service designed to connect MasterGo design tools with AI models. It enables AI models to directly retrieve DSL data from MasterGo design files.
6 |
7 | ## Key Features
8 |
9 | - Retrieves DSL data from MasterGo design files
10 | - Runs directly with npx
11 | - No external dependencies required, only Node.js environment needed
12 |
13 | ## Tutorial
14 |
15 | - https://mastergo.com/file/155675508499265?page_id=158:0002
16 |
17 | ## Usage
18 |
19 | ### Obtaining MG_MCP_TOKEN
20 |
21 | 1. Visit https://mastergo.com
22 | 2. Enter personal settings
23 | 3. Click the Security Settings tab
24 | 4. Find the personal access token
25 | 5. Click to generate the token
26 |
27 | ### Command Line Options
28 |
29 | ```
30 | npx @mastergo/magic-mcp --token=YOUR_TOKEN [--url=API_URL] [--rule=RULE_NAME] [--debug]
31 | ```
32 |
33 | #### Parameters:
34 |
35 | - `--token=YOUR_TOKEN` (required): MasterGo API token for authentication
36 | - `--url=API_URL` (optional): API base URL, defaults to http://localhost:3000
37 | - `--rule=RULE_NAME` (optional): Add design rules to apply, can be used multiple times
38 | - `--debug` (optional): Enable debug mode for detailed error information
39 |
40 | You can also use space-separated format for parameters:
41 |
42 | ```
43 | npx @mastergo/magic-mcp --token YOUR_TOKEN --url API_URL --rule RULE_NAME --debug
44 | ```
45 |
46 | ### LINGMA Usage
47 |
48 | Search for LINGMA in the VSCode extension marketplace and install it.
49 |
50 |
51 |
52 | After logging in, click on [MCP tools] in the chat box.
53 |
54 |
55 |
56 | Click on [MCP Square] at the top to enter the MCP marketplace, find the MasterGo design collaboration tool and install it.
57 |
58 |
59 |
60 | After installation, go back to [MCP Servers], and edit our MCP service to replace it with your own MasterGo token.
61 |
62 |
63 |
64 | Finally, switch the chat mode to agent mode in the chat interface.
65 |
66 |
67 |
68 | ### cursor Usage
69 |
70 | Cursor Mcp usage guide reference: https://docs.cursor.com/context/model-context-protocol#using-mcp-tools-in-agent
71 |
72 | ```json
73 | {
74 | "mcpServers": {
75 | "mastergo-magic-mcp": {
76 | "command": "npx",
77 | "args": [
78 | "-y",
79 | "@mastergo/magic-mcp",
80 | "--token=",
81 | "--url=https://mastergo.com"
82 | ],
83 | "env": {}
84 | }
85 | }
86 | }
87 | ```
88 |
89 | ### cline Usage
90 |
91 | ```json
92 | {
93 | "mcpServers": {
94 | "@master/mastergo-magic-mcp": {
95 | "command": "npx",
96 | "args": [
97 | "-y",
98 | "@mastergo/magic-mcp",
99 | "--token=",
100 | "--url=https://mastergo.com"
101 | ],
102 | "env": {}
103 | }
104 | }
105 | }
106 | ```
107 |
108 | ## Project Structure
109 |
110 | ### src Directory
111 |
112 | The `src` directory contains the core implementation of the MasterGo Magic MCP service:
113 |
114 | - `index.ts`: Entry point of the application that initializes the MCP server and registers all tools
115 | - `http-util.ts`: Utility for handling HTTP requests to the MasterGo API
116 | - `types.d.ts`: TypeScript type definitions for the project
117 |
118 | #### src/tools
119 |
120 | Contains implementations of MCP tools:
121 |
122 | - `base-tool.ts`: Base class for all MCP tools
123 | - `get-dsl.ts`: Tool for retrieving DSL (Domain Specific Language) data from MasterGo design files
124 | - `get-component-link.ts`: Tool for retrieving component documentation from links
125 | - `get-meta.ts`: Tool for retrieving metadata information
126 | - `get-component-workflow.ts`: Tool providing structured component development workflow for Vue and React components, generating workflow files and component specifications
127 |
128 | #### src/markdown
129 |
130 | Contains markdown files with additional documentation:
131 |
132 | - `meta.md`: Documentation about metadata structure and usage
133 | - `component-workflow.md`: Component development workflow documentation guiding structured component development process
134 |
135 | ## Local Development
136 |
137 | 1. Run `yarn` and `yarn build` to install dependencies and build the code
138 | 2. Find the absolute path of `bin/cli.js`
139 | 3. Add local MCP configuration with your token
140 |
141 | ```json
142 | "mastergo-mcp-local": {
143 | "command": "node",
144 | "args": [
145 | "absolute/path/to/bin/cli.js",
146 | "--token=mg_xxxxxx",
147 | "--url=https://mastergo.com",
148 | "--debug"
149 | ],
150 | "env": {}
151 | },
152 | ```
153 |
154 | 4. Restart your editor to ensure the local MCP is enabled
155 |
156 | After successful execution, you can debug based on the local running results. You can build your own MCP service based on your modifications.
157 |
158 | We welcome your code contributions and look forward to building MasterGo's MCP service together.
159 |
160 | ## License
161 |
162 | ISC
163 |
--------------------------------------------------------------------------------
/README.zh-CN.md:
--------------------------------------------------------------------------------
1 | # MasterGo Magic MCP
2 |
3 | [](https://deepwiki.com/mastergo-design/mastergo-magic-mcp)
4 |
5 | MasterGo Magic MCP 是一个独立的 MCP(Model Context Protocol)服务,旨在连接 MasterGo 设计工具与 AI 模型。它使 AI 模型能够直接从 MasterGo 设计文件中获取 DSL 数据。
6 |
7 | ## 主要特性
8 |
9 | - 从 MasterGo 设计文件中获取 DSL 数据
10 | - 可直接通过 npx 运行
11 | - 仅需 Node.js 环境,无需其他外部依赖
12 |
13 | ## 教程
14 |
15 | - https://mastergo.com/file/155675508499265?page_id=158:0002
16 |
17 | ## 使用方法
18 |
19 | ### 获取 MG_MCP_TOKEN
20 |
21 | 1. 访问 https://mastergo.com
22 | 2. 进入个人设置
23 | 3. 点击安全设置选项卡
24 | 4. 找到个人访问令牌
25 | 5. 点击生成令牌
26 |
27 | ### 命令行选项
28 |
29 | ```
30 | npx @mastergo/magic-mcp --token=YOUR_TOKEN [--url=API_URL] [--rule=RULE_NAME] [--debug]
31 | ```
32 |
33 | #### 参数:
34 |
35 | - `--token=YOUR_TOKEN` (必需): MasterGo API 认证令牌
36 | - `--url=API_URL` (可选): API 基础 URL,默认为 http://localhost:3000
37 | - `--rule=RULE_NAME` (可选): 添加要应用的设计规则,可多次使用
38 | - `--debug` (可选): 启用调试模式,提供详细错误信息
39 |
40 | 你也可以使用空格分隔的参数格式:
41 |
42 | ```
43 | npx @mastergo/magic-mcp --token YOUR_TOKEN --url API_URL --rule RULE_NAME --debug
44 | ```
45 |
46 | ### LINGMA 使用方法
47 |
48 | 在 vscode 拓展市场中搜索 LINGMA -> 然后安装该拓展
49 |
50 |
51 |
52 | 登录后 -> 在聊天框中点击 [MCP tools]
53 |
54 |
55 |
56 | 点击顶部 [MCP Sqaure] 进入mcp市场,在市场中找到 Mastergo设计协作工具并安装
57 |
58 |
59 |
60 | 安装完成后,需要回到 [MCP Servers], 并编辑我们的mcp服务,将自己的mastergo token 替换上去
61 |
62 |
63 |
64 | 最后在聊天界面中将聊天模式切换为agent模式。
65 |
66 |
67 |
68 | ### Cursor 使用方法
69 |
70 | Cursor Mcp 使用指南参考:https://docs.cursor.com/context/model-context-protocol#using-mcp-tools-in-agent
71 |
72 | ```json
73 | {
74 | "mcpServers": {
75 | "mastergo-magic-mcp": {
76 | "command": "npx",
77 | "args": [
78 | "-y",
79 | "@mastergo/magic-mcp",
80 | "--token=",
81 | "--url=https://mastergo.com"
82 | ],
83 | "env": {}
84 | }
85 | }
86 | }
87 | ```
88 |
89 | ### cline 使用方法
90 |
91 | ```json
92 | {
93 | "mcpServers": {
94 | "@master/mastergo-magic-mcp": {
95 | "command": "npx",
96 | "args": [
97 | "-y",
98 | "@mastergo/magic-mcp",
99 | "--token=",
100 | "--url=https://mastergo.com"
101 | ],
102 | "env": {}
103 | }
104 | }
105 | }
106 | ```
107 |
108 | ## 项目结构
109 |
110 | ### src 目录
111 |
112 | `src` 目录包含 MasterGo Magic MCP 服务的核心实现:
113 |
114 | - `index.ts`:应用程序入口点,初始化 MCP 服务器并注册所有工具
115 | - `http-util.ts`:处理与 MasterGo API 通信的 HTTP 请求工具
116 | - `types.d.ts`:项目的 TypeScript 类型定义
117 |
118 | #### src/tools
119 |
120 | 包含 MCP 工具的实现:
121 |
122 | - `base-tool.ts`:所有 MCP 工具的基类
123 | - `get-dsl.ts`:从 MasterGo 设计文件中获取 DSL(领域特定语言)数据的工具
124 | - `get-component-link.ts`:从链接中获取组件文档的工具
125 | - `get-meta.ts`:获取元数据信息的工具
126 | - `get-component-workflow.ts`:提供结构化的组件开发工作流工具,支持 Vue 和 React 组件开发,生成所需的工作流文件和组件规范
127 |
128 | #### src/markdown
129 |
130 | 包含附加文档的 markdown 文件:
131 |
132 | - `meta.md`:关于元数据结构和用法的文档
133 | - `component-workflow.md`:组件开发工作流程文档,指导结构化组件开发过程
134 |
135 | ## 本地开发
136 |
137 | 1. 运行 `yarn` 和 `yarn build`,安装依赖并构建代码
138 | 2. 查看 `bin/cli.js` 的绝对路径
139 | 3. 在 MCP 配置中添加本地 MCP 配置,其中 token 为您获取的 token
140 |
141 | ```json
142 | "mastergo-mcp-local": {
143 | "command": "node",
144 | "args": [
145 | "bin/cli.js绝对路径地址",
146 | "--token=mg_xxxxxx",
147 | "--url=https://mastergo.com",
148 | "--debug"
149 | ],
150 | "env": {}
151 | },
152 | ```
153 |
154 | 4. 重启编辑器,确认本地 MCP 已开启
155 |
156 | 运行成功后,就可以基于本地运行的结果进行调试。您可以基于自己的修改构建自己的 MCP 服务。
157 |
158 | 欢迎您为我们提供代码贡献,并期待大家一起共建 MasterGo 的 MCP 服务。
159 |
160 | ## 许可证
161 |
162 | ISC
163 |
--------------------------------------------------------------------------------
/bin/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const { spawn } = require("child_process");
4 | const path = require("path");
5 | const fs = require("fs");
6 |
7 | // Get arguments
8 | const args = process.argv.slice(2);
9 | let token = "";
10 | let baseUrl = "http://localhost:3000";
11 | let debug = false;
12 | // Array to collect rules
13 | let rules = [];
14 |
15 | // Parse arguments
16 | for (let i = 0; i < args.length; i++) {
17 | if (args[i] === "--token" && i + 1 < args.length) {
18 | token = args[i + 1];
19 | i++;
20 | } else if (args[i] === "--url" && i + 1 < args.length) {
21 | baseUrl = args[i + 1];
22 | i++;
23 | } else if (args[i].startsWith("--token=")) {
24 | token = args[i].split("=")[1];
25 | } else if (args[i].startsWith("--url=")) {
26 | baseUrl = args[i].split("=")[1];
27 | } else if (args[i] === "--debug") {
28 | debug = true;
29 | // Add support for --rule parameter
30 | } else if (args[i] === "--rule" && i + 1 < args.length) {
31 | rules.push(args[i + 1]);
32 | i++;
33 | } else if (args[i].startsWith("--rule=")) {
34 | rules.push(args[i].split("=")[1]);
35 | }
36 | }
37 |
38 | // Check required arguments
39 | if (!token && !process.env.MASTERGO_API_TOKEN) {
40 | console.error("Error: Missing MasterGo API Token");
41 | console.error(
42 | "Usage: npx mastergo-magic-mcp --token=YOUR_TOKEN [--url=API_URL] [--rule=RULE_NAME]"
43 | );
44 | console.error("Use --help or -h for more information");
45 | process.exit(1);
46 | }
47 |
48 | // Set environment variables
49 | const env = {
50 | MASTERGO_API_TOKEN: token,
51 | ...process.env,
52 | API_BASE_URL: baseUrl,
53 | DEBUG: debug ? "true" : "false",
54 | // Add RULES environment variable as stringified array
55 | RULES: JSON.stringify(rules),
56 | };
57 |
58 | // Get package path
59 | const packageDir = path.resolve(__dirname, "../dist");
60 | const indexPath = path.join(packageDir, "index.js");
61 |
62 | // Check if file exists
63 | if (!fs.existsSync(indexPath)) {
64 | console.error(
65 | "Error: Executable file not found. Please ensure the package is correctly installed."
66 | );
67 | process.exit(1);
68 | }
69 |
70 | if (debug) {
71 | console.log("Debug information:");
72 | console.log(`Package path: ${indexPath}`);
73 | console.log(`Token: ${token ? "set" : "not set"}`);
74 | console.log(`API URL: ${baseUrl}`);
75 | console.log(`Rules: ${rules.length > 0 ? rules.join(", ") : "none"}`);
76 | console.log(`Debug mode: ${debug ? "enabled" : "disabled"}`);
77 | }
78 |
79 | try {
80 | // Directly run the compiled file
81 | if (debug) {
82 | console.log("Using node to run the compiled code...");
83 | }
84 |
85 | // Directly use node to run the file, passing environment variables
86 | const child = spawn("node", [indexPath], {
87 | env: env,
88 | stdio: "inherit",
89 | });
90 |
91 | child.on("error", (error) => {
92 | console.error("Startup error:", error);
93 | if (debug) {
94 | console.error("Detailed error information:", error.stack);
95 | }
96 | process.exit(1);
97 | });
98 |
99 | child.on("exit", (code) => {
100 | process.exit(code || 0);
101 | });
102 | } catch (error) {
103 | console.error("Runtime error:", error);
104 | if (debug) {
105 | console.error("Detailed error information:", error.stack);
106 | }
107 | process.exit(1);
108 | }
109 |
--------------------------------------------------------------------------------
/build.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | const esbuild = require("esbuild");
4 | const { execSync } = require("child_process");
5 | const fs = require("fs");
6 | const path = require("path");
7 |
8 | // Ensure the dist directory exists
9 | if (!fs.existsSync("dist")) {
10 | fs.mkdirSync("dist");
11 | }
12 |
13 | // Ensure the bin directory exists
14 | if (!fs.existsSync("bin")) {
15 | fs.mkdirSync("bin");
16 | }
17 |
18 | // Recursively delete a directory
19 | function removeDir(dirPath) {
20 | if (fs.existsSync(dirPath)) {
21 | fs.readdirSync(dirPath).forEach((file) => {
22 | const curPath = path.join(dirPath, file);
23 | if (fs.lstatSync(curPath).isDirectory()) {
24 | // Recursively delete subdirectories
25 | removeDir(curPath);
26 | } else {
27 | // Delete the file
28 | fs.unlinkSync(curPath);
29 | }
30 | });
31 | // Delete the directory itself
32 | fs.rmdirSync(dirPath);
33 | }
34 | }
35 |
36 | async function build() {
37 | try {
38 | console.log("🚀 Starting the build process...");
39 |
40 | // Clean up old build files
41 | console.log("🧹 Cleaning up old build files...");
42 | if (fs.existsSync("dist")) {
43 | // First delete the dist directory
44 | removeDir("dist");
45 | // Re-create the dist directory
46 | fs.mkdirSync("dist");
47 | }
48 |
49 | // Use esbuild to bundle all code into a single file
50 | console.log("📦 Using esbuild to bundle all code into a single file...");
51 | await esbuild.build({
52 | entryPoints: ["src/index.ts"],
53 | bundle: true,
54 | platform: "node",
55 | target: "node16",
56 | outfile: "dist/index.js",
57 | minify: true,
58 | sourcemap: false,
59 | format: "cjs",
60 | // Exclude only node built-in modules to ensure all third-party dependencies are bundled
61 | external: [
62 | "path",
63 | "fs",
64 | "child_process",
65 | "http",
66 | "https",
67 | "util",
68 | "os",
69 | "stream",
70 | "zlib",
71 | "events",
72 | "buffer",
73 | "crypto",
74 | "net",
75 | "dns",
76 | "tls",
77 | "url",
78 | "querystring",
79 | "assert",
80 | ],
81 | // Ensure all modules are correctly resolved
82 | resolveExtensions: [".ts", ".js", ".json", ".node"],
83 | // Ensure all dependencies are correctly loaded
84 | loader: {
85 | ".ts": "ts",
86 | ".js": "js",
87 | ".json": "json",
88 | ".node": "file",
89 | ".md": "text",
90 | },
91 | // Define environment variables
92 | define: {
93 | "process.env.NODE_ENV": '"production"',
94 | },
95 | // Enable tree shaking
96 | treeShaking: true,
97 | });
98 |
99 | // Verify if only one file is generated
100 | console.log("🔍 Verifying the build output...");
101 | const files = fs.readdirSync("dist");
102 | if (files.length > 1 || (files.length === 1 && files[0] !== "index.js")) {
103 | console.warn("⚠️ Warning: The build produced multiple files, not a single file");
104 | console.warn("📁 File list:", files);
105 | } else {
106 | console.log("✅ Verification successful: All code has been bundled into a single file");
107 | }
108 |
109 | // The file header is already in the source file, no need to add it again
110 | console.log("✅ The source file already includes the shebang, no need to add it again");
111 |
112 | // Add executable permissions
113 | console.log("🔑 Adding executable permissions...");
114 | fs.chmodSync("dist/index.js", "755");
115 | fs.chmodSync("bin/cli.js", "755");
116 |
117 | // Display file size
118 | const stats = fs.statSync("dist/index.js");
119 | const fileSizeInKB = (stats.size / 1024).toFixed(2);
120 | console.log(`📦 Build output size: ${fileSizeInKB} KB`);
121 |
122 | console.log("✅ Build successful!");
123 | console.log("📦 Executable file located at: dist/index.js");
124 | console.log("📦 CLI entry located at: bin/cli.js");
125 |
126 | console.log("🚀 You can publish the package using the following command:");
127 | console.log(" npm publish");
128 | console.log("");
129 | console.log("🔧 Or you can test locally using the following command:");
130 | console.log(
131 | " node bin/cli.js --token=YOUR_TOKEN [--url=API_URL] [--framework=FRAMEWORK]"
132 | );
133 | } catch (error) {
134 | console.error("❌ Build failed:", error);
135 | process.exit(1);
136 | }
137 | }
138 |
139 | build();
140 |
--------------------------------------------------------------------------------
/images/image-20250507174245589.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mastergo-design/mastergo-magic-mcp/ea015ea1f3bb31ff98e6905a6381d46b5a236052/images/image-20250507174245589.png
--------------------------------------------------------------------------------
/images/image-20250507174511910.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mastergo-design/mastergo-magic-mcp/ea015ea1f3bb31ff98e6905a6381d46b5a236052/images/image-20250507174511910.png
--------------------------------------------------------------------------------
/images/image-20250507174840456.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mastergo-design/mastergo-magic-mcp/ea015ea1f3bb31ff98e6905a6381d46b5a236052/images/image-20250507174840456.png
--------------------------------------------------------------------------------
/images/image-20250507175005364.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mastergo-design/mastergo-magic-mcp/ea015ea1f3bb31ff98e6905a6381d46b5a236052/images/image-20250507175005364.png
--------------------------------------------------------------------------------
/images/image-20250507175107044.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mastergo-design/mastergo-magic-mcp/ea015ea1f3bb31ff98e6905a6381d46b5a236052/images/image-20250507175107044.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@mastergo/magic-mcp",
3 | "version": "0.0.4-beta.11",
4 | "description": "MasterGo MCP standalone service",
5 | "main": "dist/index.js",
6 | "bin": {
7 | "mastergo-magic-mcp": "bin/cli.js"
8 | },
9 | "files": [
10 | "dist/**/*",
11 | "bin/**/*",
12 | "!**/*.map",
13 | "!**/.DS_Store",
14 | "!**/.idea",
15 | "!**/.vscode"
16 | ],
17 | "engines": {
18 | "node": ">=18"
19 | },
20 | "scripts": {
21 | "build": "node build.js",
22 | "start": "node bin/cli.js --token=test --url=http://localhost:3000 --debug",
23 | "prepublishOnly": "npm run build"
24 | },
25 | "keywords": [
26 | "mastergo",
27 | "mcp",
28 | "ai"
29 | ],
30 | "author": "",
31 | "license": "ISC",
32 | "private": false,
33 | "dependencies": {
34 | "@modelcontextprotocol/sdk": "^1.6.1",
35 | "axios": "^1.6.0",
36 | "zod": "^3.22.4"
37 | },
38 | "devDependencies": {
39 | "@types/node": "^20.8.10",
40 | "@typescript-eslint/eslint-plugin": "^6.9.1",
41 | "@typescript-eslint/parser": "^6.9.1",
42 | "esbuild": "^0.25.1",
43 | "esbuild-plugin-tsc": "^0.5.0",
44 | "eslint": "^8.52.0",
45 | "pkg": "^5.8.1",
46 | "prettier": "^3.0.3",
47 | "ts-node": "^10.9.1",
48 | "typescript": "^5.2.2"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/http-util.ts:
--------------------------------------------------------------------------------
1 | // Make a request through axios and set the request interceptor to add the token
2 | import axios, {
3 | AxiosInstance,
4 | AxiosRequestConfig,
5 | AxiosResponse,
6 | InternalAxiosRequestConfig,
7 | } from "axios";
8 |
9 | // DSL response interface
10 | export interface DslResponse {
11 | [key: string]: any;
12 | }
13 |
14 | // Code generation response interface
15 | export interface CodeResponse {
16 | code: string;
17 | [key: string]: any;
18 | }
19 |
20 | /**
21 | * HttpUtil class - responsible for managing requests and storing tokens
22 | */
23 | export class HttpUtil {
24 | private httpClient: AxiosInstance;
25 |
26 | constructor(baseUrl: string, token: string) {
27 | // Create axios instance
28 | this.httpClient = axios.create({
29 | baseURL: baseUrl,
30 | timeout: 30000, // Default 30 second timeout
31 | headers: {
32 | "Content-Type": "application/json",
33 | Accept: "application/json",
34 | },
35 | });
36 |
37 | // Request interceptor
38 | this.httpClient.interceptors.request.use(
39 | (config: InternalAxiosRequestConfig) => {
40 | // If a token exists, add it to the request header
41 | if (token) {
42 | config.headers["X-MG-UserAccessToken"] = `${token}`;
43 | }
44 | return config;
45 | },
46 | (error) => {
47 | return Promise.reject(error);
48 | }
49 | );
50 |
51 | // Response interceptor
52 | this.httpClient.interceptors.response.use(
53 | (response: AxiosResponse) => {
54 | return response;
55 | },
56 | (error) => {
57 | return Promise.reject(error);
58 | }
59 | );
60 | }
61 |
62 | private handleDslComponentDocumentLinks(dsl: DslResponse) {
63 | const documentLinks = new Set();
64 |
65 | const getChildrenDocumentLinks = (node: any) => {
66 | if (node?.componentInfo?.componentSetDocumentLink?.[0]) {
67 | documentLinks.add(node.componentInfo.componentSetDocumentLink[0]);
68 | }
69 |
70 | if (node.children && Array.isArray(node.children)) {
71 | for (const child of node.children) {
72 | getChildrenDocumentLinks(child);
73 | }
74 | }
75 | };
76 |
77 | for (const node of dsl.nodes ?? []) {
78 | getChildrenDocumentLinks(node);
79 | }
80 |
81 | return Array.from(documentLinks);
82 | }
83 |
84 | public async getMeta(fileId: string, layerId: string): Promise {
85 | const response = await this.httpClient.get("/mcp/meta", {
86 | params: { fileId, layerId },
87 | });
88 | return response.data;
89 | }
90 |
91 | /**
92 | * Get DSL data
93 | */
94 | public async getDsl(fileId: string, layerId: string): Promise {
95 | try {
96 | const params: any = { fileId, layerId };
97 |
98 | const response = await this.httpClient.get("/mcp/dsl", { params });
99 | const result = {
100 | dsl: response.data,
101 | componentDocumentLinks: this.handleDslComponentDocumentLinks(
102 | response.data
103 | ),
104 | rules: [
105 | "token filed must be generated as a variable (colors, shadows, fonts, etc.) and the token field must be displayed in the comment",
106 | `
107 | componentDocumentLinks is a list of frontend component documentation links used in the DSL layer, designed to help you understand how to use the components.
108 | When it exists and is not empty, you need to use mcp__getComponentLink in a for loop to get the URL content of all components in the list, understand how to use the components, and generate code using the components.
109 | For example:
110 | \`\`\`js
111 | const componentDocumentLinks = [
112 | 'https://example.com/ant/button.mdx',
113 | 'https://example.com/ant/button.mdx'
114 | ]
115 | for (const url of componentDocumentLinks) {
116 | const componentLink = await mcp__getComponentLink(url);
117 | console.log(componentLink);
118 | }
119 | \`\`\`
120 | `,
121 | ...(JSON.parse(process.env.RULES ?? "[]") as string[]),
122 | ],
123 | };
124 | return result;
125 | } catch (error) {
126 | throw error;
127 | }
128 | }
129 |
130 | public async getComponentStyleJson(fileId: string, layerId: string) {
131 | const response = await this.httpClient.get(`/mcp/style`, {
132 | params: { fileId, layerId },
133 | });
134 | return response.data;
135 | }
136 |
137 | /**
138 | * General request method
139 | */
140 | public async request(config: AxiosRequestConfig): Promise {
141 | try {
142 | const response = await this.httpClient(config);
143 | return response.data;
144 | } catch (error) {
145 | throw error;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5 | import { HttpUtil } from "./http-util";
6 | import { GetDslTool } from "./tools/get-dsl";
7 | import { GetComponentLinkTool } from "./tools/get-component-link";
8 | import { GetMetaTool } from "./tools/get-meta";
9 | import { GetComponentWorkflowTool } from "./tools/get-component-workflow";
10 | import { GetVersionTool } from "./tools/get-version";
11 |
12 | // Logging function, only outputs when the DEBUG environment variable is true
13 | const log = (message: string) => {
14 | if (process.env.DEBUG === "true") {
15 | console.log(message);
16 | }
17 | };
18 |
19 | // Main function
20 | function main() {
21 | // Retrieve token and baseUrl from environment variables
22 | const token = process.env.MASTERGO_API_TOKEN;
23 | const baseUrl = process.env.API_BASE_URL || "http://localhost:3000";
24 | const debug = process.env.DEBUG === "true";
25 |
26 | if (!token) {
27 | console.error("Error: MASTERGO_API_TOKEN environment variable not set");
28 | process.exit(1);
29 | }
30 |
31 | log(`Starting MasterGo MCP server...`);
32 | log(`API base URL: ${baseUrl}`);
33 |
34 | // Create server instance
35 | const server = new McpServer({
36 | name: "MasterGoMcpServer",
37 | version: "0.0.1",
38 | });
39 |
40 | // Create HTTP utility
41 | const httpUtil = new HttpUtil(baseUrl, token);
42 |
43 | // Register tools
44 | new GetVersionTool().register(server);
45 | new GetDslTool(httpUtil).register(server);
46 | new GetComponentLinkTool(httpUtil).register(server);
47 | new GetMetaTool(httpUtil).register(server);
48 | new GetComponentWorkflowTool(httpUtil).register(server);
49 |
50 | // Connect to standard input/output
51 | server.connect(new StdioServerTransport());
52 |
53 | // Only output server started message in debug mode
54 | if (debug) {
55 | console.log("MasterGo MCP server started and waiting for connection...");
56 | }
57 | }
58 |
59 | // Start the program
60 | main();
61 |
--------------------------------------------------------------------------------
/src/markdown/component-workflow.md:
--------------------------------------------------------------------------------
1 | ---
2 | description:
3 | globs:
4 | alwaysApply: true
5 | ---
6 |
7 | # MasterGo Component System Specification v1.0
8 |
9 | ## Core Contents
10 |
11 | - Project Environment Setup
12 | - Component Interaction Design
13 | - Component Development Workflow
14 |
15 | ---
16 |
17 | ## Project Environment Setup
18 |
19 | ### Environment Check
20 |
21 | Check if project is initialized:
22 |
23 | - `package.json`
24 | - TypeScript configuration
25 | - Vite configuration
26 | - VitePress configuration (`docs/.vitepress/`)
27 | - Vue and testing dependencies
28 |
29 | ### Environment Initialization
30 |
31 | Required steps:
32 |
33 | ```bash
34 | npm init -y
35 | npm install vue@latest typescript vite@latest vitepress@latest vitest@latest @vitejs/plugin-vue@latest
36 | npm install -D @vue/test-utils jsdom @types/node
37 | ```
38 |
39 | Required configuration files:
40 |
41 | - `tsconfig.json`
42 | - `vite.config.ts`
43 | - `docs/.vitepress/config.ts`
44 | - `vitest.config.ts`
45 |
46 | ### Project Structure
47 |
48 | ```
49 | project-root/
50 | ├── docs/ # Component documentation
51 | │ ├── .vitepress/ # VitePress configuration
52 | │ ├── components/ # Component docs and demos
53 | ├── src/
54 | │ ├── components/ # Component source code
55 | │ ├── styles/ # Style files
56 | ├── __tests__/ # Component tests
57 | ```
58 |
59 | ### Required Scripts
60 |
61 | ```json
62 | {
63 | "scripts": {
64 | "dev": "vitepress dev docs",
65 | "build": "vitepress build docs",
66 | "test": "vitest run",
67 | "test:ui": "vitest --ui"
68 | }
69 | }
70 | ```
71 |
72 | ### Project Verification
73 |
74 | **CRITICAL STEP**: After project initialization, scripts must be run to verify configuration:
75 |
76 | 1. Run the development server:
77 |
78 | ```bash
79 | npm run dev
80 | ```
81 |
82 | 2. Verify the test environment:
83 |
84 | ```bash
85 | npm run test
86 | ```
87 |
88 | 3. Ensure no errors appear in the console for each script
89 | 4. Resolve any errors before proceeding to component development
90 | 5. Project is considered properly initialized only when all scripts run without errors
91 |
92 | ---
93 |
94 | ## Component Interaction Design Specification
95 |
96 | ### Core Principles
97 |
98 | - **CSS Priority**: Use CSS pseudo-classes for basic states
99 | - **State Extension**: Allow overriding default states via props
100 | - **Consistency**: Maintain consistent state management patterns
101 | - **Performance Priority**: Minimize JavaScript state management
102 |
103 | ### State Priority
104 |
105 | CSS Pseudo-classes > Props-specified States > JavaScript State Management
106 |
107 | ### Component Reuse Principles
108 |
109 | Reuse decision priority:
110 |
111 | 1. Direct Use (when functionality completely matches)
112 | 2. Component Composition (implement by combining existing components)
113 | 3. Component Extension (add new functionality based on existing components)
114 | 4. Redevelopment (only when above methods are not feasible)
115 |
116 | ---
117 |
118 | ## Component Development Workflow
119 |
120 | ### Complete Process
121 |
122 | ```
123 | [Environment Check] → [Project Verification] → [Component Analysis] → [User Confirmation] → [Test Generation] → [Component Development] → [Validation] → [Documentation & Preview]
124 | ```
125 |
126 | ### 1. Component Analysis
127 |
128 | **Input**: Component JSON specification
129 | **Output**: Architecture document (`.mastergo/${componentName}-arch.md`)
130 |
131 | #### Slot Analysis
132 |
133 | AI must analyze component design and infer:
134 |
135 | - Slots that may be needed
136 | - Purpose of each slot
137 | - Default content suggestions
138 | - Optional/required status
139 |
140 | #### Checklist
141 |
142 | - [ ] Property analysis
143 | - [ ] States and variants identification
144 | - [ ] Common styles extraction
145 | - [ ] Interface definition
146 | - [ ] Slot definition
147 |
148 | #### Architecture Document Verification
149 |
150 | **CRITICAL BREAK POINT**: After generating the architecture document, execution must pause.
151 |
152 | 1. Present the architecture document to the user for review
153 | 2. Ask user to verify all aspects of the document:
154 | - Component properties and types
155 | - State definitions
156 | - Slot specifications
157 | - Component structure
158 | - Image assets and their paths
159 | 3. If user identifies issues:
160 | - Collect all feedback
161 | - Make required modifications to the architecture document
162 | - Present updated document for review
163 | 4. Repeat review cycle until user explicitly approves the document
164 | 5. Only proceed to Test Generation phase after user confirmation
165 |
166 | #### Image Resource Handling
167 |
168 | **CRITICAL STEP**: After user confirmation of the architecture document, and before proceeding to Test Generation:
169 |
170 | 1. **Resource Inventory and Path Documentation**:
171 |
172 | - The architecture document must include an "Image Resources" section that clearly lists all necessary resources in a table format:
173 |
174 | ```markdown
175 | ## Image Resources
176 |
177 | ### Resource List and Paths
178 |
179 | | Icon Description | Original Path | Target Path | Icon Color Control |
180 | | ---------------- | ------------------------- | ------------------------------------------------------- | ---------------------------------------------------- |
181 | | Close Icon | `/original/path/icon.svg` | `src/components/${componentName}/images/icon-close.svg` | Dynamically controlled, defaults to match text color |
182 | | Other Icon | ... | ... | ... |
183 | ```
184 |
185 | 2. **Copy Images**:
186 |
187 | - Copy all necessary image resources listed in the architecture document to the component-specific directory.
188 | - Use semantic filenames such as `icon-close.svg`, `icon-success.svg`, `bg-header.png`, etc., ensuring the names clearly indicate the purpose of each image.
189 | - The target path must be `src/components/${componentName}/images/`. Create this directory if it doesn't exist.
190 | - Example:
191 | ```bash
192 | mkdir -p src/components/${componentName}/images
193 | cp /original/path/close-icon.svg src/components/${componentName}/images/icon-close.svg
194 | ```
195 |
196 | 3. **SVG Image Import and Color Specification**:
197 |
198 | - The architecture document must clearly specify the import method and color control approach for SVG icons.
199 | - SVGs must be imported using the following method to ensure dynamic color control:
200 |
201 | ```typescript
202 | import CloseIcon from "./images/icon-close.svg?raw"; // ?raw ensures it's imported as a string
203 | ```
204 |
205 | - The architecture document must include code examples for SVG usage and color control:
206 |
207 | ````markdown
208 | ### Icon Import and Usage Method
209 |
210 | ```typescript
211 | // In ${componentName}.vue, import icons
212 | import CloseIcon from "./images/icon-close.svg?raw";
213 | import SuccessIcon from "./images/icon-success.svg?raw";
214 | ```
215 | ````
216 |
217 | Using SVGs in templates and controlling their color:
218 |
219 | ```html
220 |
221 |
222 |
223 |
224 |
233 | ```
234 |
235 | - For each SVG icon, the architecture document must clearly specify:
236 | 1. Default color
237 | 2. Whether the color is fixed or needs to be dynamically controlled
238 | 3. Color variations in different states
239 |
240 | ### 2. Test Generation
241 |
242 | **Input**: Approved architecture document
243 | **Output**: Component unit tests
244 |
245 | #### Test Coverage
246 |
247 | - All component properties
248 | - All component states and behaviors
249 | - Edge cases
250 | - All inferred slots
251 | - State management (hover, focus, active, disabled, etc.)
252 |
253 | ### 3. Component Development
254 |
255 | **Input**: Architecture document and test cases
256 | **Output**: Functional component
257 |
258 | #### Required Files
259 |
260 | - `src/components/${componentName}/index.ts`
261 | - `src/components/${componentName}/types.ts`
262 | - `src/components/${componentName}/${componentName}.vue`
263 |
264 | #### Development Method
265 |
266 | - Test-driven development
267 | - Must follow UI interaction design specifications
268 | - Iterative implementation: Minimal code → Run tests → Refactor → Next test
269 |
270 | ### 4. Validation
271 |
272 | - All tests pass
273 | - Component visually matches design
274 | - Component is accessible
275 | - Responsive behavior is correct
276 |
277 | ### 5. Documentation & Preview
278 |
279 | **Output**: VitePress documentation and interactive previews
280 |
281 | #### Documentation Content
282 |
283 | - Component overview
284 | - API reference
285 | - Interactive examples
286 | - Complete slot documentation
287 | - Various states and use cases demonstrations
288 |
289 | #### Interactive Preview
290 |
291 | ````md
292 | ## Basic Usage
293 |
294 | :::demo
295 |
296 | ```vue
297 |
298 |
299 |
300 | ```
301 |
302 | :::
303 | ````
304 |
305 | ### Checkpoints
306 |
307 | - **Environment**: Correct configuration, dependencies installed, documentation preview system working
308 | - **Structure**: Files created, exports working, interfaces defined, slot definitions
309 | - **Tests**: Coverage for all features, edge cases, slots and states
310 | - **Implementation**: Renders correctly, properties work, state management complies with specifications, styles applied correctly, slot functionality works
311 | - **Documentation**: Feature documentation complete, examples available, API reference complete, slot usage documentation complete
312 |
--------------------------------------------------------------------------------
/src/markdown/meta.md:
--------------------------------------------------------------------------------
1 | The `results` returns an XML file, which contains two types of information:
2 |
3 | - **meta**: Describes the site, environment, requirements, and other context.
4 | - **action**: Corresponds to the entry page name and `targetLayerId`, which is the ID of the target page.
5 |
6 | I need you to write a task.md file in the current directory according to the following steps, and strictly follow these steps to generate the final project code.
7 |
8 | ## Steps
9 | 1. Obtain the `results` information, extract the `meta` and `action` data, and create a new `task.md` file.
10 | 2. Analyze the `meta` field, summarize the requirement description, and write it into task.md.
11 | 3. Analyze the `action` field, and write the page information into task.md.
12 | 4. Use the `targetLayerId` from the `action` field to call the `mcp__getDsl` method to get data.
13 | 5. Analyze the page data to check if there is an `interactive` field. If it exists, this field contains information about the current node's navigation to another page. You must continue to call the `mcp__getDsl` method according to the `interactive` field.
14 | 6. Repeat step 5 until all page data has been parsed and written into task.md.
15 | 7. According to the content in task.md, sequentially parse the pages listed in task.md and generate code. Complete the project construction.
16 |
17 | ## Example
18 | **Note**: Be sure to follow the order described in the example. Ensure that all page information is obtained!
19 |
20 |
21 | uppose the obtained results are:
22 | ```xml
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | ```
31 | Write the following into task.md:
32 |
33 |
34 |
35 |
36 | ```markdown
37 | Requirement Description: This is a food delivery app, which includes login, food ordering, and address management features. It should be built using React and use Ant Design as the component library.
38 |
39 | ## Page List:
40 | Login Page (layerId: 0:1)
41 | Food Delivery Page (layerId: 0:2)
42 |
43 | ## Navigation Information
44 |
45 |
46 | ```
47 |
48 | Use `mcp__getDsl` to parse the 0:1 page and analyze the data.
49 |
50 | The data might be:
51 | ```json
52 | {
53 | nodes: [{
54 | id: "0:1",
55 | // ...others
56 | children: [{
57 | id: "1:12",
58 | interactive: [
59 | type: "navigation",
60 | targetLayerId: "0:3"
61 | ]
62 | }]
63 | }]
64 | }
65 | ```
66 |
67 | if you find that the node data of page 0:1 contains the `interactive` field with id 0:3, write the 0:3 page and add the navigation information:
68 | ```markdown
69 |
70 | ## Page List:
71 | Login Page (layerId: 0:1)
72 | Food Delivery Page (layerId: 0:2)
73 | Login Page Navigation Page (layerId: 0:3)
74 |
75 | ## Navigation Information
76 | 0:1 => 0:3
77 |
78 | ```
79 | Continue to parse 0:3. If the data contains the `interactive` field, continue writing.
80 | Repeat this process until the data parsed by `mcp__getDsl` no longer contains the `interactive` field.
81 | Then, use `mcp__getDsl` to parse the 0:2 page and repeat the steps for the 0:1 page.
82 |
83 | After completion, generate the project code sequentially according to the page list in task.md.
84 |
--------------------------------------------------------------------------------
/src/tools/base-tool.ts:
--------------------------------------------------------------------------------
1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2 | import { z } from "zod";
3 |
4 | export abstract class BaseTool {
5 | abstract name: string;
6 | abstract description: string;
7 | abstract schema: z.ZodObject;
8 |
9 | register(server: McpServer) {
10 | server.tool(
11 | this.name,
12 | this.description,
13 | this.schema.shape,
14 | this.execute.bind(this)
15 | );
16 | }
17 |
18 | abstract execute(args: z.infer): Promise<{
19 | content: Array<{ type: "text"; text: string }>;
20 | }>;
21 | }
22 |
--------------------------------------------------------------------------------
/src/tools/get-component-link.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { BaseTool } from "./base-tool";
3 | import { HttpUtil } from "../http-util";
4 |
5 | const COMPONENT_LINK_TOOL_NAME = "mcp__getComponentLink";
6 | const COMPONENT_LINK_TOOL_DESCRIPTION = `When the data returned by mcp__getDsl contains a non-empty componentDocumentLinks array, this tool is used to sequentially retrieve URLs from the componentDocumentLinks array and then obtain component documentation data. The returned document data is used for you to generate frontend code based on components.`;
7 |
8 | export class GetComponentLinkTool extends BaseTool {
9 | name = COMPONENT_LINK_TOOL_NAME;
10 | description = COMPONENT_LINK_TOOL_DESCRIPTION;
11 | private httpUtil: HttpUtil;
12 |
13 | constructor(httpUtil: HttpUtil) {
14 | super();
15 | this.httpUtil = httpUtil;
16 | }
17 |
18 | schema = z.object({
19 | url: z
20 | .string()
21 | .describe(
22 | "Component documentation link URL, from the componentDocumentLinks property, please ensure the URL is valid"
23 | ),
24 | });
25 |
26 | async execute({ url }: z.infer) {
27 | try {
28 | const data = await this.httpUtil.request({
29 | method: "GET",
30 | url,
31 | });
32 |
33 | return {
34 | content: [
35 | {
36 | type: "text" as const,
37 | text: `${data}`,
38 | },
39 | ],
40 | };
41 | } catch (error) {
42 | return {
43 | content: [
44 | {
45 | type: "text" as const,
46 | text: JSON.stringify({
47 | error: "Failed to get component documentation",
48 | message: error instanceof Error ? error.message : String(error),
49 | }),
50 | },
51 | ],
52 | };
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/tools/get-component-workflow.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import fs from "fs";
3 | import { BaseTool } from "./base-tool";
4 | import { HttpUtil } from "../http-util";
5 | import componentWorkflow from "../markdown/component-workflow.md";
6 |
7 | const COMPONENT_GENERATOR_TOOL_NAME = "mcp__getComponentGenerator";
8 | const COMPONENT_GENERATOR_TOOL_DESCRIPTION = `
9 | Users need to actively call this tool to get the component development workflow. When Generator is mentioned, please actively call this tool.
10 | This tool provides a structured workflow for component development following best practices.
11 | You must provide an absolute rootPath of workspace to save workflow files.
12 | `;
13 |
14 | export class GetComponentWorkflowTool extends BaseTool {
15 | name = COMPONENT_GENERATOR_TOOL_NAME;
16 | description = COMPONENT_GENERATOR_TOOL_DESCRIPTION;
17 | private httpUtil: HttpUtil;
18 |
19 | constructor(httpUtil: HttpUtil) {
20 | super();
21 | this.httpUtil = httpUtil;
22 | }
23 |
24 | schema = z.object({
25 | rootPath: z
26 | .string()
27 | .describe(
28 | "The root path of the project, if the user does not provide, you can use the current directory as the root path"
29 | ),
30 | fileId: z
31 | .string()
32 | .describe(
33 | "MasterGo design file ID (format: file/ in MasterGo URL)"
34 | ),
35 | layerId: z
36 | .string()
37 | .describe(
38 | "Layer ID of the specific component or element to retrieve (format: ?layer_id= / file= in MasterGo URL)"
39 | ),
40 | });
41 |
42 | async execute({ rootPath, fileId, layerId }: z.infer) {
43 | const baseDir = `${rootPath}/.mastergo/`;
44 | if (!fs.existsSync(baseDir)) {
45 | fs.mkdirSync(baseDir, { recursive: true });
46 | }
47 | const workflowFilePath = `${baseDir}/component-workflow.md`;
48 | const jsonData = await this.httpUtil.getComponentStyleJson(fileId, layerId);
49 | const componentJsonDir = `${baseDir}/${jsonData[0].name}.json`;
50 | const walkLayer = (layer: any) => {
51 | if (layer.path && layer.path.length > 0) {
52 | layer.imageUrls = [];
53 | const id = layer.id.replaceAll("/", "&");
54 | const imageDir = `${baseDir}/images`;
55 | if (!fs.existsSync(imageDir)) {
56 | fs.mkdirSync(imageDir, { recursive: true });
57 | }
58 | (layer.path ?? []).forEach((svgPath: string, index: number) => {
59 | const filePath = `${imageDir}/${id}-${index}.svg`;
60 | if (!fs.existsSync(filePath)) {
61 | fs.writeFileSync(
62 | filePath,
63 | ``
66 | );
67 | }
68 | layer.imageUrls.push(filePath);
69 | });
70 | delete layer.path;
71 | }
72 | if (layer.children) {
73 | layer.children.forEach((child: any) => {
74 | walkLayer(child);
75 | });
76 | }
77 | };
78 | walkLayer(jsonData[0]);
79 |
80 | //文件夹可能也不存在递归创建
81 | if (!fs.existsSync(workflowFilePath)) {
82 | fs.writeFileSync(workflowFilePath, componentWorkflow);
83 | }
84 |
85 | fs.writeFileSync(componentJsonDir, JSON.stringify(jsonData[0]));
86 |
87 | try {
88 | return {
89 | content: [
90 | {
91 | type: "text" as const,
92 | text: JSON.stringify({
93 | files: {
94 | workflow: workflowFilePath,
95 | componentSpec: componentJsonDir,
96 | },
97 | message: "Component development files successfully created",
98 | rules: [
99 | `Follow the component workflow process defined in file://${workflowFilePath} for structured development. This workflow contains a lot of content, you'll need to read it in multiple sessions.`,
100 | `Implement the component according to the specifications in file://${componentJsonDir}, ensuring all properties and states are properly handled.`,
101 | ],
102 | }),
103 | },
104 | ],
105 | };
106 | } catch (error: any) {
107 | const errorMessage = error.response?.data ?? error?.message;
108 | return {
109 | isError: true,
110 | content: [
111 | {
112 | type: "text" as const,
113 | text: JSON.stringify(errorMessage),
114 | },
115 | ],
116 | };
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/tools/get-dsl.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { BaseTool } from "./base-tool";
3 | import { HttpUtil } from "../http-util";
4 |
5 | const DSL_TOOL_NAME = "mcp__getDsl";
6 | const DSL_TOOL_DESCRIPTION = `
7 | "Use this tool to retrieve the DSL (Domain Specific Language) data from MasterGo design files and the rules you must follow when generating code.
8 | This tool is useful when you need to analyze the structure of a design, understand component hierarchy, or extract design properties.
9 | You must provide a fileId and layerId to identify the specific design element.
10 | This tool returns the raw DSL data in JSON format that you can then parse and analyze.
11 | This tool also returns the rules you must follow when generating code.
12 | The DSL data can also be used to transform and generate code for different frameworks."
13 | `;
14 |
15 | export class GetDslTool extends BaseTool {
16 | name = DSL_TOOL_NAME;
17 | description = DSL_TOOL_DESCRIPTION;
18 | private httpUtil: HttpUtil;
19 |
20 | constructor(httpUtil: HttpUtil) {
21 | super();
22 | this.httpUtil = httpUtil;
23 | }
24 |
25 | schema = z.object({
26 | fileId: z
27 | .string()
28 | .describe(
29 | "MasterGo design file ID (format: file/ in MasterGo URL)"
30 | ),
31 | layerId: z
32 | .string()
33 | .describe(
34 | "Layer ID of the specific component or element to retrieve (format: ?layer_id= / file= in MasterGo URL)"
35 | ),
36 | });
37 |
38 | async execute({ fileId, layerId }: z.infer) {
39 | try {
40 | const dsl = await this.httpUtil.getDsl(fileId, layerId);
41 | return {
42 | content: [
43 | {
44 | type: "text" as const,
45 | text: JSON.stringify(dsl),
46 | },
47 | ],
48 | };
49 | } catch (error: any) {
50 | const errorMessage = error.response?.data ?? error?.message;
51 | return {
52 | isError: true,
53 | content: [
54 | {
55 | type: "text" as const,
56 | text: JSON.stringify(errorMessage),
57 | },
58 | ],
59 | };
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/tools/get-meta.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { BaseTool } from "./base-tool";
3 | import { HttpUtil } from "../http-util";
4 | import rules from "../markdown/meta.md";
5 |
6 | const META_TOOL_NAME = "mcp__getMeta";
7 | const META_TOOL_DESCRIPTION = `
8 | Use this tool when the user intends to build a complete website or needs to obtain high-level site
9 | configuration information. You must provide a fileld and layerld to identify the specific design element.
10 | This tool returns the rules and results of the site and page. The rules is a markdown file, you must
11 | follow the rules and use the results to analyze the site and page.
12 | `;
13 |
14 | export class GetMetaTool extends BaseTool {
15 | name = META_TOOL_NAME;
16 | description = META_TOOL_DESCRIPTION;
17 | private httpUtil: HttpUtil;
18 |
19 | constructor(httpUtil: HttpUtil) {
20 | super();
21 | this.httpUtil = httpUtil;
22 | }
23 |
24 | schema = z.object({
25 | fileId: z
26 | .string()
27 | .describe(
28 | "MasterGo design file ID (format: file/ in MasterGo URL)"
29 | ),
30 | layerId: z
31 | .string()
32 | .describe(
33 | "Layer ID of the specific component or element to retrieve (format: ?layer_id= / file= in MasterGo URL)"
34 | ),
35 | });
36 |
37 | async execute({ fileId, layerId }: z.infer) {
38 | try {
39 | const result = await this.httpUtil.getMeta(fileId, layerId);
40 | return {
41 | content: [
42 | {
43 | type: "text" as const,
44 | text: JSON.stringify({
45 | result,
46 | rules,
47 | }),
48 | },
49 | ],
50 | };
51 | } catch (error: any) {
52 | const errorMessage = error.response?.data ?? error?.message;
53 | return {
54 | isError: true,
55 | content: [
56 | {
57 | type: "text" as const,
58 | text: JSON.stringify(errorMessage),
59 | },
60 | ],
61 | };
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/tools/get-version.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import { BaseTool } from "./base-tool";
3 | import packageJson from "../../package.json";
4 |
5 | const VERSION_TOOL_NAME = `version_${packageJson.version}`;
6 | const VERSION_TOOL_DESCRIPTION = `the current version is ${packageJson.version}`;
7 |
8 | export class GetVersionTool extends BaseTool {
9 | name = VERSION_TOOL_NAME;
10 | description = VERSION_TOOL_DESCRIPTION;
11 |
12 | constructor() {
13 | super();
14 | }
15 |
16 | schema = z.object({});
17 |
18 | async execute({}: z.infer) {
19 | return {
20 | content: [
21 | {
22 | type: "text" as const,
23 | text: JSON.stringify(packageJson.version),
24 | },
25 | ],
26 | };
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/types.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.md' {
2 | const content: string;
3 | export default content;
4 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "module": "NodeNext",
5 | "moduleResolution": "NodeNext",
6 | "esModuleInterop": true,
7 | "strict": true,
8 | "outDir": "dist",
9 | "sourceMap": false,
10 | "declaration": false,
11 | "resolveJsonModule": true,
12 | "skipLibCheck": true,
13 | "forceConsistentCasingInFileNames": true
14 | },
15 | "include": ["src/**/*"],
16 | "exclude": ["node_modules", "dist"]
17 | }
18 |
--------------------------------------------------------------------------------