@pixel-normal-edit/mcp 2.0.7 → 2.0.10

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.
Files changed (51) hide show
  1. package/domains/art-tree/advanced_lessons.js +11 -11
  2. package/domains/art-tree/advanced_tools.js +12 -12
  3. package/domains/art-tree/analysis_lessons.js +32 -0
  4. package/domains/art-tree/analysis_shapes.js +146 -0
  5. package/domains/art-tree/analysis_tools.js +49 -0
  6. package/domains/art-tree/hidden_lessons.js +3 -3
  7. package/domains/art-tree/index.js +10 -0
  8. package/domains/art-tree/layer_lessons.js +32 -0
  9. package/domains/art-tree/layer_shapes.js +117 -0
  10. package/domains/art-tree/layer_tools.js +43 -0
  11. package/domains/art-tree/lessons.js +19 -19
  12. package/domains/art-tree/light_lessons.js +3 -3
  13. package/domains/art-tree/light_shapes.js +5 -5
  14. package/domains/art-tree/material_lessons.js +71 -0
  15. package/domains/art-tree/material_shapes.js +130 -0
  16. package/domains/art-tree/material_tools.js +49 -0
  17. package/domains/art-tree/perspective_lessons.js +1 -1
  18. package/domains/art-tree/perspective_tools.js +1 -1
  19. package/domains/art-tree/sky_lessons_1.js +82 -0
  20. package/domains/art-tree/sky_shapes_1.js +68 -0
  21. package/domains/art-tree/sky_tools.js +51 -0
  22. package/domains/art-tree/surface_lessons.js +7 -7
  23. package/domains/art-tree/tools.js +27 -27
  24. package/domains/art-tree/transform_lessons_1.js +2 -2
  25. package/domains/art-tree/transform_lessons_2.js +4 -4
  26. package/domains/art-tree/transform_tools.js +8 -8
  27. package/domains/art-tree/vocab_lessons.js +32 -0
  28. package/domains/art-tree/vocab_shapes.js +116 -0
  29. package/domains/art-tree/vocab_tools.js +41 -0
  30. package/index.js +4 -0
  31. package/package.json +1 -1
  32. package/rules/README.md +403 -0
  33. package/rules/index.js +34 -0
  34. package/rules/prerequisites.js +145 -0
  35. package/rules/rules.js +111 -0
  36. package/rules/workflow.js +200 -0
  37. package/tools/{anchors.js → anchor-tools.js} +1 -1
  38. package/tools/{animation.js → animation-tools.js} +1 -1
  39. package/tools/{canvas.js → canvas-tools.js} +1 -1
  40. package/tools/{colors.js → color-tools.js} +1 -1
  41. package/tools/{drawing.js → drawing-tools.js} +1 -1
  42. package/tools/{filters.js → filter-tools.js} +1 -1
  43. package/tools/{health.js → health-tools.js} +1 -1
  44. package/tools/{history.js → history-tools.js} +1 -1
  45. package/tools/index.js +31 -13
  46. package/tools/layer-tools.js +80 -0
  47. package/tools/{modes.js → mode-tools.js} +1 -1
  48. package/tools/{query.js → query-tools.js} +1 -1
  49. package/tools/{region.js → region-tools.js} +1 -1
  50. package/tools/{sprite.js → sprite-tools.js} +1 -1
  51. package/tools/{workspace.js → workspace-tools.js} +2 -3
@@ -2,7 +2,7 @@ const shapes = require('./shapes');
2
2
  const surfaceShapes = require('./surface_shapes');
3
3
 
4
4
  /**
5
- * Lesson: Surface Types (Mặt phẳng, lồi, lõm)
5
+ * Lesson: Surface Types (Flat, convex, concave)
6
6
  */
