@falkordb/mcpserver 1.0.1
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/.env.example +26 -0
- package/LICENSE +21 -0
- package/README.md +412 -0
- package/dist/config/index.js +27 -0
- package/dist/config/index.test.js +23 -0
- package/dist/errors/AppError.js +27 -0
- package/dist/errors/ErrorHandler.js +46 -0
- package/dist/errors/ErrorHandler.test.js +146 -0
- package/dist/index.js +234 -0
- package/dist/mcp/prompts.js +229 -0
- package/dist/mcp/resources.js +26 -0
- package/dist/mcp/tools.js +258 -0
- package/dist/models/mcp-client-config.js +34 -0
- package/dist/models/mcp-client-config.test.js +173 -0
- package/dist/models/mcp.types.js +4 -0
- package/dist/services/falkordb.service.js +175 -0
- package/dist/services/falkordb.service.test.js +489 -0
- package/dist/services/logger.service.js +151 -0
- package/dist/services/logger.service.test.js +115 -0
- package/dist/services/redis.service.js +179 -0
- package/dist/services/redis.service.test.js +399 -0
- package/dist/utils/connection-parser.js +71 -0
- package/dist/utils/connection-parser.test.js +232 -0
- package/package.json +99 -0
package/.env.example
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Environment Configuration
|
|
2
|
+
NODE_ENV=development
|
|
3
|
+
|
|
4
|
+
# MCP Transport Configuration
|
|
5
|
+
# Transport mode: 'stdio' (default) or 'http' (Streamable HTTP)
|
|
6
|
+
MCP_TRANSPORT=stdio
|
|
7
|
+
# Port for HTTP transport (default: 3000)
|
|
8
|
+
# MCP_PORT=3000
|
|
9
|
+
# API key for HTTP transport authentication (required for HTTP mode)
|
|
10
|
+
# MCP_API_KEY=
|
|
11
|
+
|
|
12
|
+
# FalkorDB Configuration
|
|
13
|
+
FALKORDB_HOST=localhost
|
|
14
|
+
FALKORDB_PORT=6379
|
|
15
|
+
FALKORDB_USERNAME=
|
|
16
|
+
FALKORDB_PASSWORD=
|
|
17
|
+
# Set to 'true' to use read-only queries by default (useful for replica instances)
|
|
18
|
+
FALKORDB_DEFAULT_READONLY=false
|
|
19
|
+
|
|
20
|
+
# Redis Configuration (for key-value operations)
|
|
21
|
+
REDIS_URL=redis://localhost:6379
|
|
22
|
+
REDIS_USERNAME=
|
|
23
|
+
REDIS_PASSWORD=
|
|
24
|
+
|
|
25
|
+
# Logging Configuration (optional)
|
|
26
|
+
ENABLE_FILE_LOGGING=false
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 FalkorDB
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
[](https://github.com/falkordb/FalkorDB-MCPServer/actions/workflows/node.yml)
|
|
2
|
+
[](https://codecov.io/gh/falkordb/FalkorDB-MCPServer)
|
|
3
|
+
[](https://github.com/falkordb/FalkorDB-MCPServer/blob/main/LICENSE)
|
|
4
|
+
[](https://discord.com/invite/99y2Ubh6tg)
|
|
5
|
+
[](https://x.com/falkordb)
|
|
6
|
+
[](https://modelcontextprotocol.io)
|
|
7
|
+
|
|
8
|
+
# FalkorDB MCP Server
|
|
9
|
+
|
|
10
|
+
[](https://app.falkordb.cloud)
|
|
11
|
+
|
|
12
|
+
A Model Context Protocol (MCP) server for FalkorDB, allowing AI models to query and interact with graph databases.
|
|
13
|
+
FalkorDB MCP Server enables AI assistants like Claude to interact with FalkorDB graph databases using natural language. Query your graph data, create relationships, and manage your knowledge graph - all through conversational AI.
|
|
14
|
+
|
|
15
|
+
## 🎯 What is this?
|
|
16
|
+
|
|
17
|
+
This server implements the [Model Context Protocol (MCP)](https://modelcontextprotocol.io), allowing AI models to:
|
|
18
|
+
- **Query graph databases** using OpenCypher (with read-only mode support)
|
|
19
|
+
- **Create and manage** nodes and relationships
|
|
20
|
+
- **Store and retrieve** key-value data
|
|
21
|
+
- **List and explore** multiple graphs
|
|
22
|
+
- **Delete graphs** when needed
|
|
23
|
+
- **Read-only queries** for replica instances or to prevent accidental writes
|
|
24
|
+
|
|
25
|
+
## 🚀 Quick Start
|
|
26
|
+
|
|
27
|
+
### Prerequisites
|
|
28
|
+
|
|
29
|
+
- Node.js 18+
|
|
30
|
+
- FalkorDB instance (running locally or remotely)
|
|
31
|
+
- Claude Desktop app (for AI integration)
|
|
32
|
+
|
|
33
|
+
### Running from npm
|
|
34
|
+
|
|
35
|
+
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"falkordb": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": [
|
|
43
|
+
"-y",
|
|
44
|
+
"@falkordb/mcpserver@latest"
|
|
45
|
+
],
|
|
46
|
+
"env": {
|
|
47
|
+
"FALKORDB_HOST": "localhost",
|
|
48
|
+
"FALKORDB_PORT": "6379",
|
|
49
|
+
"FALKORDB_USERNAME": "",
|
|
50
|
+
"FALKORDB_PASSWORD": ""
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Installation
|
|
58
|
+
|
|
59
|
+
1. **Clone and install:**
|
|
60
|
+
```bash
|
|
61
|
+
git clone https://github.com/FalkorDB/FalkorDB-MCPServer.git
|
|
62
|
+
cd FalkorDB-MCPServer
|
|
63
|
+
npm install
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
2. **Configure environment:**
|
|
67
|
+
```bash
|
|
68
|
+
cp .env.example .env
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Edit `.env`:
|
|
72
|
+
```env
|
|
73
|
+
# Environment Configuration
|
|
74
|
+
NODE_ENV=development
|
|
75
|
+
|
|
76
|
+
# FalkorDB Configuration
|
|
77
|
+
FALKORDB_HOST=localhost
|
|
78
|
+
FALKORDB_PORT=6379
|
|
79
|
+
FALKORDB_USERNAME= # Optional
|
|
80
|
+
FALKORDB_PASSWORD= # Optional
|
|
81
|
+
FALKORDB_DEFAULT_READONLY=false # Set to 'true' for read-only mode (useful for replicas)
|
|
82
|
+
|
|
83
|
+
# Redis Configuration (for key-value operations)
|
|
84
|
+
REDIS_URL=redis://localhost:6379
|
|
85
|
+
REDIS_USERNAME= # Optional
|
|
86
|
+
REDIS_PASSWORD= # Optional
|
|
87
|
+
|
|
88
|
+
# Logging Configuration (optional)
|
|
89
|
+
ENABLE_FILE_LOGGING=false
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
3. **Build the project:**
|
|
93
|
+
```bash
|
|
94
|
+
npm run build
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 🤖 Claude Desktop Integration
|
|
98
|
+
|
|
99
|
+
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"mcpServers": {
|
|
104
|
+
"falkordb": {
|
|
105
|
+
"command": "node",
|
|
106
|
+
"args": [
|
|
107
|
+
"/absolute/path/to/falkordb-mcpserver/dist/index.js"
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Restart Claude Desktop and you'll see the FalkorDB tools available!
|
|
115
|
+
|
|
116
|
+
## 📚 Available MCP Tools
|
|
117
|
+
|
|
118
|
+
Once connected, you can ask Claude to:
|
|
119
|
+
|
|
120
|
+
### 🔍 Query Graphs
|
|
121
|
+
```text
|
|
122
|
+
"Show me all people who know each other"
|
|
123
|
+
"Find the shortest path between two nodes"
|
|
124
|
+
"What relationships does John have?"
|
|
125
|
+
"Run a read-only query on the replica instance"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Note:** The `query_graph` tool now supports a `readOnly` parameter to execute queries in read-only mode using `GRAPH.RO_QUERY`. This is ideal for:
|
|
129
|
+
- Running queries on replica instances
|
|
130
|
+
- Preventing accidental write operations
|
|
131
|
+
- Ensuring data integrity in production environments
|
|
132
|
+
|
|
133
|
+
There's also a dedicated `query_graph_readonly` tool that always executes queries in read-only mode.
|
|
134
|
+
|
|
135
|
+
### 📝 Manage Data
|
|
136
|
+
```text
|
|
137
|
+
"Create a new person named Alice who knows Bob"
|
|
138
|
+
"Add a 'WORKS_AT' relationship between Alice and TechCorp"
|
|
139
|
+
"Store my API key in the database"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 📊 Explore Structure
|
|
143
|
+
```text
|
|
144
|
+
"List all available graphs"
|
|
145
|
+
"Show me the structure of the user_data graph"
|
|
146
|
+
"Delete the old_test graph"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 🛠️ Development
|
|
150
|
+
|
|
151
|
+
### Commands
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Development with hot-reload
|
|
155
|
+
npm run dev
|
|
156
|
+
|
|
157
|
+
# Development with TypeScript execution (faster startup)
|
|
158
|
+
npm run dev:ts
|
|
159
|
+
|
|
160
|
+
# Run tests
|
|
161
|
+
npm test
|
|
162
|
+
|
|
163
|
+
# Run tests in watch mode
|
|
164
|
+
npm run test:watch
|
|
165
|
+
|
|
166
|
+
# Run tests with coverage report
|
|
167
|
+
npm run test:coverage
|
|
168
|
+
|
|
169
|
+
# Lint code
|
|
170
|
+
npm run lint
|
|
171
|
+
|
|
172
|
+
# Lint and auto-fix issues
|
|
173
|
+
npm run lint:fix
|
|
174
|
+
|
|
175
|
+
# Build for production
|
|
176
|
+
npm run build
|
|
177
|
+
|
|
178
|
+
# Start production server
|
|
179
|
+
npm start
|
|
180
|
+
|
|
181
|
+
# Inspect MCP server with debugging tools
|
|
182
|
+
npm run inspect
|
|
183
|
+
|
|
184
|
+
# Clean build artifacts
|
|
185
|
+
npm run clean
|
|
186
|
+
|
|
187
|
+
# Full CI pipeline (test, lint, build)
|
|
188
|
+
npm run prepublish
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Project Structure
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
src/
|
|
195
|
+
├── index.ts # MCP server entry point
|
|
196
|
+
├── services/ # Core business logic
|
|
197
|
+
│ ├── falkordb.service.ts # FalkorDB operations
|
|
198
|
+
│ ├── redis.service.ts # Key-value operations
|
|
199
|
+
│ └── logger.service.ts # Logging and MCP notifications
|
|
200
|
+
├── mcp/ # MCP protocol implementations
|
|
201
|
+
│ ├── tools.ts # MCP tool definitions
|
|
202
|
+
│ ├── resources.ts # MCP resource definitions
|
|
203
|
+
│ └── prompts.ts # MCP prompt definitions
|
|
204
|
+
├── errors/ # Error handling framework
|
|
205
|
+
│ ├── AppError.ts # Custom error classes
|
|
206
|
+
│ └── ErrorHandler.ts # Global error handling
|
|
207
|
+
├── config/ # Configuration management
|
|
208
|
+
│ └── index.ts # Environment configuration
|
|
209
|
+
├── models/ # TypeScript type definitions
|
|
210
|
+
│ ├── mcp.types.ts # MCP protocol types
|
|
211
|
+
│ └── mcp-client-config.ts # Configuration models
|
|
212
|
+
└── utils/ # Utility functions
|
|
213
|
+
└── connection-parser.ts # Connection string parsing
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## 🔧 Advanced Configuration
|
|
217
|
+
|
|
218
|
+
### Transport Modes
|
|
219
|
+
|
|
220
|
+
The server supports two transport modes:
|
|
221
|
+
|
|
222
|
+
#### stdio (default)
|
|
223
|
+
Used for direct integration with AI clients like Claude Desktop. Communication happens via standard input/output.
|
|
224
|
+
|
|
225
|
+
```env
|
|
226
|
+
MCP_TRANSPORT=stdio
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### Streamable HTTP
|
|
230
|
+
Exposes the MCP server over HTTP for remote or networked access. Supports multiple concurrent sessions via the MCP Streamable HTTP protocol.
|
|
231
|
+
|
|
232
|
+
```env
|
|
233
|
+
MCP_TRANSPORT=http
|
|
234
|
+
MCP_PORT=3000
|
|
235
|
+
MCP_API_KEY=your-secret-api-key # Optional but recommended
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
When using HTTP transport, clients connect by sending a POST request with an `initialize` message. The server returns an `Mcp-Session-Id` header that must be included in subsequent requests. API key authentication is enforced via the `Authorization: Bearer <key>` header when `MCP_API_KEY` is set.
|
|
239
|
+
|
|
240
|
+
**Testing HTTP transport:**
|
|
241
|
+
|
|
242
|
+
1. Start the server:
|
|
243
|
+
```bash
|
|
244
|
+
MCP_TRANSPORT=http MCP_PORT=3000 npm start
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
2. Use the MCP Inspector to connect:
|
|
248
|
+
```bash
|
|
249
|
+
npx @modelcontextprotocol/inspector --transport streamable-http --url http://localhost:3000
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
> **Note:** `npm run inspect` uses stdio transport. For HTTP, start the server and inspector separately as shown above.
|
|
253
|
+
|
|
254
|
+
**API Key Authentication:**
|
|
255
|
+
|
|
256
|
+
When `MCP_API_KEY` is set, all HTTP requests must include an `Authorization` header:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
MCP_TRANSPORT=http MCP_API_KEY=my-secret-key npm start
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Clients must then send:
|
|
263
|
+
```text
|
|
264
|
+
Authorization: Bearer my-secret-key
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Requests without a valid key receive a `401 Unauthorized` response. Auth is only enforced in HTTP mode — stdio mode ignores `MCP_API_KEY` since only the parent process can communicate.
|
|
268
|
+
|
|
269
|
+
### Using with Docker
|
|
270
|
+
|
|
271
|
+
Build and run the MCP server in a Docker container (defaults to HTTP transport):
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
docker build -t falkordb-mcpserver .
|
|
275
|
+
docker run -p 3000:3000 \
|
|
276
|
+
-e FALKORDB_HOST=host.docker.internal \
|
|
277
|
+
-e FALKORDB_PORT=6379 \
|
|
278
|
+
-e MCP_API_KEY=your-secret-key \
|
|
279
|
+
falkordb-mcpserver
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Or use with `docker-compose` alongside FalkorDB:
|
|
283
|
+
|
|
284
|
+
```yaml
|
|
285
|
+
services:
|
|
286
|
+
falkordb:
|
|
287
|
+
image: falkordb/falkordb:latest
|
|
288
|
+
ports:
|
|
289
|
+
- "6379:6379"
|
|
290
|
+
|
|
291
|
+
mcp-server:
|
|
292
|
+
build: .
|
|
293
|
+
ports:
|
|
294
|
+
- "3000:3000"
|
|
295
|
+
environment:
|
|
296
|
+
- FALKORDB_HOST=falkordb
|
|
297
|
+
- FALKORDB_PORT=6379
|
|
298
|
+
- MCP_TRANSPORT=http
|
|
299
|
+
- MCP_PORT=3000
|
|
300
|
+
- MCP_API_KEY=your-secret-key
|
|
301
|
+
depends_on:
|
|
302
|
+
- falkordb
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Using with Remote FalkorDB
|
|
306
|
+
|
|
307
|
+
For cloud-hosted FalkorDB instances:
|
|
308
|
+
|
|
309
|
+
```env
|
|
310
|
+
FALKORDB_HOST=your-instance.falkordb.com
|
|
311
|
+
FALKORDB_PORT=6379
|
|
312
|
+
FALKORDB_USERNAME=your-username
|
|
313
|
+
FALKORDB_PASSWORD=your-secure-password
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Read-Only Mode for Replica Instances
|
|
317
|
+
|
|
318
|
+
If you're connecting to a FalkorDB replica instance or want to ensure no write operations are performed, you can enable read-only mode by default:
|
|
319
|
+
|
|
320
|
+
```env
|
|
321
|
+
FALKORDB_DEFAULT_READONLY=true
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
This will make all queries execute using `GRAPH.RO_QUERY` by default. You can still override this per-query by setting the `readOnly` parameter in the `query_graph` tool.
|
|
325
|
+
|
|
326
|
+
**Use cases:**
|
|
327
|
+
- **Replica instances**: Prevent writes to read replicas in replication setups
|
|
328
|
+
- **Production safety**: Ensure critical data isn't accidentally modified
|
|
329
|
+
- **Reporting/analytics**: Run queries for dashboards without risk of data changes
|
|
330
|
+
- **Multi-tenant environments**: Provide read-only access to certain users
|
|
331
|
+
|
|
332
|
+
### Running Multiple Instances
|
|
333
|
+
|
|
334
|
+
You can run multiple MCP servers for different FalkorDB instances:
|
|
335
|
+
|
|
336
|
+
```json
|
|
337
|
+
{
|
|
338
|
+
"mcpServers": {
|
|
339
|
+
"falkordb-dev": {
|
|
340
|
+
"command": "node",
|
|
341
|
+
"args": ["path/to/server/dist/index.js"],
|
|
342
|
+
"env": {
|
|
343
|
+
"FALKORDB_HOST": "dev.falkordb.local",
|
|
344
|
+
"FALKORDB_DEFAULT_READONLY": "false"
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"falkordb-prod-replica": {
|
|
348
|
+
"command": "node",
|
|
349
|
+
"args": ["path/to/server/dist/index.js"],
|
|
350
|
+
"env": {
|
|
351
|
+
"FALKORDB_HOST": "replica.falkordb.com",
|
|
352
|
+
"FALKORDB_DEFAULT_READONLY": "true"
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## 📖 Example Usage
|
|
360
|
+
|
|
361
|
+
Here's what you can do once connected:
|
|
362
|
+
|
|
363
|
+
```cypher
|
|
364
|
+
// Claude can help you write queries like:
|
|
365
|
+
MATCH (p:Person)-[:KNOWS]->(friend:Person)
|
|
366
|
+
WHERE p.name = 'Alice'
|
|
367
|
+
RETURN friend.name, friend.age
|
|
368
|
+
|
|
369
|
+
// Or create complex data structures:
|
|
370
|
+
CREATE (alice:Person {name: 'Alice', age: 30})
|
|
371
|
+
CREATE (bob:Person {name: 'Bob', age: 25})
|
|
372
|
+
CREATE (alice)-[:KNOWS {since: 2020}]->(bob)
|
|
373
|
+
|
|
374
|
+
// And even analyze your graph:
|
|
375
|
+
MATCH path = shortestPath((start:Person)-[*]-(end:Person))
|
|
376
|
+
WHERE start.name = 'Alice' AND end.name = 'Charlie'
|
|
377
|
+
RETURN path
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## 🤝 Contributing
|
|
381
|
+
|
|
382
|
+
We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.md) for details.
|
|
383
|
+
|
|
384
|
+
### Development Workflow
|
|
385
|
+
|
|
386
|
+
1. Fork the repository
|
|
387
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
388
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
389
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
390
|
+
5. Open a Pull Request
|
|
391
|
+
|
|
392
|
+
## 📝 License
|
|
393
|
+
|
|
394
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
395
|
+
|
|
396
|
+
## 🙏 Acknowledgments
|
|
397
|
+
|
|
398
|
+
- Built on the [Model Context Protocol SDK](https://github.com/anthropics/model-context-protocol)
|
|
399
|
+
- Powered by [FalkorDB](https://www.falkordb.com/)
|
|
400
|
+
- Inspired by the growing MCP ecosystem
|
|
401
|
+
|
|
402
|
+
## 🔗 Resources
|
|
403
|
+
|
|
404
|
+
- [FalkorDB Documentation](https://docs.falkordb.com)
|
|
405
|
+
- [MCP Specification](https://modelcontextprotocol.io/docs)
|
|
406
|
+
- [OpenCypher Query Language](https://opencypher.org/)
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
<p align="center">
|
|
411
|
+
Made with ❤️ by the FalkorDB team & Katie Mulliken
|
|
412
|
+
</p>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
// Load environment variables from .env file
|
|
3
|
+
dotenv.config({
|
|
4
|
+
quiet: true,
|
|
5
|
+
});
|
|
6
|
+
export const config = {
|
|
7
|
+
server: {
|
|
8
|
+
port: parseInt(process.env.PORT || process.env.MCP_PORT || '3000'),
|
|
9
|
+
nodeEnv: process.env.NODE_ENV || 'development',
|
|
10
|
+
},
|
|
11
|
+
falkorDB: {
|
|
12
|
+
host: process.env.FALKORDB_HOST || 'localhost',
|
|
13
|
+
port: parseInt(process.env.FALKORDB_PORT || '6379'),
|
|
14
|
+
username: process.env.FALKORDB_USERNAME || '',
|
|
15
|
+
password: process.env.FALKORDB_PASSWORD || '',
|
|
16
|
+
defaultReadOnly: process.env.FALKORDB_DEFAULT_READONLY === 'true',
|
|
17
|
+
},
|
|
18
|
+
redis: {
|
|
19
|
+
url: process.env.REDIS_URL || 'redis://localhost:6379',
|
|
20
|
+
username: process.env.REDIS_USERNAME || '',
|
|
21
|
+
password: process.env.REDIS_PASSWORD || '',
|
|
22
|
+
},
|
|
23
|
+
mcp: {
|
|
24
|
+
transport: (process.env.MCP_TRANSPORT || 'stdio'),
|
|
25
|
+
apiKey: process.env.MCP_API_KEY || '',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { config } from '../config';
|
|
2
|
+
describe('Config', () => {
|
|
3
|
+
test('should have server configuration', () => {
|
|
4
|
+
expect(config).toHaveProperty('server');
|
|
5
|
+
expect(config.server).toHaveProperty('port');
|
|
6
|
+
expect(config.server).toHaveProperty('nodeEnv');
|
|
7
|
+
});
|
|
8
|
+
test('should have FalkorDB configuration', () => {
|
|
9
|
+
expect(config).toHaveProperty('falkorDB');
|
|
10
|
+
expect(config.falkorDB).toHaveProperty('host');
|
|
11
|
+
expect(config.falkorDB).toHaveProperty('port');
|
|
12
|
+
expect(config.falkorDB).toHaveProperty('username');
|
|
13
|
+
expect(config.falkorDB).toHaveProperty('password');
|
|
14
|
+
expect(config.falkorDB).toHaveProperty('defaultReadOnly');
|
|
15
|
+
expect(typeof config.falkorDB.defaultReadOnly).toBe('boolean');
|
|
16
|
+
});
|
|
17
|
+
test('should have MCP configuration', () => {
|
|
18
|
+
expect(config).toHaveProperty('mcp');
|
|
19
|
+
expect(config.mcp).toHaveProperty('transport');
|
|
20
|
+
expect(config.mcp).toHaveProperty('apiKey');
|
|
21
|
+
expect(['stdio', 'http']).toContain(config.mcp.transport);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom application error class that extends the built-in Error
|
|
3
|
+
* Follows Node.js best practices for error handling in MCP servers
|
|
4
|
+
*/
|
|
5
|
+
export class AppError extends Error {
|
|
6
|
+
name;
|
|
7
|
+
isOperational;
|
|
8
|
+
constructor(name, description, isOperational = true) {
|
|
9
|
+
super(description);
|
|
10
|
+
// Restore prototype chain for proper instanceof checks
|
|
11
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
12
|
+
this.name = name;
|
|
13
|
+
this.isOperational = isOperational;
|
|
14
|
+
// Capture stack trace, excluding constructor call from it
|
|
15
|
+
Error.captureStackTrace(this, this.constructor);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Common error types for the MCP application
|
|
20
|
+
*/
|
|
21
|
+
export const CommonErrors = {
|
|
22
|
+
CONNECTION_FAILED: 'CONNECTION_FAILED',
|
|
23
|
+
INVALID_INPUT: 'INVALID_INPUT',
|
|
24
|
+
RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',
|
|
25
|
+
OPERATION_FAILED: 'OPERATION_FAILED',
|
|
26
|
+
INITIALIZATION_FAILED: 'INITIALIZATION_FAILED'
|
|
27
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { AppError } from './AppError.js';
|
|
2
|
+
import { logger } from '../services/logger.service.js';
|
|
3
|
+
/**
|
|
4
|
+
* Centralized error handler following Node.js best practices for MCP servers
|
|
5
|
+
* Handles logging, monitoring, and determining crash behavior
|
|
6
|
+
*/
|
|
7
|
+
export class ErrorHandler {
|
|
8
|
+
async handleError(err) {
|
|
9
|
+
await this.logError(err);
|
|
10
|
+
await this.determineIfOperationalError(err);
|
|
11
|
+
}
|
|
12
|
+
isTrustedError(error) {
|
|
13
|
+
if (error instanceof AppError) {
|
|
14
|
+
return error.isOperational;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
async logError(err) {
|
|
19
|
+
await logger.error('Unhandled error occurred', err, {
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
errorType: err.constructor.name
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async determineIfOperationalError(err) {
|
|
25
|
+
if (this.isTrustedError(err)) {
|
|
26
|
+
await logger.info('Operational error handled gracefully', {
|
|
27
|
+
errorName: err.name,
|
|
28
|
+
errorMessage: err.message
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
await logger.error('Programmer error detected - may require process restart', err, {
|
|
33
|
+
recommendation: 'Review code for bugs',
|
|
34
|
+
severity: 'critical'
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
crashIfUntrustedError(error) {
|
|
39
|
+
if (!this.isTrustedError(error)) {
|
|
40
|
+
logger.errorSync('Crashing process due to untrusted error', error);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Export singleton instance
|
|
46
|
+
export const errorHandler = new ErrorHandler();
|