#
tokens: 22009/50000 52/52 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .editorconfig
├── .github
│   └── workflows
│       └── publish.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .verdaccio
│   └── config.yml
├── .vscode
│   └── extensions.json
├── DEVELOP.md
├── eslint.config.js
├── jest.config.ts
├── jest.preset.js
├── libs
│   └── graphrag-memory
│       ├── eslint.config.js
│       ├── jest.config.ts
│       ├── package.json
│       ├── project.json
│       ├── README.md
│       ├── src
│       │   ├── index.ts
│       │   └── lib
│       │       ├── graphrag-memory.spec.ts
│       │       └── graphrag-memory.ts
│       ├── tsconfig.json
│       ├── tsconfig.lib.json
│       └── tsconfig.spec.json
├── nx.json
├── package-lock.json
├── package.json
├── project.json
├── README.md
├── servers
│   ├── mcp-json-memory
│   │   ├── eslint.config.cjs
│   │   ├── jest.config.ts
│   │   ├── package.json
│   │   ├── project.json
│   │   ├── src
│   │   │   ├── assets
│   │   │   │   └── .gitkeep
│   │   │   ├── json-memory.ts
│   │   │   └── main.ts
│   │   ├── tsconfig.app.json
│   │   ├── tsconfig.json
│   │   └── tsconfig.spec.json
│   ├── mcp-neo4j-cypher
│   │   ├── .flake8
│   │   ├── .python-version
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── src
│   │   │   └── mcp_neo4j_cypher
│   │   │       ├── __init__.py
│   │   │       ├── __pycache__
│   │   │       │   ├── __init__.cpython-312.pyc
│   │   │       │   └── server.cpython-312.pyc
│   │   │       └── server.py
│   │   └── uv.lock
│   └── mcp-neo4j-memory
│       ├── eslint.config.js
│       ├── jest.config.ts
│       ├── project.json
│       ├── src
│       │   ├── assets
│       │   │   └── .gitkeep
│       │   ├── main.ts
│       │   └── neo4j-memory.ts
│       ├── tsconfig.app.json
│       ├── tsconfig.json
│       └── tsconfig.spec.json
└── tsconfig.base.json
```

# Files

--------------------------------------------------------------------------------
/servers/mcp-json-memory/src/assets/.gitkeep:
--------------------------------------------------------------------------------

```
1 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/src/assets/.gitkeep:
--------------------------------------------------------------------------------

```
1 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-cypher/.python-version:
--------------------------------------------------------------------------------

```
1 | 3.12.7
2 | 
```

--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------

```
1 | {
2 |   "singleQuote": true
3 | }
4 | 
```

--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------

```
1 | # Add files here to ignore them from prettier formatting
2 | /dist
3 | /coverage
4 | /.nx/cache
5 | /.nx/workspace-data
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-cypher/.flake8:
--------------------------------------------------------------------------------

```
 1 | [flake8]
 2 | exclude =
 3 | 	.git,
 4 | 	__pycache__,
 5 | 	build,
 6 | 	dist,
 7 | 	.tox,
 8 | 	venv,
 9 | 	.venv,
10 | 	.pytest_cache
11 | max-line-length = 120
12 | 
```

--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------

```
 1 | # Editor configuration, see http://editorconfig.org
 2 | root = true
 3 | 
 4 | [*]
 5 | charset = utf-8
 6 | indent_style = space
 7 | indent_size = 2
 8 | insert_final_newline = true
 9 | trim_trailing_whitespace = true
10 | 
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 | 
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
 2 | 
 3 | # compiled output
 4 | dist
 5 | tmp
 6 | /out-tsc
 7 | 
 8 | # dependencies
 9 | node_modules
10 | 
11 | # IDEs and editors
12 | /.idea
13 | .project
14 | .classpath
15 | .c9/
16 | *.launch
17 | .settings/
18 | *.sublime-workspace
19 | 
20 | # python venc
21 | .venv
22 | 
23 | # IDE - VSCode
24 | .vscode/*
25 | !.vscode/settings.json
26 | !.vscode/tasks.json
27 | !.vscode/launch.json
28 | !.vscode/extensions.json
29 | 
30 | # misc
31 | /.sass-cache
32 | /connect.lock
33 | /coverage
34 | /libpeerconnection.log
35 | npm-debug.log
36 | yarn-error.log
37 | testem.log
38 | /typings
39 | 
40 | # System Files
41 | .DS_Store
42 | Thumbs.db
43 | 
44 | .nx/cache
45 | .nx/workspace-data
46 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | # graphrag-memory
 2 | 
 3 | This library was generated with [Nx](https://nx.dev).
 4 | 
 5 | ## Building
 6 | 
 7 | Run `nx build graphrag-memory` to build the library.
 8 | 
 9 | ## Running unit tests
10 | 
11 | Run `nx test graphrag-memory` to execute the unit tests via [Jest](https://jestjs.io).
12 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | # Neo4j MCP Clients & Servers
 2 | 
 3 | Model Context Protocol (MCP) is a [standardized protocol](https://modelcontextprotocol.io/introduction) for managing context between large language models (LLMs) and external systems. 
 4 | 
 5 | This lets you use Claude Desktop, or any MCP Client, to use natural language to accomplish things with Neo4j and your Aura account, e.g.:
 6 | 
 7 | * `What is in this graph?`
 8 | 
 9 | ## Servers
10 | 
11 | ### `mcp-neo4j-cypher` - natural language to Cypher queries
12 | 
13 | ### `mcp-neo4j-memory` - knowledge graph memory stored in Neo4j
14 | 
15 | ### `mcp-json-memory` - knowledge graph memory stored in a file
16 | 
17 | A reference server for modeling memory as a knowledge graph.
18 | 
19 | ## Contributing
20 | 
21 | Contributions are welcome! Please feel free to submit a Pull Request.
22 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-cypher/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Neo4j MCP Server
  2 | 
  3 | ## Overview
  4 | A Model Context Protocol (MCP) server implementation that provides database interaction and allows graph exploration capabilities through neo4j. This server enables running Cypher graph queries, analyzing complex domain data, and automatically generating business insights that can be enhanced with Claude's analysis when an Anthropic API key is provided.
  5 | 
  6 | ## Components
  7 | 
  8 | ### Resources
  9 | 
 10 | ### Prompts
 11 | The server provides a demonstration prompt:
 12 | - `mcp-demo`: Interactive prompt that guides users through database operations
 13 |   - Generates appropriate database schemas and sample data
 14 | 
 15 | ### Tools
 16 | The server offers six core tools:
 17 | 
 18 | #### Query Tools
 19 | - `read-neo4j-cypher`
 20 |    - Execute Cypher read queries to read data from the database
 21 |    - Input: 
 22 |      - `query` (string): The Cypher query to execute
 23 |    - Returns: Query results as array of objects
 24 | 
 25 | - `write-neo4j-cypher`
 26 |    - Execute updating Cypher queries
 27 |    - Input:
 28 |      - `query` (string): The Cypher update query
 29 |    - Returns: a result summary counter with `{ nodes_updated: number, relationships_created: number, ... }`
 30 | 
 31 | #### Schema Tools
 32 | - `get-neo4j-schema`
 33 |    - Get a list of all nodes types in the graph database, their attributes with name, type and relationships to other node types
 34 |    - No input required
 35 |    - Returns: List of node label with two dictionaries one for attributes and one for relationships
 36 | 
 37 | ## Usage with Claude Desktop
 38 | 
 39 | ### Released Package
 40 | 
 41 | Can be found on PyPi https://pypi.org/project/mcp-neo4j-cypher/
 42 | 
 43 | Add the server to your `claude_desktop_config.json` with configuration of 
 44 | 
 45 | * db-url
 46 | * username
 47 | * password
 48 | 
 49 | ```json
 50 | "mcpServers": {
 51 |   "neo4j": {
 52 |     "command": "uvx",
 53 |     "args": [
 54 |       "mcp-neo4j-cypher",
 55 |       "--db-url",
 56 |       "bolt://localhost",
 57 |       "--username",
 58 |       "neo4j",
 59 |       "--password",
 60 |       "<your-password>"
 61 |     ]
 62 |   }
 63 | }
 64 | ```
 65 | 
 66 | Here is an example connection for the movie database with Movie, Person (Actor, Director), Genre, User and ratings.
 67 | 
 68 | ```json
 69 | {
 70 |   "mcpServers": {
 71 |     "movies-neo4j": {
 72 |       "command": "uvx",
 73 |       "args": ["mcp-neo4j-cypher", 
 74 |       "--db-url", "neo4j+s://demo.neo4jlabs.com", 
 75 |       "--user", "recommendations", 
 76 |       "--password", "recommendations"]
 77 |     }   
 78 |   }
 79 | }
 80 | ```
 81 | 
 82 | ### Development
 83 | 
 84 | ```json
 85 | # Add the server to your claude_desktop_config.json
 86 | "mcpServers": {
 87 |   "neo4j": {
 88 |     "command": "uv",
 89 |     "args": [
 90 |       "--directory",
 91 |       "parent_of_servers_repo/servers/src/neo4j",
 92 |       "run",
 93 |       "mcp-neo4j-cypher",
 94 |       "--db-url",
 95 |       "bolt://localhost",
 96 |       "--username",
 97 |       "neo4j",
 98 |       "--password",
 99 |       "<your-password>"
100 |     ]
101 |   }
102 | }
103 | ```
104 | 
105 | ## License
106 | 
107 | This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
108 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/package.json:
--------------------------------------------------------------------------------

```json
1 | {
2 |   "type":"module"
3 | }
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/src/index.ts:
--------------------------------------------------------------------------------

```typescript
1 | export * from './lib/graphrag-memory';
2 | 
```