7
7
  function lessonSurfaceTypes(canvasSize = 32, color = '#2196f3') {
8
8
  const commands = [];
@@ -10,20 +10,20 @@ function lessonSurfaceTypes(canvasSize = 32, color = '#2196f3') {
10
10
  const qX = Math.floor(canvasSize / 4);
11
11
  const r = Math.floor(canvasSize * 0.15);
12
12
 
13
- // 1. Flat Plane (Mặt phẳng)
13
+ // 1. Flat Plane
14
14
  const w = Math.floor(canvasSize * 0.2);
15
15
  commands.push(shapes.drawRectangle(qX - w/2, midY - w/2, w, w, '#4caf50', false));
16
16
  // Add some grid lines to show it's flat
17
17
  commands.push(shapes.drawLine(qX, midY - w/2, qX, midY + w/2, '#4caf50'));
18
18
  commands.push(shapes.drawLine(qX - w/2, midY, qX + w/2, midY, '#4caf50'));
19
19
 
20
- // 2. Convex Surface (Mặt lồi - e.g. Dome/Sphere)
20
+ // 2. Convex Surface (e.g. Dome/Sphere)
21
21
  // We use an ellipse that curves outwards (downwards)
22
22
  commands.push(shapes.drawEllipse(qX * 2, midY, r, r, '#ff9800', false));
23
23
  // Cross contour curving DOWN (convex towards viewer)
24
24
  commands.push(shapes.drawEllipse(qX * 2, midY + Math.floor(r*0.2), r, Math.floor(r*0.3), '#ff9800', false));
25
25
 
26
- // 3. Concave Surface (Mặt lõm - e.g. Bowl)
26
+ // 3. Concave Surface (e.g. Bowl)
27
27
  // Draw the top rim of a bowl
28
28
  commands.push(shapes.drawEllipse(qX * 3, midY, r, Math.floor(r*0.3), '#9c27b0', false));
29
29
  // Draw the bottom curve (the inside of the bowl)
@@ -38,7 +38,7 @@ function lessonSurfaceTypes(canvasSize = 32, color = '#2196f3') {
38
38
  }
39
39
 
40
40
  /**
41
- * Lesson: Edge Types (Cạnh cứng vuông vức vs Cạnh mềm bo góc)
41
+ * Lesson: Edge Types (Hard sharp corners vs Soft rounded edges)
42
42
  */
43
43
  function lessonEdgeTypes(canvasSize = 32, color = '#ff5722') {
44
44
  const commands = [];
@@ -47,10 +47,10 @@ function lessonEdgeTypes(canvasSize = 32, color = '#ff5722') {
47
47
  const midY = Math.floor(canvasSize / 2);
48
48
  const w = Math.floor(canvasSize * 0.25);
49
49
 
50
- // 1. Hard Edge (Cạnh cứng - Sharp corners)
50
+ // 1. Hard Edge (Sharp corners)
51
51
  commands.push(shapes.drawRectangle(qX1 - w/2, midY - w/2, w, w, '#e91e63', false));
52
52
 
53
- // 2. Soft Edge / Transitional (Cạnh mềm / Mặt chuyển tiếp)
53
+ // 2. Soft Edge / Transitional
54
54
  // Draw a box with rounded corners (fillet)
55
55
  const r = Math.floor(w * 0.2); // Corner radius
56
56
  const rx = qX2 - w/2;
@@ -96,126 +96,126 @@ function register(server) {
96
96
  // ── Lesson Tools ──────────────────────────────────────────────────────
97
97
 
98
98
  registerTool(server, 'art_tree_lesson_lines',
99
- 'Lesson: Vẽ đường thẳng — Introduction to drawing straight lines',
99
+ 'Lesson: Lines — Introduction to drawing straight lines',
100
100
  { canvasSize: z.number().int().min(16).max(64).default(32),
101
101
  color: hexColor.default('#ff0000') },
102
102
  async (p) => {
103
103
  const commands = lessons.lessonLines(p.canvasSize, p.color);
104
104
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
105
- return { content: [{ type: 'text', text: `✓ Bài học đường thẳng hoàn thành (${commands.length} nét vẽ)` }] };
105
+ return { content: [{ type: 'text', text: `✓ Lines lesson completed (${commands.length} strokes)` }] };
106
106
  });
107
107
 
108
108
  registerTool(server, 'art_tree_lesson_squares',
109
- 'Lesson: Hình vuông & Hình chữ nhật — Understanding right angles and proportions',
109
+ 'Lesson: Squares & Rectangles — Understanding right angles and proportions',
110
110
  { canvasSize: z.number().int().min(16).max(64).default(32),
111
111
  color: hexColor.default('#1565c0') },
112
112
  async (p) => {
113
113
  const commands = lessons.lessonSquares(p.canvasSize, p.color);
114
114
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
115
- return { content: [{ type: 'text', text: `✓ Bài học hình vuông & chữ nhật hoàn thành (${commands.length} nét vẽ)` }] };
115
+ return { content: [{ type: 'text', text: `✓ Squares & Rectangles lesson completed (${commands.length} strokes)` }] };
116
116
  });
117
117
 
118
118
  registerTool(server, 'art_tree_lesson_circles',
119
- 'Lesson: Hình tròn — Learning curves and symmetry',
119
+ 'Lesson: Circles — Learning curves and symmetry',
120
120
  { canvasSize: z.number().int().min(16).max(64).default(32),
121
121
  color: hexColor.default('#e91e63') },
122
122
  async (p) => {
123
123
  const commands = lessons.lessonCircles(p.canvasSize, p.color);
124
124
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
125
- return { content: [{ type: 'text', text: `✓ Bài học hình tròn hoàn thành (${commands.length} nét vẽ)` }] };
125
+ return { content: [{ type: 'text', text: `✓ Circles lesson completed (${commands.length} strokes)` }] };
126
126
  });
127
127
 
128
128
  registerTool(server, 'art_tree_lesson_ellipses',
129
- 'Lesson: Hình elip — Understanding oval shapes and proportions',
129
+ 'Lesson: Ellipses — Understanding oval shapes and proportions',
130
130
  { canvasSize: z.number().int().min(16).max(64).default(32),
131
131
  color: hexColor.default('#9c27b0') },
132
132
  async (p) => {
133
133
  const commands = lessons.lessonEllipses(p.canvasSize, p.color);
134
134
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
135
- return { content: [{ type: 'text', text: `✓ Bài học hình elip hoàn thành (${commands.length} nét vẽ)` }] };
135
+ return { content: [{ type: 'text', text: `✓ Ellipses lesson completed (${commands.length} strokes)` }] };
136
136
  });
137
137
 
138
138
  registerTool(server, 'art_tree_lesson_triangles',
139
- 'Lesson: Hình tam giác — Three-point shapes and stability',
139
+ 'Lesson: Triangles — Three-point shapes and stability',
140
140
  { canvasSize: z.number().int().min(16).max(64).default(32),
141
141
  color: hexColor.default('#ff5722') },
142
142
  async (p) => {
143
143
  const commands = lessons.lessonTriangles(p.canvasSize, p.color);
144
144
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
145
- return { content: [{ type: 'text', text: `✓ Bài học hình tam giác hoàn thành (${commands.length} nét vẽ)` }] };
145
+ return { content: [{ type: 'text', text: `✓ Triangles lesson completed (${commands.length} strokes)` }] };
146
146
  });
147
147
 
148
148
  registerTool(server, 'art_tree_lesson_polygons',
149
- 'Lesson: Đa giác — Multi-sided shapes',
149
+ 'Lesson: Polygons — Multi-sided shapes',
150
150
  { canvasSize: z.number().int().min(16).max(64).default(32),
151
151
  color: hexColor.default('#607d8b') },
152
152
  async (p) => {
153
153
  const commands = lessons.lessonPolygons(p.canvasSize, p.color);
154
154
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
155
- return { content: [{ type: 'text', text: `✓ Bài học đa giác hoàn thành (${commands.length} nét vẽ)` }] };
155
+ return { content: [{ type: 'text', text: `✓ Polygons lesson completed (${commands.length} strokes)` }] };
156
156
  });
157
157
 
158
158
  registerTool(server, 'art_tree_lesson_composition',
159
- 'Lesson: Tổng hợp — Combining basic shapes to create simple objects (house, sun, tree)',
159
+ 'Lesson: Composition — Combining basic shapes to create simple objects (house, sun, tree)',
160
160
  { canvasSize: z.number().int().min(16).max(64).default(32) },
161
161
  async (p) => {
162
162
  const commands = lessons.lessonComposition(p.canvasSize);
163
163
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
164
- return { content: [{ type: 'text', text: `✓ Bài học tổng hợp hoàn thành (${commands.length} nét vẽ)` }] };
164
+ return { content: [{ type: 'text', text: `✓ Composition lesson completed (${commands.length} strokes)` }] };
165
165
  });
166
166
 
167
167
  registerTool(server, 'art_tree_lesson_freehand',
168
- 'Lesson: Vẽ bằng tay Luyện vẽ bằng tay, hạn chế dùng thước',
168
+ 'Lesson: Freehand DrawingPractice freehand drawing without rulers',
169
169
  { canvasSize: z.number().int().min(16).max(64).default(32), color: hexColor.default('#795548') },
170
170
  async (p) => {
171
171
  const commands = lessons.lessonFreehand(p.canvasSize, p.color);
172
172
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
173
- return { content: [{ type: 'text', text: `✓ Bài học vẽ tay hoàn thành (${commands.length} đoạn thẳng nhỏ)` }] };
173
+ return { content: [{ type: 'text', text: `✓ Freehand drawing lesson completed (${commands.length} small segments)` }] };
174
174
  });
175
175
 
176
176
  registerTool(server, 'art_tree_lesson_proportions',
177
- 'Lesson: Tỉ lệ góc Tập giữ tỉ lệ và góc (Proportions and Angles)',
177
+ 'Lesson: Proportions and AnglesPractice maintaining proportions and angles',
178
178
  { canvasSize: z.number().int().min(16).max(64).default(32), color: hexColor.default('#3f51b5') },
179
179
  async (p) => {
180
180
  const commands = lessons.lessonProportionsAndAngles(p.canvasSize, p.color);
181
181
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
182
- return { content: [{ type: 'text', text: `✓ Bài học tỉ lệ và góc hoàn thành` }] };
182
+ return { content: [{ type: 'text', text: `✓ Proportions and Angles lesson completed` }] };
183
183
  });
184
184
 
185
185
  registerTool(server, 'art_tree_lesson_curves',
186
- 'Lesson: Đường cong Đường cong C, S',
186
+ 'Lesson: CurvesC-curves and S-curves',
187
187
  { canvasSize: z.number().int().min(16).max(64).default(32), color: hexColor.default('#9c27b0') },
188
188
  async (p) => {
189
189
  const commands = lessons.lessonCurves(p.canvasSize, p.color);
190
190
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
191
- return { content: [{ type: 'text', text: `✓ Bài học đường cong C, S hoàn thành (${commands.length} nét)` }] };
191
+ return { content: [{ type: 'text', text: `✓ Curves (C, S) lesson completed (${commands.length} strokes)` }] };
192
192
  });
193
193
 
194
194
  registerTool(server, 'art_tree_lesson_spiral',
195
- 'Lesson: Xoắn ốc Vẽ đường xoắn ốc',
195
+ 'Lesson: SpiralDrawing spiral curves',
196
196
  { canvasSize: z.number().int().min(16).max(64).default(32), color: hexColor.default('#ff9800') },
197
197
  async (p) => {
198
198
  const commands = lessons.lessonSpiral(p.canvasSize, p.color);
199
199
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
200
- return { content: [{ type: 'text', text: `✓ Bài học xoắn ốc hoàn thành (${commands.length} nét)` }] };
200
+ return { content: [{ type: 'text', text: `✓ Spiral lesson completed (${commands.length} strokes)` }] };
201
201
  });
202
202
 
203
203
  registerTool(server, 'art_tree_lesson_strokes',
204
- 'Lesson: Các loại nét Nét dài, nét ngắn, nét đậm–nhạt',
204
+ 'Lesson: Stroke TypesLong strokes, short strokes, thick and thin lines',
205
205
  { canvasSize: z.number().int().min(16).max(64).default(32), color: hexColor.default('#2196f3') },
206
206
  async (p) => {
207
207
  const commands = lessons.lessonStrokes(p.canvasSize, p.color);
208
208
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
209
- return { content: [{ type: 'text', text: `✓ Bài học nét vẽ hoàn thành` }] };
209
+ return { content: [{ type: 'text', text: `✓ Strokes lesson completed` }] };
210
210
  });
211
211
 
212
212
  registerTool(server, 'art_tree_lesson_parallel_intersecting',
213
- 'Lesson: Song song & giao nhauVẽ các đường song song và đường giao nhau',
213
+ 'Lesson: Parallel & Intersecting LinesDrawing parallel and intersecting lines',
214
214
  { canvasSize: z.number().int().min(16).max(64).default(32), color: hexColor.default('#00bcd4') },
215
215
  async (p) => {
216
216
  const commands = lessons.lessonParallelAndIntersecting(p.canvasSize, p.color);
217
217
  await Promise.all(commands.map(cmd => sendCommand(cmd)));
218
- return { content: [{ type: 'text', text: `✓ Bài học song song giao nhau hoàn thành` }] };
218
+ return { content: [{ type: 'text', text: `✓ Parallel & Intersecting Lines lesson completed` }] };
219
219
  });
220
220
 
221
221
  registerTool(server, 'art_tree_lesson_catalog',
@@ -226,7 +226,7 @@ function register(server) {
226
226
  const text = catalog.map(l =>
227
227
  ` • ${l.id}: ${l.name} — ${l.description}`
228
228
  ).join('\n');
229
- return { content: [{ type: 'text', text: `📚 Danh sách bài học Art Tree:\n\n${text}` }] };
229
+ return { content: [{ type: 'text', text: `📚 Art Tree Lesson Catalog:\n\n${text}` }] };
230
230
  });
231
231
  }
232
232
 
@@ -53,7 +53,7 @@ function lessonSquash(canvasSize = 32, color = '#ff9800') {
53
53
  }
54
54
 
55
55
  /**
56
- * Lesson: Taper & Swell (Thu nhỏ hoặc phình to)
56
+ * Lesson: Taper & Swell (Narrow or bulge)
57
57
  * Cylinder -> Bottle
58
58
  */
59
59
  function lessonTaperSwell(canvasSize = 32, color = '#00bcd4') {
@@ -80,7 +80,7 @@ function lessonTaperSwell(canvasSize = 32, color = '#00bcd4') {
80
80
  }
81
81
 
82
82
  /**
83
- * Lesson: Bend (Uốn cong)
83
+ * Lesson: Bend (Curved bending)
84
84
  * Cylinder -> Bent Tube
85
85
  */
86
86
  function lessonBend(canvasSize = 32, color = '#e91e63') {
@@ -3,7 +3,7 @@ const transformShapes = require('./transform_shapes');
3
3
  const structureLessons = require('./structure_lessons');
4
4
 
5
5
  /**
6
- * Lesson: Rotate (Xoay)
6
+ * Lesson: Rotate (Rotation)
7
7
  * Analyzing how objects change when rotated around X, Y, Z axes.
8
8
  * We can reuse the Axis Orientation lesson as it perfectly demonstrates rotation.
9
9
  */
@@ -13,7 +13,7 @@ function lessonRotate(canvasSize = 32, color = '#ff5722') {
13
13
  }
14
14
 
15
15
  /**
16
- * Lesson: Cut (Cắt khối)
16
+ * Lesson: Cut (Slice a form)
17
17
  * Sphere -> Truncated Sphere (exposing internal cross-section)
18
18
  */
19
19
  function lessonCut(canvasSize = 32, color = '#8bc34a') {
@@ -32,7 +32,7 @@ function lessonCut(canvasSize = 32, color = '#8bc34a') {
32
32
  }
33
33
 
34
34
  /**
35
- * Lesson: Hollow (Khoét rỗng)
35
+ * Lesson: Hollow (Carve interior)
36
36
  * Cylinder -> Pipe/Hole
37
37
  */
38
38
  function lessonHollow(canvasSize = 32, color = '#3f51b5') {
@@ -50,7 +50,7 @@ function lessonHollow(canvasSize = 32, color = '#3f51b5') {
50
50
  }
51
51
 
52
52
  /**
53
- * Lesson: Combine (Ghép khối)
53
+ * Lesson: Combine (Merge forms)
54
54
  * Box + Cylinder (e.g., a wheel on an axle, or a tower on a base)
55
55
  */
56
56
  function lessonCombine(canvasSize = 32, color = '#607d8b') {
@@ -89,14 +89,14 @@ function register(server) {
89
89
  {},
90
90
  () => {
91
91
  const text = `📚 Transformation Lessons:
92
- • transform_stretch: Stretch/Elongate (Cầu -> Trứng)
93
- • transform_squash: Squash/Compress (Cầu -> Đĩa dẹt)
94
- • transform_taper: Taper/Swell (Trụ -> Chai)
95
- • transform_bend: Bend (Trụ -> Ống cong)
96
- • transform_rotate: Rotate (Xoay 3D)
97
- • transform_cut: Cut/Truncate (Cắt khối)
98
- • transform_hollow: Hollow out (Khoét rỗng)
99
- • transform_combine: Combine (Ghép khối)`;
92
+ • transform_stretch: Stretch/Elongate (Sphere -> Egg)
93
+ • transform_squash: Squash/Compress (Sphere -> Flat disc)
94
+ • transform_taper: Taper/Swell (Cylinder -> Bottle)
95
+ • transform_bend: Bend (Cylinder -> Bent tube)
96
+ • transform_rotate: Rotate (3D rotation analysis)
97
+ • transform_cut: Cut/Truncate (Slice a form)
98
+ • transform_hollow: Hollow out (Carve interior)
99
+ • transform_combine: Combine (Merge forms)`;
100
100
  return { content: [{ type: 'text', text }] };
101
101
  });
102
102
  }
@@ -0,0 +1,32 @@
1
+ const vocabShapes = require('./vocab_shapes');
2
+
3
+ /**
4
+ * Lesson: Visual Vocabulary - House Breakdown
5
+ * A 5-step process of recalling and drawing parts of an object.
6
+ * Users can supply the step number (1 to 5) to see the progressive breakdown.
7
+ */
8
+ function lessonVocabHouse(canvasSize = 64, step = 1) {
9
+ const cx = Math.floor(canvasSize / 2);
10
+ const cy = Math.floor(canvasSize * 0.45);
11
+
12
+ // Ensure step is between 1 and 5
13
+ const validStep = Math.max(1, Math.min(5, step));
14
+
15
+ return vocabShapes.drawHouseBreakdown(cx, cy, canvasSize, validStep);
16
+ }
17
+
18
+ function getVocabLessonCatalog() {
19
+ return [
20
+ {
21
+ id: 'vocab_house',
22
+ name: 'House Breakdown (5 Steps)',
23
+ description: 'Break down a house: Masses -> Structural -> Functional -> Identity -> Materials. Supply step=1..5',
24
+ fn: lessonVocabHouse
25
+ }
26
+ ];
27
+ }
28
+
29
+ module.exports = {
30
+ lessonVocabHouse,
31
+ getVocabLessonCatalog
32
+ };
@@ -0,0 +1,116 @@
1
+ const shapes = require('./shapes');
2
+
3
+ /**
4
+ * Draws a 5-step breakdown of a House.
5
+ * Step 1: Main Masses (Thân + Mái)
6
+ * Step 2: Structural Parts (Cột, Móng, Hiên/Bậc thềm)
7
+ * Step 3: Functional Parts (Cửa, Cửa sổ)
8
+ * Step 4: Identifying Details (Ống khói, Viền mái, Khung cửa)
9
+ * Step 5: Materials (Ván gỗ, Gạch)
10
+ */
11
+ function drawHouseBreakdown(cx, cy, scale, step) {
12
+ const commands = [];
13
+ const color = '#37474f';
14
+
15
+ const w = Math.floor(scale * 0.5);
16
+ const h = Math.floor(scale * 0.4);
17
+ const roofH = Math.floor(scale * 0.25);
18
+
19
+ const leftX = cx - Math.floor(w/2);
20
+ const rightX = cx + Math.floor(w/2);
21
+ const topY = cy;
22
+ const botY = cy + h;
23
+ const roofTipY = topY - roofH;
24
+
25
+ // STEP 1: MAIN MASSES
26
+ if (step >= 1) {
27
+ // Main Body Box
28
+ commands.push(shapes.drawRectangle(leftX, topY, w, h, color, false));
29
+ // Roof Triangle
30
+ commands.push(shapes.drawLine(leftX, topY, cx, roofTipY, color));
31
+ commands.push(shapes.drawLine(cx, roofTipY, rightX, topY, color));
32
+ }
33
+
34
+ // STEP 2: STRUCTURAL PARTS
35
+ if (step >= 2) {
36
+ // Corner Columns (Cột)
37
+ commands.push(shapes.drawLine(leftX - 4, topY, leftX - 4, botY, color));
38
+ commands.push(shapes.drawLine(rightX + 4, topY, rightX + 4, botY, color));
39
+ // Foundation (Móng)
40
+ commands.push(shapes.drawRectangle(leftX - 6, botY, w + 12, 5, color, false));
41
+ // Front Porch Steps (Bậc thềm)
42
+ const pW = Math.floor(w * 0.4);
43
+ const pX = cx - Math.floor(pW/2);
44
+ commands.push(shapes.drawRectangle(pX, botY + 5, pW, 4, color, false));
45
+ commands.push(shapes.drawRectangle(pX - 2, botY + 9, pW + 4, 4, color, false));
46
+ }
47
+
48
+ // STEP 3: FUNCTIONAL PARTS
49
+ if (step >= 3) {
50
+ // Door (Cửa ra vào)
51
+ const dW = Math.floor(w * 0.25);
52
+ const dH = Math.floor(h * 0.6);
53
+ const dX = cx - Math.floor(dW/2);
54
+ commands.push(shapes.drawRectangle(dX, botY - dH, dW, dH, color, false));
55
+
56
+ // Windows (Cửa sổ)
57
+ const winW = Math.floor(w * 0.2);
58
+ const winH = Math.floor(h * 0.35);
59
+ const winY = topY + Math.floor(h * 0.2);
60
+ // Left window
61
+ commands.push(shapes.drawRectangle(leftX + 8, winY, winW, winH, color, false));
62
+ // Right window
63
+ commands.push(shapes.drawRectangle(rightX - 8 - winW, winY, winW, winH, color, false));
64
+ }
65
+
66
+ // STEP 4: IDENTIFYING DETAILS
67
+ if (step >= 4) {
68
+ // Chimney (Ống khói)
69
+ const chimW = Math.floor(w * 0.15);
70
+ const chimX = leftX + Math.floor(w * 0.1);
71
+ const chimY = topY - Math.floor(roofH * 0.6);
72
+ commands.push(shapes.drawRectangle(chimX, chimY, chimW, Math.floor(roofH * 0.5), color, false));
73
+ commands.push(shapes.drawRectangle(chimX - 2, chimY - 4, chimW + 4, 4, color, false)); // Chimney cap
74
+
75
+ // Roof Trim (Viền mái)
76
+ commands.push(shapes.drawLine(leftX - 6, topY + 4, cx, roofTipY - 6, color));
77
+ commands.push(shapes.drawLine(cx, roofTipY - 6, rightX + 6, topY + 4, color));
78
+
79
+ // Window/Door Frames & Knobs (Khung cửa)
80
+ const winW = Math.floor(w * 0.2);
81
+ const winH = Math.floor(h * 0.35);
82
+ const winY = topY + Math.floor(h * 0.2);
83
+ // Left window cross
84
+ commands.push(shapes.drawLine(leftX + 8 + Math.floor(winW/2), winY, leftX + 8 + Math.floor(winW/2), winY + winH, color));
85
+ commands.push(shapes.drawLine(leftX + 8, winY + Math.floor(winH/2), leftX + 8 + winW, winY + Math.floor(winH/2), color));
86
+ // Right window cross
87
+ commands.push(shapes.drawLine(rightX - 8 - Math.floor(winW/2), winY, rightX - 8 - Math.floor(winW/2), winY + winH, color));
88
+ commands.push(shapes.drawLine(rightX - 8 - winW, winY + Math.floor(winH/2), rightX - 8, winY + Math.floor(winH/2), color));
89
+ // Door knob
90
+ commands.push(shapes.drawCircle(cx + Math.floor(w * 0.08), botY - Math.floor(h * 0.3), 1, color, true));
91
+ }
92
+
93
+ // STEP 5: SURFACE MATERIALS
94
+ if (step >= 5) {
95
+ const matColor = '#9e9e9e';
96
+ // Wood Planks on the main body
97
+ for (let i = 1; i < 5; i++) {
98
+ const plankY = topY + i * Math.floor(h / 5);
99
+ commands.push(shapes.drawLine(leftX + 2, plankY, rightX - 2, plankY, matColor));
100
+ }
101
+
102
+ // Brick lines on the chimney
103
+ const chimW = Math.floor(w * 0.15);
104
+ const chimX = leftX + Math.floor(w * 0.1);
105
+ const chimY = topY - Math.floor(roofH * 0.6);
106
+ commands.push(shapes.drawLine(chimX, chimY + 4, chimX + chimW, chimY + 4, matColor));
107
+ commands.push(shapes.drawLine(chimX, chimY + 8, chimX + chimW, chimY + 8, matColor));
108
+ commands.push(shapes.drawLine(chimX + 4, chimY + 4, chimX + 4, chimY + 8, matColor)); // vertical brick line
109
+ }
110
+
111
+ return commands;
112
+ }
113
+
114
+ module.exports = {
115
+ drawHouseBreakdown
116
+ };
@@ -0,0 +1,41 @@
1
+ const { z } = require('zod');
2
+ const { registerTool, sendCommand } = require('../../core/server');
3
+ const vocabLessons = require('./vocab_lessons');
4
+
5
+ /**
6
+ * Register all visual vocabulary tools on the MCP server.
7
+ * @param {McpServer} server
8
+ */
9
+ function register(server) {
10
+ registerTool(server, 'art_tree_lesson_vocab_house',
11
+ 'Lesson: Visual Vocabulary - 5-Step Breakdown of a House. Pass step (1 to 5).',
12
+ {
13
+ canvasSize: z.number().int().min(16).max(128).default(64),
14
+ step: z.number().int().min(1).max(5).describe('The breakdown step (1=Main Masses, 2=Structural, 3=Functional, 4=Identity, 5=Materials)')
15
+ },
16
+ async (p) => {
17
+ const commands = vocabLessons.lessonVocabHouse(p.canvasSize, p.step);
18
+ await Promise.all(commands.map(cmd => sendCommand(cmd)));
19
+ const steps = [
20
+ "1. Main Masses (Khối chính: Thân nhà, Mái)",
21
+ "2. Structural Parts (Bộ phận lớn: Cột, Móng, Bậc thềm)",
22
+ "3. Functional Parts (Chức năng: Cửa, Cửa sổ)",
23
+ "4. Identifying Details (Nhận diện: Ống khói, Viền mái, Khung cửa)",
24
+ "5. Surface Materials (Vật liệu: Ván gỗ, Gạch)"
25
+ ];
26
+ return { content: [{ type: 'text', text: `✓ Step ${p.step} Vocabulary breakdown completed:\n${steps[p.step - 1]}` }] };
27
+ });
28
+
29
+ registerTool(server, 'art_tree_lesson_vocab_catalog',
30
+ 'Get the catalog of all available Visual Vocabulary lessons',
31
+ {},
32
+ () => {
33
+ const catalog = vocabLessons.getVocabLessonCatalog();
34
+ const text = catalog.map(l =>
35
+ ` • ${l.id}: ${l.name} — ${l.description}`
36
+ ).join('\n');
37
+ return { content: [{ type: 'text', text: `📚 Visual Vocabulary Lessons:\n\n${text}` }] };
38
+ });
39
+ }
40
+
41
+ module.exports = { register };
package/index.js CHANGED
@@ -28,6 +28,7 @@ require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') }
28
28
  const { createServer } = require('./core/server');
29
29
  const { registerAll: registerCoreTools } = require('./tools/index');
30
30
  const { registerAll: registerArtTree } = require('./domains/art-tree/index');
31
+ const { registerAll: registerRules } = require('./rules/index');
31
32
 
32
33
  // ── Initialize ────────────────────────────────────────────────────────────
33
34
  const server = createServer();
@@ -35,6 +36,9 @@ const server = createServer();
35
36
  // ── Register Core Tools ───────────────────────────────────────────────────
36
37
  registerCoreTools(server);
37
38
 
39
+ // ── Register Rules / Workflow Tools (BẮT BUỘC: chạy trước khi vẽ) ────────
40
+ registerRules(server);
41
+
38
42
  // ── Register Domain Modules ───────────────────────────────────────────────
39
43
  registerArtTree(server);
40
44
  // Future domains: registerPixelArt(server), registerCharacterDrawing(server), etc.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixel-normal-edit/mcp",
3
- "version": "2.0.7",
3
+ "version": "2.0.10",
4
4
  "description": "MCP server for Pixel Normal Edit canvas - enables AI agents to draw pixel art",
5
5
  "main": "index.js",
6
6
  "bin": {