@creatoria/miniapp-mcp 0.1.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 +469 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/defaults.d.ts +73 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +118 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/loader.d.ts +50 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +189 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/core/element-ref.d.ts +44 -0
- package/dist/core/element-ref.d.ts.map +1 -0
- package/dist/core/element-ref.js +213 -0
- package/dist/core/element-ref.js.map +1 -0
- package/dist/core/logger.d.ts +55 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +378 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/output.d.ts +21 -0
- package/dist/core/output.d.ts.map +1 -0
- package/dist/core/output.js +56 -0
- package/dist/core/output.js.map +1 -0
- package/dist/core/report-generator.d.ts +24 -0
- package/dist/core/report-generator.d.ts.map +1 -0
- package/dist/core/report-generator.js +212 -0
- package/dist/core/report-generator.js.map +1 -0
- package/dist/core/session.d.ts +83 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +306 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/timeout.d.ts +49 -0
- package/dist/core/timeout.d.ts.map +1 -0
- package/dist/core/timeout.js +67 -0
- package/dist/core/timeout.js.map +1 -0
- package/dist/core/tool-logger.d.ts +83 -0
- package/dist/core/tool-logger.d.ts.map +1 -0
- package/dist/core/tool-logger.js +453 -0
- package/dist/core/tool-logger.js.map +1 -0
- package/dist/core/validation.d.ts +39 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +93 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +85 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/assert.d.ts +108 -0
- package/dist/tools/assert.d.ts.map +1 -0
- package/dist/tools/assert.js +291 -0
- package/dist/tools/assert.js.map +1 -0
- package/dist/tools/automator.d.ts +45 -0
- package/dist/tools/automator.d.ts.map +1 -0
- package/dist/tools/automator.js +186 -0
- package/dist/tools/automator.js.map +1 -0
- package/dist/tools/element.d.ts +253 -0
- package/dist/tools/element.d.ts.map +1 -0
- package/dist/tools/element.js +615 -0
- package/dist/tools/element.js.map +1 -0
- package/dist/tools/index.d.ts +97 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +1565 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/miniprogram.d.ts +79 -0
- package/dist/tools/miniprogram.d.ts.map +1 -0
- package/dist/tools/miniprogram.js +245 -0
- package/dist/tools/miniprogram.js.map +1 -0
- package/dist/tools/network.d.ts +65 -0
- package/dist/tools/network.d.ts.map +1 -0
- package/dist/tools/network.js +205 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/page.d.ts +108 -0
- package/dist/tools/page.d.ts.map +1 -0
- package/dist/tools/page.js +307 -0
- package/dist/tools/page.js.map +1 -0
- package/dist/tools/record.d.ts +86 -0
- package/dist/tools/record.d.ts.map +1 -0
- package/dist/tools/record.js +316 -0
- package/dist/tools/record.js.map +1 -0
- package/dist/tools/snapshot.d.ts +82 -0
- package/dist/tools/snapshot.d.ts.map +1 -0
- package/dist/tools/snapshot.js +258 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/types.d.ts +240 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/docs/SIMPLE_USAGE.md +210 -0
- package/docs/api/README.md +244 -0
- package/docs/api/assert.md +1015 -0
- package/docs/api/automator.md +345 -0
- package/docs/api/element.md +1454 -0
- package/docs/api/miniprogram.md +558 -0
- package/docs/api/network.md +883 -0
- package/docs/api/page.md +909 -0
- package/docs/api/record.md +963 -0
- package/docs/api/snapshot.md +792 -0
- package/docs/architecture.E-Docs.md +1359 -0
- package/docs/architecture.F1.md +720 -0
- package/docs/architecture.F2.md +871 -0
- package/docs/architecture.F3.md +905 -0
- package/docs/architecture.md +90 -0
- package/docs/charter.A1.align.yaml +170 -0
- package/docs/charter.A2.align.yaml +199 -0
- package/docs/charter.A3.align.yaml +242 -0
- package/docs/charter.A4.align.yaml +227 -0
- package/docs/charter.B1.align.yaml +179 -0
- package/docs/charter.B2.align.yaml +200 -0
- package/docs/charter.B3.align.yaml +200 -0
- package/docs/charter.B4.align.yaml +188 -0
- package/docs/charter.C1.align.yaml +190 -0
- package/docs/charter.C2.align.yaml +202 -0
- package/docs/charter.C3.align.yaml +211 -0
- package/docs/charter.C4.align.yaml +263 -0
- package/docs/charter.C5.align.yaml +220 -0
- package/docs/charter.D1.align.yaml +190 -0
- package/docs/charter.D2.align.yaml +234 -0
- package/docs/charter.D3.align.yaml +206 -0
- package/docs/charter.E-Docs.align.yaml +294 -0
- package/docs/charter.F1.align.yaml +193 -0
- package/docs/charter.F2.align.yaml +248 -0
- package/docs/charter.F3.align.yaml +287 -0
- package/docs/charter.G.align.yaml +174 -0
- package/docs/charter.align.yaml +111 -0
- package/docs/examples/session-report-usage.md +449 -0
- package/docs/maintenance.md +682 -0
- package/docs/playwright-mcp/350/260/203/347/240/224.md +53 -0
- package/docs/setup-guide.md +775 -0
- package/docs/tasks.A1.atomize.md +296 -0
- package/docs/tasks.A2.atomize.md +408 -0
- package/docs/tasks.A3.atomize.md +564 -0
- package/docs/tasks.A4.atomize.md +496 -0
- package/docs/tasks.B1.atomize.md +352 -0
- package/docs/tasks.B2.atomize.md +561 -0
- package/docs/tasks.B3.atomize.md +508 -0
- package/docs/tasks.B4.atomize.md +504 -0
- package/docs/tasks.C1.atomize.md +540 -0
- package/docs/tasks.C2.atomize.md +665 -0
- package/docs/tasks.C3.atomize.md +745 -0
- package/docs/tasks.C4.atomize.md +908 -0
- package/docs/tasks.C5.atomize.md +755 -0
- package/docs/tasks.D1.atomize.md +547 -0
- package/docs/tasks.D2.atomize.md +619 -0
- package/docs/tasks.D3.atomize.md +790 -0
- package/docs/tasks.E-Docs.atomize.md +1204 -0
- package/docs/tasks.atomize.md +189 -0
- package/docs/troubleshooting.md +855 -0
- package/docs//345/256/214/346/225/264/345/256/236/347/216/260/346/226/271/346/241/210.md +155 -0
- package/docs//345/274/200/345/217/221/344/273/273/345/212/241/350/256/241/345/210/222.md +110 -0
- package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226API/345/256/214/346/225/264/346/226/207/346/241/243.md +894 -0
- package/docs//345/276/256/344/277/241/345/260/217/347/250/213/345/272/217/350/207/252/345/212/250/345/214/226/345/256/214/346/225/264/346/223/215/344/275/234/346/211/213/345/206/214.md +1885 -0
- package/docs//346/216/245/345/217/243/346/226/271/346/241/210.md +565 -0
- package/docs//347/254/254/344/270/200/347/211/210/346/234/254/346/226/271/346/241/210.md +380 -0
- package/package.json +87 -0
package/README.md
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
# @creatoria/miniapp-mcp
|
|
2
|
+
|
|
3
|
+
> 🤖 Enable AI assistants to orchestrate WeChat Mini Program testing through natural language
|
|
4
|
+
|
|
5
|
+
**@creatoria/miniapp-mcp** is a production-ready MCP (Model Context Protocol) server that wraps WeChat's official `miniprogram-automator` SDK into 65 AI-friendly tools. Let LLMs like Claude control your Mini Program with simple natural language commands - from navigation and interaction to assertions and debugging.
|
|
6
|
+
|
|
7
|
+
**Why?** Traditional UI automation requires writing brittle scripts. With MCP, you describe what to test in plain English, and AI agents handle the implementation details - making test creation 10x faster and maintenance effortless.
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@creatoria/miniapp-mcp) [](https://github.com/rn1024/creatoria-miniapp-mcp) [](https://www.typescriptlang.org/) [](./LICENSE) [](https://modelcontextprotocol.io/)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 📦 Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Using npx (recommended - no installation needed)
|
|
17
|
+
npx -y @creatoria/miniapp-mcp
|
|
18
|
+
|
|
19
|
+
# Or install globally
|
|
20
|
+
npm install -g @creatoria/miniapp-mcp
|
|
21
|
+
|
|
22
|
+
# Or install locally
|
|
23
|
+
npm install @creatoria/miniapp-mcp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ✨ Core Features
|
|
29
|
+
|
|
30
|
+
- 🎯 **65 AI-Friendly Tools**: Complete coverage across 8 categories (Automator, MiniProgram, Page, Element, Assert, Snapshot, Record, Network)
|
|
31
|
+
- 🤖 **Natural Language Testing**: Describe tests in plain English, let AI write automation code
|
|
32
|
+
- 🔧 **MCP Native**: Seamlessly integrates with Claude Desktop, Cline, and any MCP client
|
|
33
|
+
- 🧪 **Test Automation**: 9 assertion tools + 6 recording tools for robust test workflows
|
|
34
|
+
- 📸 **Debug Snapshots**: Capture page/app/element state for troubleshooting
|
|
35
|
+
- 🎨 **TypeScript First**: Full type definitions, 545 tests, 100% pass rate
|
|
36
|
+
- 🔄 **Session Isolation**: Multi-session support with automatic 30-min cleanup
|
|
37
|
+
- ⚙️ **Flexible Config**: Environment variables, config files, or CLI arguments
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 📋 前置要求
|
|
42
|
+
|
|
43
|
+
- **Node.js**: >= 18.0.0
|
|
44
|
+
- **微信开发者工具**: 已安装并启用 CLI([下载地址](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html))
|
|
45
|
+
- **小程序项目**: 用于测试的微信小程序项目目录
|
|
46
|
+
- **pnpm**: 推荐使用 pnpm 作为包管理器(`npm install -g pnpm`)
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 🚀 Quickstart (< 2 minutes)
|
|
51
|
+
|
|
52
|
+
### 1. Configure MCP Client
|
|
53
|
+
|
|
54
|
+
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"mcpServers": {
|
|
59
|
+
"miniprogram": {
|
|
60
|
+
"command": "npx",
|
|
61
|
+
"args": [
|
|
62
|
+
"-y",
|
|
63
|
+
"@creatoria/miniapp-mcp",
|
|
64
|
+
"--project-path",
|
|
65
|
+
"/path/to/your/miniprogram",
|
|
66
|
+
"--port",
|
|
67
|
+
"9420"
|
|
68
|
+
],
|
|
69
|
+
"env": {}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**That's it!** Restart Claude Desktop and you're ready to go. The package will be automatically downloaded on first use.
|
|
76
|
+
|
|
77
|
+
### 2. Alternative: Using Config File
|
|
78
|
+
|
|
79
|
+
Create a `.mcp.json` in your project root:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"projectPath": "/path/to/your/miniprogram",
|
|
84
|
+
"cliPath": "/Applications/wechatwebdevtools.app/Contents/MacOS/cli",
|
|
85
|
+
"port": 9420,
|
|
86
|
+
"capabilities": ["core", "assert", "snapshot"]
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Then use simplified config:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"mcpServers": {
|
|
95
|
+
"miniprogram": {
|
|
96
|
+
"command": "npx",
|
|
97
|
+
"args": ["-y", "@creatoria/miniapp-mcp", "--config", ".mcp.json"]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
See [Setup Guide](./docs/setup-guide.md) for advanced configuration.
|
|
104
|
+
|
|
105
|
+
### 3. First Automation (Optional)
|
|
106
|
+
|
|
107
|
+
Talk to Claude in natural language:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
You: Launch my mini program and navigate to the product list page
|
|
111
|
+
|
|
112
|
+
Claude: [Calls automator.launch + miniprogram.navigate]
|
|
113
|
+
✅ Mini program launched
|
|
114
|
+
✅ Navigated to pages/product/list
|
|
115
|
+
|
|
116
|
+
You: Find the first product title and verify it contains "iPhone"
|
|
117
|
+
|
|
118
|
+
Claude: [Calls page.query + element.getText + assert.text]
|
|
119
|
+
✅ Found element with text: "iPhone 15 Pro"
|
|
120
|
+
✅ Assertion passed: text contains "iPhone"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Quick Examples
|
|
124
|
+
|
|
125
|
+
**Example 1: Navigation**
|
|
126
|
+
```javascript
|
|
127
|
+
// Launch and navigate to a page
|
|
128
|
+
await automator.launch({ projectPath: "/path/to/project" })
|
|
129
|
+
await miniprogram.navigate({ url: "/pages/home/home" })
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Example 2: Element Interaction**
|
|
133
|
+
```javascript
|
|
134
|
+
// Find element, tap it, and input text
|
|
135
|
+
const btn = await page.query({ selector: ".search-btn" })
|
|
136
|
+
await element.tap({ refId: btn.refId })
|
|
137
|
+
await element.input({ selector: ".search-input", value: "iPhone" })
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Example 3: Assertions**
|
|
141
|
+
```javascript
|
|
142
|
+
// Verify element exists and has correct text
|
|
143
|
+
await assert.exists({ selector: ".product-title" })
|
|
144
|
+
await assert.text({ selector: ".product-title", expected: "iPhone 15" })
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
📚 **Next Steps**: Check out [Usage Examples](./examples/) for complete workflows including form submission, snapshot debugging, and test recording.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 🛠️ Tool Catalog (65 Tools across 8 Categories)
|
|
152
|
+
|
|
153
|
+
### Automator (4 tools) - Connection & Lifecycle
|
|
154
|
+
|
|
155
|
+
| Tool | Description |
|
|
156
|
+
|------|-------------|
|
|
157
|
+
| `miniprogram.launch` | Launch WeChat Mini Program with automator |
|
|
158
|
+
| `miniprogram.connect` | Connect to an already running WeChat DevTools instance |
|
|
159
|
+
| `miniprogram.disconnect` | Disconnect from miniprogram but keep IDE running |
|
|
160
|
+
| `miniprogram.close` | Close current mini program session and cleanup all resources |
|
|
161
|
+
|
|
162
|
+
### MiniProgram (6 tools) - App-Level Operations
|
|
163
|
+
|
|
164
|
+
| Tool | Description |
|
|
165
|
+
|------|-------------|
|
|
166
|
+
| `miniprogram.navigate` | Navigate to a page using various navigation methods (navigateTo, redirectTo, reLaunch, switchTab, navigateBack) |
|
|
167
|
+
| `miniprogram.call.wx` | Call a WeChat API method (wx.*) in the mini program |
|
|
168
|
+
| `miniprogram.evaluate` | Evaluate JavaScript code in the mini program context |
|
|
169
|
+
| `miniprogram.screenshot` | Take a screenshot of the mini program |
|
|
170
|
+
| `miniprogram.get.page.stack` | Get the current page stack |
|
|
171
|
+
| `miniprogram.get.system.info` | Get system information |
|
|
172
|
+
|
|
173
|
+
### Page (8 tools) - Page-Level Operations
|
|
174
|
+
|
|
175
|
+
| Tool | Description |
|
|
176
|
+
|------|-------------|
|
|
177
|
+
| `page.query` | Query a single element on the page |
|
|
178
|
+
| `page.query.all` | Query all matching elements on the page |
|
|
179
|
+
| `page.wait.for` | Wait for a condition to be met (selector or timeout) |
|
|
180
|
+
| `page.get.data` | Get page data (optionally at a specific path) |
|
|
181
|
+
| `page.set.data` | Set page data |
|
|
182
|
+
| `page.call.method` | Call a method on the page |
|
|
183
|
+
| `page.get.size` | Get page size (width, height, scrollHeight) |
|
|
184
|
+
| `page.get.scroll.top` | Get page scroll position |
|
|
185
|
+
|
|
186
|
+
### Element (23 tools) - Element-Level Operations
|
|
187
|
+
|
|
188
|
+
| Tool | Description |
|
|
189
|
+
|------|-------------|
|
|
190
|
+
| `element.tap` | Tap (click) an element |
|
|
191
|
+
| `element.longpress` | Long press an element |
|
|
192
|
+
| `element.input` | Input text into an element (input/textarea only) |
|
|
193
|
+
| `element.get.text` | Get element text content |
|
|
194
|
+
| `element.get.attribute` | Get element attribute (特性) |
|
|
195
|
+
| `element.get.property` | Get element property (属性) |
|
|
196
|
+
| `element.get.value` | Get element value |
|
|
197
|
+
| `element.get.size` | Get element size (width, height) |
|
|
198
|
+
| `element.get.offset` | Get element offset (position) |
|
|
199
|
+
| `element.trigger` | Trigger an event on the element |
|
|
200
|
+
| `element.get.style` | Get element style value |
|
|
201
|
+
| `element.touchstart` | Touch start on element |
|
|
202
|
+
| `element.touchmove` | Touch move on element |
|
|
203
|
+
| `element.touchend` | Touch end on element |
|
|
204
|
+
| `element.scroll.to` | Scroll to position (ScrollView only) |
|
|
205
|
+
| `element.scroll.width` | Get scroll width (ScrollView only) |
|
|
206
|
+
| `element.scroll.height` | Get scroll height (ScrollView only) |
|
|
207
|
+
| `element.swipe.to` | Swipe to index (Swiper only) |
|
|
208
|
+
| `element.move.to` | Move to position (MovableView only) |
|
|
209
|
+
| `element.slide.to` | Slide to value (Slider only) |
|
|
210
|
+
| `element.call.context.method` | Call context method (ContextElement only) |
|
|
211
|
+
| `element.set.data` | Set data on custom element (CustomElement only) |
|
|
212
|
+
| `element.call.method` | Call method on custom element (CustomElement only) |
|
|
213
|
+
|
|
214
|
+
### Assert (9 tools) - Testing & Verification
|
|
215
|
+
|
|
216
|
+
| Tool | Description |
|
|
217
|
+
|------|-------------|
|
|
218
|
+
| `assert.exists` | Assert that an element exists on the page |
|
|
219
|
+
| `assert.not.exists` | Assert that an element does not exist on the page |
|
|
220
|
+
| `assert.text` | Assert element text equals expected value |
|
|
221
|
+
| `assert.text.contains` | Assert element text contains expected substring |
|
|
222
|
+
| `assert.value` | Assert element value equals expected value |
|
|
223
|
+
| `assert.attribute` | Assert element attribute equals expected value |
|
|
224
|
+
| `assert.property` | Assert element property equals expected value |
|
|
225
|
+
| `assert.data` | Assert page data equals expected value |
|
|
226
|
+
| `assert.visible` | Assert element is visible (has non-zero size) |
|
|
227
|
+
|
|
228
|
+
### Snapshot (3 tools) - State Capture & Debugging
|
|
229
|
+
|
|
230
|
+
| Tool | Description |
|
|
231
|
+
|------|-------------|
|
|
232
|
+
| `snapshot.page` | Capture complete page snapshot (data + screenshot) |
|
|
233
|
+
| `snapshot.full` | Capture complete application snapshot (system info + page stack + current page) |
|
|
234
|
+
| `snapshot.element` | Capture element snapshot (properties + optional screenshot) |
|
|
235
|
+
|
|
236
|
+
### Record (6 tools) - Action Recording & Replay
|
|
237
|
+
|
|
238
|
+
| Tool | Description |
|
|
239
|
+
|------|-------------|
|
|
240
|
+
| `record.start` | Start recording user actions for later replay |
|
|
241
|
+
| `record.stop` | Stop the current recording and save the sequence |
|
|
242
|
+
| `record.list` | List all saved action sequences |
|
|
243
|
+
| `record.get` | Get details of a specific sequence |
|
|
244
|
+
| `record.delete` | Delete a saved sequence |
|
|
245
|
+
| `record.replay` | Replay a recorded action sequence |
|
|
246
|
+
|
|
247
|
+
### Network (6 tools) - Network Mock & Testing
|
|
248
|
+
|
|
249
|
+
| Tool | Description |
|
|
250
|
+
|------|-------------|
|
|
251
|
+
| `network.mock.wx.method` | Mock a WeChat API method (wx.*) for testing |
|
|
252
|
+
| `network.restore.wx.method` | Restore a previously mocked WeChat API method |
|
|
253
|
+
| `network.mock.request` | Mock wx.request to return specific data (convenience wrapper) |
|
|
254
|
+
| `network.mock.request.failure` | Mock wx.request to fail with specific error |
|
|
255
|
+
| `network.restore.request` | Restore wx.request to original behavior |
|
|
256
|
+
| `network.restore.all.mocks` | Restore all mocked WeChat API methods at once |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
📚 **Documentation**:
|
|
261
|
+
- [Complete API Reference](./docs/api/) - Detailed API documentation for all 65 tools
|
|
262
|
+
- [Usage Examples](./examples/) - Real-world automation scripts
|
|
263
|
+
- [Integration Tests](./tests/integration/) - End-to-end test scenarios
|
|
264
|
+
|
|
265
|
+
## 🏗️ 项目结构
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
creatoria-miniapp-mcp/
|
|
269
|
+
├── src/ # 源代码
|
|
270
|
+
│ ├── server.ts # MCP 服务器入口
|
|
271
|
+
│ ├── cli.ts # CLI 入口
|
|
272
|
+
│ ├── types.ts # TypeScript 类型定义
|
|
273
|
+
│ ├── config/ # 配置管理
|
|
274
|
+
│ │ └── index.ts # 配置加载和验证
|
|
275
|
+
│ ├── core/ # 核心模块
|
|
276
|
+
│ │ ├── session.ts # 会话管理器
|
|
277
|
+
│ │ ├── output.ts # 输出管理器(截图、快照)
|
|
278
|
+
│ │ └── element-ref.ts # 元素引用解析器
|
|
279
|
+
│ └── tools/ # MCP 工具实现
|
|
280
|
+
│ ├── index.ts # 工具注册器(65 个工具)
|
|
281
|
+
│ ├── automator.ts # Automator 工具(4 个)
|
|
282
|
+
│ ├── miniprogram.ts # MiniProgram 工具(6 个)
|
|
283
|
+
│ ├── page.ts # Page 工具(8 个)
|
|
284
|
+
│ ├── element.ts # Element 工具(23 个)
|
|
285
|
+
│ ├── assert.ts # Assert 工具(9 个)
|
|
286
|
+
│ ├── snapshot.ts # Snapshot 工具(3 个)
|
|
287
|
+
│ └── record.ts # Record 工具(6 个)
|
|
288
|
+
│
|
|
289
|
+
├── tests/ # 测试文件
|
|
290
|
+
│ ├── unit/ # 单元测试(545 个测试)
|
|
291
|
+
│ │ ├── session.test.ts
|
|
292
|
+
│ │ ├── output.test.ts
|
|
293
|
+
│ │ ├── element-ref.test.ts
|
|
294
|
+
│ │ ├── automator.test.ts
|
|
295
|
+
│ │ ├── miniprogram.test.ts
|
|
296
|
+
│ │ ├── page.test.ts
|
|
297
|
+
│ │ ├── element.test.ts
|
|
298
|
+
│ │ ├── assert.test.ts
|
|
299
|
+
│ │ ├── snapshot.test.ts
|
|
300
|
+
│ │ ├── record.test.ts
|
|
301
|
+
│ │ └── tool-registration.test.ts
|
|
302
|
+
│ └── integration/ # 集成测试(需要测试小程序项目)
|
|
303
|
+
│
|
|
304
|
+
├── docs/ # 文档
|
|
305
|
+
│ ├── setup-guide.md # 配置指南
|
|
306
|
+
│ ├── architecture.md # 系统架构
|
|
307
|
+
│ ├── troubleshooting.md # 故障排除
|
|
308
|
+
│ ├── charter.*.yaml # 任务对齐文档
|
|
309
|
+
│ ├── tasks.*.atomize.md # 任务分解文档
|
|
310
|
+
│ └── api/ # API 参考文档
|
|
311
|
+
│ ├── README.md # API 文档索引
|
|
312
|
+
│ ├── automator.md
|
|
313
|
+
│ ├── miniprogram.md
|
|
314
|
+
│ ├── page.md
|
|
315
|
+
│ ├── element.md
|
|
316
|
+
│ ├── assert.md
|
|
317
|
+
│ └── snapshot.md
|
|
318
|
+
│
|
|
319
|
+
├── examples/ # 使用示例
|
|
320
|
+
│ ├── README.md # 示例索引
|
|
321
|
+
│ ├── 01-basic-navigation.md
|
|
322
|
+
│ ├── 02-form-interaction.md
|
|
323
|
+
│ ├── 03-assertion-testing.md
|
|
324
|
+
│ ├── 04-snapshot-debugging.md
|
|
325
|
+
│ └── 05-advanced-automation.md
|
|
326
|
+
│
|
|
327
|
+
├── scripts/ # 脚本
|
|
328
|
+
│ ├── launch-wx-devtools.sh # 启动微信开发者工具
|
|
329
|
+
│ └── setup-devtools-port.sh # 配置自动化端口
|
|
330
|
+
│
|
|
331
|
+
├── .llm/ # LLM 工作流程文档(6A 工作法)
|
|
332
|
+
│ ├── state.json # 项目状态(SSOT)
|
|
333
|
+
│ ├── prompts/ # 工作流程规范
|
|
334
|
+
│ ├── session_log/ # 会话日志
|
|
335
|
+
│ └── qa/ # 验收文档
|
|
336
|
+
│
|
|
337
|
+
├── dist/ # 构建输出
|
|
338
|
+
├── package.json # 项目配置
|
|
339
|
+
├── tsconfig.json # TypeScript 配置
|
|
340
|
+
├── jest.config.js # Jest 测试配置
|
|
341
|
+
└── README.md # 本文件
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## 📚 Documentation
|
|
347
|
+
|
|
348
|
+
### User Documentation
|
|
349
|
+
- [**Setup Guide**](./docs/setup-guide.md) - Environment setup and configuration
|
|
350
|
+
- [**API Reference**](./docs/api/) - Complete API docs for all 65 tools
|
|
351
|
+
- [**Usage Examples**](./examples/) - Real-world automation scenarios
|
|
352
|
+
- [**Troubleshooting**](./docs/troubleshooting.md) - Common issues and solutions
|
|
353
|
+
|
|
354
|
+
### Known Issues
|
|
355
|
+
- Type-only build/typecheck warnings may occur due to upstream `miniprogram-automator` type declarations. CI marks build/typecheck as non-blocking and runtime is unaffected. See `scripts/smoke-test.sh` and `.github/workflows/ci.yml` for handling details.
|
|
356
|
+
|
|
357
|
+
### Developer Documentation
|
|
358
|
+
- [**Architecture**](./docs/architecture.md) - System design and technical decisions
|
|
359
|
+
- [**Contributing Guide**](./CONTRIBUTING.md) - How to contribute to the project
|
|
360
|
+
- [**Task Breakdown**](./docs/) - Development tasks and progress tracking (35 charter + task docs)
|
|
361
|
+
|
|
362
|
+
### 6A Workflow Documentation (Internal)
|
|
363
|
+
- [`.llm/state.json`](./.llm/state.json) - Project state (Single Source of Truth)
|
|
364
|
+
- [`.llm/prompts/`](./.llm/prompts/) - 6A workflow specifications
|
|
365
|
+
- [`.llm/session_log/`](./.llm/session_log/) - Development session logs
|
|
366
|
+
- [`.llm/qa/`](./.llm/qa/) - Acceptance documentation
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## 🧪 开发
|
|
371
|
+
|
|
372
|
+
### 常用命令
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
# 构建
|
|
376
|
+
pnpm build
|
|
377
|
+
|
|
378
|
+
# 开发模式(watch)
|
|
379
|
+
pnpm dev
|
|
380
|
+
|
|
381
|
+
# 运行测试
|
|
382
|
+
pnpm test
|
|
383
|
+
|
|
384
|
+
# 运行测试(watch 模式)
|
|
385
|
+
pnpm test:watch
|
|
386
|
+
|
|
387
|
+
# 类型检查
|
|
388
|
+
pnpm typecheck
|
|
389
|
+
|
|
390
|
+
# 代码检查
|
|
391
|
+
pnpm lint
|
|
392
|
+
|
|
393
|
+
# 代码格式化
|
|
394
|
+
pnpm format
|
|
395
|
+
|
|
396
|
+
# 格式检查
|
|
397
|
+
pnpm format:check
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### 测试状态
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
$ pnpm test
|
|
404
|
+
|
|
405
|
+
Test Suites: 21 passed, 21 total
|
|
406
|
+
Tests: 545 passed, 545 total
|
|
407
|
+
Snapshots: 0 total
|
|
408
|
+
Time: ~6s
|
|
409
|
+
|
|
410
|
+
✅ 100% 测试通过率
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**Test Coverage** (545 tests total):
|
|
414
|
+
- Core modules: Session, Logger, Output, ElementRef
|
|
415
|
+
- Tool implementations: Automator, MiniProgram, Page, Element
|
|
416
|
+
- Capabilities: Assert, Snapshot, Record, Network
|
|
417
|
+
- Infrastructure: Config, Tool registration, Helpers
|
|
418
|
+
- Quality: Smoke tests, Release scripts
|
|
419
|
+
|
|
420
|
+
### 添加新工具
|
|
421
|
+
|
|
422
|
+
查看 [贡献指南](./CONTRIBUTING.md) 了解如何添加新工具。
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## 🤝 贡献
|
|
427
|
+
|
|
428
|
+
欢迎贡献!请查看 [贡献指南](./CONTRIBUTING.md) 了解:
|
|
429
|
+
|
|
430
|
+
- 6A 工作法开发流程
|
|
431
|
+
- 代码规范和测试要求
|
|
432
|
+
- Pull Request 流程
|
|
433
|
+
- 常见问题
|
|
434
|
+
|
|
435
|
+
### 贡献者
|
|
436
|
+
|
|
437
|
+
感谢所有贡献者!
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## 📄 许可证
|
|
442
|
+
|
|
443
|
+
本项目采用 [MIT License](./LICENSE) 开源协议。
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## 🔗 相关链接
|
|
448
|
+
|
|
449
|
+
- [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
|
|
450
|
+
- [miniprogram-automator 官方文档](https://developers.weixin.qq.com/miniprogram/dev/devtools/auto/)
|
|
451
|
+
- [微信小程序开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html)
|
|
452
|
+
- [Claude Desktop](https://claude.ai/download)
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## 📮 联系方式
|
|
457
|
+
|
|
458
|
+
- **Issues**: [GitHub Issues](https://github.com/your-org/creatoria-miniapp-mcp/issues)
|
|
459
|
+
- **Discussions**: [GitHub Discussions](https://github.com/your-org/creatoria-miniapp-mcp/discussions)
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
**Project Status**: ✅ Stage A-H Complete / M5 Milestone Ready (65 tools, 545 tests, CI/CD, release automation)
|
|
464
|
+
|
|
465
|
+
**Last Updated**: 2025-10-03
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
Made with ❤️ using the [6A Workflow](./docs/charter.E-Docs.align.yaml) (Align → Architect → Atomize → Approve → Automate → Assess)
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;GAEG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for creatoria-miniapp-mcp
|
|
4
|
+
*/
|
|
5
|
+
import { startServer } from './server.js';
|
|
6
|
+
import { loadConfig } from './config/loader.js';
|
|
7
|
+
/**
|
|
8
|
+
* Parse CLI arguments
|
|
9
|
+
* Supports:
|
|
10
|
+
* - --project-path <path>
|
|
11
|
+
* - --cli-path <path>
|
|
12
|
+
* - --port <number>
|
|
13
|
+
* - --capabilities <cap1,cap2,...>
|
|
14
|
+
* - --output-dir <path>
|
|
15
|
+
* - --timeout <ms>
|
|
16
|
+
* - --session-timeout <ms>
|
|
17
|
+
* - --config <path> (explicit config file)
|
|
18
|
+
*/
|
|
19
|
+
function parseCLIArgs() {
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
const cliConfig = {};
|
|
22
|
+
let configPath;
|
|
23
|
+
for (let i = 0; i < args.length; i++) {
|
|
24
|
+
const arg = args[i];
|
|
25
|
+
const nextArg = args[i + 1];
|
|
26
|
+
switch (arg) {
|
|
27
|
+
case '--project-path':
|
|
28
|
+
if (nextArg) {
|
|
29
|
+
cliConfig.projectPath = nextArg;
|
|
30
|
+
i++;
|
|
31
|
+
}
|
|
32
|
+
break;
|
|
33
|
+
case '--cli-path':
|
|
34
|
+
if (nextArg) {
|
|
35
|
+
cliConfig.cliPath = nextArg;
|
|
36
|
+
i++;
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
case '--port':
|
|
40
|
+
if (nextArg) {
|
|
41
|
+
const port = parseInt(nextArg, 10);
|
|
42
|
+
if (!isNaN(port)) {
|
|
43
|
+
cliConfig.port = port;
|
|
44
|
+
}
|
|
45
|
+
i++;
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
case '--capabilities':
|
|
49
|
+
if (nextArg) {
|
|
50
|
+
cliConfig.capabilities = nextArg.split(',').map((s) => s.trim());
|
|
51
|
+
i++;
|
|
52
|
+
}
|
|
53
|
+
break;
|
|
54
|
+
case '--output-dir':
|
|
55
|
+
if (nextArg) {
|
|
56
|
+
cliConfig.outputDir = nextArg;
|
|
57
|
+
i++;
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
case '--timeout':
|
|
61
|
+
if (nextArg) {
|
|
62
|
+
const timeout = parseInt(nextArg, 10);
|
|
63
|
+
if (!isNaN(timeout)) {
|
|
64
|
+
cliConfig.timeout = timeout;
|
|
65
|
+
}
|
|
66
|
+
i++;
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
case '--session-timeout':
|
|
70
|
+
if (nextArg) {
|
|
71
|
+
const timeout = parseInt(nextArg, 10);
|
|
72
|
+
if (!isNaN(timeout)) {
|
|
73
|
+
cliConfig.sessionTimeout = timeout;
|
|
74
|
+
}
|
|
75
|
+
i++;
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
case '--config':
|
|
79
|
+
if (nextArg) {
|
|
80
|
+
configPath = nextArg;
|
|
81
|
+
i++;
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
case '--help':
|
|
85
|
+
case '-h':
|
|
86
|
+
printHelp();
|
|
87
|
+
process.exit(0);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return { cliConfig, configPath };
|
|
92
|
+
}
|
|
93
|
+
function printHelp() {
|
|
94
|
+
console.log(`
|
|
95
|
+
creatoria-miniapp-mcp - WeChat Mini Program MCP Server
|
|
96
|
+
|
|
97
|
+
Usage:
|
|
98
|
+
creatoria-miniapp-mcp [options]
|
|
99
|
+
|
|
100
|
+
Options:
|
|
101
|
+
--project-path <path> Path to mini program project
|
|
102
|
+
--cli-path <path> Path to WeChat DevTools CLI
|
|
103
|
+
--port <number> Automation port (default: 9420)
|
|
104
|
+
--capabilities <list> Comma-separated capability list (default: core)
|
|
105
|
+
--output-dir <path> Output directory for artifacts (default: .mcp-artifacts)
|
|
106
|
+
--timeout <ms> Global timeout in milliseconds (default: 30000)
|
|
107
|
+
--session-timeout <ms> Session timeout in milliseconds (default: 1800000)
|
|
108
|
+
--config <path> Path to config file
|
|
109
|
+
--help, -h Show this help message
|
|
110
|
+
|
|
111
|
+
Configuration Priority:
|
|
112
|
+
CLI arguments > Environment variables > Config file > Defaults
|
|
113
|
+
|
|
114
|
+
Environment Variables:
|
|
115
|
+
MCP_PROJECT_PATH Project path
|
|
116
|
+
MCP_CLI_PATH CLI path
|
|
117
|
+
MCP_PORT Port number
|
|
118
|
+
MCP_CAPABILITIES Comma-separated capabilities
|
|
119
|
+
MCP_OUTPUT_DIR Output directory
|
|
120
|
+
MCP_TIMEOUT Timeout in milliseconds
|
|
121
|
+
MCP_SESSION_TIMEOUT Session timeout in milliseconds
|
|
122
|
+
|
|
123
|
+
Config File:
|
|
124
|
+
Searches for .mcp.json, mcp.config.json, or .mcp.config.json
|
|
125
|
+
in current directory and parent directories.
|
|
126
|
+
|
|
127
|
+
Example:
|
|
128
|
+
creatoria-miniapp-mcp --project-path ./my-miniprogram --port 9420
|
|
129
|
+
creatoria-miniapp-mcp --config ./custom-config.json
|
|
130
|
+
`);
|
|
131
|
+
}
|
|
132
|
+
// Parse CLI arguments and load configuration
|
|
133
|
+
const { cliConfig, configPath } = parseCLIArgs();
|
|
134
|
+
// Load full configuration from all sources
|
|
135
|
+
const config = loadConfig({
|
|
136
|
+
configPath,
|
|
137
|
+
cliConfig,
|
|
138
|
+
});
|
|
139
|
+
// Start server with merged configuration
|
|
140
|
+
startServer(config).catch((error) => {
|
|
141
|
+
console.error('Failed to start server:', error);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
});
|
|
144
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|