--------------------------------------------------------------------------------
/jest.preset.js:
--------------------------------------------------------------------------------

```javascript
1 | const nxPreset = require('@nx/jest/preset').default;
2 | 
3 | module.exports = { ...nxPreset };
4 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/eslint.config.cjs:
--------------------------------------------------------------------------------

```
1 | const baseConfig = require('../../eslint.config.js');
2 | 
3 | module.exports = [...baseConfig];
4 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/eslint.config.js:
--------------------------------------------------------------------------------

```javascript
1 | const baseConfig = require('../../eslint.config.js');
2 | 
3 | module.exports = [...baseConfig];
4 | 
```

--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------

```typescript
1 | import { getJestProjectsAsync } from '@nx/jest';
2 | 
3 | export default async () => ({
4 |   projects: await getJestProjectsAsync(),
5 | });
6 | 
```

--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------

```json
1 | {
2 |   "recommendations": [
3 |     "nrwl.angular-console",
4 |     "esbenp.prettier-vscode",
5 |     "dbaeumer.vscode-eslint",
6 |     "firsttris.vscode-jest-runner"
7 |   ]
8 | }
9 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/package.json:
--------------------------------------------------------------------------------

```json
1 | {
2 |   "name": "@neo4j/graphrag-memory",
3 |   "version": "0.0.1",
4 |   "dependencies": {},
5 |   "type": "commonjs",
6 |   "main": "./index.cjs",
7 |   "typings": "./index.d.ts"
8 | }
9 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/src/lib/graphrag-memory.spec.ts:
--------------------------------------------------------------------------------

```typescript
1 | import {  } from './graphrag-memory';
2 | 
3 | describe('graphragMemory does not yet have functionality', () => {
4 |   it('should be able to run tests', () => {
5 |     expect(true).toEqual(true);
6 |   });
7 | });
8 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/tsconfig.lib.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "./tsconfig.json",
 3 |   "compilerOptions": {
 4 |     "outDir": "../../dist/out-tsc",
 5 |     "declaration": true,
 6 |     "types": ["node"]
 7 |   },
 8 |   "include": ["src/**/*.ts"],
 9 |   "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "../../tsconfig.base.json",
 3 |   "files": [],
 4 |   "include": [],
 5 |   "references": [
 6 |     {
 7 |       "path": "./tsconfig.app.json"
 8 |     },
 9 |     {
10 |       "path": "./tsconfig.spec.json"
11 |     }
12 |   ],
13 |   "compilerOptions": {
14 |     "esModuleInterop": true
15 |   }
16 | }
17 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "../../tsconfig.base.json",
 3 |   "files": [],
 4 |   "include": [],
 5 |   "references": [
 6 |     {
 7 |       "path": "./tsconfig.app.json"
 8 |     },
 9 |     {
10 |       "path": "./tsconfig.spec.json"
11 |     }
12 |   ],
13 |   "compilerOptions": {
14 |     "esModuleInterop": true
15 |   }
16 | }
17 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/tsconfig.spec.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "./tsconfig.json",
 3 |   "compilerOptions": {
 4 |     "outDir": "../../dist/out-tsc",
 5 |     "module": "commonjs",
 6 |     "types": ["jest", "node"]
 7 |   },
 8 |   "include": [
 9 |     "jest.config.ts",
10 |     "src/**/*.test.ts",
11 |     "src/**/*.spec.ts",
12 |     "src/**/*.d.ts"
13 |   ]
14 | }
15 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/tsconfig.spec.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "./tsconfig.json",
 3 |   "compilerOptions": {
 4 |     "outDir": "../../dist/out-tsc",
 5 |     "module": "commonjs",
 6 |     "types": ["jest", "node"]
 7 |   },
 8 |   "include": [
 9 |     "jest.config.ts",
10 |     "src/**/*.test.ts",
11 |     "src/**/*.spec.ts",
12 |     "src/**/*.d.ts"
13 |   ]
14 | }
15 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/tsconfig.spec.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "./tsconfig.json",
 3 |   "compilerOptions": {
 4 |     "outDir": "../../dist/out-tsc",
 5 |     "module": "commonjs",
 6 |     "types": ["jest", "node"]
 7 |   },
 8 |   "include": [
 9 |     "jest.config.ts",
10 |     "src/**/*.test.ts",
11 |     "src/**/*.spec.ts",
12 |     "src/**/*.d.ts"
13 |   ]
14 | }
15 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/tsconfig.app.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "./tsconfig.json",
 3 |   "compilerOptions": {
 4 |     "target": "es2022",
 5 |     "outDir": "../../dist/out-tsc",
 6 |     "module": "ES2022",
 7 |     "types": ["node"]
 8 |   },
 9 |   "include": ["src/**/*.ts"],
10 |   "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
11 | }
12 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/tsconfig.app.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "./tsconfig.json",
 3 |   "compilerOptions": {
 4 |     "target": "es2022",
 5 |     "outDir": "../../dist/out-tsc",
 6 |     "module": "ES2022",
 7 |     "types": ["node"]
 8 |   },
 9 |   "include": ["src/**/*.ts"],
10 |   "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
11 | }
12 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/jest.config.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export default {
 2 |   displayName: 'graphrag-memory',
 3 |   preset: '../../jest.preset.js',
 4 |   testEnvironment: 'node',
 5 |   transform: {
 6 |     '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
 7 |   },
 8 |   moduleFileExtensions: ['ts', 'js', 'html'],
 9 |   coverageDirectory: '../../coverage/libs/graphrag-memory',
10 | };
11 | 
```

--------------------------------------------------------------------------------
/project.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "@mcp-neo4j/source",
 3 |   "$schema": "node_modules/nx/schemas/project-schema.json",
 4 |   "targets": {
 5 |     "local-registry": {
 6 |       "executor": "@nx/js:verdaccio",
 7 |       "options": {
 8 |         "port": 4873,
 9 |         "config": ".verdaccio/config.yml",
10 |         "storage": "tmp/local-registry/storage"
11 |       }
12 |     }
13 |   }
14 | }
15 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/jest.config.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export default {
 2 |   displayName: 'mcp-json-memory',
 3 |   preset: '../../jest.preset.js',
 4 |   testEnvironment: 'node',
 5 |   transform: {
 6 |     '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
 7 |   },
 8 |   moduleFileExtensions: ['ts', 'js', 'html'],
 9 |   coverageDirectory: '../../coverage/servers/mcp-json-memory',
10 | };
11 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/jest.config.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export default {
 2 |   displayName: 'mcp-neo4j-memory',
 3 |   preset: '../../jest.preset.js',
 4 |   testEnvironment: 'node',
 5 |   transform: {
 6 |     '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
 7 |   },
 8 |   moduleFileExtensions: ['ts', 'js', 'html'],
 9 |   coverageDirectory: '../../coverage/servers/mcp-neo4j-memory',
10 | };
11 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-cypher/pyproject.toml:
--------------------------------------------------------------------------------

```toml
 1 | [project]
 2 | name = "mcp-neo4j-cypher"
 3 | version = "0.1.1"
 4 | description = "A simple Neo4j MCP server"
 5 | readme = "README.md"
 6 | requires-python = ">=3.10"
 7 | dependencies = ["mcp>=0.9.1", "neo4j>=5.26.0"]
 8 | 
 9 | [build-system]
10 | requires = ["hatchling"]
11 | build-backend = "hatchling.build"
12 | 
13 | [tool.uv]
14 | dev-dependencies = ["pyright>=1.1.389"]
15 | 
16 | [project.scripts]
17 | mcp-neo4j-cypher = "mcp_neo4j_cypher:main"
18 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/eslint.config.js:
--------------------------------------------------------------------------------

```javascript
 1 | const baseConfig = require('../../eslint.config.js');
 2 | 
 3 | module.exports = [
 4 |   ...baseConfig,
 5 |   {
 6 |     files: ['**/*.json'],
 7 |     rules: {
 8 |       '@nx/dependency-checks': [
 9 |         'error',
10 |         {
11 |           ignoredFiles: [
12 |             '{projectRoot}/eslint.config.{js,cjs,mjs}',
13 |             '{projectRoot}/esbuild.config.{js,ts,mjs,mts}',
14 |           ],
15 |         },
16 |       ],
17 |     },
18 |     languageOptions: {
19 |       parser: require('jsonc-eslint-parser'),
20 |     },
21 |   },
22 | ];
23 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "extends": "../../tsconfig.base.json",
 3 |   "compilerOptions": {
 4 |     "module": "commonjs",
 5 |     "forceConsistentCasingInFileNames": true,
 6 |     "strict": true,
 7 |     "noImplicitOverride": true,
 8 |     "noImplicitReturns": true,
 9 |     "noFallthroughCasesInSwitch": true,
10 |     "noPropertyAccessFromIndexSignature": true
11 |   },
12 |   "files": [],
13 |   "include": [],
14 |   "references": [
15 |     {
16 |       "path": "./tsconfig.lib.json"
17 |     },
18 |     {
19 |       "path": "./tsconfig.spec.json"
20 |     }
21 |   ]
22 | }
23 | 
```

--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compileOnSave": false,
 3 |   "compilerOptions": {
 4 |     "rootDir": ".",
 5 |     "sourceMap": true,
 6 |     "declaration": false,
 7 |     "moduleResolution": "node",
 8 |     "emitDecoratorMetadata": true,
 9 |     "experimentalDecorators": true,
10 |     "importHelpers": true,
11 |     "target": "es2015",
12 |     "module": "esnext",
13 |     "lib": ["es2020", "dom"],
14 |     "skipLibCheck": true,
15 |     "skipDefaultLibCheck": true,
16 |     "baseUrl": ".",
17 |     "paths": {
18 |       "@neo4j/graphrag-memory": ["libs/graphrag-memory/src/index.ts"]
19 |     }
20 |   },
21 |   "exclude": ["node_modules", "tmp"]
22 | }
23 | 
```

