@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.
@@ -0,0 +1,232 @@
1
+ import { parseFalkorDBConnectionString } from './connection-parser';
2
+ describe('Connection Parser Utility', () => {
3
+ // Mock console.error to avoid noise in test output
4
+ let consoleErrorSpy;
5
+ beforeEach(() => {
6
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
7
+ });
8
+ afterEach(() => {
9
+ consoleErrorSpy.mockRestore();
10
+ });
11
+ describe('parseFalkorDBConnectionString', () => {
12
+ it('should return default options for empty string', () => {
13
+ // Act
14
+ const result = parseFalkorDBConnectionString('');
15
+ // Assert
16
+ expect(result).toEqual({
17
+ host: 'localhost',
18
+ port: 6379
19
+ });
20
+ });
21
+ it('should return default options for undefined input', () => {
22
+ // Act
23
+ const result = parseFalkorDBConnectionString(undefined);
24
+ // Assert
25
+ expect(result).toEqual({
26
+ host: 'localhost',
27
+ port: 6379
28
+ });
29
+ });
30
+ it('should return default options for null input', () => {
31
+ // Act
32
+ const result = parseFalkorDBConnectionString(null);
33
+ // Assert
34
+ expect(result).toEqual({
35
+ host: 'localhost',
36
+ port: 6379
37
+ });
38
+ });
39
+ it('should parse simple host', () => {
40
+ // Act
41
+ const result = parseFalkorDBConnectionString('redis.example.com');
42
+ // Assert
43
+ expect(result).toEqual({
44
+ host: 'redis.example.com',
45
+ port: 6379
46
+ });
47
+ });
48
+ it('should parse host with port', () => {
49
+ // Act
50
+ const result = parseFalkorDBConnectionString('redis.example.com:1234');
51
+ // Assert
52
+ expect(result).toEqual({
53
+ host: 'redis.example.com',
54
+ port: 1234
55
+ });
56
+ });
57
+ it('should parse host with invalid port (use default)', () => {
58
+ // Act
59
+ const result = parseFalkorDBConnectionString('redis.example.com:invalid');
60
+ // Assert
61
+ expect(result).toEqual({
62
+ host: 'redis.example.com',
63
+ port: 6379
64
+ });
65
+ });
66
+ it('should parse connection string with protocol prefix', () => {
67
+ // Act
68
+ const result = parseFalkorDBConnectionString('falkordb://redis.example.com:1234');
69
+ // Assert
70
+ expect(result).toEqual({
71
+ host: 'redis.example.com',
72
+ port: 1234
73
+ });
74
+ });
75
+ it('should parse connection string with username and password', () => {
76
+ // Act
77
+ const result = parseFalkorDBConnectionString('falkordb://user:pass@redis.example.com:1234');
78
+ // Assert
79
+ expect(result).toEqual({
80
+ host: 'redis.example.com',
81
+ port: 1234,
82
+ username: 'user',
83
+ password: 'pass'
84
+ });
85
+ });
86
+ it('should parse connection string with only password', () => {
87
+ // Act
88
+ const result = parseFalkorDBConnectionString('falkordb://mypassword@redis.example.com:1234');
89
+ // Assert
90
+ expect(result).toEqual({
91
+ host: 'redis.example.com',
92
+ port: 1234,
93
+ password: 'mypassword'
94
+ });
95
+ });
96
+ it('should parse connection string with empty username', () => {
97
+ // Act
98
+ const result = parseFalkorDBConnectionString('falkordb://:password@redis.example.com:1234');
99
+ // Assert
100
+ expect(result).toEqual({
101
+ host: 'redis.example.com',
102
+ port: 1234,
103
+ password: 'password'
104
+ });
105
+ });
106
+ it('should parse connection string with empty password', () => {
107
+ // Act
108
+ const result = parseFalkorDBConnectionString('falkordb://username:@redis.example.com:1234');
109
+ // Assert
110
+ expect(result).toEqual({
111
+ host: 'redis.example.com',
112
+ port: 1234,
113
+ username: 'username'
114
+ });
115
+ });
116
+ it('should handle missing host part with default', () => {
117
+ // Act
118
+ const result = parseFalkorDBConnectionString('falkordb://:1234');
119
+ // Assert
120
+ expect(result).toEqual({
121
+ host: 'localhost',
122
+ port: 1234
123
+ });
124
+ });
125
+ it('should handle missing port part with default', () => {
126
+ // Act
127
+ const result = parseFalkorDBConnectionString('falkordb://redis.example.com:');
128
+ // Assert
129
+ expect(result).toEqual({
130
+ host: 'redis.example.com',
131
+ port: 6379
132
+ });
133
+ });
134
+ it('should handle auth with missing host part', () => {
135
+ // Act
136
+ const result = parseFalkorDBConnectionString('falkordb://user:pass@:1234');
137
+ // Assert
138
+ expect(result).toEqual({
139
+ host: 'localhost',
140
+ port: 1234,
141
+ username: 'user',
142
+ password: 'pass'
143
+ });
144
+ });
145
+ it('should handle complex real-world connection string', () => {
146
+ // Act
147
+ const result = parseFalkorDBConnectionString('falkordb://admin:secret123@prod-redis.company.com:16379');
148
+ // Assert
149
+ expect(result).toEqual({
150
+ host: 'prod-redis.company.com',
151
+ port: 16379,
152
+ username: 'admin',
153
+ password: 'secret123'
154
+ });
155
+ });
156
+ it('should handle localhost with auth', () => {
157
+ // Act
158
+ const result = parseFalkorDBConnectionString('falkordb://user:pass@localhost:6379');
159
+ // Assert
160
+ expect(result).toEqual({
161
+ host: 'localhost',
162
+ port: 6379,
163
+ username: 'user',
164
+ password: 'pass'
165
+ });
166
+ });
167
+ it('should handle IPv4 address', () => {
168
+ // Act
169
+ const result = parseFalkorDBConnectionString('falkordb://192.168.1.100:6379');
170
+ // Assert
171
+ expect(result).toEqual({
172
+ host: '192.168.1.100',
173
+ port: 6379
174
+ });
175
+ });
176
+ it('should handle IPv4 address with auth', () => {
177
+ // Act
178
+ const result = parseFalkorDBConnectionString('falkordb://user:pass@192.168.1.100:6379');
179
+ // Assert
180
+ expect(result).toEqual({
181
+ host: '192.168.1.100',
182
+ port: 6379,
183
+ username: 'user',
184
+ password: 'pass'
185
+ });
186
+ });
187
+ it('should return defaults on parsing error and log error', () => {
188
+ // Arrange - create a scenario that might cause parsing issues
189
+ // We'll simulate this by mocking parseInt to throw
190
+ const originalParseInt = global.parseInt;
191
+ global.parseInt = jest.fn(() => {
192
+ throw new Error('Parsing error');
193
+ });
194
+ try {
195
+ // Act
196
+ const result = parseFalkorDBConnectionString('falkordb://host:port');
197
+ // Assert
198
+ expect(result).toEqual({
199
+ host: 'localhost',
200
+ port: 6379
201
+ });
202
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error parsing connection string:', expect.any(Error));
203
+ }
204
+ finally {
205
+ // Cleanup
206
+ global.parseInt = originalParseInt;
207
+ }
208
+ });
209
+ it('should handle edge case with multiple @ symbols', () => {
210
+ // Act
211
+ const result = parseFalkorDBConnectionString('falkordb://user@domain:pass@host:1234');
212
+ // Assert - after fixing parser to use lastIndexOf('@')
213
+ expect(result).toEqual({
214
+ host: 'host',
215
+ port: 1234,
216
+ username: 'user@domain',
217
+ password: 'pass'
218
+ });
219
+ });
220
+ it('should handle edge case with multiple : in auth', () => {
221
+ // Act
222
+ const result = parseFalkorDBConnectionString('falkordb://user:pass:extra@host:1234');
223
+ // Assert - after fixing parser to properly rejoin password with multiple ':'
224
+ expect(result).toEqual({
225
+ host: 'host',
226
+ port: 1234,
227
+ username: 'user',
228
+ password: 'pass:extra'
229
+ });
230
+ });
231
+ });
232
+ });
package/package.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "@falkordb/mcpserver",
3
+ "version": "1.0.1",
4
+ "description": "Model Context Protocol server for FalkorDB graph databases - enables AI assistants to query and manage graph data using natural language",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=18.0.0",
9
+ "npm": ">=8.0.0"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/FalkorDB/FalkorDB-MCPServer.git"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/FalkorDB/FalkorDB-MCPServer/issues"
17
+ },
18
+ "homepage": "https://github.com/FalkorDB/FalkorDB-MCPServer#readme",
19
+ "author": {
20
+ "name": "Katie Mulliken",
21
+ "email": "katie@mulliken.net",
22
+ "url": "https://github.com/SecKatie"
23
+ },
24
+ "license": "MIT",
25
+ "keywords": [
26
+ "mcp",
27
+ "model-context-protocol",
28
+ "falkordb",
29
+ "graph-database",
30
+ "knowledge-graph",
31
+ "ai",
32
+ "claude",
33
+ "opencypher",
34
+ "cypher",
35
+ "redis",
36
+ "graph",
37
+ "database",
38
+ "typescript",
39
+ "server",
40
+ "chatbot",
41
+ "llm",
42
+ "anthropic",
43
+ "neo4j",
44
+ "graph-query"
45
+ ],
46
+ "files": [
47
+ "dist/**/*",
48
+ "README.md",
49
+ "LICENSE",
50
+ ".env.example"
51
+ ],
52
+ "bin": {
53
+ "falkordb-mcp": "./dist/index.js"
54
+ },
55
+ "scripts": {
56
+ "build": "tsc",
57
+ "start": "node dist/index.js",
58
+ "dev": "nodemon --watch 'src/**/*.ts' --exec 'npm run build && npm start'",
59
+ "dev:ts": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts",
60
+ "lint": "eslint . --ext .ts",
61
+ "lint:fix": "eslint . --ext .ts --fix",
62
+ "test": "jest",
63
+ "test:watch": "jest --watch",
64
+ "test:coverage": "jest --coverage",
65
+ "test:ci": "jest --coverage --ci --watchAll=false",
66
+ "inspect": "npm run build && npx -y @modelcontextprotocol/inspector node $PWD/dist/index.js",
67
+ "clean": "rm -rf dist coverage",
68
+ "prepublish": "npm run test:ci && npm run lint && npm run build",
69
+ "prepublishOnly": "npm run clean && npm run test:ci && npm run lint && npm run build"
70
+ },
71
+ "devDependencies": {
72
+ "@types/jest": "^30.0.0",
73
+ "@types/node": "^20.14.0",
74
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
75
+ "@typescript-eslint/parser": "^8.38.0",
76
+ "eslint": "^9.31.0",
77
+ "jest": "^30.0.5",
78
+ "nodemon": "^3.1.10",
79
+ "ts-jest": "^29.4.0",
80
+ "ts-node": "^10.9.2",
81
+ "typescript": "^5.8.3"
82
+ },
83
+ "dependencies": {
84
+ "@modelcontextprotocol/sdk": "^1.17.0",
85
+ "dotenv": "^17.2.1",
86
+ "falkordb": "^6.3.0",
87
+ "platformdirs": "^4.3.8-rc3",
88
+ "redis": "^4.0.0",
89
+ "zod": "^3.23.0"
90
+ },
91
+ "publishConfig": {
92
+ "access": "public",
93
+ "registry": "https://registry.npmjs.org/"
94
+ },
95
+ "funding": {
96
+ "type": "github",
97
+ "url": "https://github.com/sponsors/SecKatie"
98
+ }
99
+ }