@og-mcp/reactflow-mcp 1.0.4 → 1.0.6

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.
@@ -41,22 +41,22 @@ function register(server) {
41
41
  if (desc.includes("custom node") || desc.includes("custom-node")) {
42
42
  imports.add("Handle");
43
43
  imports.add("Position");
44
- additionalComponents += `
45
- type CustomNodeData = { label: string };
46
- type CustomNodeType = Node<CustomNodeData, 'custom'>;
47
-
48
- const CustomNode = memo(({ data, selected }: NodeProps<CustomNodeType>) => (
49
- <>
50
- <Handle type="target" position={Position.Left} />
51
- <div className={\`px-4 py-2 rounded border shadow-sm bg-white \${selected ? 'border-blue-500' : 'border-gray-200'}\`}>
52
- {data.label}
53
- </div>
54
- <Handle type="source" position={Position.Right} />
55
- </>
56
- ));
57
- CustomNode.displayName = 'CustomNode';
58
-
59
- const nodeTypes = { custom: CustomNode };
44
+ additionalComponents += `
45
+ type CustomNodeData = { label: string };
46
+ type CustomNodeType = Node<CustomNodeData, 'custom'>;
47
+
48
+ const CustomNode = memo(({ data, selected }: NodeProps<CustomNodeType>) => (
49
+ <>
50
+ <Handle type="target" position={Position.Left} />
51
+ <div className={\`px-4 py-2 rounded border shadow-sm bg-white \${selected ? 'border-blue-500' : 'border-gray-200'}\`}>
52
+ {data.label}
53
+ </div>
54
+ <Handle type="source" position={Position.Right} />
55
+ </>
56
+ ));
57
+ CustomNode.displayName = 'CustomNode';
58
+
59
+ const nodeTypes = { custom: CustomNode };
60
60
  `;
61
61
  extraImports.push("import { memo } from 'react';");
62
62
  xyflowImports.add("type NodeProps");
@@ -66,21 +66,21 @@ const nodeTypes = { custom: CustomNode };
66
66
  // Drag and drop
67
67
  if (desc.includes("drag") && desc.includes("drop") || desc.includes("sidebar")) {
68
68
  xyflowImports.add("useReactFlow");
69
- beforeReturn += `
70
- const { screenToFlowPosition, addNodes } = useReactFlow();
71
-
72
- const onDragOver = useCallback((event: React.DragEvent) => {
73
- event.preventDefault();
74
- event.dataTransfer.dropEffect = 'move';
75
- }, []);
76
-
77
- const onDrop = useCallback((event: React.DragEvent) => {
78
- event.preventDefault();
79
- const type = event.dataTransfer.getData('application/reactflow');
80
- if (!type) return;
81
- const position = screenToFlowPosition({ x: event.clientX, y: event.clientY });
82
- addNodes({ id: crypto.randomUUID(), type, position, data: { label: 'New Node' } });
83
- }, [screenToFlowPosition, addNodes]);
69
+ beforeReturn += `
70
+ const { screenToFlowPosition, addNodes } = useReactFlow();
71
+
72
+ const onDragOver = useCallback((event: React.DragEvent) => {
73
+ event.preventDefault();
74
+ event.dataTransfer.dropEffect = 'move';
75
+ }, []);
76
+
77
+ const onDrop = useCallback((event: React.DragEvent) => {
78
+ event.preventDefault();
79
+ const type = event.dataTransfer.getData('application/reactflow');
80
+ if (!type) return;
81
+ const position = screenToFlowPosition({ x: event.clientX, y: event.clientY });
82
+ addNodes({ id: crypto.randomUUID(), type, position, data: { label: 'New Node' } });
83
+ }, [screenToFlowPosition, addNodes]);
84
84
  `;
85
85
  extraImports.push("import { useCallback } from 'react';");
86
86
  flowProps.push("onDragOver={onDragOver}", "onDrop={onDrop}");
@@ -93,27 +93,27 @@ const nodeTypes = { custom: CustomNode };
93
93
  if (desc.includes("dag") || desc.includes("cycle") || desc.includes("pipeline")) {
94
94
  xyflowImports.add("getOutgoers");
95
95
  xyflowImports.add("useReactFlow");
96
- beforeReturn += `
97
- const { getNodes, getEdges } = useReactFlow();
98
-
99
- const isValidConnection = useCallback((connection: Connection) => {
100
- const allNodes = getNodes();
101
- const allEdges = getEdges();
102
- const target = allNodes.find((n) => n.id === connection.target);
103
- const source = allNodes.find((n) => n.id === connection.source);
104
- if (!target || !source) return false;
105
- // Prevent cycles
106
- const hasCycle = (node: Node, visited = new Set<string>()): boolean => {
107
- if (visited.has(node.id)) return false;
108
- visited.add(node.id);
109
- if (node.id === source.id) return true;
110
- for (const outgoer of getOutgoers(node, allNodes, allEdges)) {
111
- if (hasCycle(outgoer, visited)) return true;
112
- }
113
- return false;
114
- };
115
- return !hasCycle(target);
116
- }, [getNodes, getEdges]);
96
+ beforeReturn += `
97
+ const { getNodes, getEdges } = useReactFlow();
98
+
99
+ const isValidConnection = useCallback((connection: Connection) => {
100
+ const allNodes = getNodes();
101
+ const allEdges = getEdges();
102
+ const target = allNodes.find((n) => n.id === connection.target);
103
+ const source = allNodes.find((n) => n.id === connection.source);
104
+ if (!target || !source) return false;
105
+ // Prevent cycles
106
+ const hasCycle = (node: Node, visited = new Set<string>()): boolean => {
107
+ if (visited.has(node.id)) return false;
108
+ visited.add(node.id);
109
+ if (node.id === source.id) return true;
110
+ for (const outgoer of getOutgoers(node, allNodes, allEdges)) {
111
+ if (hasCycle(outgoer, visited)) return true;
112
+ }
113
+ return false;
114
+ };
115
+ return !hasCycle(target);
116
+ }, [getNodes, getEdges]);
117
117
  `;
118
118
  xyflowImports.add("type Connection");
119
119
  xyflowImports.add("type Node");
@@ -123,35 +123,35 @@ const nodeTypes = { custom: CustomNode };
123
123
  // Store vs useState
124
124
  if (useStore) {
125
125
  flowProps.push("onNodesChange={onNodesChange}", "onEdgesChange={onEdgesChange}", "onConnect={onConnect}");
126
- storeCode = `
127
- // --- store.ts ---
128
- import { create } from 'zustand';
129
- import { type Node, type Edge, type OnNodesChange, type OnEdgesChange, type OnConnect, applyNodeChanges, applyEdgeChanges, addEdge } from '@xyflow/react';
130
-
131
- const initialNodes: Node[] = [
132
- { id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
133
- { id: '2', position: { x: 250, y: 100 }, data: { label: 'Node 2' } },
134
- ];
135
-
136
- const initialEdges: Edge[] = [
137
- { id: 'e1-2', source: '1', target: '2' },
138
- ];
139
-
140
- type FlowState = {
141
- nodes: Node[]; edges: Edge[];
142
- onNodesChange: OnNodesChange; onEdgesChange: OnEdgesChange; onConnect: OnConnect;
143
- };
144
-
145
- const useFlowStore = create<FlowState>((set, get) => ({
146
- nodes: initialNodes,
147
- edges: initialEdges,
148
- onNodesChange: (changes) => set({ nodes: applyNodeChanges(changes, get().nodes) }),
149
- onEdgesChange: (changes) => set({ edges: applyEdgeChanges(changes, get().edges) }),
150
- onConnect: (connection) => set({ edges: addEdge(connection, get().edges) }),
151
- }));
152
-
153
- const selector = (s: FlowState) => s;
154
- export { useFlowStore, selector };
126
+ storeCode = `
127
+ // --- store.ts ---
128
+ import { create } from 'zustand';
129
+ import { type Node, type Edge, type OnNodesChange, type OnEdgesChange, type OnConnect, applyNodeChanges, applyEdgeChanges, addEdge } from '@xyflow/react';
130
+
131
+ const initialNodes: Node[] = [
132
+ { id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
133
+ { id: '2', position: { x: 250, y: 100 }, data: { label: 'Node 2' } },
134
+ ];
135
+
136
+ const initialEdges: Edge[] = [
137
+ { id: 'e1-2', source: '1', target: '2' },
138
+ ];
139
+
140
+ type FlowState = {
141
+ nodes: Node[]; edges: Edge[];
142
+ onNodesChange: OnNodesChange; onEdgesChange: OnEdgesChange; onConnect: OnConnect;
143
+ };
144
+
145
+ const useFlowStore = create<FlowState>((set, get) => ({
146
+ nodes: initialNodes,
147
+ edges: initialEdges,
148
+ onNodesChange: (changes) => set({ nodes: applyNodeChanges(changes, get().nodes) }),
149
+ onEdgesChange: (changes) => set({ edges: applyEdgeChanges(changes, get().edges) }),
150
+ onConnect: (connection) => set({ edges: addEdge(connection, get().edges) }),
151
+ }));
152
+
153
+ const selector = (s: FlowState) => s;
154
+ export { useFlowStore, selector };
155
155
  `;
156
156
  beforeReturn =
157
157
  ` const { nodes, edges, onNodesChange, onEdgesChange, onConnect } = useFlowStore(selector);\n` +
@@ -164,14 +164,14 @@ export { useFlowStore, selector };
164
164
  imports.add("addEdge");
165
165
  extraImports.push("import { useCallback } from 'react';");
166
166
  beforeReturn =
167
- ` const [nodes, setNodes, onNodesChange] = useNodesState([
168
- { id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
169
- { id: '2', position: { x: 250, y: 100 }, data: { label: 'Node 2' } },
170
- ]);
171
- const [edges, setEdges, onEdgesChange] = useEdgesState([
172
- { id: 'e1-2', source: '1', target: '2' },
173
- ]);
174
- const onConnect = useCallback((conn) => setEdges((eds) => addEdge(conn, eds)), [setEdges]);
167
+ ` const [nodes, setNodes, onNodesChange] = useNodesState([
168
+ { id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
169
+ { id: '2', position: { x: 250, y: 100 }, data: { label: 'Node 2' } },
170
+ ]);
171
+ const [edges, setEdges, onEdgesChange] = useEdgesState([
172
+ { id: 'e1-2', source: '1', target: '2' },
173
+ ]);
174
+ const onConnect = useCallback((conn) => setEdges((eds) => addEdge(conn, eds)), [setEdges]);
175
175
  ` + beforeReturn;
176
176
  flowProps.push("onNodesChange={onNodesChange}", "onEdgesChange={onEdgesChange}", "onConnect={onConnect}");
177
177
  }
package/package.json CHANGED
@@ -1,54 +1,54 @@
1
- {
2
- "name": "@og-mcp/reactflow-mcp",
3
- "version": "1.0.4",
4
- "description": "MCP server that gives AI assistants accurate React Flow (@xyflow/react) v12 documentation, API references, patterns, and code generation",
5
- "main": "dist/index.js",
6
- "bin": {
7
- "reactflow-mcp": "dist/index.js"
8
- },
9
- "scripts": {
10
- "build": "tsc",
11
- "start": "node dist/index.js",
12
- "dev": "tsc --watch"
13
- },
14
- "keywords": [
15
- "mcp",
16
- "model-context-protocol",
17
- "reactflow",
18
- "xyflow",
19
- "react-flow",
20
- "react",
21
- "node-based-ui",
22
- "graph",
23
- "flow",
24
- "ai",
25
- "claude",
26
- "cursor",
27
- "windsurf"
28
- ],
29
- "repository": {
30
- "type": "git",
31
- "url": "https://github.com/codingdud/reactflow-mcp-server.git"
32
- },
33
- "homepage": "https://github.com/codingdud/reactflow-mcp-server#readme",
34
- "bugs": {
35
- "url": "https://github.com/codingdud/reactflow-mcp-server/issues"
36
- },
37
- "author": "Orkait",
38
- "license": "MIT",
39
- "engines": {
40
- "node": ">=18"
41
- },
42
- "files": [
43
- "dist",
44
- "LICENSE",
45
- "README.md"
46
- ],
47
- "dependencies": {
48
- "@modelcontextprotocol/sdk": "^1.17.0"
49
- },
50
- "devDependencies": {
51
- "@types/node": "^20.0.0",
52
- "typescript": "^5.5.0"
53
- }
54
- }
1
+ {
2
+ "name": "@og-mcp/reactflow-mcp",
3
+ "version": "1.0.6",
4
+ "description": "MCP server that gives AI assistants accurate React Flow (@xyflow/react) v12 documentation, API references, patterns, and code generation",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "reactflow-mcp": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node dist/index.js",
12
+ "dev": "tsc --watch"
13
+ },
14
+ "keywords": [
15
+ "mcp",
16
+ "model-context-protocol",
17
+ "reactflow",
18
+ "xyflow",
19
+ "react-flow",
20
+ "react",
21
+ "node-based-ui",
22
+ "graph",
23
+ "flow",
24
+ "ai",
25
+ "claude",
26
+ "cursor",
27
+ "windsurf"
28
+ ],
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/codingdud/reactflow-mcp-server.git"
32
+ },
33
+ "homepage": "https://github.com/codingdud/reactflow-mcp-server#readme",
34
+ "bugs": {
35
+ "url": "https://github.com/codingdud/reactflow-mcp-server/issues"
36
+ },
37
+ "author": "Orkait",
38
+ "license": "MIT",
39
+ "engines": {
40
+ "node": ">=18"
41
+ },
42
+ "files": [
43
+ "dist",
44
+ "LICENSE",
45
+ "README.md"
46
+ ],
47
+ "dependencies": {
48
+ "@modelcontextprotocol/sdk": "^1.17.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^20.0.0",
52
+ "typescript": "^5.5.0"
53
+ }
54
+ }