--------------------------------------------------------------------------------
/.verdaccio/config.yml:
--------------------------------------------------------------------------------

```yaml
 1 | # path to a directory with all packages
 2 | storage: ../tmp/local-registry/storage
 3 | 
 4 | # a list of other known repositories we can talk to
 5 | uplinks:
 6 |   npmjs:
 7 |     url: https://registry.npmjs.org/
 8 |     maxage: 60m
 9 | 
10 | packages:
11 |   '**':
12 |     # give all users (including non-authenticated users) full access
13 |     # because it is a local registry
14 |     access: $all
15 |     publish: $all
16 |     unpublish: $all
17 | 
18 |     # if package is not available locally, proxy requests to npm registry
19 |     proxy: npmjs
20 | 
21 | # log settings
22 | log:
23 |   type: stdout
24 |   format: pretty
25 |   level: warn
26 | 
27 | publish:
28 |   allow_offline: true # set offline to true to allow publish offline
29 | 
```

--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------

```javascript
 1 | const nx = require('@nx/eslint-plugin');
 2 | 
 3 | module.exports = [
 4 |   ...nx.configs['flat/base'],
 5 |   ...nx.configs['flat/typescript'],
 6 |   ...nx.configs['flat/javascript'],
 7 |   {
 8 |     ignores: ['**/dist'],
 9 |   },
10 |   {
11 |     files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
12 |     rules: {
13 |       '@nx/enforce-module-boundaries': [
14 |         'error',
15 |         {
16 |           enforceBuildableLibDependency: true,
17 |           allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'],
18 |           depConstraints: [
19 |             {
20 |               sourceTag: '*',
21 |               onlyDependOnLibsWithTags: ['*'],
22 |             },
23 |           ],
24 |         },
25 |       ],
26 |     },
27 |   },
28 |   {
29 |     files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
30 |     // Override or add rules here
31 |     rules: {},
32 |   },
33 | ];
34 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-cypher/src/mcp_neo4j_cypher/__init__.py:
--------------------------------------------------------------------------------

```python
 1 | from . import server
 2 | import asyncio
 3 | import argparse
 4 | import os
 5 | 
 6 | 
 7 | def main():
 8 |     """Main entry point for the package."""
 9 |     parser = argparse.ArgumentParser(description='Neo4j Cypher MCP Server')
10 |     parser.add_argument('--db-url', 
11 |                        default="bolt://localhost:7687",
12 |                        help='Neo4j connection URL')
13 |     parser.add_argument('--username', 
14 |                        default="neo4j",
15 |                        help='Neo4j username')
16 |     parser.add_argument('--password', 
17 |                        default="password",
18 |                        help='Neo4j password')
19 |     
20 |     args = parser.parse_args()
21 |     asyncio.run(server.main(args.db_url, args.username, args.password))
22 | 
23 | 
24 | # Optionally expose other important items at package level
25 | __all__ = ["main", "server"]
26 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/project.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "graphrag-memory",
 3 |   "$schema": "../../node_modules/nx/schemas/project-schema.json",
 4 |   "sourceRoot": "libs/graphrag-memory/src",
 5 |   "projectType": "library",
 6 |   "release": {
 7 |     "version": {
 8 |       "generatorOptions": {
 9 |         "packageRoot": "dist/{projectRoot}",
10 |         "currentVersionResolver": "git-tag"
11 |       }
12 |     }
13 |   },
14 |   "tags": [],
15 |   "targets": {
16 |     "build": {
17 |       "executor": "@nx/esbuild:esbuild",
18 |       "outputs": ["{options.outputPath}"],
19 |       "options": {
20 |         "outputPath": "dist/libs/graphrag-memory",
21 |         "main": "libs/graphrag-memory/src/index.ts",
22 |         "tsConfig": "libs/graphrag-memory/tsconfig.lib.json",
23 |         "format": ["cjs"],
24 |         "assets": ["libs/graphrag-memory/*.md"],
25 |         "generatePackageJson": true
26 |       }
27 |     },
28 |     "nx-release-publish": {
29 |       "options": {
30 |         "packageRoot": "dist/{projectRoot}"
31 |       }
32 |     }
33 |   }
34 | }
35 | 
```

--------------------------------------------------------------------------------
/libs/graphrag-memory/src/lib/graphrag-memory.ts:
--------------------------------------------------------------------------------

```typescript
 1 | 
 2 | 
 3 | export interface Entity {
 4 |   name: string;
 5 |   entityType: string;
 6 |   observations: string[];
 7 | }
 8 | 
 9 | export interface Relation {
10 |   from: string;
11 |   to: string;
12 |   relationType: string;
13 | }
14 | 
15 | export interface KnowledgeGraph {
16 |   entities: Entity[];
17 |   relations: Relation[];
18 | }
19 | 
20 | // The KnowledgeGraphMemory interface contains all operations to interact with the knowledge graph
21 | export interface KnowledgeGraphMemory {
22 | 
23 |   createEntities(entities: Entity[]): Promise<Entity[]>;
24 | 
25 |   createRelations(relations: Relation[]): Promise<Relation[]>;
26 | 
27 |   addObservations(observations: { entityName: string; contents: string[] }[]): Promise<{ entityName: string; addedObservations: string[] }[]>;
28 |   
29 |   deleteEntities(entityNames: string[]): Promise<void>;
30 | 
31 |   deleteObservations(deletions: { entityName: string; observations: string[] }[]): Promise<void>;
32 | 
33 |   deleteRelations(relations: Relation[]): Promise<void>;
34 | 
35 |   readGraph(): Promise<KnowledgeGraph>;
36 | 
37 |   // Very basic search function
38 |   searchNodes(query: string): Promise<KnowledgeGraph>;
39 | 
40 |   openNodes(names: string[]): Promise<KnowledgeGraph>;
41 | 
42 | }
43 | 
44 | 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "@mcp-neo4j/source",
 3 |   "version": "0.0.0",
 4 |   "license": "MIT",
 5 |   "scripts": {},
 6 |   "private": true,
 7 |   "dependencies": {
 8 |     "@modelcontextprotocol/sdk": "^1.0.1",
 9 |     "axios": "^1.6.0",
10 |     "neo4j-driver": "^5.27.0"
11 |   },
12 |   "devDependencies": {
13 |     "@eslint/js": "^9.8.0",
14 |     "@nx/esbuild": "20.1.4",
15 |     "@nx/eslint": "20.1.4",
16 |     "@nx/eslint-plugin": "20.1.4",
17 |     "@nx/jest": "20.1.4",
18 |     "@nx/js": "20.1.4",
19 |     "@nx/node": "20.1.4",
20 |     "@nx/workspace": "20.1.4",
21 |     "@nxlv/python": "^20.0.1",
22 |     "@swc-node/register": "~1.9.1",
23 |     "@swc/core": "~1.5.7",
24 |     "@swc/helpers": "~0.5.11",
25 |     "@types/jest": "^29.5.12",
26 |     "@types/node": "~18.16.9",
27 |     "esbuild": "^0.19.2",
28 |     "eslint": "^9.8.0",
29 |     "eslint-config-prettier": "^9.0.0",
30 |     "jest": "^29.7.0",
31 |     "jest-environment-node": "^29.7.0",
32 |     "nx": "20.1.4",
33 |     "prettier": "^2.6.2",
34 |     "ts-jest": "^29.1.0",
35 |     "ts-node": "10.9.1",
36 |     "tslib": "^2.3.0",
37 |     "typescript": "~5.5.2",
38 |     "typescript-eslint": "^8.0.0",
39 |     "verdaccio": "^5.0.4"
40 |   },
41 |   "nx": {
42 |     "includedScripts": []
43 |   }
44 | }
45 | 
```

--------------------------------------------------------------------------------
/nx.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "$schema": "./node_modules/nx/schemas/nx-schema.json",
 3 |   "namedInputs": {
 4 |     "default": ["{projectRoot}/**/*", "sharedGlobals"],
 5 |     "production": [
 6 |       "default",
 7 |       "!{projectRoot}/.eslintrc.json",
 8 |       "!{projectRoot}/eslint.config.js",
 9 |       "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
10 |       "!{projectRoot}/tsconfig.spec.json",
11 |       "!{projectRoot}/jest.config.[jt]s",
12 |       "!{projectRoot}/src/test-setup.[jt]s",
13 |       "!{projectRoot}/test-setup.[jt]s"
14 |     ],
15 |     "sharedGlobals": ["{workspaceRoot}/.github/workflows/ci.yml"]
16 |   },
17 |   "nxCloudId": "6750280b426ab2447467d096",
18 |   "targetDefaults": {
19 |     "@nx/esbuild:esbuild": {
20 |       "cache": true,
21 |       "dependsOn": ["^build"],
22 |       "inputs": ["production", "^production"]
23 |     }
24 |   },
25 |   "plugins": [
26 |     {
27 |       "plugin": "@nx/eslint/plugin",
28 |       "options": {
29 |         "targetName": "lint"
30 |       }
31 |     },
32 |     {
33 |       "plugin": "@nx/jest/plugin",
34 |       "options": {
35 |         "targetName": "test"
36 |       },
37 |       "exclude": [
38 |         "apps/mcp-neo4j-e2e/**/*",
39 |         "mcp-neo4j-memory-e2e/**/*",
40 |         "servers/mcp-neo4j-memory-e2e/**/*",
41 |         "servers/mcp-json-memory-e2e/**/*"
42 |       ]
43 |     },
44 |     {
45 |       "plugin":"@nxlv/python"
46 |     }
47 |   ],
48 |   "release": {
49 |     "version": {
50 |       "preVersionCommand": "npx nx run-many -t build"
51 |     }
52 |   }
53 | }
54 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/project.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "mcp-json-memory",
 3 |   "$schema": "../../node_modules/nx/schemas/project-schema.json",
 4 |   "sourceRoot": "servers/mcp-json-memory/src",
 5 |   "projectType": "application",
 6 |   "tags": [],
 7 |   "targets": {
 8 |     "build": {
 9 |       "executor": "@nx/esbuild:esbuild",
10 |       "outputs": ["{options.outputPath}"],
11 |       "defaultConfiguration": "production",
12 |       "options": {
13 |         "platform": "node",
14 |         "outputPath": "dist/servers/mcp-json-memory",
15 |         "format": ["esm"],
16 |         "bundle": false,
17 |         "main": "servers/mcp-json-memory/src/main.ts",
18 |         "tsConfig": "servers/mcp-json-memory/tsconfig.app.json",
19 |         "assets": ["servers/mcp-json-memory/src/assets"],
20 |         "generatePackageJson": true,
21 |         "esbuildOptions": {
22 |           "sourcemap": true,
23 |           "outExtension": {
24 |             ".js": ".js"
25 |           }
26 |         }
27 |       },
28 |       "configurations": {
29 |         "development": {},
30 |         "production": {
31 |           "esbuildOptions": {
32 |             "sourcemap": false,
33 |             "outExtension": {
34 |               ".js": ".js"
35 |             }
36 |           }
37 |         }
38 |       }
39 |     },
40 |     "serve": {
41 |       "executor": "@nx/js:node",
42 |       "defaultConfiguration": "development",
43 |       "dependsOn": ["build"],
44 |       "options": {
45 |         "buildTarget": "mcp-json-memory:build",
46 |         "runBuildTargetDependencies": false
47 |       },
48 |       "configurations": {
49 |         "development": {
50 |           "buildTarget": "mcp-json-memory:build:development"
51 |         },
52 |         "production": {
53 |           "buildTarget": "mcp-json-memory:build:production"
54 |         }
55 |       }
56 |     }
57 |   }
58 | }
59 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/project.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "mcp-neo4j-memory",
 3 |   "$schema": "../../node_modules/nx/schemas/project-schema.json",
 4 |   "sourceRoot": "servers/mcp-neo4j-memory/src",
 5 |   "projectType": "application",
 6 |   "tags": [],
 7 |   "targets": {
 8 |     "build": {
 9 |       "executor": "@nx/esbuild:esbuild",
10 |       "outputs": ["{options.outputPath}"],
11 |       "defaultConfiguration": "production",
12 |       "options": {
13 |         "platform": "node",
14 |         "outputPath": "dist/servers/mcp-neo4j-memory",
15 |         "format": ["esm"],
16 |         "bundle": false,
17 |         "main": "servers/mcp-neo4j-memory/src/main.ts",
18 |         "tsConfig": "servers/mcp-neo4j-memory/tsconfig.app.json",
19 |         "assets": ["servers/mcp-neo4j-memory/src/assets"],
20 |         "generatePackageJson": true,
21 |         "esbuildOptions": {
22 |           "sourcemap": true,
23 |           "outExtension": {
24 |             ".js": ".js"
25 |           }
26 |         }
27 |       },
28 |       "configurations": {
29 |         "development": {},
30 |         "production": {
31 |           "esbuildOptions": {
32 |             "sourcemap": false,
33 |             "outExtension": {
34 |               ".js": ".js"
35 |             }
36 |           }
37 |         }
38 |       }
39 |     },
40 |     "serve": {
41 |       "executor": "@nx/js:node",
42 |       "defaultConfiguration": "development",
43 |       "dependsOn": ["build"],
44 |       "options": {
45 |         "buildTarget": "mcp-neo4j-memory:build",
46 |         "runBuildTargetDependencies": false
47 |       },
48 |       "configurations": {
49 |         "development": {
50 |           "buildTarget": "mcp-neo4j-memory:build:development"
51 |         },
52 |         "production": {
53 |           "buildTarget": "mcp-neo4j-memory:build:production"
54 |         }
55 |       }
56 |     }
57 |   }
58 | }
59 | 
```

