fix: rename edit_diagram type field to operation for better model compatibility (#402)

Fixes #374 - Models were confused by the `type` field name and sent
`operation` instead. This change:

- Renames DiagramOperation.type to DiagramOperation.operation across
  all files (MCP server, web app, hooks, components, system prompts)
- Adds JSON examples in tool descriptions to show correct format
- Updates all test data to use the new field name

Affected files:
- lib/utils.ts
- app/api/chat/route.ts
- hooks/use-diagram-tool-handlers.ts
- components/chat-message-display.tsx
- lib/system-prompts.ts
- packages/mcp-server/src/diagram-operations.ts
- packages/mcp-server/src/index.ts
- scripts/test-diagram-operations.mjs

MCP server version bumped to 0.1.6
This commit is contained in:
Dayuan Jiang
2025-12-25 13:19:04 +09:00
committed by GitHub
parent ed069afdea
commit 3047d19238
9 changed files with 78 additions and 62 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@next-ai-drawio/mcp-server",
"version": "0.1.5",
"version": "0.1.6",
"description": "MCP server for Next AI Draw.io - AI-powered diagram generation with real-time browser preview",
"type": "module",
"main": "dist/index.js",

View File

@@ -4,7 +4,7 @@
*/
export interface DiagramOperation {
type: "update" | "add" | "delete"
operation: "update" | "add" | "delete"
cell_id: string
new_xml?: string
}
@@ -77,7 +77,7 @@ export function applyDiagramOperations(
// Process each operation
for (const op of operations) {
if (op.type === "update") {
if (op.operation === "update") {
const existingCell = cellMap.get(op.cell_id)
if (!existingCell) {
errors.push({
@@ -129,7 +129,7 @@ export function applyDiagramOperations(
// Update the map with the new element
cellMap.set(op.cell_id, importedNode)
} else if (op.type === "add") {
} else if (op.operation === "add") {
// Check if ID already exists
if (cellMap.has(op.cell_id)) {
errors.push({
@@ -181,7 +181,7 @@ export function applyDiagramOperations(
// Add to map
cellMap.set(op.cell_id, importedNode)
} else if (op.type === "delete") {
} else if (op.operation === "delete") {
const existingCell = cellMap.get(op.cell_id)
if (!existingCell) {
errors.push({

View File

@@ -265,14 +265,22 @@ server.registerTool(
"- add: Add a new cell. Provide cell_id (new unique id) and new_xml.\n" +
"- update: Replace an existing cell by its id. Provide cell_id and complete new_xml.\n" +
"- delete: Remove a cell by its id. Only cell_id is needed.\n\n" +
"For add/update, new_xml must be a complete mxCell element including mxGeometry.",
"For add/update, new_xml must be a complete mxCell element including mxGeometry.\n\n" +
"Example - Add a rectangle:\n" +
'{"operations": [{"operation": "add", "cell_id": "rect-1", "new_xml": "<mxCell id=\\"rect-1\\" value=\\"Hello\\" style=\\"rounded=0;\\" vertex=\\"1\\" parent=\\"1\\"><mxGeometry x=\\"100\\" y=\\"100\\" width=\\"120\\" height=\\"60\\" as=\\"geometry\\"/></mxCell>"}]}\n\n' +
"Example - Update a cell:\n" +
'{"operations": [{"operation": "update", "cell_id": "3", "new_xml": "<mxCell id=\\"3\\" value=\\"New Label\\" style=\\"rounded=1;\\" vertex=\\"1\\" parent=\\"1\\"><mxGeometry x=\\"100\\" y=\\"100\\" width=\\"120\\" height=\\"60\\" as=\\"geometry\\"/></mxCell>"}]}\n\n' +
"Example - Delete a cell:\n" +
'{"operations": [{"operation": "delete", "cell_id": "rect-1"}]}',
inputSchema: {
operations: z
.array(
z.object({
type: z
operation: z
.enum(["update", "add", "delete"])
.describe("Operation type"),
.describe(
"Operation to perform: add, update, or delete",
),
cell_id: z.string().describe("The id of the mxCell"),
new_xml: z
.string()
@@ -356,13 +364,13 @@ server.registerTool(
)
if (fixed) {
log.info(
`Operation ${op.type} ${op.cell_id}: XML auto-fixed: ${fixes.join(", ")}`,
`Operation ${op.operation} ${op.cell_id}: XML auto-fixed: ${fixes.join(", ")}`,
)
return { ...op, new_xml: fixed }
}
if (!valid && error) {
log.warn(
`Operation ${op.type} ${op.cell_id}: XML validation failed: ${error}`,
`Operation ${op.operation} ${op.cell_id}: XML validation failed: ${error}`,
)
}
}