@mentagen/mcp 0.5.0 → 0.7.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/dist/index.js +3 -0
- package/dist/resources/index.js +93 -0
- package/dist/tools/batch-update.js +18 -6
- package/dist/tools/check-collision.js +30 -12
- package/dist/tools/create-graph.js +22 -16
- package/dist/tools/create.js +17 -15
- package/dist/tools/find-overlaps.js +24 -4
- package/dist/tools/find-position.js +97 -72
- package/dist/tools/grid-calc.js +44 -27
- package/dist/tools/index.js +55 -96
- package/dist/tools/list-nodes.js +5 -4
- package/dist/tools/list-positions.js +5 -4
- package/dist/tools/read.js +14 -1
- package/dist/tools/size-calc.js +10 -5
- package/dist/tools/update.js +21 -23
- package/dist/utils/units.js +19 -0
- package/package.json +2 -2
package/dist/tools/grid-calc.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { findCollidingNodes, findSuggestedPosition, } from '../utils/collision.js';
|
|
3
|
+
import { pixelsToUnits, unitsToPixels } from '../utils/units.js';
|
|
3
4
|
const GRID_SIZE = 16;
|
|
4
5
|
export const gridCalcSchema = z
|
|
5
6
|
.object({
|
|
@@ -9,23 +10,23 @@ export const gridCalcSchema = z
|
|
|
9
10
|
value: z
|
|
10
11
|
.number()
|
|
11
12
|
.optional()
|
|
12
|
-
.describe('Value to snap to the grid (for snap operation)'),
|
|
13
|
+
.describe('Value to snap to the grid in units (for snap operation)'),
|
|
13
14
|
position: z
|
|
14
15
|
.number()
|
|
15
16
|
.optional()
|
|
16
|
-
.describe('Current x or y position (for next_x/next_y operations)'),
|
|
17
|
+
.describe('Current x or y position in units (for next_x/next_y operations)'),
|
|
17
18
|
size: z
|
|
18
19
|
.number()
|
|
19
20
|
.optional()
|
|
20
|
-
.describe('Width or height of the current node (for next_x/next_y)'),
|
|
21
|
+
.describe('Width or height of the current node in units (for next_x/next_y)'),
|
|
21
22
|
gap: z
|
|
22
23
|
.number()
|
|
23
24
|
.optional()
|
|
24
|
-
.describe('Gap between nodes in
|
|
25
|
+
.describe('Gap between nodes in grid units. Use 6+ for connected nodes, 1 for unrelated (default: 1)'),
|
|
25
26
|
units: z
|
|
26
27
|
.number()
|
|
27
28
|
.optional()
|
|
28
|
-
.describe('Number of grid units
|
|
29
|
+
.describe('Number of grid units (for grid_units operation - deprecated, returns same value)'),
|
|
29
30
|
// Collision-aware params (optional)
|
|
30
31
|
boardId: z
|
|
31
32
|
.string()
|
|
@@ -34,19 +35,19 @@ export const gridCalcSchema = z
|
|
|
34
35
|
nodeWidth: z
|
|
35
36
|
.number()
|
|
36
37
|
.optional()
|
|
37
|
-
.describe('Width of node being placed (required with boardId)'),
|
|
38
|
+
.describe('Width of node being placed in grid units (required with boardId)'),
|
|
38
39
|
nodeHeight: z
|
|
39
40
|
.number()
|
|
40
41
|
.optional()
|
|
41
|
-
.describe('Height of node being placed (required with boardId)'),
|
|
42
|
+
.describe('Height of node being placed in grid units (required with boardId)'),
|
|
42
43
|
nodeY: z
|
|
43
44
|
.number()
|
|
44
45
|
.optional()
|
|
45
|
-
.describe('Y position of node (required for next_x collision check)'),
|
|
46
|
+
.describe('Y position of node in grid units (required for next_x collision check)'),
|
|
46
47
|
nodeX: z
|
|
47
48
|
.number()
|
|
48
49
|
.optional()
|
|
49
|
-
.describe('X position of node (required for next_y collision check)'),
|
|
50
|
+
.describe('X position of node in grid units (required for next_y collision check)'),
|
|
50
51
|
excludeNodeId: z
|
|
51
52
|
.string()
|
|
52
53
|
.optional()
|
|
@@ -85,30 +86,26 @@ export function snapToGrid(value) {
|
|
|
85
86
|
}
|
|
86
87
|
/**
|
|
87
88
|
* Calculate the next position after a node, with a gap.
|
|
88
|
-
*
|
|
89
|
+
* All inputs and output are in grid units.
|
|
89
90
|
*/
|
|
90
91
|
export function calculateNextPosition(position, size, gap) {
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Convert grid units to pixels.
|
|
95
|
-
* 1 grid unit = 16 pixels.
|
|
96
|
-
*/
|
|
97
|
-
export function gridUnitsToPixels(units) {
|
|
98
|
-
return units * GRID_SIZE;
|
|
92
|
+
return position + size + gap;
|
|
99
93
|
}
|
|
100
94
|
/**
|
|
101
95
|
* Calculate result based on operation type.
|
|
96
|
+
* All operations now work with grid units.
|
|
102
97
|
*/
|
|
103
98
|
function calculateResult(params) {
|
|
104
99
|
if (params.operation === 'snap') {
|
|
105
|
-
|
|
100
|
+
// Snap to nearest integer unit
|
|
101
|
+
return Math.round(params.value);
|
|
106
102
|
}
|
|
107
103
|
if (params.operation === 'grid_units') {
|
|
108
|
-
return
|
|
104
|
+
// Deprecated: just return the units value (identity operation)
|
|
105
|
+
return params.units;
|
|
109
106
|
}
|
|
110
107
|
// next_x or next_y
|
|
111
|
-
return calculateNextPosition(params.position, params.size, params.gap ??
|
|
108
|
+
return calculateNextPosition(params.position, params.size, params.gap ?? 1);
|
|
112
109
|
}
|
|
113
110
|
/**
|
|
114
111
|
* Build input object for result output.
|
|
@@ -156,18 +153,38 @@ function supportsCollisionCheck(operation) {
|
|
|
156
153
|
*/
|
|
157
154
|
async function checkPositionCollision(params, baseResult, client) {
|
|
158
155
|
const nodes = await client.listNodes({ boardId: params.boardId, limit: 500 });
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
156
|
+
// Convert units to pixels for collision checking
|
|
157
|
+
const xPixels = params.operation === 'next_x'
|
|
158
|
+
? unitsToPixels(baseResult.result)
|
|
159
|
+
: unitsToPixels(params.nodeX ?? 0);
|
|
160
|
+
const yPixels = params.operation === 'next_y'
|
|
161
|
+
? unitsToPixels(baseResult.result)
|
|
162
|
+
: unitsToPixels(params.nodeY ?? 0);
|
|
163
|
+
const rectPixels = {
|
|
164
|
+
x: xPixels,
|
|
165
|
+
y: yPixels,
|
|
166
|
+
width: unitsToPixels(params.nodeWidth),
|
|
167
|
+
height: unitsToPixels(params.nodeHeight),
|
|
168
|
+
};
|
|
169
|
+
const collisionResult = findCollidingNodes(rectPixels, nodes, params.excludeNodeId);
|
|
163
170
|
const collision = {
|
|
164
171
|
checked: true,
|
|
165
172
|
collides: collisionResult.collides,
|
|
166
|
-
collidingNodes: collisionResult.collidingNodes
|
|
173
|
+
collidingNodes: collisionResult.collidingNodes.map(node => ({
|
|
174
|
+
...node,
|
|
175
|
+
rect: {
|
|
176
|
+
x: pixelsToUnits(node.rect.x),
|
|
177
|
+
y: pixelsToUnits(node.rect.y),
|
|
178
|
+
width: pixelsToUnits(node.rect.width),
|
|
179
|
+
height: pixelsToUnits(node.rect.height),
|
|
180
|
+
},
|
|
181
|
+
})),
|
|
167
182
|
};
|
|
168
183
|
if (collisionResult.collides) {
|
|
169
184
|
const direction = params.operation === 'next_x' ? 'x' : 'y';
|
|
170
|
-
|
|
185
|
+
const suggestedPixels = findSuggestedPosition(xPixels, yPixels, rectPixels.width, rectPixels.height, nodes, direction, params.excludeNodeId);
|
|
186
|
+
collision.suggestedPosition =
|
|
187
|
+
suggestedPixels !== null ? pixelsToUnits(suggestedPixels) : null;
|
|
171
188
|
}
|
|
172
189
|
return collision;
|
|
173
190
|
}
|
package/dist/tools/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextpro
|
|
|
5
5
|
import { batchUpdateSchema, handleBatchUpdate } from './batch-update.js';
|
|
6
6
|
import { boardsSchema, handleBoards } from './boards.js';
|
|
7
7
|
import { checkCollisionSchema, handleCheckCollision, } from './check-collision.js';
|
|
8
|
-
import { colorsSchema, handleColors } from './colors.js';
|
|
9
8
|
import { createSchema, handleCreate } from './create.js';
|
|
10
9
|
import { createBoardSchema, handleCreateBoard } from './create-board.js';
|
|
11
10
|
import { createEdgeSchema, handleCreateEdge } from './create-edge.js';
|
|
@@ -22,11 +21,9 @@ import { handleListNodes, listNodesSchema } from './list-nodes.js';
|
|
|
22
21
|
import { handleListOrganizations, listOrganizationsSchema, } from './list-organizations.js';
|
|
23
22
|
import { handleListPositions, listPositionsSchema } from './list-positions.js';
|
|
24
23
|
import { handleListTeams, listTeamsSchema } from './list-teams.js';
|
|
25
|
-
import { handleNodeTypes, nodeTypesSchema } from './node-types.js';
|
|
26
24
|
import { handlePatchContent, patchContentSchema } from './patch-content.js';
|
|
27
25
|
import { handleRead, readSchema } from './read.js';
|
|
28
26
|
import { handleSearch, searchSchema } from './search.js';
|
|
29
|
-
import { handleSearchBoard, searchBoardSchema } from './search-board.js';
|
|
30
27
|
import { handleSearchBoards, searchBoardsSchema } from './search-boards.js';
|
|
31
28
|
import { handleSizeCalc, sizeCalcSchema } from './size-calc.js';
|
|
32
29
|
import { handleUpdate, updateSchema } from './update.js';
|
|
@@ -204,7 +201,7 @@ export function registerTools(server, client, config) {
|
|
|
204
201
|
},
|
|
205
202
|
{
|
|
206
203
|
name: 'mentagen_search_nodes',
|
|
207
|
-
description: 'Search for nodes
|
|
204
|
+
description: 'Search for nodes using semantic search. Returns matching nodes with truncated content previews and direct links. Use mentagen_read_node with the node ID to retrieve full content.',
|
|
208
205
|
inputSchema: {
|
|
209
206
|
type: 'object',
|
|
210
207
|
properties: {
|
|
@@ -234,34 +231,6 @@ export function registerTools(server, client, config) {
|
|
|
234
231
|
required: ['query'],
|
|
235
232
|
},
|
|
236
233
|
},
|
|
237
|
-
{
|
|
238
|
-
name: 'mentagen_search_board',
|
|
239
|
-
description: 'Search for nodes within a SPECIFIC board using semantic search. Use this when you know which board to search in. Returns matching nodes with truncated content previews and direct links. Use mentagen_read_node with the node ID to retrieve full content.',
|
|
240
|
-
inputSchema: {
|
|
241
|
-
type: 'object',
|
|
242
|
-
properties: {
|
|
243
|
-
boardId: {
|
|
244
|
-
type: 'string',
|
|
245
|
-
description: 'The board ID to search within (required)',
|
|
246
|
-
},
|
|
247
|
-
query: {
|
|
248
|
-
type: 'string',
|
|
249
|
-
description: 'The search query - can be a question or keywords',
|
|
250
|
-
},
|
|
251
|
-
limit: {
|
|
252
|
-
type: 'number',
|
|
253
|
-
description: 'Maximum number of results (default: 10)',
|
|
254
|
-
default: 10,
|
|
255
|
-
},
|
|
256
|
-
semanticRatio: {
|
|
257
|
-
type: 'number',
|
|
258
|
-
description: 'Balance between semantic (1.0) and keyword (0.0) search',
|
|
259
|
-
default: 0.5,
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
required: ['boardId', 'query'],
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
234
|
{
|
|
266
235
|
name: 'mentagen_read_node',
|
|
267
236
|
description: 'Read a single node by ID. Returns the full node content without truncation, unlike search results. Includes a direct link to the node.',
|
|
@@ -313,11 +282,11 @@ export function registerTools(server, client, config) {
|
|
|
313
282
|
},
|
|
314
283
|
x: {
|
|
315
284
|
type: 'number',
|
|
316
|
-
description: 'X position (
|
|
285
|
+
description: 'X position in grid units (1 unit = 16px, default: 6)',
|
|
317
286
|
},
|
|
318
287
|
y: {
|
|
319
288
|
type: 'number',
|
|
320
|
-
description: 'Y position (
|
|
289
|
+
description: 'Y position in grid units (1 unit = 16px, default: 6)',
|
|
321
290
|
},
|
|
322
291
|
width: {
|
|
323
292
|
type: 'number',
|
|
@@ -359,23 +328,23 @@ export function registerTools(server, client, config) {
|
|
|
359
328
|
},
|
|
360
329
|
color: {
|
|
361
330
|
type: 'string',
|
|
362
|
-
description: 'Node color name (
|
|
331
|
+
description: 'Node color name (see mentagen://colors resource for available colors)',
|
|
363
332
|
},
|
|
364
333
|
x: {
|
|
365
334
|
type: 'number',
|
|
366
|
-
description: 'X position
|
|
335
|
+
description: 'X position in grid units (1 unit = 16px)',
|
|
367
336
|
},
|
|
368
337
|
y: {
|
|
369
338
|
type: 'number',
|
|
370
|
-
description: 'Y position
|
|
339
|
+
description: 'Y position in grid units (1 unit = 16px)',
|
|
371
340
|
},
|
|
372
341
|
width: {
|
|
373
342
|
type: 'number',
|
|
374
|
-
description: 'Node width in
|
|
343
|
+
description: 'Node width in grid units (1 unit = 16px)',
|
|
375
344
|
},
|
|
376
345
|
height: {
|
|
377
346
|
type: 'number',
|
|
378
|
-
description: 'Node height in
|
|
347
|
+
description: 'Node height in grid units (1 unit = 16px)',
|
|
379
348
|
},
|
|
380
349
|
autoSize: {
|
|
381
350
|
type: 'boolean',
|
|
@@ -423,10 +392,22 @@ export function registerTools(server, client, config) {
|
|
|
423
392
|
name: { type: 'string', description: 'New name' },
|
|
424
393
|
content: { type: 'string', description: 'New content' },
|
|
425
394
|
color: { type: 'string', description: 'Node color' },
|
|
426
|
-
x: {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
395
|
+
x: {
|
|
396
|
+
type: 'number',
|
|
397
|
+
description: 'X position in grid units (1 unit = 16px)',
|
|
398
|
+
},
|
|
399
|
+
y: {
|
|
400
|
+
type: 'number',
|
|
401
|
+
description: 'Y position in grid units (1 unit = 16px)',
|
|
402
|
+
},
|
|
403
|
+
width: {
|
|
404
|
+
type: 'number',
|
|
405
|
+
description: 'Width in grid units (1 unit = 16px)',
|
|
406
|
+
},
|
|
407
|
+
height: {
|
|
408
|
+
type: 'number',
|
|
409
|
+
description: 'Height in grid units (1 unit = 16px)',
|
|
410
|
+
},
|
|
430
411
|
},
|
|
431
412
|
required: ['nodeId'],
|
|
432
413
|
},
|
|
@@ -563,15 +544,21 @@ export function registerTools(server, client, config) {
|
|
|
563
544
|
description: 'Node type (default: text).',
|
|
564
545
|
},
|
|
565
546
|
color: { type: 'string', description: 'Node color' },
|
|
566
|
-
x: {
|
|
567
|
-
|
|
547
|
+
x: {
|
|
548
|
+
type: 'number',
|
|
549
|
+
description: 'X position in grid units (1 unit = 16px)',
|
|
550
|
+
},
|
|
551
|
+
y: {
|
|
552
|
+
type: 'number',
|
|
553
|
+
description: 'Y position in grid units (1 unit = 16px)',
|
|
554
|
+
},
|
|
568
555
|
width: {
|
|
569
556
|
type: 'number',
|
|
570
|
-
description: 'DO NOT USE - auto-calculated from name',
|
|
557
|
+
description: 'Width in grid units (1 unit = 16px, DO NOT USE - auto-calculated from name)',
|
|
571
558
|
},
|
|
572
559
|
height: {
|
|
573
560
|
type: 'number',
|
|
574
|
-
description: 'DO NOT USE - auto-calculated from name',
|
|
561
|
+
description: 'Height in grid units (1 unit = 16px, DO NOT USE - auto-calculated from name)',
|
|
575
562
|
},
|
|
576
563
|
},
|
|
577
564
|
required: ['tempId', 'name'],
|
|
@@ -715,25 +702,9 @@ export function registerTools(server, client, config) {
|
|
|
715
702
|
required: ['boardId'],
|
|
716
703
|
},
|
|
717
704
|
},
|
|
718
|
-
{
|
|
719
|
-
name: 'mentagen_colors',
|
|
720
|
-
description: 'Get the list of available colors for nodes. Returns color names and their RGB values.',
|
|
721
|
-
inputSchema: {
|
|
722
|
-
type: 'object',
|
|
723
|
-
properties: {},
|
|
724
|
-
},
|
|
725
|
-
},
|
|
726
|
-
{
|
|
727
|
-
name: 'mentagen_node_types',
|
|
728
|
-
description: 'Get the list of supported node types with descriptions and usage guidance. Use this to understand what types of nodes can be created.',
|
|
729
|
-
inputSchema: {
|
|
730
|
-
type: 'object',
|
|
731
|
-
properties: {},
|
|
732
|
-
},
|
|
733
|
-
},
|
|
734
705
|
{
|
|
735
706
|
name: 'mentagen_grid_calc',
|
|
736
|
-
description: 'Math helper for calculating node positions
|
|
707
|
+
description: 'Math helper for calculating node positions in grid units (1 unit = 16px). Use gap=6+ for connected nodes, gap=1 for unrelated nodes. Operations: "snap" rounds to nearest integer unit, "next_x"/"next_y" calculate position after a node, "grid_units" is deprecated (returns same value).',
|
|
737
708
|
inputSchema: {
|
|
738
709
|
type: 'object',
|
|
739
710
|
properties: {
|
|
@@ -744,23 +715,23 @@ export function registerTools(server, client, config) {
|
|
|
744
715
|
},
|
|
745
716
|
value: {
|
|
746
717
|
type: 'number',
|
|
747
|
-
description: 'Value to snap to the grid (for snap operation)',
|
|
718
|
+
description: 'Value to snap to the grid in units (for snap operation)',
|
|
748
719
|
},
|
|
749
720
|
position: {
|
|
750
721
|
type: 'number',
|
|
751
|
-
description: 'Current x or y position (for next_x/next_y operations)',
|
|
722
|
+
description: 'Current x or y position in units (for next_x/next_y operations)',
|
|
752
723
|
},
|
|
753
724
|
size: {
|
|
754
725
|
type: 'number',
|
|
755
|
-
description: 'Width or height of the current node (for next_x/next_y)',
|
|
726
|
+
description: 'Width or height of the current node in units (for next_x/next_y)',
|
|
756
727
|
},
|
|
757
728
|
gap: {
|
|
758
729
|
type: 'number',
|
|
759
|
-
description: 'Gap in
|
|
730
|
+
description: 'Gap in grid units (1 unit = 16px). Use 6+ for connected nodes, 1 for unrelated (default: 1)',
|
|
760
731
|
},
|
|
761
732
|
units: {
|
|
762
733
|
type: 'number',
|
|
763
|
-
description: 'Number of grid units
|
|
734
|
+
description: 'Number of grid units (1 unit = 16px, for grid_units operation - deprecated, returns same value)',
|
|
764
735
|
},
|
|
765
736
|
boardId: {
|
|
766
737
|
type: 'string',
|
|
@@ -768,19 +739,19 @@ export function registerTools(server, client, config) {
|
|
|
768
739
|
},
|
|
769
740
|
nodeWidth: {
|
|
770
741
|
type: 'number',
|
|
771
|
-
description: 'Width of node being placed (required with boardId)',
|
|
742
|
+
description: 'Width of node being placed in grid units (1 unit = 16px, required with boardId)',
|
|
772
743
|
},
|
|
773
744
|
nodeHeight: {
|
|
774
745
|
type: 'number',
|
|
775
|
-
description: 'Height of node being placed (required with boardId)',
|
|
746
|
+
description: 'Height of node being placed in grid units (1 unit = 16px, required with boardId)',
|
|
776
747
|
},
|
|
777
748
|
nodeY: {
|
|
778
749
|
type: 'number',
|
|
779
|
-
description: 'Y position of node (for next_x collision check)',
|
|
750
|
+
description: 'Y position of node in grid units (1 unit = 16px, for next_x collision check)',
|
|
780
751
|
},
|
|
781
752
|
nodeX: {
|
|
782
753
|
type: 'number',
|
|
783
|
-
description: 'X position of node (for next_y collision check)',
|
|
754
|
+
description: 'X position of node in grid units (1 unit = 16px, for next_y collision check)',
|
|
784
755
|
},
|
|
785
756
|
excludeNodeId: {
|
|
786
757
|
type: 'string',
|
|
@@ -802,19 +773,19 @@ export function registerTools(server, client, config) {
|
|
|
802
773
|
},
|
|
803
774
|
x: {
|
|
804
775
|
type: 'number',
|
|
805
|
-
description: 'Left position of the rectangle',
|
|
776
|
+
description: 'Left position of the rectangle in grid units (1 unit = 16px)',
|
|
806
777
|
},
|
|
807
778
|
y: {
|
|
808
779
|
type: 'number',
|
|
809
|
-
description: 'Top position of the rectangle',
|
|
780
|
+
description: 'Top position of the rectangle in grid units (1 unit = 16px)',
|
|
810
781
|
},
|
|
811
782
|
width: {
|
|
812
783
|
type: 'number',
|
|
813
|
-
description: 'Width of the rectangle',
|
|
784
|
+
description: 'Width of the rectangle in grid units (1 unit = 16px)',
|
|
814
785
|
},
|
|
815
786
|
height: {
|
|
816
787
|
type: 'number',
|
|
817
|
-
description: 'Height of the rectangle',
|
|
788
|
+
description: 'Height of the rectangle in grid units (1 unit = 16px)',
|
|
818
789
|
},
|
|
819
790
|
excludeNodeId: {
|
|
820
791
|
type: 'string',
|
|
@@ -840,7 +811,7 @@ export function registerTools(server, client, config) {
|
|
|
840
811
|
},
|
|
841
812
|
{
|
|
842
813
|
name: 'mentagen_find_position',
|
|
843
|
-
description: 'Find a valid non-colliding position for a new node. IMPORTANT: Use gap=
|
|
814
|
+
description: 'Find a valid non-colliding position for a new node. IMPORTANT: Use gap=6+ (96px+) when nodes will be connected by edges, otherwise gap=1 (16px) is fine for unrelated nodes. All positions are in grid units (1 unit = 16px).',
|
|
844
815
|
inputSchema: {
|
|
845
816
|
type: 'object',
|
|
846
817
|
properties: {
|
|
@@ -850,11 +821,11 @@ export function registerTools(server, client, config) {
|
|
|
850
821
|
},
|
|
851
822
|
width: {
|
|
852
823
|
type: 'number',
|
|
853
|
-
description: 'Width of the node to place',
|
|
824
|
+
description: 'Width of the node to place in grid units (1 unit = 16px)',
|
|
854
825
|
},
|
|
855
826
|
height: {
|
|
856
827
|
type: 'number',
|
|
857
|
-
description: 'Height of the node to place',
|
|
828
|
+
description: 'Height of the node to place in grid units (1 unit = 16px)',
|
|
858
829
|
},
|
|
859
830
|
anchorNodeId: {
|
|
860
831
|
type: 'string',
|
|
@@ -867,15 +838,15 @@ export function registerTools(server, client, config) {
|
|
|
867
838
|
},
|
|
868
839
|
gap: {
|
|
869
840
|
type: 'number',
|
|
870
|
-
description: 'Gap between nodes in
|
|
841
|
+
description: 'Gap between nodes in grid units (1 unit = 16px). Use 6+ for connected nodes (edges), 1 for unrelated nodes',
|
|
871
842
|
},
|
|
872
843
|
startX: {
|
|
873
844
|
type: 'number',
|
|
874
|
-
description: 'Explicit start X (ignored if anchorNodeId provided)',
|
|
845
|
+
description: 'Explicit start X in grid units (1 unit = 16px, ignored if anchorNodeId provided)',
|
|
875
846
|
},
|
|
876
847
|
startY: {
|
|
877
848
|
type: 'number',
|
|
878
|
-
description: 'Explicit start Y (ignored if anchorNodeId provided)',
|
|
849
|
+
description: 'Explicit start Y in grid units (1 unit = 16px, ignored if anchorNodeId provided)',
|
|
879
850
|
},
|
|
880
851
|
},
|
|
881
852
|
required: ['boardId', 'width', 'height'],
|
|
@@ -883,7 +854,7 @@ export function registerTools(server, client, config) {
|
|
|
883
854
|
},
|
|
884
855
|
{
|
|
885
856
|
name: 'mentagen_size_calc',
|
|
886
|
-
description: 'Calculate recommended node dimensions based on name and type. Returns width and height values (
|
|
857
|
+
description: 'Calculate recommended node dimensions based on name and type. Returns width and height values in grid units (1 unit = 16px) sized to fit the title. Content is intentionally ignored — nodes are sized for their title with content scrollable inside.',
|
|
887
858
|
inputSchema: {
|
|
888
859
|
type: 'object',
|
|
889
860
|
properties: {
|
|
@@ -966,10 +937,6 @@ export function registerTools(server, client, config) {
|
|
|
966
937
|
const params = searchSchema.parse(args);
|
|
967
938
|
return handleSearch(client, params, config.mentagenUrl);
|
|
968
939
|
},
|
|
969
|
-
mentagen_search_board: async (args) => {
|
|
970
|
-
const params = searchBoardSchema.parse(args);
|
|
971
|
-
return handleSearchBoard(client, params, config.mentagenUrl);
|
|
972
|
-
},
|
|
973
940
|
mentagen_read_node: async (args) => {
|
|
974
941
|
const params = readSchema.parse(args);
|
|
975
942
|
return handleRead(client, params, config.mentagenUrl);
|
|
@@ -1020,14 +987,6 @@ export function registerTools(server, client, config) {
|
|
|
1020
987
|
const params = linkSchema.parse(args);
|
|
1021
988
|
return handleLink(params, config);
|
|
1022
989
|
},
|
|
1023
|
-
mentagen_colors: async (args) => {
|
|
1024
|
-
colorsSchema.parse(args);
|
|
1025
|
-
return handleColors();
|
|
1026
|
-
},
|
|
1027
|
-
mentagen_node_types: async (args) => {
|
|
1028
|
-
nodeTypesSchema.parse(args);
|
|
1029
|
-
return handleNodeTypes();
|
|
1030
|
-
},
|
|
1031
990
|
mentagen_grid_calc: async (args) => {
|
|
1032
991
|
const params = gridCalcSchema.parse(args);
|
|
1033
992
|
return handleGridCalc(params, client);
|
package/dist/tools/list-nodes.js
CHANGED
|
@@ -2,6 +2,7 @@ import Papa from 'papaparse';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { formatDate } from '../utils/ejson.js';
|
|
4
4
|
import { formatError } from '../utils/errors.js';
|
|
5
|
+
import { pixelsToUnits } from '../utils/units.js';
|
|
5
6
|
import { getNodeUrl } from '../utils/urls.js';
|
|
6
7
|
export const listNodesSchema = z.object({
|
|
7
8
|
boardId: z.string().describe('The board ID to list nodes from'),
|
|
@@ -27,10 +28,10 @@ function formatNodesTsv(nodes) {
|
|
|
27
28
|
id: n._id,
|
|
28
29
|
name: n.name,
|
|
29
30
|
type: n.type,
|
|
30
|
-
x: n.x,
|
|
31
|
-
y: n.y,
|
|
32
|
-
width: n.width,
|
|
33
|
-
height: n.height,
|
|
31
|
+
x: pixelsToUnits(n.x),
|
|
32
|
+
y: pixelsToUnits(n.y),
|
|
33
|
+
width: pixelsToUnits(n.width),
|
|
34
|
+
height: pixelsToUnits(n.height),
|
|
34
35
|
content: truncateContent(n.content ?? null, MAX_CONTENT_LENGTH),
|
|
35
36
|
updatedAt: formatDate(n.updatedAt),
|
|
36
37
|
link: n.link,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Papa from 'papaparse';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { formatError } from '../utils/errors.js';
|
|
4
|
+
import { pixelsToUnits } from '../utils/units.js';
|
|
4
5
|
export const listPositionsSchema = z.object({
|
|
5
6
|
boardId: z.string().describe('The board ID to list node positions from'),
|
|
6
7
|
limit: z
|
|
@@ -13,10 +14,10 @@ function formatPositionsTsv(nodes) {
|
|
|
13
14
|
const rows = nodes.map(n => ({
|
|
14
15
|
id: n._id,
|
|
15
16
|
name: n.name,
|
|
16
|
-
x: n.x,
|
|
17
|
-
y: n.y,
|
|
18
|
-
w: n.width,
|
|
19
|
-
h: n.height,
|
|
17
|
+
x: pixelsToUnits(n.x),
|
|
18
|
+
y: pixelsToUnits(n.y),
|
|
19
|
+
w: pixelsToUnits(n.width),
|
|
20
|
+
h: pixelsToUnits(n.height),
|
|
20
21
|
}));
|
|
21
22
|
return Papa.unparse(rows, {
|
|
22
23
|
delimiter: '\t',
|
package/dist/tools/read.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { formatError } from '../utils/errors.js';
|
|
3
|
+
import { pixelsToUnits } from '../utils/units.js';
|
|
3
4
|
import { getNodeUrl } from '../utils/urls.js';
|
|
4
5
|
export const readSchema = z.object({
|
|
5
6
|
boardId: z.string().describe('The board ID containing the node'),
|
|
@@ -13,9 +14,21 @@ export async function handleRead(client, params, baseUrl) {
|
|
|
13
14
|
});
|
|
14
15
|
// Exclude large fields that aren't useful for AI consumption
|
|
15
16
|
const { _vectors, __v, textDetections, ...nodeData } = node;
|
|
16
|
-
//
|
|
17
|
+
// Convert position fields from pixels to units
|
|
17
18
|
const response = {
|
|
18
19
|
...nodeData,
|
|
20
|
+
x: 'x' in nodeData && typeof nodeData.x === 'number'
|
|
21
|
+
? pixelsToUnits(nodeData.x)
|
|
22
|
+
: nodeData.x,
|
|
23
|
+
y: 'y' in nodeData && typeof nodeData.y === 'number'
|
|
24
|
+
? pixelsToUnits(nodeData.y)
|
|
25
|
+
: nodeData.y,
|
|
26
|
+
width: 'width' in nodeData && typeof nodeData.width === 'number'
|
|
27
|
+
? pixelsToUnits(nodeData.width)
|
|
28
|
+
: nodeData.width,
|
|
29
|
+
height: 'height' in nodeData && typeof nodeData.height === 'number'
|
|
30
|
+
? pixelsToUnits(nodeData.height)
|
|
31
|
+
: nodeData.height,
|
|
19
32
|
link: getNodeUrl(baseUrl, params.boardId, params.nodeId),
|
|
20
33
|
};
|
|
21
34
|
return {
|
package/dist/tools/size-calc.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { pixelsToUnits } from '../utils/units.js';
|
|
2
3
|
// Grid and constraint constants (from src/common/boards/constraints.ts)
|
|
4
|
+
// Values in pixels (internal calculations)
|
|
3
5
|
const GRID = 16;
|
|
4
|
-
const MIN_WIDTH = 128;
|
|
5
|
-
const MIN_HEIGHT = 64;
|
|
6
|
-
const MAX_WIDTH = 512; //
|
|
7
|
-
const MAX_HEIGHT = 512;
|
|
6
|
+
const MIN_WIDTH = 128; // 8 units
|
|
7
|
+
const MIN_HEIGHT = 64; // 4 units
|
|
8
|
+
const MAX_WIDTH = 512; // 32 units - reasonable max for auto-sizing (not the 4096 absolute max)
|
|
9
|
+
const MAX_HEIGHT = 512; // 32 units
|
|
8
10
|
// Text measurement constants (from measure-node-size.ts)
|
|
9
11
|
const MAX_AUTO_WIDTH = 400;
|
|
10
12
|
const PADDING_X = 12;
|
|
@@ -96,7 +98,10 @@ export function calculateNodeSize(name, type) {
|
|
|
96
98
|
return { width, height };
|
|
97
99
|
}
|
|
98
100
|
export function handleSizeCalc(params) {
|
|
99
|
-
const { width, height } = calculateNodeSize(params.name, params.type);
|
|
101
|
+
const { width: widthPixels, height: heightPixels } = calculateNodeSize(params.name, params.type);
|
|
102
|
+
// Convert output to units
|
|
103
|
+
const width = pixelsToUnits(widthPixels);
|
|
104
|
+
const height = pixelsToUnits(heightPixels);
|
|
100
105
|
return {
|
|
101
106
|
content: [
|
|
102
107
|
{
|