--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------

```yaml
 1 | # This workflow will upload a Python Package to PyPI when a release is created
 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
 3 | 
 4 | # This workflow uses actions that are not certified by GitHub.
 5 | # They are provided by a third-party and are governed by
 6 | # separate terms of service, privacy policy, and support
 7 | # documentation.
 8 | 
 9 | name: Publish Python Package
10 | 
11 | on:
12 |   release:
13 |     types: [published]
14 | 
15 | permissions:
16 |   contents: read
17 | 
18 | jobs:
19 |   release-build:
20 |     runs-on: ubuntu-latest
21 | 
22 |     steps:
23 |       - uses: actions/checkout@v4
24 | 
25 |       - uses: actions/setup-python@v5
26 |         with:
27 |           python-version: "3.x"
28 | 
29 |       - name: Build release distributions
30 |         run: |
31 |           cd servers/mcp-neo4j-cypher/
32 |           python -m pip install build
33 |           python -m build
34 | 
35 |       - name: Upload distributions
36 |         uses: actions/upload-artifact@v4
37 |         with:
38 |           name: release-dists
39 |           path: servers/mcp-neo4j-cypher/dist/
40 | 
41 |   pypi-publish:
42 |     runs-on: ubuntu-latest
43 |     needs:
44 |       - release-build
45 |     permissions:
46 |       # IMPORTANT: this permission is mandatory for trusted publishing
47 |       id-token: write
48 | 
49 |     # Dedicated environments with protections for publishing are strongly recommended.
50 |     # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
51 |     environment:
52 |       name: pypi
53 |       url: https://pypi.org/project/mcp-neo4j-cypher/
54 | 
55 |     steps:
56 |       - name: Retrieve release distributions
57 |         uses: actions/download-artifact@v4
58 |         with:
59 |           name: release-dists
60 |           path: servers/mcp-neo4j-cypher/dist/
61 | 
62 |       - name: Publish release distributions to PyPI
63 |         uses: pypa/gh-action-pypi-publish@release/v1
64 |         with:
65 |           packages-dir: servers/mcp-neo4j-cypher/dist/
```

--------------------------------------------------------------------------------
/DEVELOP.md:
--------------------------------------------------------------------------------

