@arvoretech/db-diagram-mcp 1.0.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/README.md +46 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/mermaid.d.ts +9 -0
- package/dist/mermaid.d.ts.map +1 -0
- package/dist/mermaid.js +183 -0
- package/dist/mermaid.js.map +1 -0
- package/dist/mermaid.test.d.ts +2 -0
- package/dist/mermaid.test.d.ts.map +1 -0
- package/dist/mermaid.test.js +118 -0
- package/dist/mermaid.test.js.map +1 -0
- package/dist/parser.d.ts +4 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +148 -0
- package/dist/parser.js.map +1 -0
- package/dist/parser.test.d.ts +2 -0
- package/dist/parser.test.d.ts.map +1 -0
- package/dist/parser.test.js +110 -0
- package/dist/parser.test.js.map +1 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +117 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +37 -0
- package/dist/types.js.map +1 -0
- package/dist/visualizer.d.ts +2 -0
- package/dist/visualizer.d.ts.map +1 -0
- package/dist/visualizer.js +106 -0
- package/dist/visualizer.js.map +1 -0
- package/package.json +43 -0
- package/src/index.ts +23 -0
- package/src/mermaid.test.ts +135 -0
- package/src/mermaid.ts +250 -0
- package/src/parser.test.ts +118 -0
- package/src/parser.ts +185 -0
- package/src/server.ts +163 -0
- package/src/types.ts +88 -0
- package/src/visualizer.ts +116 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { parseDDL, extractInlineForeignKeys } from "./parser.js";
|
|
3
|
+
const sampleDDL = `
|
|
4
|
+
CREATE TABLE users (
|
|
5
|
+
id INT NOT NULL AUTO_INCREMENT,
|
|
6
|
+
email VARCHAR(255) NOT NULL,
|
|
7
|
+
name VARCHAR(100),
|
|
8
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
9
|
+
PRIMARY KEY (id),
|
|
10
|
+
UNIQUE KEY (email)
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
CREATE TABLE posts (
|
|
14
|
+
id INT NOT NULL AUTO_INCREMENT,
|
|
15
|
+
user_id INT NOT NULL,
|
|
16
|
+
title VARCHAR(255) NOT NULL,
|
|
17
|
+
body TEXT,
|
|
18
|
+
published_at TIMESTAMP,
|
|
19
|
+
PRIMARY KEY (id),
|
|
20
|
+
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE TABLE comments (
|
|
24
|
+
id INT NOT NULL AUTO_INCREMENT,
|
|
25
|
+
post_id INT NOT NULL,
|
|
26
|
+
user_id INT NOT NULL,
|
|
27
|
+
content TEXT NOT NULL,
|
|
28
|
+
PRIMARY KEY (id),
|
|
29
|
+
FOREIGN KEY (post_id) REFERENCES posts(id),
|
|
30
|
+
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE TABLE tags (
|
|
34
|
+
id INT NOT NULL AUTO_INCREMENT,
|
|
35
|
+
name VARCHAR(50) NOT NULL UNIQUE,
|
|
36
|
+
PRIMARY KEY (id)
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
CREATE TABLE post_tags (
|
|
40
|
+
post_id INT NOT NULL,
|
|
41
|
+
tag_id INT NOT NULL,
|
|
42
|
+
PRIMARY KEY (post_id, tag_id),
|
|
43
|
+
FOREIGN KEY (post_id) REFERENCES posts(id),
|
|
44
|
+
FOREIGN KEY (tag_id) REFERENCES tags(id)
|
|
45
|
+
);
|
|
46
|
+
`;
|
|
47
|
+
describe("parseDDL", () => {
|
|
48
|
+
it("parses all tables", () => {
|
|
49
|
+
const schema = parseDDL(sampleDDL);
|
|
50
|
+
expect(schema.tables).toHaveLength(5);
|
|
51
|
+
expect(schema.tables.map((t) => t.name)).toEqual([
|
|
52
|
+
"users",
|
|
53
|
+
"posts",
|
|
54
|
+
"comments",
|
|
55
|
+
"tags",
|
|
56
|
+
"post_tags",
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
it("parses columns correctly", () => {
|
|
60
|
+
const schema = parseDDL(sampleDDL);
|
|
61
|
+
const users = schema.tables.find((t) => t.name === "users");
|
|
62
|
+
expect(users.columns).toHaveLength(4);
|
|
63
|
+
const idCol = users.columns.find((c) => c.name === "id");
|
|
64
|
+
expect(idCol.primaryKey).toBe(true);
|
|
65
|
+
expect(idCol.nullable).toBe(false);
|
|
66
|
+
const emailCol = users.columns.find((c) => c.name === "email");
|
|
67
|
+
expect(emailCol.nullable).toBe(false);
|
|
68
|
+
});
|
|
69
|
+
it("parses foreign keys", () => {
|
|
70
|
+
const schema = parseDDL(sampleDDL);
|
|
71
|
+
const posts = schema.tables.find((t) => t.name === "posts");
|
|
72
|
+
expect(posts.foreignKeys).toHaveLength(1);
|
|
73
|
+
expect(posts.foreignKeys[0]).toEqual({
|
|
74
|
+
columns: ["user_id"],
|
|
75
|
+
referencedTable: "users",
|
|
76
|
+
referencedColumns: ["id"],
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
it("parses composite primary keys", () => {
|
|
80
|
+
const schema = parseDDL(sampleDDL);
|
|
81
|
+
const postTags = schema.tables.find((t) => t.name === "post_tags");
|
|
82
|
+
const pkCols = postTags.columns.filter((c) => c.primaryKey);
|
|
83
|
+
expect(pkCols.map((c) => c.name)).toEqual(["post_id", "tag_id"]);
|
|
84
|
+
});
|
|
85
|
+
it("parses multiple foreign keys on one table", () => {
|
|
86
|
+
const schema = parseDDL(sampleDDL);
|
|
87
|
+
const comments = schema.tables.find((t) => t.name === "comments");
|
|
88
|
+
expect(comments.foreignKeys).toHaveLength(2);
|
|
89
|
+
});
|
|
90
|
+
it("handles PostgreSQL inline references", () => {
|
|
91
|
+
const pgDDL = `
|
|
92
|
+
CREATE TABLE orders (
|
|
93
|
+
id SERIAL PRIMARY KEY,
|
|
94
|
+
customer_id INT NOT NULL REFERENCES customers(id),
|
|
95
|
+
total DECIMAL(10,2)
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
CREATE TABLE customers (
|
|
99
|
+
id SERIAL PRIMARY KEY,
|
|
100
|
+
name VARCHAR(100) NOT NULL
|
|
101
|
+
);
|
|
102
|
+
`;
|
|
103
|
+
let schema = parseDDL(pgDDL);
|
|
104
|
+
schema = extractInlineForeignKeys(pgDDL, schema);
|
|
105
|
+
const orders = schema.tables.find((t) => t.name === "orders");
|
|
106
|
+
expect(orders.foreignKeys).toHaveLength(1);
|
|
107
|
+
expect(orders.foreignKeys[0].referencedTable).toBe("customers");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=parser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.test.js","sourceRoot":"","sources":["../src/parser.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAEjE,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CjB,CAAC;AAEF,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/C,OAAO;YACP,OAAO;YACP,UAAU;YACV,MAAM;YACN,WAAW;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAE,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAEtC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAE,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAE,CAAC;QAChE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAE,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACnC,OAAO,EAAE,CAAC,SAAS,CAAC;YACpB,eAAe,EAAE,OAAO;YACxB,iBAAiB,EAAE,CAAC,IAAI,CAAC;SAC1B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAE,CAAC;QACpE,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAE,CAAC;QACnE,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,KAAK,GAAG;;;;;;;;;;;CAWjB,CAAC;QACE,IAAI,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC7B,MAAM,GAAG,wBAAwB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAE,CAAC;QAC/D,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAmBA,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAY;;IAU1B,OAAO,CAAC,UAAU;IAqHZ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,qBAAqB,IAAI,IAAI;CAS9B"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { parseDDL, extractInlineForeignKeys } from "./parser.js";
|
|
4
|
+
import { generateErd, generateDomainMap, explainTable, traceFlow } from "./mermaid.js";
|
|
5
|
+
import { visualize } from "./visualizer.js";
|
|
6
|
+
import { GenerateErdParamsSchema, GenerateDomainMapParamsSchema, ExplainTableParamsSchema, TraceFlowParamsSchema, VisualizeParamsSchema, } from "./types.js";
|
|
7
|
+
export class DbDiagramMCPServer {
|
|
8
|
+
server;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.server = new McpServer({
|
|
11
|
+
name: "db-diagram-mcp-server",
|
|
12
|
+
version: "1.0.0",
|
|
13
|
+
});
|
|
14
|
+
this.setupTools();
|
|
15
|
+
}
|
|
16
|
+
setupTools() {
|
|
17
|
+
this.server.registerTool("generate_erd", {
|
|
18
|
+
title: "Generate ERD",
|
|
19
|
+
description: "Generate a Mermaid ER diagram from SQL DDL. Optionally filter to specific tables.",
|
|
20
|
+
inputSchema: {
|
|
21
|
+
ddl: GenerateErdParamsSchema.shape.ddl,
|
|
22
|
+
tables: GenerateErdParamsSchema.shape.tables,
|
|
23
|
+
title: GenerateErdParamsSchema.shape.title,
|
|
24
|
+
},
|
|
25
|
+
}, async (params) => {
|
|
26
|
+
const { ddl, tables, title } = params;
|
|
27
|
+
let schema = parseDDL(ddl);
|
|
28
|
+
schema = extractInlineForeignKeys(ddl, schema);
|
|
29
|
+
const diagram = generateErd(schema, { tables, title });
|
|
30
|
+
return { content: [{ type: "text", text: diagram }] };
|
|
31
|
+
});
|
|
32
|
+
this.server.registerTool("generate_domain_map", {
|
|
33
|
+
title: "Generate Domain Map",
|
|
34
|
+
description: "Generate a Mermaid diagram showing all tables related to an entry table within N hops.",
|
|
35
|
+
inputSchema: {
|
|
36
|
+
ddl: GenerateDomainMapParamsSchema.shape.ddl,
|
|
37
|
+
entryTable: GenerateDomainMapParamsSchema.shape.entryTable,
|
|
38
|
+
depth: GenerateDomainMapParamsSchema.shape.depth,
|
|
39
|
+
},
|
|
40
|
+
}, async (params) => {
|
|
41
|
+
const { ddl, entryTable, depth } = params;
|
|
42
|
+
let schema = parseDDL(ddl);
|
|
43
|
+
schema = extractInlineForeignKeys(ddl, schema);
|
|
44
|
+
const diagram = generateDomainMap(schema, entryTable, depth ?? 3);
|
|
45
|
+
return { content: [{ type: "text", text: diagram }] };
|
|
46
|
+
});
|
|
47
|
+
this.server.registerTool("explain_table", {
|
|
48
|
+
title: "Explain Table",
|
|
49
|
+
description: "Show a table's columns, relationships (incoming and outgoing), and a mini ER diagram of its neighborhood.",
|
|
50
|
+
inputSchema: {
|
|
51
|
+
ddl: ExplainTableParamsSchema.shape.ddl,
|
|
52
|
+
table: ExplainTableParamsSchema.shape.table,
|
|
53
|
+
},
|
|
54
|
+
}, async (params) => {
|
|
55
|
+
const { ddl, table } = params;
|
|
56
|
+
let schema = parseDDL(ddl);
|
|
57
|
+
schema = extractInlineForeignKeys(ddl, schema);
|
|
58
|
+
const explanation = explainTable(schema, table);
|
|
59
|
+
return { content: [{ type: "text", text: explanation }] };
|
|
60
|
+
});
|
|
61
|
+
this.server.registerTool("trace_flow", {
|
|
62
|
+
title: "Trace Flow",
|
|
63
|
+
description: "Find relationship paths between two tables and generate a Mermaid diagram of the connecting tables.",
|
|
64
|
+
inputSchema: {
|
|
65
|
+
ddl: TraceFlowParamsSchema.shape.ddl,
|
|
66
|
+
from: TraceFlowParamsSchema.shape.from,
|
|
67
|
+
to: TraceFlowParamsSchema.shape.to,
|
|
68
|
+
},
|
|
69
|
+
}, async (params) => {
|
|
70
|
+
const { ddl, from, to } = params;
|
|
71
|
+
let schema = parseDDL(ddl);
|
|
72
|
+
schema = extractInlineForeignKeys(ddl, schema);
|
|
73
|
+
const flow = traceFlow(schema, from, to);
|
|
74
|
+
return { content: [{ type: "text", text: flow }] };
|
|
75
|
+
});
|
|
76
|
+
this.server.registerTool("visualize", {
|
|
77
|
+
title: "Visualize Diagram",
|
|
78
|
+
description: "Render a Mermaid ER diagram in the browser. Accepts DDL (generates ERD) or raw Mermaid code.",
|
|
79
|
+
inputSchema: {
|
|
80
|
+
ddl: VisualizeParamsSchema.shape.ddl,
|
|
81
|
+
mermaid: VisualizeParamsSchema.shape.mermaid,
|
|
82
|
+
tables: VisualizeParamsSchema.shape.tables,
|
|
83
|
+
title: VisualizeParamsSchema.shape.title,
|
|
84
|
+
},
|
|
85
|
+
}, async (params) => {
|
|
86
|
+
const { ddl, mermaid: rawMermaid, tables, title } = params;
|
|
87
|
+
let mermaidCode;
|
|
88
|
+
if (rawMermaid) {
|
|
89
|
+
mermaidCode = rawMermaid;
|
|
90
|
+
}
|
|
91
|
+
else if (ddl) {
|
|
92
|
+
let schema = parseDDL(ddl);
|
|
93
|
+
schema = extractInlineForeignKeys(ddl, schema);
|
|
94
|
+
mermaidCode = generateErd(schema, { tables, title });
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
return { content: [{ type: "text", text: "Provide either 'ddl' or 'mermaid' parameter." }] };
|
|
98
|
+
}
|
|
99
|
+
const url = await visualize(mermaidCode);
|
|
100
|
+
return { content: [{ type: "text", text: `Diagram opened at ${url} (auto-closes in 5 minutes)` }] };
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
async start() {
|
|
104
|
+
const transport = new StdioServerTransport();
|
|
105
|
+
await this.server.connect(transport);
|
|
106
|
+
console.error("DB Diagram MCP Server started successfully");
|
|
107
|
+
}
|
|
108
|
+
setupGracefulShutdown() {
|
|
109
|
+
const shutdown = async (signal) => {
|
|
110
|
+
console.error(`Received ${signal}, shutting down gracefully...`);
|
|
111
|
+
process.exit(0);
|
|
112
|
+
};
|
|
113
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
114
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export interface Column {
|
|
3
|
+
name: string;
|
|
4
|
+
type: string;
|
|
5
|
+
nullable: boolean;
|
|
6
|
+
primaryKey: boolean;
|
|
7
|
+
unique: boolean;
|
|
8
|
+
defaultValue?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ForeignKey {
|
|
11
|
+
columns: string[];
|
|
12
|
+
referencedTable: string;
|
|
13
|
+
referencedColumns: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface Table {
|
|
16
|
+
name: string;
|
|
17
|
+
columns: Column[];
|
|
18
|
+
foreignKeys: ForeignKey[];
|
|
19
|
+
}
|
|
20
|
+
export interface Schema {
|
|
21
|
+
tables: Table[];
|
|
22
|
+
}
|
|
23
|
+
export declare const GenerateErdParamsSchema: z.ZodObject<{
|
|
24
|
+
ddl: z.ZodString;
|
|
25
|
+
tables: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
26
|
+
title: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, "strip", z.ZodTypeAny, {
|
|
28
|
+
ddl: string;
|
|
29
|
+
tables?: string[] | undefined;
|
|
30
|
+
title?: string | undefined;
|
|
31
|
+
}, {
|
|
32
|
+
ddl: string;
|
|
33
|
+
tables?: string[] | undefined;
|
|
34
|
+
title?: string | undefined;
|
|
35
|
+
}>;
|
|
36
|
+
export type GenerateErdParams = z.infer<typeof GenerateErdParamsSchema>;
|
|
37
|
+
export declare const GenerateDomainMapParamsSchema: z.ZodObject<{
|
|
38
|
+
ddl: z.ZodString;
|
|
39
|
+
entryTable: z.ZodString;
|
|
40
|
+
depth: z.ZodDefault<z.ZodNumber>;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
ddl: string;
|
|
43
|
+
entryTable: string;
|
|
44
|
+
depth: number;
|
|
45
|
+
}, {
|
|
46
|
+
ddl: string;
|
|
47
|
+
entryTable: string;
|
|
48
|
+
depth?: number | undefined;
|
|
49
|
+
}>;
|
|
50
|
+
export type GenerateDomainMapParams = z.infer<typeof GenerateDomainMapParamsSchema>;
|
|
51
|
+
export declare const ExplainTableParamsSchema: z.ZodObject<{
|
|
52
|
+
ddl: z.ZodString;
|
|
53
|
+
table: z.ZodString;
|
|
54
|
+
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
ddl: string;
|
|
56
|
+
table: string;
|
|
57
|
+
}, {
|
|
58
|
+
ddl: string;
|
|
59
|
+
table: string;
|
|
60
|
+
}>;
|
|
61
|
+
export type ExplainTableParams = z.infer<typeof ExplainTableParamsSchema>;
|
|
62
|
+
export declare const TraceFlowParamsSchema: z.ZodObject<{
|
|
63
|
+
ddl: z.ZodString;
|
|
64
|
+
from: z.ZodString;
|
|
65
|
+
to: z.ZodString;
|
|
66
|
+
}, "strip", z.ZodTypeAny, {
|
|
67
|
+
ddl: string;
|
|
68
|
+
from: string;
|
|
69
|
+
to: string;
|
|
70
|
+
}, {
|
|
71
|
+
ddl: string;
|
|
72
|
+
from: string;
|
|
73
|
+
to: string;
|
|
74
|
+
}>;
|
|
75
|
+
export type TraceFlowParams = z.infer<typeof TraceFlowParamsSchema>;
|
|
76
|
+
export declare const VisualizeParamsSchema: z.ZodObject<{
|
|
77
|
+
ddl: z.ZodOptional<z.ZodString>;
|
|
78
|
+
mermaid: z.ZodOptional<z.ZodString>;
|
|
79
|
+
tables: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
80
|
+
title: z.ZodOptional<z.ZodString>;
|
|
81
|
+
}, "strip", z.ZodTypeAny, {
|
|
82
|
+
ddl?: string | undefined;
|
|
83
|
+
tables?: string[] | undefined;
|
|
84
|
+
title?: string | undefined;
|
|
85
|
+
mermaid?: string | undefined;
|
|
86
|
+
}, {
|
|
87
|
+
ddl?: string | undefined;
|
|
88
|
+
tables?: string[] | undefined;
|
|
89
|
+
title?: string | undefined;
|
|
90
|
+
mermaid?: string | undefined;
|
|
91
|
+
}>;
|
|
92
|
+
export type VisualizeParams = z.infer<typeof VisualizeParamsSchema>;
|
|
93
|
+
export interface McpToolResult {
|
|
94
|
+
[x: string]: unknown;
|
|
95
|
+
content: Array<{
|
|
96
|
+
type: "text";
|
|
97
|
+
text: string;
|
|
98
|
+
}>;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,eAAO,MAAM,uBAAuB;;;;;;;;;;;;EAOlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,6BAA6B;;;;;;;;;;;;EAWxC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;EAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;EAIhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;EAKhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAIpE,MAAM,WAAW,aAAa;IAC5B,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const GenerateErdParamsSchema = z.object({
|
|
3
|
+
ddl: z.string().min(1).describe("SQL DDL statements (CREATE TABLE)"),
|
|
4
|
+
tables: z
|
|
5
|
+
.array(z.string())
|
|
6
|
+
.optional()
|
|
7
|
+
.describe("Filter to specific tables (omit for all)"),
|
|
8
|
+
title: z.string().optional().describe("Diagram title"),
|
|
9
|
+
});
|
|
10
|
+
export const GenerateDomainMapParamsSchema = z.object({
|
|
11
|
+
ddl: z.string().min(1).describe("SQL DDL statements (CREATE TABLE)"),
|
|
12
|
+
entryTable: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe("Starting table to trace relationships from"),
|
|
15
|
+
depth: z
|
|
16
|
+
.number()
|
|
17
|
+
.min(1)
|
|
18
|
+
.max(10)
|
|
19
|
+
.default(3)
|
|
20
|
+
.describe("How many relationship hops to follow (default: 3)"),
|
|
21
|
+
});
|
|
22
|
+
export const ExplainTableParamsSchema = z.object({
|
|
23
|
+
ddl: z.string().min(1).describe("SQL DDL statements (CREATE TABLE)"),
|
|
24
|
+
table: z.string().describe("Table name to explain"),
|
|
25
|
+
});
|
|
26
|
+
export const TraceFlowParamsSchema = z.object({
|
|
27
|
+
ddl: z.string().min(1).describe("SQL DDL statements (CREATE TABLE)"),
|
|
28
|
+
from: z.string().describe("Source table"),
|
|
29
|
+
to: z.string().describe("Target table"),
|
|
30
|
+
});
|
|
31
|
+
export const VisualizeParamsSchema = z.object({
|
|
32
|
+
ddl: z.string().optional().describe("SQL DDL statements (CREATE TABLE). Provide either ddl or mermaid."),
|
|
33
|
+
mermaid: z.string().optional().describe("Raw Mermaid diagram code to render directly."),
|
|
34
|
+
tables: z.array(z.string()).optional().describe("Filter to specific tables (only when using ddl)"),
|
|
35
|
+
title: z.string().optional().describe("Diagram title"),
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2BxB,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACpE,MAAM,EAAE,CAAC;SACN,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,0CAA0C,CAAC;IACvD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;CACvD,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACpE,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,QAAQ,CAAC,4CAA4C,CAAC;IACzD,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,OAAO,CAAC,CAAC,CAAC;SACV,QAAQ,CAAC,mDAAmD,CAAC;CACjE,CAAC,CAAC;AAMH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACpE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;CACpD,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IACpE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;IACzC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;CACxC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;IACxG,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;IACvF,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;IAClG,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;CACvD,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visualizer.d.ts","sourceRoot":"","sources":["../src/visualizer.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA2B9D"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { exec } from "node:child_process";
|
|
3
|
+
import { platform } from "node:os";
|
|
4
|
+
export function visualize(mermaidCode) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
const html = buildHtml(mermaidCode);
|
|
7
|
+
const server = createServer((req, res) => {
|
|
8
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
9
|
+
res.end(html);
|
|
10
|
+
});
|
|
11
|
+
server.listen(0, "127.0.0.1", () => {
|
|
12
|
+
const address = server.address();
|
|
13
|
+
if (!address || typeof address === "string") {
|
|
14
|
+
reject(new Error("Failed to get server address"));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const url = `http://127.0.0.1:${address.port}`;
|
|
18
|
+
openBrowser(url);
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
server.close();
|
|
21
|
+
}, 300_000);
|
|
22
|
+
resolve(url);
|
|
23
|
+
});
|
|
24
|
+
server.on("error", reject);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function openBrowser(url) {
|
|
28
|
+
const cmd = platform() === "darwin"
|
|
29
|
+
? `open "${url}"`
|
|
30
|
+
: platform() === "win32"
|
|
31
|
+
? `start "${url}"`
|
|
32
|
+
: `xdg-open "${url}"`;
|
|
33
|
+
exec(cmd, () => { });
|
|
34
|
+
}
|
|
35
|
+
function buildHtml(mermaidCode) {
|
|
36
|
+
const escaped = mermaidCode.replace(/</g, "<").replace(/>/g, ">");
|
|
37
|
+
return `<!DOCTYPE html>
|
|
38
|
+
<html lang="en">
|
|
39
|
+
<head>
|
|
40
|
+
<meta charset="UTF-8">
|
|
41
|
+
<title>DB Diagram</title>
|
|
42
|
+
<style>
|
|
43
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
44
|
+
html, body { width: 100%; height: 100%; overflow: hidden; background: #1a1a2e; }
|
|
45
|
+
#viewport { width: 100%; height: 100%; cursor: grab; overflow: hidden; }
|
|
46
|
+
#viewport.dragging { cursor: grabbing; }
|
|
47
|
+
#diagram { display: inline-block; padding: 2rem; transform-origin: 0 0; }
|
|
48
|
+
</style>
|
|
49
|
+
</head>
|
|
50
|
+
<body>
|
|
51
|
+
<div id="viewport">
|
|
52
|
+
<div id="diagram">
|
|
53
|
+
<pre class="mermaid">${escaped}</pre>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
<script type="module">
|
|
57
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
58
|
+
mermaid.initialize({ startOnLoad: true, theme: 'dark', er: { useMaxWidth: false, layoutDirection: 'LR' } });
|
|
59
|
+
|
|
60
|
+
const viewport = document.getElementById('viewport');
|
|
61
|
+
const diagram = document.getElementById('diagram');
|
|
62
|
+
let isPanning = false;
|
|
63
|
+
let startX = 0, startY = 0;
|
|
64
|
+
let offsetX = 0, offsetY = 0;
|
|
65
|
+
let scale = 1;
|
|
66
|
+
|
|
67
|
+
function applyTransform() {
|
|
68
|
+
diagram.style.transform = \`translate(\${offsetX}px, \${offsetY}px) scale(\${scale})\`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
viewport.addEventListener('mousedown', (e) => {
|
|
72
|
+
isPanning = true;
|
|
73
|
+
startX = e.clientX - offsetX;
|
|
74
|
+
startY = e.clientY - offsetY;
|
|
75
|
+
viewport.classList.add('dragging');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
window.addEventListener('mousemove', (e) => {
|
|
79
|
+
if (!isPanning) return;
|
|
80
|
+
offsetX = e.clientX - startX;
|
|
81
|
+
offsetY = e.clientY - startY;
|
|
82
|
+
applyTransform();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
window.addEventListener('mouseup', () => {
|
|
86
|
+
isPanning = false;
|
|
87
|
+
viewport.classList.remove('dragging');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
viewport.addEventListener('wheel', (e) => {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
const delta = e.deltaY > 0 ? 0.9 : 1.1;
|
|
93
|
+
const newScale = Math.min(Math.max(scale * delta, 0.1), 5);
|
|
94
|
+
const rect = viewport.getBoundingClientRect();
|
|
95
|
+
const mx = e.clientX - rect.left;
|
|
96
|
+
const my = e.clientY - rect.top;
|
|
97
|
+
offsetX -= (mx - offsetX) * (newScale / scale - 1);
|
|
98
|
+
offsetY -= (my - offsetY) * (newScale / scale - 1);
|
|
99
|
+
scale = newScale;
|
|
100
|
+
applyTransform();
|
|
101
|
+
}, { passive: false });
|
|
102
|
+
</script>
|
|
103
|
+
</body>
|
|
104
|
+
</html>`;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=visualizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visualizer.js","sourceRoot":"","sources":["../src/visualizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAU,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,MAAM,UAAU,SAAS,CAAC,WAAmB;IAC3C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;QACpC,MAAM,MAAM,GAAW,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC/C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;YACjC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC5C,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;gBAClD,OAAO;YACT,CAAC;YAED,MAAM,GAAG,GAAG,oBAAoB,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/C,WAAW,CAAC,GAAG,CAAC,CAAC;YAEjB,UAAU,CAAC,GAAG,EAAE;gBACd,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC,EAAE,OAAO,CAAC,CAAC;YAEZ,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,GAAG,GACP,QAAQ,EAAE,KAAK,QAAQ;QACrB,CAAC,CAAC,SAAS,GAAG,GAAG;QACjB,CAAC,CAAC,QAAQ,EAAE,KAAK,OAAO;YACtB,CAAC,CAAC,UAAU,GAAG,GAAG;YAClB,CAAC,CAAC,aAAa,GAAG,GAAG,CAAC;IAE5B,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,SAAS,CAAC,WAAmB;IACpC,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAExE,OAAO;;;;;;;;;;;;;;;;2BAgBkB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAmD1B,CAAC;AACT,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arvoretech/db-diagram-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP Server that generates Mermaid ER diagrams from SQL DDL",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"db-diagram-mcp": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"dev": "tsx src/index.ts",
|
|
16
|
+
"start": "node dist/index.js",
|
|
17
|
+
"test": "vitest",
|
|
18
|
+
"test:cov": "vitest --coverage",
|
|
19
|
+
"lint": "eslint src/**/*.ts",
|
|
20
|
+
"lint:fix": "eslint src/**/*.ts --fix"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"database",
|
|
25
|
+
"diagram",
|
|
26
|
+
"erd",
|
|
27
|
+
"mermaid",
|
|
28
|
+
"ddl",
|
|
29
|
+
"ai",
|
|
30
|
+
"arvore"
|
|
31
|
+
],
|
|
32
|
+
"author": "Arvore",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/arvoreeducacao/arvore-mcp-servers.git",
|
|
37
|
+
"directory": "packages/db-diagram"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@modelcontextprotocol/sdk": "~1.22.0",
|
|
41
|
+
"zod": "^3.22.4"
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { DbDiagramMCPServer } from "./server.js";
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
const server = new DbDiagramMCPServer();
|
|
7
|
+
server.setupGracefulShutdown();
|
|
8
|
+
await server.start();
|
|
9
|
+
} catch (error) {
|
|
10
|
+
console.error("Failed to start DB Diagram MCP Server:", error);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { DbDiagramMCPServer } from "./server.js";
|
|
15
|
+
export { parseDDL, extractInlineForeignKeys } from "./parser.js";
|
|
16
|
+
export {
|
|
17
|
+
generateErd,
|
|
18
|
+
generateDomainMap,
|
|
19
|
+
explainTable,
|
|
20
|
+
traceFlow,
|
|
21
|
+
} from "./mermaid.js";
|
|
22
|
+
export { visualize } from "./visualizer.js";
|
|
23
|
+
export * from "./types.js";
|