@pixel-normal-edit/mcp 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * tools.js — Art Tree: MCP Tool Registration
4
+ *
5
+ * Layer: MCP Tool API (exposes Shape API and Lesson API as MCP tools)
6
+ *
7
+ * Registers art-tree tools on the MCP server. These tools use
8
+ * the existing primitive actions (drawLine, drawRect, etc.) via
9
+ * sendCommand — they do NOT create their own drawing system.
10
+ */
11
+ const { z } = require('zod');
12
+ const { registerTool, sendCommand } = require('../../core/server');
13
+ const shapes = require('./shapes');
14
+ const lessons = require('./lessons');
15
+
16
+ const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/).describe('Hex color e.g. #ff0000');
17
+
18
+ /**
19
+ * Register all art-tree tools on the MCP server.
20
+ * @param {McpServer} server
21
+ */
22
+ function register(server) {
23
+ // ── Shape Tools ───────────────────────────────────────────────────────
24
+
25
+ registerTool(server, 'art_tree_draw_line',
26
+ 'Draw a straight line between two points (Art Tree shape lesson)',
27
+ { x0: z.number().int(), y0: z.number().int(), x1: z.number().int(), y1: z.number().int(), color: hexColor },
28
+ (p) => shapes.drawLine(p.x0, p.y0, p.x1, p.y1, p.color));
29
+
30
+ registerTool(server, 'art_tree_draw_square',
31
+ 'Draw a square aligned to axes (Art Tree shape lesson)',
32
+ { x: z.number().int().describe('Top-left X'), y: z.number().int().describe('Top-left Y'),
33
+ size: z.number().int().min(1).describe('Side length'), color: hexColor,
34
+ filled: z.boolean().default(false) },
35
+ (p) => shapes.drawSquare(p.x, p.y, p.size, p.color, p.filled));
36
+
37
+ registerTool(server, 'art_tree_draw_rectangle',
38
+ 'Draw a rectangle aligned to axes (Art Tree shape lesson)',
39
+ { x: z.number().int().describe('Top-left X'), y: z.number().int().describe('Top-left Y'),
40
+ w: z.number().int().min(1).describe('Width'), h: z.number().int().min(1).describe('Height'),
41
+ color: hexColor, filled: z.boolean().default(false) },
42
+ (p) => shapes.drawRectangle(p.x, p.y, p.w, p.h, p.color, p.filled));
43
+
44
+ registerTool(server, 'art_tree_draw_circle',
45
+ 'Draw a circle (Art Tree shape lesson)',
46
+ { cx: z.number().int().describe('Center X'), cy: z.number().int().describe('Center Y'),
47
+ r: z.number().int().min(1).describe('Radius'), color: hexColor,
48
+ filled: z.boolean().default(false) },
49
+ (p) => shapes.drawCircle(p.cx, p.cy, p.r, p.color, p.filled));
50
+
51
+ registerTool(server, 'art_tree_draw_ellipse',
52
+ 'Draw an ellipse (Art Tree shape lesson)',
53
+ { cx: z.number().int(), cy: z.number().int(),
54
+ rx: z.number().int().min(1).describe('Horizontal radius'),
55
+ ry: z.number().int().min(1).describe('Vertical radius'),
56
+ color: hexColor, filled: z.boolean().default(false) },
57
+ (p) => shapes.drawEllipse(p.cx, p.cy, p.rx, p.ry, p.color, p.filled));
58
+
59
+ registerTool(server, 'art_tree_draw_triangle',
60
+ 'Draw a triangle from three vertices (Art Tree shape lesson)',
61
+ { x1: z.number().int(), y1: z.number().int(), x2: z.number().int(), y2: z.number().int(),
62
+ x3: z.number().int(), y3: z.number().int(), color: hexColor,
63
+ filled: z.boolean().default(false) },
64
+ (p) => shapes.drawTriangle([
65
+ { x: p.x1, y: p.y1 }, { x: p.x2, y: p.y2 }, { x: p.x3, y: p.y3 }
66
+ ], p.color, p.filled));
67
+
68
+ registerTool(server, 'art_tree_draw_equilateral_triangle',
69
+ 'Draw an equilateral triangle centered at (cx, cy) (Art Tree shape lesson)',
70
+ { cx: z.number().int(), cy: z.number().int(),
71
+ sideLength: z.number().int().min(1).describe('Length of each side'),
72
+ color: hexColor, filled: z.boolean().default(false) },
73
+ (p) => shapes.drawEquilateralTriangle(p.cx, p.cy, p.sideLength, p.color, p.filled));
74
+
75
+ registerTool(server, 'art_tree_draw_regular_polygon',
76
+ 'Draw a regular polygon (Art Tree shape lesson)',
77
+ { cx: z.number().int(), cy: z.number().int(),
78
+ sides: z.number().int().min(3).max(12).describe('Number of sides (3-12)'),
79
+ radius: z.number().int().min(1).describe('Distance from center to vertices'),
80
+ color: hexColor, filled: z.boolean().default(false) },
81
+ (p) => shapes.drawRegularPolygon(p.cx, p.cy, p.sides, p.radius, p.color, p.filled));
82
+
83
+ registerTool(server, 'art_tree_draw_grid',
84
+ 'Draw a grid of squares (Art Tree foundation lesson)',
85
+ { startX: z.number().int().default(0), startY: z.number().int().default(0),
86
+ cols: z.number().int().min(1).max(32).describe('Number of columns'),
87
+ rows: z.number().int().min(1).max(32).describe('Number of rows'),
88
+ cellSize: z.number().int().min(1).max(16).describe('Size of each cell'),
89
+ color: hexColor.default('#cccccc') },
90
+ async (p) => {
91
+ const commands = shapes.drawGrid(p.startX, p.startY, p.cols, p.rows, p.cellSize, p.color);
92
+ const results = await Promise.all(commands.map(cmd => sendCommand(cmd)));
93
+ return { content: [{ type: 'text', text: `✓ Grid (${p.cols}×${p.rows}) drawn with ${commands.length} lines` }] };
94
+ });
95
+
96
+ // ── Lesson Tools ──────────────────────────────────────────────────────
97
+
98
+ registerTool(server, 'art_tree_lesson_lines',
99
+ 'Lesson: Vẽ đường thẳng — Introduction to drawing straight lines',
100
+ { canvasSize: z.number().int().min(16).max(64).default(32),
101
+ color: hexColor.default('#ff0000') },
102
+ async (p) => {
103
+ const commands = lessons.lessonLines(p.canvasSize, p.color);
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ẽ)` }] };
106
+ });
107
+
108
+ registerTool(server, 'art_tree_lesson_squares',
109
+ 'Lesson: Hình vuông & Hình chữ nhật — Understanding right angles and proportions',
110
+ { canvasSize: z.number().int().min(16).max(64).default(32),
111
+ color: hexColor.default('#1565c0') },
112
+ async (p) => {
113
+ const commands = lessons.lessonSquares(p.canvasSize, p.color);
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ẽ)` }] };
116
+ });
117
+
118
+ registerTool(server, 'art_tree_lesson_circles',
119
+ 'Lesson: Hình tròn — Learning curves and symmetry',
120
+ { canvasSize: z.number().int().min(16).max(64).default(32),
121
+ color: hexColor.default('#e91e63') },
122
+ async (p) => {
123
+ const commands = lessons.lessonCircles(p.canvasSize, p.color);
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ẽ)` }] };
126
+ });
127
+
128
+ registerTool(server, 'art_tree_lesson_ellipses',
129
+ 'Lesson: Hình elip — Understanding oval shapes and proportions',
130
+ { canvasSize: z.number().int().min(16).max(64).default(32),
131
+ color: hexColor.default('#9c27b0') },
132
+ async (p) => {
133
+ const commands = lessons.lessonEllipses(p.canvasSize, p.color);
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ẽ)` }] };
136
+ });
137
+
138
+ registerTool(server, 'art_tree_lesson_triangles',
139
+ 'Lesson: Hình tam giác — Three-point shapes and stability',
140
+ { canvasSize: z.number().int().min(16).max(64).default(32),
141
+ color: hexColor.default('#ff5722') },
142
+ async (p) => {
143
+ const commands = lessons.lessonTriangles(p.canvasSize, p.color);
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ẽ)` }] };
146
+ });
147
+
148
+ registerTool(server, 'art_tree_lesson_polygons',
149
+ 'Lesson: Đa giác — Multi-sided shapes',
150
+ { canvasSize: z.number().int().min(16).max(64).default(32),
151
+ color: hexColor.default('#607d8b') },
152
+ async (p) => {
153
+ const commands = lessons.lessonPolygons(p.canvasSize, p.color);
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ẽ)` }] };
156
+ });
157
+
158
+ registerTool(server, 'art_tree_lesson_composition',
159
+ 'Lesson: Tổng hợp — Combining basic shapes to create simple objects (house, sun, tree)',
160
+ { canvasSize: z.number().int().min(16).max(64).default(32) },
161
+ async (p) => {
162
+ const commands = lessons.lessonComposition(p.canvasSize);
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ẽ)` }] };
165
+ });
166
+
167
+ registerTool(server, 'art_tree_lesson_catalog',
168
+ 'Get the catalog of all available Art Tree lessons with descriptions',
169
+ {},
170
+ () => {
171
+ const catalog = lessons.getLessonCatalog();
172
+ const text = catalog.map(l =>
173
+ ` • ${l.id}: ${l.name} — ${l.description}`
174
+ ).join('\n');
175
+ return { content: [{ type: 'text', text: `📚 Danh sách bài học Art Tree:\n\n${text}` }] };
176
+ });
177
+ }
178
+
179
+ module.exports = { register };