```markdown
 1 | # McpNeo4j
 2 | 
 3 | <a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a>
 4 | 
 5 | ✨ Your new, shiny [Nx workspace](https://nx.dev) is almost ready ✨.
 6 | 
 7 | [Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/node?utm_source=nx_project&amp;utm_medium=readme&amp;utm_campaign=nx_projects) or run `npx nx graph` to visually explore what was created. Now, let's get you up to speed!
 8 | 
 9 | Include python support via [@nxlv/python plugin](https://github.com/lucasvieirasilva/nx-plugins/tree/main/packages/nx-python)
10 | 
11 | ## Finish your CI setup
12 | 
13 | [Click here to finish setting up your workspace!](https://cloud.nx.app/connect/Wx1erwy80w)
14 | 
15 | 
16 | ## Run tasks
17 | 
18 | To run the dev server for your app, use:
19 | 
20 | ```sh
21 | npx nx serve mcp-neo4j
22 | ```
23 | 
24 | To create a production bundle:
25 | 
26 | ```sh
27 | npx nx build mcp-neo4j
28 | ```
29 | 
30 | To see all available targets to run for a project, run:
31 | 
32 | ```sh
33 | npx nx show project mcp-neo4j
34 | ```
35 | 
36 | These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the `project.json` or `package.json` files.
37 | 
38 | [More about running tasks in the docs &raquo;](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
39 | 
40 | ## Add new projects
41 | 
42 | While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature.
43 | 
44 | Use the plugin's generator to create new projects.
45 | 
46 | To generate a new application, use:
47 | 
48 | ```sh
49 | npx nx g @nx/node:app demo
50 | ```
51 | 
52 | To generate a new library, use:
53 | 
54 | ```sh
55 | npx nx g @nx/node:lib mylib
56 | ```
57 | 
58 | You can use `npx nx list` to get a list of installed plugins. Then, run `npx nx list <plugin-name>` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE.
59 | 
60 | [Learn more about Nx plugins &raquo;](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry &raquo;](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
61 | 
62 | 
63 | [Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
64 | 
65 | ## Install Nx Console
66 | 
67 | Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ.
68 | 
69 | [Install Nx Console &raquo;](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
70 | 
71 | ## Useful links
72 | 
73 | Learn more:
74 | 
75 | - [Learn more about this workspace setup](https://nx.dev/nx-api/node?utm_source=nx_project&amp;utm_medium=readme&amp;utm_campaign=nx_projects)
76 | - [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
77 | - [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
78 | - [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
79 | 
80 | And join the Nx community:
81 | - [Discord](https://go.nx.dev/community)
82 | - [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl)
83 | - [Our Youtube channel](https://www.youtube.com/@nxdevtools)
84 | - [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects)
85 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-cypher/src/mcp_neo4j_cypher/server.py:
--------------------------------------------------------------------------------

```python
  1 | import neo4j
  2 | import logging
  3 | from logging.handlers import RotatingFileHandler
  4 | from contextlib import closing
  5 | from pathlib import Path
  6 | from mcp.server.models import InitializationOptions
  7 | import mcp.types as types
  8 | from mcp.server import NotificationOptions, Server
  9 | import mcp.server.stdio
 10 | from pydantic import AnyUrl
 11 | from typing import Any
 12 | from neo4j import GraphDatabase
 13 | import re
 14 | 
 15 | logger = logging.getLogger('mcp_neo4j_cypher')
 16 | logger.info("Starting MCP neo4j Server")
 17 | 
 18 | def is_write_query(query: str) -> bool:
 19 |     return re.search(r"\b(MERGE|CREATE|SET|DELETE|REMOVE|ADD)\b", query, re.IGNORECASE) is not None
 20 | 
 21 | class neo4jDatabase:
 22 |     def __init__(self,  neo4j_uri: str, neo4j_username: str, neo4j_password: str):
 23 |         """Initialize connection to the neo4j database"""
 24 |         logger.debug(f"Initializing database connection to {neo4j_uri}")
 25 |         d = GraphDatabase.driver(neo4j_uri, auth=(neo4j_username, neo4j_password))
 26 |         d.verify_connectivity()
 27 |         self.driver = d
 28 | 
 29 |     def _execute_query(self, query: str, params: dict[str, Any] | None = None) -> list[dict[str, Any]]:
 30 |         """Execute a Cypher query and return results as a list of dictionaries"""
 31 |         logger.debug(f"Executing query: {query}")
 32 |         try:
 33 |             result = self.driver.execute_query(query, params)
 34 |             counters = vars(result.summary.counters)
 35 |             if is_write_query(query):
 36 |                 logger.debug(f"Write query affected {counters}")
 37 |                 return [counters]
 38 |             else:
 39 |                 results = [dict(r) for r in result.records]
 40 |                 logger.debug(f"Read query returned {len(results)} rows")
 41 |                 return results
 42 |         except Exception as e:
 43 |             logger.error(f"Database error executing query: {e}\n{query}")
 44 |             raise
 45 | 
 46 | async def main(neo4j_url: str, neo4j_username: str, neo4j_password: str):
 47 |     logger.info(f"Connecting to neo4j MCP Server with DB URL: {neo4j_url}")
 48 | 
 49 |     db = neo4jDatabase(neo4j_url, neo4j_username, neo4j_password)
 50 |     server = Server("neo4j-manager")
 51 | 
 52 |     # Register handlers
 53 |     logger.debug("Registering handlers")
 54 | 
 55 |     @server.list_tools()
 56 |     async def handle_list_tools() -> list[types.Tool]:
 57 |         """List available tools"""
 58 |         return [
 59 |             types.Tool(
 60 |                 name="read-neo4j-cypher",
 61 |                 description="Execute a Cypher query on the neo4j database",
 62 |                 inputSchema={
 63 |                     "type": "object",
 64 |                     "properties": {
 65 |                         "query": {"type": "string", "description": "Cypher read query to execute"},
 66 |                     },
 67 |                     "required": ["query"],
 68 |                 },
 69 |             ),
 70 |             types.Tool(
 71 |                 name="write-neo4j-cypher",
 72 |                 description="Execute a write Cypher query on the neo4j database",
 73 |                 inputSchema={
 74 |                     "type": "object",
 75 |                     "properties": {
 76 |                         "query": {"type": "string", "description": "Cypher write query to execute"},
 77 |                     },
 78 |                     "required": ["query"],
 79 |                 },
 80 |             ),
 81 |             types.Tool(
 82 |                 name="get-neo4j-schema",
 83 |                 description="List all node types, their attributes and their relationships TO other node-types in the neo4j database",
 84 |                 inputSchema={
 85 |                     "type": "object",
 86 |                     "properties": {},
 87 |                 },
 88 |             )
 89 |         ]
 90 | 
 91 |     @server.call_tool()
 92 |     async def handle_call_tool(
 93 |         name: str, arguments: dict[str, Any] | None
 94 |     ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
 95 |         """Handle tool execution requests"""
 96 |         try:
 97 |             if name == "get-neo4j-schema":
 98 |                 results = db._execute_query(
 99 |                     """
100 | call apoc.meta.data() yield label, property, type, other, unique, index, elementType
101 | where elementType = 'node' and not label starts with '_'
102 | with label, 
103 |     collect(case when type <> 'RELATIONSHIP' then [property, type + case when unique then " unique" else "" end + case when index then " indexed" else "" end] end) as attributes,
104 |     collect(case when type = 'RELATIONSHIP' then [property, head(other)] end) as relationships
105 | RETURN label, apoc.map.fromPairs(attributes) as attributes, apoc.map.fromPairs(relationships) as relationships
106 |                     """
107 |                 )
108 |                 return [types.TextContent(type="text", text=str(results))]
109 | 
110 |             elif name == "read-neo4j-cypher":
111 |                 if is_write_query(arguments["query"]):
112 |                     raise ValueError("Only MATCH queries are allowed for read-query")
113 |                 results = db._execute_query(arguments["query"])
114 |                 return [types.TextContent(type="text", text=str(results))]
115 | 
116 |             elif name == "write-neo4j-cypher":
117 |                 if not is_write_query(arguments["query"]):
118 |                     raise ValueError("Only write queries are allowed for write-query")
119 |                 results = db._execute_query(arguments["query"])
120 |                 return [types.TextContent(type="text", text=str(results))]
121 |             
122 |             else:
123 |                 raise ValueError(f"Unknown tool: {name}")
124 | 
125 |         except Exception as e:
126 |             return [types.TextContent(type="text", text=f"Error: {str(e)}")]
127 | 
128 |     async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
129 |         logger.info("Server running with stdio transport")
130 |         await server.run(
131 |             read_stream,
132 |             write_stream,
133 |             InitializationOptions(
134 |                 server_name="neo4j",
135 |                 server_version="0.1.0",
136 |                 capabilities=server.get_capabilities(
137 |                     notification_options=NotificationOptions(),
138 |                     experimental_capabilities={},
139 |                 ),
140 |             ),
141 |         )
142 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/src/json-memory.ts:
--------------------------------------------------------------------------------

```typescript
  1 | 
  2 | import path from 'path';
  3 | import { fileURLToPath } from 'url';
  4 | import { promises as fs } from 'fs';
  5 | import { KnowledgeGraphMemory, Entity, KnowledgeGraph, Relation } from "@neo4j/graphrag-memory";
  6 | 
  7 | // Default path to the JSONL file, you can change this to your desired local path 
  8 | // by passing in an arg to the memory-server
  9 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
 10 | const DEFAULT_MEMORY_FILE_PATH = path.join(__dirname, 'memory.json');
 11 | 
 12 | // The JsonMemory class contains all operations to interact with the knowledge graph
 13 | export class JsonMemory implements KnowledgeGraphMemory {
 14 |   private memoryFilePath: string;
 15 |   constructor(args: string[]) {
 16 |     this.memoryFilePath = (args.length > 0) ? args[0] : DEFAULT_MEMORY_FILE_PATH;
 17 |   }
 18 | 
 19 |   private async loadGraph(): Promise<KnowledgeGraph> {
 20 |     try {
 21 |       const data = await fs.readFile(this.memoryFilePath, "utf-8");
 22 |       const lines = data.split("\n").filter(line => line.trim() !== "");
 23 |       return lines.reduce((graph: KnowledgeGraph, line) => {
 24 |         const item = JSON.parse(line);
 25 |         if (item.type === "entity") graph.entities.push(item as Entity);
 26 |         if (item.type === "relation") graph.relations.push(item as Relation);
 27 |         return graph;
 28 |       }, { entities: [], relations: [] });
 29 |     } catch (error) {
 30 |       if (error instanceof Error && 'code' in error && (error as any).code === "ENOENT") {
 31 |         console.error(`Error! (${error})`);
 32 |         return { entities: [], relations: [] };
 33 |       }
 34 |       throw error;
 35 |     }
 36 |   }
 37 | 
 38 |   private async saveGraph(graph: KnowledgeGraph): Promise<void> {
 39 |     const lines = [
 40 |       ...graph.entities.map(e => JSON.stringify({ type: "entity", ...e })),
 41 |       ...graph.relations.map(r => JSON.stringify({ type: "relation", ...r })),
 42 |     ];
 43 |     await fs.writeFile(this.memoryFilePath, lines.join("\n"));
 44 |   }
 45 | 
 46 |   async createEntities(entities: Entity[]): Promise<Entity[]> {
 47 |     const graph = await this.loadGraph();
 48 |     const newEntities = entities.filter(e => !graph.entities.some(existingEntity => existingEntity.name === e.name));
 49 |     graph.entities.push(...newEntities);
 50 |     await this.saveGraph(graph);
 51 |     return newEntities;
 52 |   }
 53 | 
 54 |   async createRelations(relations: Relation[]): Promise<Relation[]> {
 55 |     const graph = await this.loadGraph();
 56 |     const newRelations = relations.filter(r => !graph.relations.some(existingRelation => 
 57 |       existingRelation.from === r.from && 
 58 |       existingRelation.to === r.to && 
 59 |       existingRelation.relationType === r.relationType
 60 |     ));
 61 |     graph.relations.push(...newRelations);
 62 |     await this.saveGraph(graph);
 63 |     return newRelations;
 64 |   }
 65 | 
 66 |   async addObservations(observations: { entityName: string; contents: string[] }[]): Promise<{ entityName: string; addedObservations: string[] }[]> {
 67 |     const graph = await this.loadGraph();
 68 |     const results = observations.map(o => {
 69 |       const entity = graph.entities.find(e => e.name === o.entityName);
 70 |       if (!entity) {
 71 |         throw new Error(`Entity with name ${o.entityName} not found`);
 72 |       }
 73 |       const newObservations = o.contents.filter(content => !entity.observations.includes(content));
 74 |       entity.observations.push(...newObservations);
 75 |       return { entityName: o.entityName, addedObservations: newObservations };
 76 |     });
 77 |     await this.saveGraph(graph);
 78 |     return results;
 79 |   }
 80 | 
 81 |   async deleteEntities(entityNames: string[]): Promise<void> {
 82 |     const graph = await this.loadGraph();
 83 |     graph.entities = graph.entities.filter(e => !entityNames.includes(e.name));
 84 |     graph.relations = graph.relations.filter(r => !entityNames.includes(r.from) && !entityNames.includes(r.to));
 85 |     await this.saveGraph(graph);
 86 |   }
 87 | 
 88 |   async deleteObservations(deletions: { entityName: string; observations: string[] }[]): Promise<void> {
 89 |     const graph = await this.loadGraph();
 90 |     deletions.forEach(d => {
 91 |       const entity = graph.entities.find(e => e.name === d.entityName);
 92 |       if (entity) {
 93 |         entity.observations = entity.observations.filter(o => !d.observations.includes(o));
 94 |       }
 95 |     });
 96 |     await this.saveGraph(graph);
 97 |   }
 98 | 
 99 |   async deleteRelations(relations: Relation[]): Promise<void> {
100 |     const graph = await this.loadGraph();
101 |     graph.relations = graph.relations.filter(r => !relations.some(delRelation => 
102 |       r.from === delRelation.from && 
103 |       r.to === delRelation.to && 
104 |       r.relationType === delRelation.relationType
105 |     ));
106 |     await this.saveGraph(graph);
107 |   }
108 | 
109 |   async readGraph(): Promise<KnowledgeGraph> {
110 | 
111 |     return this.loadGraph();
112 |   }
113 | 
114 |   // Very basic search function
115 |   async searchNodes(query: string): Promise<KnowledgeGraph> {
116 |     const graph = await this.loadGraph();
117 | 
118 |     // Filter entities
119 |     const filteredEntities = graph.entities.filter(e => 
120 |       e.name.toLowerCase().includes(query.toLowerCase()) ||
121 |       e.entityType.toLowerCase().includes(query.toLowerCase()) ||
122 |       e.observations.some(o => o.toLowerCase().includes(query.toLowerCase()))
123 |     );
124 |   
125 |     // Create a Set of filtered entity names for quick lookup
126 |     const filteredEntityNames = new Set(filteredEntities.map(e => e.name));
127 |   
128 |     // Filter relations to only include those between filtered entities
129 |     const filteredRelations = graph.relations.filter(r => 
130 |       filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to)
131 |     );
132 |   
133 |     const filteredGraph: KnowledgeGraph = {
134 |       entities: filteredEntities,
135 |       relations: filteredRelations,
136 |     };
137 |   
138 |     return filteredGraph;
139 |   }
140 | 
141 |   async openNodes(names: string[]): Promise<KnowledgeGraph> {
142 |     const graph = await this.loadGraph();
143 |     
144 |     // Filter entities
145 |     const filteredEntities = graph.entities.filter(e => names.includes(e.name));
146 |   
147 |     // Create a Set of filtered entity names for quick lookup
148 |     const filteredEntityNames = new Set(filteredEntities.map(e => e.name));
149 |   
150 |     // Filter relations to only include those between filtered entities
151 |     const filteredRelations = graph.relations.filter(r => 
152 |       filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to)
153 |     );
154 |   
155 |     const filteredGraph: KnowledgeGraph = {
156 |       entities: filteredEntities,
157 |       relations: filteredRelations,
158 |     };
159 |   
160 |     return filteredGraph;
161 |   }
162 | }
163 | 
164 | 
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/src/neo4j-memory.ts:
--------------------------------------------------------------------------------

```typescript
  1 | 
  2 | import path from 'path';
  3 | import { fileURLToPath } from 'url';
  4 | import { promises as fs } from 'fs';
  5 | 
  6 | import neo4j, { Integer, Node, Relationship, Driver as Neo4jDriver } from 'neo4j-driver'
  7 | 
  8 | import { KnowledgeGraphMemory, Entity, KnowledgeGraph, Relation } from "@neo4j/graphrag-memory";
  9 | 
 10 | type EntityNode = Node<Integer, Entity>
 11 | 
 12 | type EntityRelationship = Relationship<Integer, Relation>
 13 | 
 14 | interface EntityWithRelationsResult {
 15 |   entity: EntityNode,
 16 |   relations: EntityRelationship[]
 17 | }
 18 | 
 19 | export class Neo4jMemory implements KnowledgeGraphMemory {
 20 |   constructor(private neo4jDriver: Neo4jDriver) { }
 21 | 
 22 |   private async loadGraph(): Promise<KnowledgeGraph> {
 23 |     const session = this.neo4jDriver.session()
 24 | 
 25 |     try {
 26 |       // Execute a Cypher statement in a Read Transaction
 27 |       const res = await session.executeRead(tx => tx.run<EntityWithRelationsResult>(`
 28 |         MATCH (entity:Memory)
 29 |         OPTIONAL MATCH (entity)-[r]->(other)
 30 |         RETURN entity, collect(r) as relations
 31 |       `))
 32 |       const kgMemory:KnowledgeGraph = res.records.reduce(
 33 |         (kg, row) => {
 34 |           const entityNode = row.get('entity');
 35 |           const entityRelationships = row.get('relations');
 36 | 
 37 |           kg.entities.push(entityNode.properties);
 38 |           kg.relations.push(...entityRelationships.map(r => r.properties))
 39 |           return kg
 40 |         }, 
 41 |         ({entities:[], relations:[]} as KnowledgeGraph)
 42 |       )
 43 |   
 44 |       console.error(JSON.stringify(kgMemory.entities))
 45 |       console.error(JSON.stringify(kgMemory.relations))
 46 | 
 47 |       return kgMemory
 48 |     } catch (error) {
 49 |       console.error(error)
 50 |     }
 51 |     finally {
 52 |       // Close the Session
 53 |       await session.close()
 54 |     }
 55 |     
 56 |     return {
 57 |       entities: [],
 58 |       relations: []    
 59 |     };
 60 |   }
 61 | 
 62 |   private async saveGraph(graph: KnowledgeGraph): Promise<void> {
 63 |     const session = this.neo4jDriver.session()
 64 | 
 65 |     return session.executeWrite(async txc => {
 66 |       await txc.run(`
 67 |         UNWIND $memoryGraph.entities as entity
 68 |         MERGE (entityMemory:Memory { entityID: entity.name })
 69 |         SET entityMemory += entity
 70 |         `
 71 |         ,
 72 |         {
 73 |           memoryGraph:graph
 74 |         }
 75 |       )
 76 |       await txc.run(`
 77 |         UNWIND $memoryGraph.relations as relation
 78 |         MATCH (from:Memory),(to:Memory)
 79 |         WHERE from.entityID = relation.from
 80 |           AND  to.entityID = relation.to
 81 |         MERGE (from)-[r:Memory {relationType:relation.relationType}]->(to)
 82 |         `
 83 |         ,
 84 |         {
 85 |           memoryGraph:graph
 86 |         }
 87 |       )
 88 | 
 89 |     })
 90 |   
 91 |   }
 92 | 
 93 |   async createEntities(entities: Entity[]): Promise<Entity[]> {
 94 |     const graph = await this.loadGraph();
 95 |     const newEntities = entities.filter(e => !graph.entities.some(existingEntity => existingEntity.name === e.name));
 96 |     graph.entities.push(...newEntities);
 97 |     await this.saveGraph(graph);
 98 |     return newEntities;
 99 |   }
100 | 
101 |   async createRelations(relations: Relation[]): Promise<Relation[]> {
102 |     const graph = await this.loadGraph();
103 |     const newRelations = relations.filter(r => !graph.relations.some(existingRelation => 
104 |       existingRelation.from === r.from && 
105 |       existingRelation.to === r.to && 
106 |       existingRelation.relationType === r.relationType
107 |     ));
108 |     graph.relations.push(...newRelations);
109 |     await this.saveGraph(graph);
110 |     return newRelations;
111 |   }
112 | 
113 |   async addObservations(observations: { entityName: string; contents: string[] }[]): Promise<{ entityName: string; addedObservations: string[] }[]> {
114 |     const graph = await this.loadGraph();
115 |     const results = observations.map(o => {
116 |       const entity = graph.entities.find(e => e.name === o.entityName);
117 |       if (!entity) {
118 |         throw new Error(`Entity with name ${o.entityName} not found`);
119 |       }
120 |       const newObservations = o.contents.filter(content => !entity.observations.includes(content));
121 |       entity.observations.push(...newObservations);
122 |       return { entityName: o.entityName, addedObservations: newObservations };
123 |     });
124 |     await this.saveGraph(graph);
125 |     return results;
126 |   }
127 | 
128 |   async deleteEntities(entityNames: string[]): Promise<void> {
129 |     const graph = await this.loadGraph();
130 |     graph.entities = graph.entities.filter(e => !entityNames.includes(e.name));
131 |     graph.relations = graph.relations.filter(r => !entityNames.includes(r.from) && !entityNames.includes(r.to));
132 |     await this.saveGraph(graph);
133 |   }
134 | 
135 |   async deleteObservations(deletions: { entityName: string; observations: string[] }[]): Promise<void> {
136 |     const graph = await this.loadGraph();
137 |     deletions.forEach(d => {
138 |       const entity = graph.entities.find(e => e.name === d.entityName);
139 |       if (entity) {
140 |         entity.observations = entity.observations.filter(o => !d.observations.includes(o));
141 |       }
142 |     });
143 |     await this.saveGraph(graph);
144 |   }
145 | 
146 |   async deleteRelations(relations: Relation[]): Promise<void> {
147 |     const graph = await this.loadGraph();
148 |     graph.relations = graph.relations.filter(r => !relations.some(delRelation => 
149 |       r.from === delRelation.from && 
150 |       r.to === delRelation.to && 
151 |       r.relationType === delRelation.relationType
152 |     ));
153 |     await this.saveGraph(graph);
154 |   }
155 | 
156 |   async readGraph(): Promise<KnowledgeGraph> {
157 | 
158 |     return this.loadGraph();
159 |   }
160 | 
161 |   // Very basic search function
162 |   async searchNodes(query: string): Promise<KnowledgeGraph> {
163 |     const graph = await this.loadGraph();
164 | 
165 |     // Filter entities
166 |     const filteredEntities = graph.entities.filter(e => 
167 |       query.toLowerCase().includes(e.name.toLowerCase()) ||
168 |       query.toLowerCase().includes(e.entityType.toLowerCase()) ||
169 |       e.observations.some(o => o.toLowerCase().includes(query.toLowerCase()))
170 |     );
171 |   
172 |     // Create a Set of filtered entity names for quick lookup
173 |     const filteredEntityNames = new Set(filteredEntities.map(e => e.name));
174 |   
175 |     // Filter relations to only include those between filtered entities
176 |     const filteredRelations = graph.relations.filter(r => 
177 |       filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to)
178 |     );
179 |   
180 |     const filteredGraph: KnowledgeGraph = {
181 |       entities: filteredEntities,
182 |       relations: filteredRelations,
183 |     };
184 |   
185 |     return filteredGraph;
186 |   }
187 | 
188 |   async openNodes(names: string[]): Promise<KnowledgeGraph> {
189 |     const graph = await this.loadGraph();
190 |     
191 |     // Filter entities
192 |     const filteredEntities = graph.entities.filter(e => names.includes(e.name));
193 |   
194 |     // Create a Set of filtered entity names for quick lookup
195 |     const filteredEntityNames = new Set(filteredEntities.map(e => e.name));
196 |   
197 |     // Filter relations to only include those between filtered entities
198 |     const filteredRelations = graph.relations.filter(r => 
199 |       filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to)
200 |     );
201 |   
202 |     const filteredGraph: KnowledgeGraph = {
203 |       entities: filteredEntities,
204 |       relations: filteredRelations,
205 |     };
206 |   
207 |     return filteredGraph;
208 |   }
209 | }
210 | 
211 | 
```

--------------------------------------------------------------------------------
/servers/mcp-json-memory/src/main.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import {
  4 |   CallToolRequestSchema,
  5 |   ListToolsRequestSchema,
  6 | } from "@modelcontextprotocol/sdk/types.js";
  7 | import { KnowledgeGraphMemory, Entity, KnowledgeGraph, Relation } from "@neo4j/graphrag-memory";
  8 | import { JsonMemory } from './json-memory.js'
  9 | 
 10 | 
 11 | const args = process.argv.slice(2);
 12 | 
 13 | // Default to using the json file-based memory
 14 | const knowledgeGraphManager:KnowledgeGraphMemory = new JsonMemory(args);
 15 | 
 16 | // The server instance and tools exposed to Claude
 17 | const server = new Server({
 18 |   name: "mcp-json-memory",
 19 |   version: "1.0.1",
 20 | },    {
 21 |     capabilities: {
 22 |       tools: {},
 23 |     },
 24 |   },);
 25 | 
 26 | server.setRequestHandler(ListToolsRequestSchema, async () => {
 27 |   return {
 28 |     tools: [
 29 |       {
 30 |         name: "create_entities",
 31 |         description: "Create multiple new entities in the knowledge graph",
 32 |         inputSchema: {
 33 |           type: "object",
 34 |           properties: {
 35 |             entities: {
 36 |               type: "array",
 37 |               items: {
 38 |                 type: "object",
 39 |                 properties: {
 40 |                   name: { type: "string", description: "The name of the entity" },
 41 |                   entityType: { type: "string", description: "The type of the entity" },
 42 |                   observations: { 
 43 |                     type: "array", 
 44 |                     items: { type: "string" },
 45 |                     description: "An array of observation contents associated with the entity"
 46 |                   },
 47 |                 },
 48 |                 required: ["name", "entityType", "observations"],
 49 |               },
 50 |             },
 51 |           },
 52 |           required: ["entities"],
 53 |         },
 54 |       },
 55 |       {
 56 |         name: "create_relations",
 57 |         description: "Create multiple new relations between entities in the knowledge graph. Relations should be in active voice",
 58 |         inputSchema: {
 59 |           type: "object",
 60 |           properties: {
 61 |             relations: {
 62 |               type: "array",
 63 |               items: {
 64 |                 type: "object",
 65 |                 properties: {
 66 |                   from: { type: "string", description: "The name of the entity where the relation starts" },
 67 |                   to: { type: "string", description: "The name of the entity where the relation ends" },
 68 |                   relationType: { type: "string", description: "The type of the relation" },
 69 |                 },
 70 |                 required: ["from", "to", "relationType"],
 71 |               },
 72 |             },
 73 |           },
 74 |           required: ["relations"],
 75 |         },
 76 |       },
 77 |       {
 78 |         name: "add_observations",
 79 |         description: "Add new observations to existing entities in the knowledge graph",
 80 |         inputSchema: {
 81 |           type: "object",
 82 |           properties: {
 83 |             observations: {
 84 |               type: "array",
 85 |               items: {
 86 |                 type: "object",
 87 |                 properties: {
 88 |                   entityName: { type: "string", description: "The name of the entity to add the observations to" },
 89 |                   contents: { 
 90 |                     type: "array", 
 91 |                     items: { type: "string" },
 92 |                     description: "An array of observation contents to add"
 93 |                   },
 94 |                 },
 95 |                 required: ["entityName", "contents"],
 96 |               },
 97 |             },
 98 |           },
 99 |           required: ["observations"],
100 |         },
101 |       },
102 |       {
103 |         name: "delete_entities",
104 |         description: "Delete multiple entities and their associated relations from the knowledge graph",
105 |         inputSchema: {
106 |           type: "object",
107 |           properties: {
108 |             entityNames: { 
109 |               type: "array", 
110 |               items: { type: "string" },
111 |               description: "An array of entity names to delete" 
112 |             },
113 |           },
114 |           required: ["entityNames"],
115 |         },
116 |       },
117 |       {
118 |         name: "delete_observations",
119 |         description: "Delete specific observations from entities in the knowledge graph",
120 |         inputSchema: {
121 |           type: "object",
122 |           properties: {
123 |             deletions: {
124 |               type: "array",
125 |               items: {
126 |                 type: "object",
127 |                 properties: {
128 |                   entityName: { type: "string", description: "The name of the entity containing the observations" },
129 |                   observations: { 
130 |                     type: "array", 
131 |                     items: { type: "string" },
132 |                     description: "An array of observations to delete"
133 |                   },
134 |                 },
135 |                 required: ["entityName", "observations"],
136 |               },
137 |             },
138 |           },
139 |           required: ["deletions"],
140 |         },
141 |       },
142 |       {
143 |         name: "delete_relations",
144 |         description: "Delete multiple relations from the knowledge graph",
145 |         inputSchema: {
146 |           type: "object",
147 |           properties: {
148 |             relations: { 
149 |               type: "array", 
150 |               items: {
151 |                 type: "object",
152 |                 properties: {
153 |                   from: { type: "string", description: "The name of the entity where the relation starts" },
154 |                   to: { type: "string", description: "The name of the entity where the relation ends" },
155 |                   relationType: { type: "string", description: "The type of the relation" },
156 |                 },
157 |                 required: ["from", "to", "relationType"],
158 |               },
159 |               description: "An array of relations to delete" 
160 |             },
161 |           },
162 |           required: ["relations"],
163 |         },
164 |       },
165 |       {
166 |         name: "read_graph",
167 |         description: "Read the entire knowledge graph",
168 |         inputSchema: {
169 |           type: "object",
170 |           properties: {},
171 |         },
172 |       },
173 |       {
174 |         name: "search_nodes",
175 |         description: "Search for nodes in the knowledge graph based on a query",
176 |         inputSchema: {
177 |           type: "object",
178 |           properties: {
179 |             query: { type: "string", description: "The search query to match against entity names, types, and observation content" },
180 |           },
181 |           required: ["query"],
182 |         },
183 |       },
184 |       {
185 |         name: "open_nodes",
186 |         description: "Open specific nodes in the knowledge graph by their names",
187 |         inputSchema: {
188 |           type: "object",
189 |           properties: {
190 |             names: {
191 |               type: "array",
192 |               items: { type: "string" },
193 |               description: "An array of entity names to retrieve",
194 |             },
195 |           },
196 |           required: ["names"],
197 |         },
198 |       },
199 |     ],
200 |   };
201 | });
202 | 
203 | server.setRequestHandler(CallToolRequestSchema, async (request) => {
204 |   const { name, arguments: args } = request.params;
205 | 
206 |   if (!args) {
207 |     throw new Error(`No arguments provided for tool: ${name}`);
208 |   }
209 | 
210 |   switch (name) {
211 |     case "create_entities":
212 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.createEntities(args.entities as Entity[]), null, 2) }] };
213 |     case "create_relations":
214 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.createRelations(args.relations as Relation[]), null, 2) }] };
215 |     case "add_observations":
216 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.addObservations(args.observations as { entityName: string; contents: string[] }[]), null, 2) }] };
217 |     case "delete_entities":
218 |       await knowledgeGraphManager.deleteEntities(args.entityNames as string[]);
219 |       return { content: [{ type: "text", text: "Entities deleted successfully" }] };
220 |     case "delete_observations":
221 |       await knowledgeGraphManager.deleteObservations(args.deletions as { entityName: string; observations: string[] }[]);
222 |       return { content: [{ type: "text", text: "Observations deleted successfully" }] };
223 |     case "delete_relations":
224 |       await knowledgeGraphManager.deleteRelations(args.relations as Relation[]);
225 |       return { content: [{ type: "text", text: "Relations deleted successfully" }] };
226 |     case "read_graph":
227 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.readGraph(), null, 2) }] };
228 |     case "search_nodes":
229 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.searchNodes(args.query as string), null, 2) }] };
230 |     case "open_nodes":
231 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.openNodes(args.names as string[]), null, 2) }] };
232 |     default:
233 |       throw new Error(`Unknown tool: ${name}`);
234 |   }
235 | });
236 | 
237 | async function main() {
238 |   const transport = new StdioServerTransport();
239 |   await server.connect(transport);
240 |   console.error("MCP Knowledge Graph Memory using Neo4j running on stdio");
241 | }
242 | 
243 | main().catch((error) => {
244 |   console.error("Fatal error in main():", error);
245 |   process.exit(1);
246 | });
```

