@zivis/mcp 0.1.11 → 0.1.12
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/pattern-packs/zivis-public-0.2.0/manifest.json +1 -1
- package/dist/server.js +0 -5
- package/dist/tools/create-diagram.d.ts +3 -73
- package/dist/tools/create-diagram.js +8 -100
- package/dist/tools/get-diagram.d.ts +1 -1
- package/dist/tools/get-diagram.js +2 -52
- package/dist/tools/list-diagrams.d.ts +1 -1
- package/dist/tools/list-diagrams.js +2 -3
- package/dist/tools/manage-diagram.d.ts +1 -64
- package/dist/tools/manage-diagram.js +2 -211
- package/dist/tools/update-mermaid-source.d.ts +1 -1
- package/dist/tools/update-mermaid-source.js +1 -3
- package/package.json +2 -2
- package/dist/tools/generate-diagram.d.ts +0 -30
- package/dist/tools/generate-diagram.js +0 -161
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"pack_id": "zivis-public",
|
|
4
4
|
"pack_name": "ZIVIS Public Pattern Pack",
|
|
5
5
|
"version": "0.2.0",
|
|
6
|
-
"built_at": "2026-
|
|
6
|
+
"built_at": "2026-09-01T21:19:00.226Z",
|
|
7
7
|
"tier": "customer_safe",
|
|
8
8
|
"description": "ZIVIS-curated public pattern pack — capsules + inference prompts evaluated locally on the user's machine.",
|
|
9
9
|
"capsules": [
|
package/dist/server.js
CHANGED
|
@@ -73,7 +73,6 @@ import { UPDATE_ENDPOINT_NAME, UPDATE_ENDPOINT_DESCRIPTION, UPDATE_ENDPOINT_SCHE
|
|
|
73
73
|
import { MANAGE_APPLICATION_NAME, MANAGE_APPLICATION_DESCRIPTION, MANAGE_APPLICATION_SCHEMA, createManageApplicationHandler, } from "./tools/manage-application.js";
|
|
74
74
|
import { MANAGE_ENDPOINT_LIFECYCLE_NAME, MANAGE_ENDPOINT_LIFECYCLE_DESCRIPTION, MANAGE_ENDPOINT_LIFECYCLE_SCHEMA, createManageEndpointLifecycleHandler, } from "./tools/manage-endpoint-lifecycle.js";
|
|
75
75
|
import { DISCOVER_LOCAL_INFRA_NAME, DISCOVER_LOCAL_INFRA_DESCRIPTION, DISCOVER_LOCAL_INFRA_SCHEMA, createDiscoverLocalInfraHandler, } from "./tools/discover-local-infra.js";
|
|
76
|
-
import { GENERATE_DIAGRAM_NAME, GENERATE_DIAGRAM_DESCRIPTION, GENERATE_DIAGRAM_SCHEMA, createGenerateDiagramHandler, } from "./tools/generate-diagram.js";
|
|
77
76
|
import { LIST_DIAGRAMS_NAME, LIST_DIAGRAMS_DESCRIPTION, LIST_DIAGRAMS_SCHEMA, createListDiagramsHandler, } from "./tools/list-diagrams.js";
|
|
78
77
|
import { GET_DIAGRAM_NAME, GET_DIAGRAM_DESCRIPTION, GET_DIAGRAM_SCHEMA, createGetDiagramHandler, } from "./tools/get-diagram.js";
|
|
79
78
|
import { CREATE_DIAGRAM_NAME, CREATE_DIAGRAM_DESCRIPTION, CREATE_DIAGRAM_SCHEMA, createCreateDiagramHandler, } from "./tools/create-diagram.js";
|
|
@@ -215,10 +214,6 @@ export async function startServer(incoming = DEFAULT_CONFIG) {
|
|
|
215
214
|
description: DISCOVER_LOCAL_INFRA_DESCRIPTION,
|
|
216
215
|
inputSchema: DISCOVER_LOCAL_INFRA_SCHEMA,
|
|
217
216
|
}, createDiscoverLocalInfraHandler());
|
|
218
|
-
server.registerTool(GENERATE_DIAGRAM_NAME, {
|
|
219
|
-
description: GENERATE_DIAGRAM_DESCRIPTION,
|
|
220
|
-
inputSchema: GENERATE_DIAGRAM_SCHEMA,
|
|
221
|
-
}, createGenerateDiagramHandler(apiClient));
|
|
222
217
|
server.registerTool(LIST_DIAGRAMS_NAME, {
|
|
223
218
|
description: LIST_DIAGRAMS_DESCRIPTION,
|
|
224
219
|
inputSchema: LIST_DIAGRAMS_SCHEMA,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { ApiClient } from "../api-client.js";
|
|
3
3
|
export declare const CREATE_DIAGRAM_NAME = "zivis_create_diagram";
|
|
4
|
-
export declare const CREATE_DIAGRAM_DESCRIPTION = "Create a new
|
|
4
|
+
export declare const CREATE_DIAGRAM_DESCRIPTION = "Create a new diagram from Mermaid source.\n\nUse this to record system architecture diagrams, data flow diagrams, attack chains, sequence diagrams, etc. from code analysis. Content is Mermaid syntax (flowchart, sequenceDiagram, etc.) \u2014 see zivis_update_mermaid_source for editing an existing diagram's source.";
|
|
5
5
|
export declare const CREATE_DIAGRAM_SCHEMA: {
|
|
6
6
|
name: z.ZodString;
|
|
7
7
|
description: z.ZodOptional<z.ZodString>;
|
|
@@ -15,84 +15,14 @@ export declare const CREATE_DIAGRAM_SCHEMA: {
|
|
|
15
15
|
trust_boundary: "trust_boundary";
|
|
16
16
|
network: "network";
|
|
17
17
|
}>;
|
|
18
|
-
|
|
19
|
-
temp_id: z.ZodOptional<z.ZodString>;
|
|
20
|
-
name: z.ZodString;
|
|
21
|
-
description: z.ZodOptional<z.ZodString>;
|
|
22
|
-
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
23
|
-
icon: z.ZodOptional<z.ZodString>;
|
|
24
|
-
color: z.ZodOptional<z.ZodString>;
|
|
25
|
-
position_x: z.ZodOptional<z.ZodNumber>;
|
|
26
|
-
position_y: z.ZodOptional<z.ZodNumber>;
|
|
27
|
-
width: z.ZodOptional<z.ZodNumber>;
|
|
28
|
-
height: z.ZodOptional<z.ZodNumber>;
|
|
29
|
-
step_order: z.ZodOptional<z.ZodNumber>;
|
|
30
|
-
boundary_temp_id: z.ZodOptional<z.ZodString>;
|
|
31
|
-
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
32
|
-
}, z.core.$strip>>>;
|
|
33
|
-
connections: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
34
|
-
source_temp_id: z.ZodOptional<z.ZodString>;
|
|
35
|
-
target_temp_id: z.ZodOptional<z.ZodString>;
|
|
36
|
-
source_node_id: z.ZodOptional<z.ZodString>;
|
|
37
|
-
target_node_id: z.ZodOptional<z.ZodString>;
|
|
38
|
-
label: z.ZodOptional<z.ZodString>;
|
|
39
|
-
description: z.ZodOptional<z.ZodString>;
|
|
40
|
-
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
41
|
-
bidirectional: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
-
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
43
|
-
}, z.core.$strip>>>;
|
|
44
|
-
boundaries: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
45
|
-
temp_id: z.ZodOptional<z.ZodString>;
|
|
46
|
-
label: z.ZodString;
|
|
47
|
-
description: z.ZodOptional<z.ZodString>;
|
|
48
|
-
color: z.ZodOptional<z.ZodString>;
|
|
49
|
-
position_x: z.ZodOptional<z.ZodNumber>;
|
|
50
|
-
position_y: z.ZodOptional<z.ZodNumber>;
|
|
51
|
-
width: z.ZodOptional<z.ZodNumber>;
|
|
52
|
-
height: z.ZodOptional<z.ZodNumber>;
|
|
53
|
-
}, z.core.$strip>>>;
|
|
18
|
+
content: z.ZodString;
|
|
54
19
|
linked_threat_model_id: z.ZodOptional<z.ZodString>;
|
|
55
20
|
};
|
|
56
21
|
export declare function createCreateDiagramHandler(apiClient: ApiClient): (params: {
|
|
57
22
|
name: string;
|
|
58
23
|
description?: string;
|
|
59
24
|
diagram_type: string;
|
|
60
|
-
|
|
61
|
-
temp_id?: string;
|
|
62
|
-
name: string;
|
|
63
|
-
description?: string;
|
|
64
|
-
tags?: string[];
|
|
65
|
-
icon?: string;
|
|
66
|
-
color?: string;
|
|
67
|
-
position_x?: number;
|
|
68
|
-
position_y?: number;
|
|
69
|
-
width?: number;
|
|
70
|
-
height?: number;
|
|
71
|
-
step_order?: number;
|
|
72
|
-
boundary_temp_id?: string;
|
|
73
|
-
metadata?: Record<string, unknown>;
|
|
74
|
-
}>;
|
|
75
|
-
connections?: Array<{
|
|
76
|
-
source_temp_id?: string;
|
|
77
|
-
target_temp_id?: string;
|
|
78
|
-
source_node_id?: string;
|
|
79
|
-
target_node_id?: string;
|
|
80
|
-
label?: string;
|
|
81
|
-
description?: string;
|
|
82
|
-
tags?: string[];
|
|
83
|
-
bidirectional?: boolean;
|
|
84
|
-
metadata?: Record<string, unknown>;
|
|
85
|
-
}>;
|
|
86
|
-
boundaries?: Array<{
|
|
87
|
-
temp_id?: string;
|
|
88
|
-
label: string;
|
|
89
|
-
description?: string;
|
|
90
|
-
color?: string;
|
|
91
|
-
position_x?: number;
|
|
92
|
-
position_y?: number;
|
|
93
|
-
width?: number;
|
|
94
|
-
height?: number;
|
|
95
|
-
}>;
|
|
25
|
+
content: string;
|
|
96
26
|
linked_threat_model_id?: string;
|
|
97
27
|
}) => Promise<{
|
|
98
28
|
content: {
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { sanitizeResponse } from "../sanitize.js";
|
|
3
3
|
export const CREATE_DIAGRAM_NAME = "zivis_create_diagram";
|
|
4
|
-
export const CREATE_DIAGRAM_DESCRIPTION = `Create a new
|
|
4
|
+
export const CREATE_DIAGRAM_DESCRIPTION = `Create a new diagram from Mermaid source.
|
|
5
5
|
|
|
6
|
-
Use this to
|
|
7
|
-
|
|
8
|
-
**Temp IDs:** When creating nodes and connections together, assign each node a temp_id (e.g., "node_0", "node_1") and reference them in connections via source_temp_id / target_temp_id. Similarly, assign boundaries a temp_id and reference them in nodes via boundary_temp_id.
|
|
9
|
-
|
|
10
|
-
**Positioning:** Nodes default to (0,0). For readable layouts, space nodes apart (e.g., 250px horizontal, 150px vertical gaps). Default node size is 200x100px. Boundaries should be sized to contain their child nodes with padding.
|
|
11
|
-
|
|
12
|
-
**Tags:** Use tags to annotate nodes with metadata (e.g., ["database", "postgres", "port:5432", "pii"]). These are searchable and displayed in the UI.
|
|
13
|
-
|
|
14
|
-
**Colors:** Use hex colors (e.g., "#336791" for databases, "#DC382D" for caches, "#009639" for proxies).`;
|
|
6
|
+
Use this to record system architecture diagrams, data flow diagrams, attack chains, sequence diagrams, etc. from code analysis. Content is Mermaid syntax (flowchart, sequenceDiagram, etc.) — see zivis_update_mermaid_source for editing an existing diagram's source.`;
|
|
15
7
|
export const CREATE_DIAGRAM_SCHEMA = {
|
|
16
8
|
name: z
|
|
17
9
|
.string()
|
|
@@ -23,51 +15,9 @@ export const CREATE_DIAGRAM_SCHEMA = {
|
|
|
23
15
|
diagram_type: z
|
|
24
16
|
.enum(["architecture", "data_flow", "attack_chain", "sequence", "trust_boundary", "network", "deployment", "custom"])
|
|
25
17
|
.describe("Type of diagram"),
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
name: z.string().describe("Node name (e.g., 'PostgreSQL', 'API Gateway')"),
|
|
30
|
-
description: z.string().optional().describe("Node description"),
|
|
31
|
-
tags: z.array(z.string()).optional().describe("Tags (e.g., ['database', 'port:5432'])"),
|
|
32
|
-
icon: z.string().optional().describe("Icon name (e.g., 'database', 'server', 'shield', 'globe')"),
|
|
33
|
-
color: z.string().optional().describe("Hex color (e.g., '#336791')"),
|
|
34
|
-
position_x: z.number().optional().describe("X position on canvas (default 0)"),
|
|
35
|
-
position_y: z.number().optional().describe("Y position on canvas (default 0)"),
|
|
36
|
-
width: z.number().optional().describe("Node width (default 200)"),
|
|
37
|
-
height: z.number().optional().describe("Node height (default 100)"),
|
|
38
|
-
step_order: z.number().optional().describe("Step order for attack chain diagrams"),
|
|
39
|
-
boundary_temp_id: z.string().optional().describe("Temp ID of boundary this node belongs to"),
|
|
40
|
-
metadata: z.record(z.string(), z.unknown()).optional().describe("Custom metadata"),
|
|
41
|
-
}))
|
|
42
|
-
.optional()
|
|
43
|
-
.describe("Nodes to create"),
|
|
44
|
-
connections: z
|
|
45
|
-
.array(z.object({
|
|
46
|
-
source_temp_id: z.string().optional().describe("Source node temp ID"),
|
|
47
|
-
target_temp_id: z.string().optional().describe("Target node temp ID"),
|
|
48
|
-
source_node_id: z.string().optional().describe("Source node UUID (if referencing existing node)"),
|
|
49
|
-
target_node_id: z.string().optional().describe("Target node UUID (if referencing existing node)"),
|
|
50
|
-
label: z.string().optional().describe("Connection label (e.g., 'HTTPS', 'depends on')"),
|
|
51
|
-
description: z.string().optional().describe("Connection description"),
|
|
52
|
-
tags: z.array(z.string()).optional().describe("Connection tags"),
|
|
53
|
-
bidirectional: z.boolean().optional().describe("Whether connection goes both ways (default false)"),
|
|
54
|
-
metadata: z.record(z.string(), z.unknown()).optional().describe("Custom metadata"),
|
|
55
|
-
}))
|
|
56
|
-
.optional()
|
|
57
|
-
.describe("Connections between nodes"),
|
|
58
|
-
boundaries: z
|
|
59
|
-
.array(z.object({
|
|
60
|
-
temp_id: z.string().optional().describe("Temporary ID for referencing in nodes (e.g., 'boundary_0')"),
|
|
61
|
-
label: z.string().describe("Boundary label (e.g., 'DMZ', 'Internal Network')"),
|
|
62
|
-
description: z.string().optional().describe("Boundary description"),
|
|
63
|
-
color: z.string().optional().describe("Hex color"),
|
|
64
|
-
position_x: z.number().optional().describe("X position (default 0)"),
|
|
65
|
-
position_y: z.number().optional().describe("Y position (default 0)"),
|
|
66
|
-
width: z.number().optional().describe("Boundary width (default 400)"),
|
|
67
|
-
height: z.number().optional().describe("Boundary height (default 300)"),
|
|
68
|
-
}))
|
|
69
|
-
.optional()
|
|
70
|
-
.describe("Boundary groups (trust boundaries, network segments)"),
|
|
18
|
+
content: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe("Mermaid diagram source (e.g., 'flowchart TD\\n A[Client] --> B[Server]')"),
|
|
71
21
|
linked_threat_model_id: z
|
|
72
22
|
.string()
|
|
73
23
|
.optional()
|
|
@@ -76,51 +26,13 @@ export const CREATE_DIAGRAM_SCHEMA = {
|
|
|
76
26
|
export function createCreateDiagramHandler(apiClient) {
|
|
77
27
|
return async (params) => {
|
|
78
28
|
try {
|
|
79
|
-
const apiNodes = params.nodes?.map((n) => ({
|
|
80
|
-
tempId: n.temp_id,
|
|
81
|
-
name: n.name,
|
|
82
|
-
description: n.description,
|
|
83
|
-
tags: n.tags,
|
|
84
|
-
icon: n.icon,
|
|
85
|
-
color: n.color,
|
|
86
|
-
positionX: n.position_x,
|
|
87
|
-
positionY: n.position_y,
|
|
88
|
-
width: n.width,
|
|
89
|
-
height: n.height,
|
|
90
|
-
stepOrder: n.step_order,
|
|
91
|
-
boundaryTempId: n.boundary_temp_id,
|
|
92
|
-
metadata: n.metadata,
|
|
93
|
-
}));
|
|
94
|
-
const apiConnections = params.connections?.map((c) => ({
|
|
95
|
-
sourceTempId: c.source_temp_id,
|
|
96
|
-
targetTempId: c.target_temp_id,
|
|
97
|
-
sourceNodeId: c.source_node_id,
|
|
98
|
-
targetNodeId: c.target_node_id,
|
|
99
|
-
label: c.label,
|
|
100
|
-
description: c.description,
|
|
101
|
-
tags: c.tags,
|
|
102
|
-
bidirectional: c.bidirectional,
|
|
103
|
-
metadata: c.metadata,
|
|
104
|
-
}));
|
|
105
|
-
const apiBoundaries = params.boundaries?.map((b) => ({
|
|
106
|
-
tempId: b.temp_id,
|
|
107
|
-
label: b.label,
|
|
108
|
-
description: b.description,
|
|
109
|
-
color: b.color,
|
|
110
|
-
positionX: b.position_x,
|
|
111
|
-
positionY: b.position_y,
|
|
112
|
-
width: b.width,
|
|
113
|
-
height: b.height,
|
|
114
|
-
}));
|
|
115
29
|
const data = await apiClient.post("/api/diagrams", {
|
|
116
30
|
name: params.name,
|
|
117
31
|
description: params.description,
|
|
118
32
|
diagramType: params.diagram_type,
|
|
119
|
-
contentType: "
|
|
33
|
+
contentType: "mermaid",
|
|
34
|
+
content: params.content,
|
|
120
35
|
sourceType: "manual",
|
|
121
|
-
nodes: apiNodes,
|
|
122
|
-
connections: apiConnections,
|
|
123
|
-
boundaries: apiBoundaries,
|
|
124
36
|
});
|
|
125
37
|
const sanitized = sanitizeResponse(data);
|
|
126
38
|
const diagramId = sanitized.id;
|
|
@@ -135,16 +47,12 @@ export function createCreateDiagramHandler(apiClient) {
|
|
|
135
47
|
catch {
|
|
136
48
|
}
|
|
137
49
|
}
|
|
138
|
-
const nodeCount = Array.isArray(sanitized.nodes) ? sanitized.nodes.length : 0;
|
|
139
|
-
const connCount = Array.isArray(sanitized.connections) ? sanitized.connections.length : 0;
|
|
140
|
-
const boundaryCount = Array.isArray(sanitized.boundaries) ? sanitized.boundaries.length : 0;
|
|
141
50
|
const result = {
|
|
142
51
|
diagram_id: diagramId,
|
|
143
52
|
name: sanitized.name,
|
|
144
53
|
diagram_type: sanitized.diagramType,
|
|
145
|
-
stats: { nodes: nodeCount, connections: connCount, boundaries: boundaryCount },
|
|
146
54
|
linked_threat_model_id: linkedThreatModelId,
|
|
147
|
-
_instruction: "Diagram created. Use zivis_get_diagram to see full content, or zivis_manage_diagram to modify.",
|
|
55
|
+
_instruction: "Diagram created. Use zivis_get_diagram to see full content, or zivis_manage_diagram to modify metadata/links, or zivis_update_mermaid_source to change the diagram source.",
|
|
148
56
|
};
|
|
149
57
|
return {
|
|
150
58
|
content: [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { ApiClient } from "../api-client.js";
|
|
3
3
|
export declare const GET_DIAGRAM_NAME = "zivis_get_diagram";
|
|
4
|
-
export declare const GET_DIAGRAM_DESCRIPTION = "Get the full content of a diagram including
|
|
4
|
+
export declare const GET_DIAGRAM_DESCRIPTION = "Get the full content of a diagram, including its Mermaid source.\n\nUse this before modifying a diagram \u2014 you need the current Mermaid source for zivis_update_mermaid_source.";
|
|
5
5
|
export declare const GET_DIAGRAM_SCHEMA: {
|
|
6
6
|
diagram_id: z.ZodString;
|
|
7
7
|
};
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { sanitizeResponse } from "../sanitize.js";
|
|
3
3
|
export const GET_DIAGRAM_NAME = "zivis_get_diagram";
|
|
4
|
-
export const GET_DIAGRAM_DESCRIPTION = `Get the full content of a diagram including
|
|
4
|
+
export const GET_DIAGRAM_DESCRIPTION = `Get the full content of a diagram, including its Mermaid source.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
For mermaid-type diagrams, the \`content\` field contains the full Mermaid source string — use it to read or render the diagram. For canvas-type diagrams, \`content\` is null and the structure is expressed via nodes/connections/boundaries.
|
|
9
|
-
|
|
10
|
-
Use this before modifying a diagram — you need node/connection/boundary IDs for zivis_manage_diagram (canvas) or the Mermaid source for zivis_update_mermaid_source (mermaid).`;
|
|
6
|
+
Use this before modifying a diagram — you need the current Mermaid source for zivis_update_mermaid_source.`;
|
|
11
7
|
export const GET_DIAGRAM_SCHEMA = {
|
|
12
8
|
diagram_id: z
|
|
13
9
|
.string()
|
|
@@ -18,49 +14,6 @@ export function createGetDiagramHandler(apiClient) {
|
|
|
18
14
|
try {
|
|
19
15
|
const data = await apiClient.get(`/api/diagrams/${params.diagram_id}`);
|
|
20
16
|
const sanitized = sanitizeResponse(data);
|
|
21
|
-
const nodes = Array.isArray(sanitized.nodes)
|
|
22
|
-
? sanitized.nodes.map((n) => ({
|
|
23
|
-
node_id: n.id,
|
|
24
|
-
name: n.name,
|
|
25
|
-
description: n.description || null,
|
|
26
|
-
tags: n.tags || [],
|
|
27
|
-
icon: n.icon || null,
|
|
28
|
-
color: n.color || null,
|
|
29
|
-
position_x: n.positionX,
|
|
30
|
-
position_y: n.positionY,
|
|
31
|
-
width: n.width,
|
|
32
|
-
height: n.height,
|
|
33
|
-
step_order: n.stepOrder || null,
|
|
34
|
-
boundary_id: n.boundaryId || null,
|
|
35
|
-
metadata: n.metadata || null,
|
|
36
|
-
linked_finding_ids: n.linkedFindingIds || [],
|
|
37
|
-
linked_evidence_ids: n.linkedEvidenceIds || [],
|
|
38
|
-
}))
|
|
39
|
-
: [];
|
|
40
|
-
const connections = Array.isArray(sanitized.connections)
|
|
41
|
-
? sanitized.connections.map((c) => ({
|
|
42
|
-
connection_id: c.id,
|
|
43
|
-
source_node_id: c.sourceNodeId,
|
|
44
|
-
target_node_id: c.targetNodeId,
|
|
45
|
-
label: c.label || null,
|
|
46
|
-
description: c.description || null,
|
|
47
|
-
tags: c.tags || [],
|
|
48
|
-
bidirectional: c.bidirectional || false,
|
|
49
|
-
metadata: c.metadata || null,
|
|
50
|
-
}))
|
|
51
|
-
: [];
|
|
52
|
-
const boundaries = Array.isArray(sanitized.boundaries)
|
|
53
|
-
? sanitized.boundaries.map((b) => ({
|
|
54
|
-
boundary_id: b.id,
|
|
55
|
-
label: b.label,
|
|
56
|
-
description: b.description || null,
|
|
57
|
-
color: b.color || null,
|
|
58
|
-
position_x: b.positionX,
|
|
59
|
-
position_y: b.positionY,
|
|
60
|
-
width: b.width,
|
|
61
|
-
height: b.height,
|
|
62
|
-
}))
|
|
63
|
-
: [];
|
|
64
17
|
const linkedThreatModelIds = Array.isArray(sanitized.threatModelLinks)
|
|
65
18
|
? sanitized.threatModelLinks.map((l) => l.threatModelId)
|
|
66
19
|
: [];
|
|
@@ -74,9 +27,6 @@ export function createGetDiagramHandler(apiClient) {
|
|
|
74
27
|
source_type: sanitized.sourceType,
|
|
75
28
|
created_at: sanitized.createdAt,
|
|
76
29
|
updated_at: sanitized.updatedAt,
|
|
77
|
-
nodes,
|
|
78
|
-
connections,
|
|
79
|
-
boundaries,
|
|
80
30
|
linked_threat_model_ids: linkedThreatModelIds,
|
|
81
31
|
};
|
|
82
32
|
return {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { ApiClient } from "../api-client.js";
|
|
3
3
|
export declare const LIST_DIAGRAMS_NAME = "zivis_list_diagrams";
|
|
4
|
-
export declare const LIST_DIAGRAMS_DESCRIPTION = "List diagrams for your organization. Returns summary info (name, type,
|
|
4
|
+
export declare const LIST_DIAGRAMS_DESCRIPTION = "List diagrams for your organization. Returns summary info (name, type, description) for each diagram.\n\nUse this tool to find existing diagrams before modifying them. To get the full content (Mermaid source), use zivis_get_diagram with the diagram_id from this response.\n\nDiagrams can be linked to threat models. Use linked_threat_model_id to find diagrams for a specific threat model.";
|
|
5
5
|
export declare const LIST_DIAGRAMS_SCHEMA: {
|
|
6
6
|
diagram_type: z.ZodOptional<z.ZodEnum<{
|
|
7
7
|
custom: "custom";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { sanitizeResponse } from "../sanitize.js";
|
|
3
3
|
export const LIST_DIAGRAMS_NAME = "zivis_list_diagrams";
|
|
4
|
-
export const LIST_DIAGRAMS_DESCRIPTION = `List diagrams for your organization. Returns summary info (name, type,
|
|
4
|
+
export const LIST_DIAGRAMS_DESCRIPTION = `List diagrams for your organization. Returns summary info (name, type, description) for each diagram.
|
|
5
5
|
|
|
6
|
-
Use this tool to find existing diagrams before modifying them. To get the full content (
|
|
6
|
+
Use this tool to find existing diagrams before modifying them. To get the full content (Mermaid source), use zivis_get_diagram with the diagram_id from this response.
|
|
7
7
|
|
|
8
8
|
Diagrams can be linked to threat models. Use linked_threat_model_id to find diagrams for a specific threat model.`;
|
|
9
9
|
export const LIST_DIAGRAMS_SCHEMA = {
|
|
@@ -52,7 +52,6 @@ export function createListDiagramsHandler(apiClient) {
|
|
|
52
52
|
description: d.description || null,
|
|
53
53
|
created_at: d.createdAt,
|
|
54
54
|
updated_at: d.updatedAt,
|
|
55
|
-
stats: d._count || null,
|
|
56
55
|
}))
|
|
57
56
|
: sanitized.diagrams;
|
|
58
57
|
return {
|
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { ApiClient } from "../api-client.js";
|
|
3
3
|
export declare const MANAGE_DIAGRAM_NAME = "zivis_manage_diagram";
|
|
4
|
-
export declare const MANAGE_DIAGRAM_DESCRIPTION = "Modify an existing diagram: update metadata,
|
|
4
|
+
export declare const MANAGE_DIAGRAM_DESCRIPTION = "Modify an existing diagram: update metadata, delete it, or link/unlink it to a threat model.\n\nTo change a diagram's Mermaid source, use zivis_update_mermaid_source instead.\n\nActions:\n- update_metadata: Update diagram name, description, or type\n- delete_diagram: Delete the entire diagram\n- link_threat_model: Link diagram to a threat model (requires threat_model_id)\n- unlink_threat_model: Unlink from a threat model (requires threat_model_id)";
|
|
5
5
|
export declare const MANAGE_DIAGRAM_SCHEMA: {
|
|
6
6
|
diagram_id: z.ZodString;
|
|
7
7
|
action: z.ZodEnum<{
|
|
8
8
|
update_metadata: "update_metadata";
|
|
9
9
|
delete_diagram: "delete_diagram";
|
|
10
|
-
add_node: "add_node";
|
|
11
|
-
update_node: "update_node";
|
|
12
|
-
delete_node: "delete_node";
|
|
13
|
-
add_connection: "add_connection";
|
|
14
|
-
update_connection: "update_connection";
|
|
15
|
-
delete_connection: "delete_connection";
|
|
16
|
-
add_boundary: "add_boundary";
|
|
17
|
-
update_boundary: "update_boundary";
|
|
18
|
-
delete_boundary: "delete_boundary";
|
|
19
10
|
link_threat_model: "link_threat_model";
|
|
20
11
|
unlink_threat_model: "unlink_threat_model";
|
|
21
12
|
}>;
|
|
@@ -31,33 +22,6 @@ export declare const MANAGE_DIAGRAM_SCHEMA: {
|
|
|
31
22
|
trust_boundary: "trust_boundary";
|
|
32
23
|
network: "network";
|
|
33
24
|
}>>;
|
|
34
|
-
node_id: z.ZodOptional<z.ZodString>;
|
|
35
|
-
node_name: z.ZodOptional<z.ZodString>;
|
|
36
|
-
node_description: z.ZodOptional<z.ZodString>;
|
|
37
|
-
node_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
38
|
-
node_icon: z.ZodOptional<z.ZodString>;
|
|
39
|
-
node_color: z.ZodOptional<z.ZodString>;
|
|
40
|
-
position_x: z.ZodOptional<z.ZodNumber>;
|
|
41
|
-
position_y: z.ZodOptional<z.ZodNumber>;
|
|
42
|
-
width: z.ZodOptional<z.ZodNumber>;
|
|
43
|
-
height: z.ZodOptional<z.ZodNumber>;
|
|
44
|
-
step_order: z.ZodOptional<z.ZodNumber>;
|
|
45
|
-
boundary_id: z.ZodOptional<z.ZodString>;
|
|
46
|
-
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
47
|
-
connection_id: z.ZodOptional<z.ZodString>;
|
|
48
|
-
source_node_id: z.ZodOptional<z.ZodString>;
|
|
49
|
-
target_node_id: z.ZodOptional<z.ZodString>;
|
|
50
|
-
label: z.ZodOptional<z.ZodString>;
|
|
51
|
-
connection_description: z.ZodOptional<z.ZodString>;
|
|
52
|
-
connection_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
53
|
-
bidirectional: z.ZodOptional<z.ZodBoolean>;
|
|
54
|
-
boundary_label: z.ZodOptional<z.ZodString>;
|
|
55
|
-
boundary_description: z.ZodOptional<z.ZodString>;
|
|
56
|
-
boundary_color: z.ZodOptional<z.ZodString>;
|
|
57
|
-
boundary_position_x: z.ZodOptional<z.ZodNumber>;
|
|
58
|
-
boundary_position_y: z.ZodOptional<z.ZodNumber>;
|
|
59
|
-
boundary_width: z.ZodOptional<z.ZodNumber>;
|
|
60
|
-
boundary_height: z.ZodOptional<z.ZodNumber>;
|
|
61
25
|
threat_model_id: z.ZodOptional<z.ZodString>;
|
|
62
26
|
};
|
|
63
27
|
type ManageDiagramParams = {
|
|
@@ -66,33 +30,6 @@ type ManageDiagramParams = {
|
|
|
66
30
|
name?: string;
|
|
67
31
|
description?: string;
|
|
68
32
|
diagram_type?: string;
|
|
69
|
-
node_id?: string;
|
|
70
|
-
node_name?: string;
|
|
71
|
-
node_description?: string;
|
|
72
|
-
node_tags?: string[];
|
|
73
|
-
node_icon?: string;
|
|
74
|
-
node_color?: string;
|
|
75
|
-
position_x?: number;
|
|
76
|
-
position_y?: number;
|
|
77
|
-
width?: number;
|
|
78
|
-
height?: number;
|
|
79
|
-
step_order?: number;
|
|
80
|
-
boundary_id?: string;
|
|
81
|
-
metadata?: Record<string, unknown>;
|
|
82
|
-
connection_id?: string;
|
|
83
|
-
source_node_id?: string;
|
|
84
|
-
target_node_id?: string;
|
|
85
|
-
label?: string;
|
|
86
|
-
connection_description?: string;
|
|
87
|
-
connection_tags?: string[];
|
|
88
|
-
bidirectional?: boolean;
|
|
89
|
-
boundary_label?: string;
|
|
90
|
-
boundary_description?: string;
|
|
91
|
-
boundary_color?: string;
|
|
92
|
-
boundary_position_x?: number;
|
|
93
|
-
boundary_position_y?: number;
|
|
94
|
-
boundary_width?: number;
|
|
95
|
-
boundary_height?: number;
|
|
96
33
|
threat_model_id?: string;
|
|
97
34
|
};
|
|
98
35
|
export declare function createManageDiagramHandler(apiClient: ApiClient): (params: ManageDiagramParams) => Promise<{
|
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { sanitizeResponse } from "../sanitize.js";
|
|
3
3
|
export const MANAGE_DIAGRAM_NAME = "zivis_manage_diagram";
|
|
4
|
-
export const MANAGE_DIAGRAM_DESCRIPTION = `Modify an existing diagram: update metadata,
|
|
4
|
+
export const MANAGE_DIAGRAM_DESCRIPTION = `Modify an existing diagram: update metadata, delete it, or link/unlink it to a threat model.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
To change a diagram's Mermaid source, use zivis_update_mermaid_source instead.
|
|
7
7
|
|
|
8
8
|
Actions:
|
|
9
9
|
- update_metadata: Update diagram name, description, or type
|
|
10
10
|
- delete_diagram: Delete the entire diagram
|
|
11
|
-
- add_node: Add a new node (requires node_name)
|
|
12
|
-
- update_node: Update an existing node (requires node_id)
|
|
13
|
-
- delete_node: Remove a node (requires node_id)
|
|
14
|
-
- add_connection: Add a connection between two nodes (requires source_node_id, target_node_id)
|
|
15
|
-
- update_connection: Update a connection (requires connection_id)
|
|
16
|
-
- delete_connection: Remove a connection (requires connection_id)
|
|
17
|
-
- add_boundary: Add a boundary group (requires boundary_label)
|
|
18
|
-
- update_boundary: Update a boundary (requires boundary_id)
|
|
19
|
-
- delete_boundary: Remove a boundary (requires boundary_id)
|
|
20
11
|
- link_threat_model: Link diagram to a threat model (requires threat_model_id)
|
|
21
12
|
- unlink_threat_model: Unlink from a threat model (requires threat_model_id)`;
|
|
22
13
|
export const MANAGE_DIAGRAM_SCHEMA = {
|
|
@@ -27,15 +18,6 @@ export const MANAGE_DIAGRAM_SCHEMA = {
|
|
|
27
18
|
.enum([
|
|
28
19
|
"update_metadata",
|
|
29
20
|
"delete_diagram",
|
|
30
|
-
"add_node",
|
|
31
|
-
"update_node",
|
|
32
|
-
"delete_node",
|
|
33
|
-
"add_connection",
|
|
34
|
-
"update_connection",
|
|
35
|
-
"delete_connection",
|
|
36
|
-
"add_boundary",
|
|
37
|
-
"update_boundary",
|
|
38
|
-
"delete_boundary",
|
|
39
21
|
"link_threat_model",
|
|
40
22
|
"unlink_threat_model",
|
|
41
23
|
])
|
|
@@ -46,33 +28,6 @@ export const MANAGE_DIAGRAM_SCHEMA = {
|
|
|
46
28
|
.enum(["architecture", "data_flow", "attack_chain", "sequence", "trust_boundary", "network", "deployment", "custom"])
|
|
47
29
|
.optional()
|
|
48
30
|
.describe("Diagram type (update_metadata)"),
|
|
49
|
-
node_id: z.string().optional().describe("Node UUID (required for update_node, delete_node)"),
|
|
50
|
-
node_name: z.string().optional().describe("Node name (required for add_node, optional for update_node)"),
|
|
51
|
-
node_description: z.string().optional().describe("Node description"),
|
|
52
|
-
node_tags: z.array(z.string()).optional().describe("Node tags (e.g., ['database', 'port:5432'])"),
|
|
53
|
-
node_icon: z.string().optional().describe("Node icon"),
|
|
54
|
-
node_color: z.string().optional().describe("Hex color (e.g., '#336791')"),
|
|
55
|
-
position_x: z.number().optional().describe("X position on canvas"),
|
|
56
|
-
position_y: z.number().optional().describe("Y position on canvas"),
|
|
57
|
-
width: z.number().optional().describe("Width in pixels"),
|
|
58
|
-
height: z.number().optional().describe("Height in pixels"),
|
|
59
|
-
step_order: z.number().optional().describe("Step order (attack chain diagrams)"),
|
|
60
|
-
boundary_id: z.string().optional().describe("Boundary UUID to assign node to, or boundary to update/delete"),
|
|
61
|
-
metadata: z.record(z.string(), z.unknown()).optional().describe("Custom metadata JSON"),
|
|
62
|
-
connection_id: z.string().optional().describe("Connection UUID (required for update_connection, delete_connection)"),
|
|
63
|
-
source_node_id: z.string().optional().describe("Source node UUID (required for add_connection)"),
|
|
64
|
-
target_node_id: z.string().optional().describe("Target node UUID (required for add_connection)"),
|
|
65
|
-
label: z.string().optional().describe("Connection label"),
|
|
66
|
-
connection_description: z.string().optional().describe("Connection description"),
|
|
67
|
-
connection_tags: z.array(z.string()).optional().describe("Connection tags"),
|
|
68
|
-
bidirectional: z.boolean().optional().describe("Whether connection goes both ways"),
|
|
69
|
-
boundary_label: z.string().optional().describe("Boundary label (required for add_boundary)"),
|
|
70
|
-
boundary_description: z.string().optional().describe("Boundary description"),
|
|
71
|
-
boundary_color: z.string().optional().describe("Boundary hex color"),
|
|
72
|
-
boundary_position_x: z.number().optional().describe("Boundary X position"),
|
|
73
|
-
boundary_position_y: z.number().optional().describe("Boundary Y position"),
|
|
74
|
-
boundary_width: z.number().optional().describe("Boundary width"),
|
|
75
|
-
boundary_height: z.number().optional().describe("Boundary height"),
|
|
76
31
|
threat_model_id: z.string().optional().describe("Threat model UUID (link/unlink)"),
|
|
77
32
|
};
|
|
78
33
|
function errorResult(message) {
|
|
@@ -107,170 +62,6 @@ export function createManageDiagramHandler(apiClient) {
|
|
|
107
62
|
await apiClient.del(base);
|
|
108
63
|
return successResult({ action: "deleted", diagram_id });
|
|
109
64
|
}
|
|
110
|
-
case "add_node": {
|
|
111
|
-
if (!params.node_name)
|
|
112
|
-
return errorResult("node_name is required for add_node");
|
|
113
|
-
const body = {
|
|
114
|
-
name: params.node_name,
|
|
115
|
-
};
|
|
116
|
-
if (params.node_description)
|
|
117
|
-
body.description = params.node_description;
|
|
118
|
-
if (params.node_tags)
|
|
119
|
-
body.tags = params.node_tags;
|
|
120
|
-
if (params.node_icon)
|
|
121
|
-
body.icon = params.node_icon;
|
|
122
|
-
if (params.node_color)
|
|
123
|
-
body.color = params.node_color;
|
|
124
|
-
if (params.position_x !== undefined)
|
|
125
|
-
body.positionX = params.position_x;
|
|
126
|
-
if (params.position_y !== undefined)
|
|
127
|
-
body.positionY = params.position_y;
|
|
128
|
-
if (params.width !== undefined)
|
|
129
|
-
body.width = params.width;
|
|
130
|
-
if (params.height !== undefined)
|
|
131
|
-
body.height = params.height;
|
|
132
|
-
if (params.step_order !== undefined)
|
|
133
|
-
body.stepOrder = params.step_order;
|
|
134
|
-
if (params.boundary_id)
|
|
135
|
-
body.boundaryId = params.boundary_id;
|
|
136
|
-
if (params.metadata)
|
|
137
|
-
body.metadata = params.metadata;
|
|
138
|
-
const data = await apiClient.post(`${base}/nodes`, body);
|
|
139
|
-
return successResult(data);
|
|
140
|
-
}
|
|
141
|
-
case "update_node": {
|
|
142
|
-
if (!params.node_id)
|
|
143
|
-
return errorResult("node_id is required for update_node");
|
|
144
|
-
const body = {};
|
|
145
|
-
if (params.node_name)
|
|
146
|
-
body.name = params.node_name;
|
|
147
|
-
if (params.node_description !== undefined)
|
|
148
|
-
body.description = params.node_description;
|
|
149
|
-
if (params.node_tags)
|
|
150
|
-
body.tags = params.node_tags;
|
|
151
|
-
if (params.node_icon !== undefined)
|
|
152
|
-
body.icon = params.node_icon;
|
|
153
|
-
if (params.node_color !== undefined)
|
|
154
|
-
body.color = params.node_color;
|
|
155
|
-
if (params.position_x !== undefined)
|
|
156
|
-
body.positionX = params.position_x;
|
|
157
|
-
if (params.position_y !== undefined)
|
|
158
|
-
body.positionY = params.position_y;
|
|
159
|
-
if (params.width !== undefined)
|
|
160
|
-
body.width = params.width;
|
|
161
|
-
if (params.height !== undefined)
|
|
162
|
-
body.height = params.height;
|
|
163
|
-
if (params.step_order !== undefined)
|
|
164
|
-
body.stepOrder = params.step_order;
|
|
165
|
-
if (params.boundary_id !== undefined)
|
|
166
|
-
body.boundaryId = params.boundary_id;
|
|
167
|
-
if (params.metadata)
|
|
168
|
-
body.metadata = params.metadata;
|
|
169
|
-
const data = await apiClient.patch(`${base}/nodes/${params.node_id}`, body);
|
|
170
|
-
return successResult(data);
|
|
171
|
-
}
|
|
172
|
-
case "delete_node": {
|
|
173
|
-
if (!params.node_id)
|
|
174
|
-
return errorResult("node_id is required for delete_node");
|
|
175
|
-
await apiClient.del(`${base}/nodes/${params.node_id}`);
|
|
176
|
-
return successResult({ action: "deleted", node_id: params.node_id });
|
|
177
|
-
}
|
|
178
|
-
case "add_connection": {
|
|
179
|
-
if (!params.source_node_id || !params.target_node_id) {
|
|
180
|
-
return errorResult("source_node_id and target_node_id are required for add_connection");
|
|
181
|
-
}
|
|
182
|
-
const body = {
|
|
183
|
-
sourceNodeId: params.source_node_id,
|
|
184
|
-
targetNodeId: params.target_node_id,
|
|
185
|
-
};
|
|
186
|
-
if (params.label)
|
|
187
|
-
body.label = params.label;
|
|
188
|
-
if (params.connection_description)
|
|
189
|
-
body.description = params.connection_description;
|
|
190
|
-
if (params.connection_tags)
|
|
191
|
-
body.tags = params.connection_tags;
|
|
192
|
-
if (params.bidirectional !== undefined)
|
|
193
|
-
body.bidirectional = params.bidirectional;
|
|
194
|
-
if (params.metadata)
|
|
195
|
-
body.metadata = params.metadata;
|
|
196
|
-
const data = await apiClient.post(`${base}/connections`, body);
|
|
197
|
-
return successResult(data);
|
|
198
|
-
}
|
|
199
|
-
case "update_connection": {
|
|
200
|
-
if (!params.connection_id)
|
|
201
|
-
return errorResult("connection_id is required for update_connection");
|
|
202
|
-
const body = {};
|
|
203
|
-
if (params.source_node_id)
|
|
204
|
-
body.sourceNodeId = params.source_node_id;
|
|
205
|
-
if (params.target_node_id)
|
|
206
|
-
body.targetNodeId = params.target_node_id;
|
|
207
|
-
if (params.label !== undefined)
|
|
208
|
-
body.label = params.label;
|
|
209
|
-
if (params.connection_description !== undefined)
|
|
210
|
-
body.description = params.connection_description;
|
|
211
|
-
if (params.connection_tags)
|
|
212
|
-
body.tags = params.connection_tags;
|
|
213
|
-
if (params.bidirectional !== undefined)
|
|
214
|
-
body.bidirectional = params.bidirectional;
|
|
215
|
-
if (params.metadata)
|
|
216
|
-
body.metadata = params.metadata;
|
|
217
|
-
const data = await apiClient.patch(`${base}/connections/${params.connection_id}`, body);
|
|
218
|
-
return successResult(data);
|
|
219
|
-
}
|
|
220
|
-
case "delete_connection": {
|
|
221
|
-
if (!params.connection_id)
|
|
222
|
-
return errorResult("connection_id is required for delete_connection");
|
|
223
|
-
await apiClient.del(`${base}/connections/${params.connection_id}`);
|
|
224
|
-
return successResult({ action: "deleted", connection_id: params.connection_id });
|
|
225
|
-
}
|
|
226
|
-
case "add_boundary": {
|
|
227
|
-
if (!params.boundary_label)
|
|
228
|
-
return errorResult("boundary_label is required for add_boundary");
|
|
229
|
-
const body = {
|
|
230
|
-
label: params.boundary_label,
|
|
231
|
-
};
|
|
232
|
-
if (params.boundary_description)
|
|
233
|
-
body.description = params.boundary_description;
|
|
234
|
-
if (params.boundary_color)
|
|
235
|
-
body.color = params.boundary_color;
|
|
236
|
-
if (params.boundary_position_x !== undefined)
|
|
237
|
-
body.positionX = params.boundary_position_x;
|
|
238
|
-
if (params.boundary_position_y !== undefined)
|
|
239
|
-
body.positionY = params.boundary_position_y;
|
|
240
|
-
if (params.boundary_width !== undefined)
|
|
241
|
-
body.width = params.boundary_width;
|
|
242
|
-
if (params.boundary_height !== undefined)
|
|
243
|
-
body.height = params.boundary_height;
|
|
244
|
-
const data = await apiClient.post(`${base}/boundaries`, body);
|
|
245
|
-
return successResult(data);
|
|
246
|
-
}
|
|
247
|
-
case "update_boundary": {
|
|
248
|
-
if (!params.boundary_id)
|
|
249
|
-
return errorResult("boundary_id is required for update_boundary");
|
|
250
|
-
const body = {};
|
|
251
|
-
if (params.boundary_label)
|
|
252
|
-
body.label = params.boundary_label;
|
|
253
|
-
if (params.boundary_description !== undefined)
|
|
254
|
-
body.description = params.boundary_description;
|
|
255
|
-
if (params.boundary_color !== undefined)
|
|
256
|
-
body.color = params.boundary_color;
|
|
257
|
-
if (params.boundary_position_x !== undefined)
|
|
258
|
-
body.positionX = params.boundary_position_x;
|
|
259
|
-
if (params.boundary_position_y !== undefined)
|
|
260
|
-
body.positionY = params.boundary_position_y;
|
|
261
|
-
if (params.boundary_width !== undefined)
|
|
262
|
-
body.width = params.boundary_width;
|
|
263
|
-
if (params.boundary_height !== undefined)
|
|
264
|
-
body.height = params.boundary_height;
|
|
265
|
-
const data = await apiClient.patch(`${base}/boundaries/${params.boundary_id}`, body);
|
|
266
|
-
return successResult(data);
|
|
267
|
-
}
|
|
268
|
-
case "delete_boundary": {
|
|
269
|
-
if (!params.boundary_id)
|
|
270
|
-
return errorResult("boundary_id is required for delete_boundary");
|
|
271
|
-
await apiClient.del(`${base}/boundaries/${params.boundary_id}`);
|
|
272
|
-
return successResult({ action: "deleted", boundary_id: params.boundary_id });
|
|
273
|
-
}
|
|
274
65
|
case "link_threat_model": {
|
|
275
66
|
if (!params.threat_model_id)
|
|
276
67
|
return errorResult("threat_model_id is required for link_threat_model");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { ApiClient } from "../api-client.js";
|
|
3
3
|
export declare const UPDATE_MERMAID_SOURCE_NAME = "zivis_update_mermaid_source";
|
|
4
|
-
export declare const UPDATE_MERMAID_SOURCE_DESCRIPTION = "Replace the Mermaid source of a diagram with new Mermaid syntax.\n\n**Use this when:**
|
|
4
|
+
export declare const UPDATE_MERMAID_SOURCE_DESCRIPTION = "Replace the Mermaid source of a diagram with new Mermaid syntax.\n\n**Use this when:** you want to add, rename, delete, or reconnect nodes in a diagram via Mermaid syntax.\n\n**Workflow:**\n1. Call zivis_get_diagram first to read the current Mermaid source.\n2. Reason about the requested change (rename a node, add a connection, restructure a subgraph, etc.).\n3. Produce a COMPLETE, valid Mermaid source string.\n4. Call this tool with the new source \u2014 it replaces the entire content atomically.\n\n**Keep the overall structure.** Only change what the user asked for. Preserve unrelated nodes, edges, labels, subgraphs, styles.";
|
|
5
5
|
export declare const UPDATE_MERMAID_SOURCE_SCHEMA: {
|
|
6
6
|
diagram_id: z.ZodString;
|
|
7
7
|
mermaid_source: z.ZodString;
|
|
@@ -3,7 +3,7 @@ import { sanitizeResponse } from "../sanitize.js";
|
|
|
3
3
|
export const UPDATE_MERMAID_SOURCE_NAME = "zivis_update_mermaid_source";
|
|
4
4
|
export const UPDATE_MERMAID_SOURCE_DESCRIPTION = `Replace the Mermaid source of a diagram with new Mermaid syntax.
|
|
5
5
|
|
|
6
|
-
**Use this when:**
|
|
6
|
+
**Use this when:** you want to add, rename, delete, or reconnect nodes in a diagram via Mermaid syntax.
|
|
7
7
|
|
|
8
8
|
**Workflow:**
|
|
9
9
|
1. Call zivis_get_diagram first to read the current Mermaid source.
|
|
@@ -11,8 +11,6 @@ export const UPDATE_MERMAID_SOURCE_DESCRIPTION = `Replace the Mermaid source of
|
|
|
11
11
|
3. Produce a COMPLETE, valid Mermaid source string.
|
|
12
12
|
4. Call this tool with the new source — it replaces the entire content atomically.
|
|
13
13
|
|
|
14
|
-
**Do not use for canvas diagrams** (structured nodes/connections). Use zivis_manage_diagram for those.
|
|
15
|
-
|
|
16
14
|
**Keep the overall structure.** Only change what the user asked for. Preserve unrelated nodes, edges, labels, subgraphs, styles.`;
|
|
17
15
|
export const UPDATE_MERMAID_SOURCE_SCHEMA = {
|
|
18
16
|
diagram_id: z.string().describe("UUID of the diagram to update"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zivis/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "ZIVIS MCP server — threat modeling, security scans, and AI red team tools for IDE integration",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://zivis.ai",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@ast-grep/lang-python": "^0.0.6",
|
|
60
60
|
"@ast-grep/napi": "^0.42.1",
|
|
61
61
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
62
|
-
"js-yaml": "^4.
|
|
62
|
+
"js-yaml": "^4.3.2",
|
|
63
63
|
"open": "^10.1.0",
|
|
64
64
|
"zod": "^4.0.0"
|
|
65
65
|
},
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import type { ApiClient } from "../api-client.js";
|
|
3
|
-
export declare const GENERATE_DIAGRAM_NAME = "zivis_generate_diagram";
|
|
4
|
-
export declare const GENERATE_DIAGRAM_DESCRIPTION = "Generate a visual architecture diagram from a Docker Compose file.\n\nReads a local docker-compose.yml and sends it to the ZIVIS platform to generate\na positioned canvas diagram with:\n- Services mapped to color-coded nodes (database, cache, app, proxy, etc.)\n- Docker networks mapped to boundary groups\n- depends_on relationships mapped to connections\n- Auto-positioned grid layout grouped by network\n\nThe diagram is saved to your organization and can be viewed/edited in the diagram editor.\n\nSupported formats: docker-compose (docker-compose.yml, compose.yml)\nComing soon: Kubernetes manifests, Terraform configs";
|
|
5
|
-
export declare const GENERATE_DIAGRAM_SCHEMA: {
|
|
6
|
-
file_path: z.ZodOptional<z.ZodString>;
|
|
7
|
-
source_format: z.ZodDefault<z.ZodEnum<{
|
|
8
|
-
"docker-compose": "docker-compose";
|
|
9
|
-
}>>;
|
|
10
|
-
name: z.ZodOptional<z.ZodString>;
|
|
11
|
-
project_dir: z.ZodOptional<z.ZodString>;
|
|
12
|
-
};
|
|
13
|
-
export declare function createGenerateDiagramHandler(apiClient: ApiClient): (params: {
|
|
14
|
-
file_path?: string;
|
|
15
|
-
source_format?: string;
|
|
16
|
-
name?: string;
|
|
17
|
-
project_dir?: string;
|
|
18
|
-
}) => Promise<{
|
|
19
|
-
content: {
|
|
20
|
-
type: "text";
|
|
21
|
-
text: string;
|
|
22
|
-
}[];
|
|
23
|
-
isError: boolean;
|
|
24
|
-
} | {
|
|
25
|
-
content: {
|
|
26
|
-
type: "text";
|
|
27
|
-
text: string;
|
|
28
|
-
}[];
|
|
29
|
-
isError?: undefined;
|
|
30
|
-
}>;
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { readFile } from "fs/promises";
|
|
3
|
-
import { join, relative, resolve } from "path";
|
|
4
|
-
import { sanitizeResponse } from "../sanitize.js";
|
|
5
|
-
function resolveWithinProjectDir(projectDir, candidate) {
|
|
6
|
-
const base = resolve(projectDir);
|
|
7
|
-
const target = resolve(base, candidate);
|
|
8
|
-
const rel = relative(base, target);
|
|
9
|
-
if (rel.startsWith(".."))
|
|
10
|
-
return null;
|
|
11
|
-
return target;
|
|
12
|
-
}
|
|
13
|
-
export const GENERATE_DIAGRAM_NAME = "zivis_generate_diagram";
|
|
14
|
-
export const GENERATE_DIAGRAM_DESCRIPTION = `Generate a visual architecture diagram from a Docker Compose file.
|
|
15
|
-
|
|
16
|
-
Reads a local docker-compose.yml and sends it to the ZIVIS platform to generate
|
|
17
|
-
a positioned canvas diagram with:
|
|
18
|
-
- Services mapped to color-coded nodes (database, cache, app, proxy, etc.)
|
|
19
|
-
- Docker networks mapped to boundary groups
|
|
20
|
-
- depends_on relationships mapped to connections
|
|
21
|
-
- Auto-positioned grid layout grouped by network
|
|
22
|
-
|
|
23
|
-
The diagram is saved to your organization and can be viewed/edited in the diagram editor.
|
|
24
|
-
|
|
25
|
-
Supported formats: docker-compose (docker-compose.yml, compose.yml)
|
|
26
|
-
Coming soon: Kubernetes manifests, Terraform configs`;
|
|
27
|
-
export const GENERATE_DIAGRAM_SCHEMA = {
|
|
28
|
-
file_path: z
|
|
29
|
-
.string()
|
|
30
|
-
.optional()
|
|
31
|
-
.describe("Path to the infrastructure file (e.g., docker-compose.yml). " +
|
|
32
|
-
"If not provided, searches the current directory for docker-compose.yml, " +
|
|
33
|
-
"docker-compose.yaml, compose.yml, or compose.yaml."),
|
|
34
|
-
source_format: z
|
|
35
|
-
.enum(["docker-compose"])
|
|
36
|
-
.default("docker-compose")
|
|
37
|
-
.describe("The format of the source file. Currently only docker-compose is supported."),
|
|
38
|
-
name: z
|
|
39
|
-
.string()
|
|
40
|
-
.optional()
|
|
41
|
-
.describe("Custom name for the generated diagram. Defaults to 'Docker Compose Architecture'."),
|
|
42
|
-
project_dir: z
|
|
43
|
-
.string()
|
|
44
|
-
.optional()
|
|
45
|
-
.describe("Project directory to search for compose files. Defaults to current working directory."),
|
|
46
|
-
};
|
|
47
|
-
const COMPOSE_FILE_CANDIDATES = [
|
|
48
|
-
"docker-compose.yml",
|
|
49
|
-
"docker-compose.yaml",
|
|
50
|
-
"compose.yml",
|
|
51
|
-
"compose.yaml",
|
|
52
|
-
];
|
|
53
|
-
export function createGenerateDiagramHandler(apiClient) {
|
|
54
|
-
return async (params) => {
|
|
55
|
-
const projectDir = params.project_dir || process.cwd();
|
|
56
|
-
const sourceFormat = params.source_format || "docker-compose";
|
|
57
|
-
let filePath = params.file_path;
|
|
58
|
-
let content = null;
|
|
59
|
-
if (filePath) {
|
|
60
|
-
const resolved = resolveWithinProjectDir(projectDir, filePath);
|
|
61
|
-
if (!resolved) {
|
|
62
|
-
return {
|
|
63
|
-
content: [
|
|
64
|
-
{
|
|
65
|
-
type: "text",
|
|
66
|
-
text: `Error: file_path must resolve inside project_dir (got: ${filePath})`,
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
isError: true,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
try {
|
|
73
|
-
content = await readFile(resolved, "utf-8");
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return {
|
|
77
|
-
content: [
|
|
78
|
-
{
|
|
79
|
-
type: "text",
|
|
80
|
-
text: `Error: File not found: ${resolved}`,
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
isError: true,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
for (const candidate of COMPOSE_FILE_CANDIDATES) {
|
|
89
|
-
try {
|
|
90
|
-
content = await readFile(join(projectDir, candidate), "utf-8");
|
|
91
|
-
filePath = candidate;
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (!content) {
|
|
98
|
-
return {
|
|
99
|
-
content: [
|
|
100
|
-
{
|
|
101
|
-
type: "text",
|
|
102
|
-
text: "Error: No docker-compose file found. Searched for: " +
|
|
103
|
-
COMPOSE_FILE_CANDIDATES.join(", "),
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
isError: true,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (content.length > 500 * 1024) {
|
|
111
|
-
return {
|
|
112
|
-
content: [
|
|
113
|
-
{
|
|
114
|
-
type: "text",
|
|
115
|
-
text: "Error: File too large (max 500KB)",
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
isError: true,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
try {
|
|
122
|
-
const data = await apiClient.post("/api/diagrams/generate", {
|
|
123
|
-
content,
|
|
124
|
-
sourceFormat,
|
|
125
|
-
name: params.name,
|
|
126
|
-
});
|
|
127
|
-
const summary = {
|
|
128
|
-
diagram_id: data.id,
|
|
129
|
-
name: data.name,
|
|
130
|
-
type: data.diagramType,
|
|
131
|
-
source_file: filePath,
|
|
132
|
-
stats: {
|
|
133
|
-
nodes: data.nodes?.length || 0,
|
|
134
|
-
connections: data.connections?.length || 0,
|
|
135
|
-
boundaries: data.boundaries?.length || 0,
|
|
136
|
-
},
|
|
137
|
-
nodes: (data.nodes || []).map((n) => ({
|
|
138
|
-
name: n.name,
|
|
139
|
-
tags: n.tags,
|
|
140
|
-
})),
|
|
141
|
-
boundaries: (data.boundaries || []).map((b) => b.label),
|
|
142
|
-
};
|
|
143
|
-
const sanitized = sanitizeResponse(summary);
|
|
144
|
-
return {
|
|
145
|
-
content: [
|
|
146
|
-
{
|
|
147
|
-
type: "text",
|
|
148
|
-
text: JSON.stringify(sanitized, null, 2),
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
catch (err) {
|
|
154
|
-
const message = err instanceof Error ? err.message : "Failed to generate diagram";
|
|
155
|
-
return {
|
|
156
|
-
content: [{ type: "text", text: `Error: ${message}` }],
|
|
157
|
-
isError: true,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
}
|