--------------------------------------------------------------------------------
/servers/mcp-neo4j-memory/src/main.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import {
  4 |   CallToolRequestSchema,
  5 |   ListToolsRequestSchema,
  6 | } from "@modelcontextprotocol/sdk/types.js";
  7 | 
  8 | import { driver as connectToNeo4j, auth as Neo4jAuth } from 'neo4j-driver'
  9 | 
 10 | import { KnowledgeGraphMemory, Entity, KnowledgeGraph, Relation } from "@neo4j/graphrag-memory";
 11 | import { Neo4jMemory } from './neo4j-memory.js'
 12 | 
 13 | 
 14 | // const args = process.argv.slice(2);
 15 | 
 16 | const neo4jDriver = connectToNeo4j(
 17 |   'neo4j://localhost:7687',
 18 |   Neo4jAuth.basic('neo4j', 'marwhompa')
 19 | )
 20 | 
 21 | const knowledgeGraphMemory:KnowledgeGraphMemory = new Neo4jMemory(neo4jDriver);
 22 | 
 23 | // The server instance and tools exposed to Claude
 24 | const server = new Server({
 25 |   name: "mcp-neo4j-memory",
 26 |   version: "1.0.1",
 27 | },    {
 28 |     capabilities: {
 29 |       tools: {},
 30 |     },
 31 |   },);
 32 | 
 33 | server.setRequestHandler(ListToolsRequestSchema, async () => {
 34 |   return {
 35 |     tools: [
 36 |       {
 37 |         name: "create_entities",
 38 |         description: "Create multiple new entities in the knowledge graph",
 39 |         inputSchema: {
 40 |           type: "object",
 41 |           properties: {
 42 |             entities: {
 43 |               type: "array",
 44 |               items: {
 45 |                 type: "object",
 46 |                 properties: {
 47 |                   name: { type: "string", description: "The name of the entity" },
 48 |                   entityType: { type: "string", description: "The type of the entity" },
 49 |                   observations: { 
 50 |                     type: "array", 
 51 |                     items: { type: "string" },
 52 |                     description: "An array of observation contents associated with the entity"
 53 |                   },
 54 |                 },
 55 |                 required: ["name", "entityType", "observations"],
 56 |               },
 57 |             },
 58 |           },
 59 |           required: ["entities"],
 60 |         },
 61 |       },
 62 |       {
 63 |         name: "create_relations",
 64 |         description: "Create multiple new relations between entities in the knowledge graph. Relations should be in active voice",
 65 |         inputSchema: {
 66 |           type: "object",
 67 |           properties: {
 68 |             relations: {
 69 |               type: "array",
 70 |               items: {
 71 |                 type: "object",
 72 |                 properties: {
 73 |                   from: { type: "string", description: "The name of the entity where the relation starts" },
 74 |                   to: { type: "string", description: "The name of the entity where the relation ends" },
 75 |                   relationType: { type: "string", description: "The type of the relation" },
 76 |                 },
 77 |                 required: ["from", "to", "relationType"],
 78 |               },
 79 |             },
 80 |           },
 81 |           required: ["relations"],
 82 |         },
 83 |       },
 84 |       {
 85 |         name: "add_observations",
 86 |         description: "Add new observations to existing entities in the knowledge graph",
 87 |         inputSchema: {
 88 |           type: "object",
 89 |           properties: {
 90 |             observations: {
 91 |               type: "array",
 92 |               items: {
 93 |                 type: "object",
 94 |                 properties: {
 95 |                   entityName: { type: "string", description: "The name of the entity to add the observations to" },
 96 |                   contents: { 
 97 |                     type: "array", 
 98 |                     items: { type: "string" },
 99 |                     description: "An array of observation contents to add"
100 |                   },
101 |                 },
102 |                 required: ["entityName", "contents"],
103 |               },
104 |             },
105 |           },
106 |           required: ["observations"],
107 |         },
108 |       },
109 |       {
110 |         name: "delete_entities",
111 |         description: "Delete multiple entities and their associated relations from the knowledge graph",
112 |         inputSchema: {
113 |           type: "object",
114 |           properties: {
115 |             entityNames: { 
116 |               type: "array", 
117 |               items: { type: "string" },
118 |               description: "An array of entity names to delete" 
119 |             },
120 |           },
121 |           required: ["entityNames"],
122 |         },
123 |       },
124 |       {
125 |         name: "delete_observations",
126 |         description: "Delete specific observations from entities in the knowledge graph",
127 |         inputSchema: {
128 |           type: "object",
129 |           properties: {
130 |             deletions: {
131 |               type: "array",
132 |               items: {
133 |                 type: "object",
134 |                 properties: {
135 |                   entityName: { type: "string", description: "The name of the entity containing the observations" },
136 |                   observations: { 
137 |                     type: "array", 
138 |                     items: { type: "string" },
139 |                     description: "An array of observations to delete"
140 |                   },
141 |                 },
142 |                 required: ["entityName", "observations"],
143 |               },
144 |             },
145 |           },
146 |           required: ["deletions"],
147 |         },
148 |       },
149 |       {
150 |         name: "delete_relations",
151 |         description: "Delete multiple relations from the knowledge graph",
152 |         inputSchema: {
153 |           type: "object",
154 |           properties: {
155 |             relations: { 
156 |               type: "array", 
157 |               items: {
158 |                 type: "object",
159 |                 properties: {
160 |                   from: { type: "string", description: "The name of the entity where the relation starts" },
161 |                   to: { type: "string", description: "The name of the entity where the relation ends" },
162 |                   relationType: { type: "string", description: "The type of the relation" },
163 |                 },
164 |                 required: ["from", "to", "relationType"],
165 |               },
166 |               description: "An array of relations to delete" 
167 |             },
168 |           },
169 |           required: ["relations"],
170 |         },
171 |       },
172 |       {
173 |         name: "read_graph",
174 |         description: "Read the entire knowledge graph",
175 |         inputSchema: {
176 |           type: "object",
177 |           properties: {},
178 |         },
179 |       },
180 |       {
181 |         name: "search_nodes",
182 |         description: "Search for nodes in the knowledge graph based on a query",
183 |         inputSchema: {
184 |           type: "object",
185 |           properties: {
186 |             query: { type: "string", description: "The search query to match against entity names, types, and observation content" },
187 |           },
188 |           required: ["query"],
189 |         },
190 |       },
191 |       {
192 |         name: "open_nodes",
193 |         description: "Open specific nodes in the knowledge graph by their names",
194 |         inputSchema: {
195 |           type: "object",
196 |           properties: {
197 |             names: {
198 |               type: "array",
199 |               items: { type: "string" },
200 |               description: "An array of entity names to retrieve",
201 |             },
202 |           },
203 |           required: ["names"],
204 |         },
205 |       },
206 |     ],
207 |   };
208 | });
209 | 
210 | server.setRequestHandler(CallToolRequestSchema, async (request) => {
211 |   const { name, arguments: args } = request.params;
212 | 
213 |   if (!args) {
214 |     throw new Error(`No arguments provided for tool: ${name}`);
215 |   }
216 | 
217 |   switch (name) {
218 |     case "create_entities":
219 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphMemory.createEntities(args.entities as Entity[]), null, 2) }] };
220 |     case "create_relations":
221 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphMemory.createRelations(args.relations as Relation[]), null, 2) }] };
222 |     case "add_observations":
223 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphMemory.addObservations(args.observations as { entityName: string; contents: string[] }[]), null, 2) }] };
224 |     case "delete_entities":
225 |       await knowledgeGraphMemory.deleteEntities(args.entityNames as string[]);
226 |       return { content: [{ type: "text", text: "Entities deleted successfully" }] };
227 |     case "delete_observations":
228 |       await knowledgeGraphMemory.deleteObservations(args.deletions as { entityName: string; observations: string[] }[]);
229 |       return { content: [{ type: "text", text: "Observations deleted successfully" }] };
230 |     case "delete_relations":
231 |       await knowledgeGraphMemory.deleteRelations(args.relations as Relation[]);
232 |       return { content: [{ type: "text", text: "Relations deleted successfully" }] };
233 |     case "read_graph":
234 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphMemory.readGraph(), null, 2) }] };
235 |     case "search_nodes":
236 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphMemory.searchNodes(args.query as string), null, 2) }] };
237 |     case "open_nodes":
238 |       return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphMemory.openNodes(args.names as string[]), null, 2) }] };
239 |     default:
240 |       throw new Error(`Unknown tool: ${name}`);
241 |   }
242 | });
243 | 
244 | async function main() {
245 |   const transport = new StdioServerTransport();
246 |   await server.connect(transport);
247 |   console.error("MCP Knowledge Graph Memory using Neo4j running on stdio");
248 | }
249 | 
250 | main().catch((error) => {
251 |   console.error("Fatal error in main():", error);
252 |   process.exit(1);
253 | });
```