Skip to content

Commit bc60c1d

Browse files
committed
Merge branch 'main' into add-data-modeling-mcp-server
2 parents 45a04f0 + 63ddf42 commit bc60c1d

File tree

6 files changed

+77
-16
lines changed

6 files changed

+77
-16
lines changed

servers/mcp-neo4j-cypher/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
### Changed
66

77
### Added
8+
* Namespace option via CLI or env variables. This allows many Cypher MCP servers to be used at once.
9+
* Allow transport to be specified via env variables
810

911

1012
## v0.2.2

servers/mcp-neo4j-cypher/README.md

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,25 @@ The server offers these core tools:
3131
- No input required
3232
- Returns: JSON serialized list of node labels with two dictionaries: one for attributes and one for relationships
3333

34+
### 🏷️ Namespacing
35+
36+
The server supports namespacing to allow multiple Neo4j MCP servers to be used simultaneously. When a namespace is provided, all tool names are prefixed with the namespace followed by a hyphen (e.g., `mydb-read-neo4j-cypher`).
37+
38+
This is useful when you need to connect to multiple Neo4j databases or instances from the same session.
39+
3440
## 🔧 Usage with Claude Desktop
3541

3642
### 💾 Released Package
3743

3844
Can be found on PyPi https://pypi.org/project/mcp-neo4j-cypher/
3945

40-
Add the server to your `claude_desktop_config.json` with the database connection configuration through environment variables. You may also specify the transport method with cli arguments.
46+
Add the server to your `claude_desktop_config.json` with the database connection configuration through environment variables. You may also specify the transport method and namespace with cli arguments or environment variables.
4147

4248
```json
4349
"mcpServers": {
4450
"neo4j-aura": {
4551
"command": "uvx",
46-
"args": [ "[email protected].2", "--transport", "stdio" ],
52+
"args": [ "[email protected].3", "--transport", "stdio" ],
4753
"env": {
4854
"NEO4J_URI": "bolt://localhost:7687",
4955
"NEO4J_USERNAME": "neo4j",
@@ -54,14 +60,50 @@ Add the server to your `claude_desktop_config.json` with the database connection
5460
}
5561
```
5662

63+
#### Multiple Database Example
64+
65+
Here's an example of connecting to multiple Neo4j databases using namespaces:
66+
67+
```json
68+
{
69+
"mcpServers": {
70+
"movies-neo4j": {
71+
"command": "uvx",
72+
"args": [ "[email protected]", "--namespace", "movies" ],
73+
"env": {
74+
"NEO4J_URI": "neo4j+s://demo.neo4jlabs.com",
75+
"NEO4J_USERNAME": "recommendations",
76+
"NEO4J_PASSWORD": "recommendations",
77+
"NEO4J_DATABASE": "recommendations"
78+
}
79+
},
80+
"local-neo4j": {
81+
"command": "uvx",
82+
"args": [ "[email protected]" ],
83+
"env": {
84+
"NEO4J_URI": "bolt://localhost:7687",
85+
"NEO4J_USERNAME": "neo4j",
86+
"NEO4J_PASSWORD": "password",
87+
"NEO4J_DATABASE": "neo4j",
88+
"NEO4J_NAMESPACE": "local"
89+
}
90+
}
91+
}
92+
}
93+
```
94+
95+
In this setup:
96+
- The movies database tools will be prefixed with `movies-` (e.g., `movies-read-neo4j-cypher`)
97+
- The local database tools will be prefixed with `local-` (e.g., `local-get-neo4j-schema`)
98+
5799
Here is an example connection for the movie database with Movie, Person (Actor, Director), Genre, User and ratings:
58100

59101
```json
60102
{
61103
"mcpServers": {
62104
"movies-neo4j": {
63105
"command": "uvx",
64-
"args": [ "[email protected].2" ],
106+
"args": [ "[email protected].3" ],
65107
"env": {
66108
"NEO4J_URI": "neo4j+s://demo.neo4jlabs.com",
67109
"NEO4J_USERNAME": "recommendations",
@@ -83,13 +125,15 @@ Syntax with `--db-url`, `--username` and `--password` command line arguments is
83125
"neo4j": {
84126
"command": "uvx",
85127
"args": [
86-
128+
87129
"--db-url",
88130
"bolt://localhost",
89131
"--username",
90132
"neo4j",
91133
"--password",
92-
"<your-password>"
134+
"<your-password>",
135+
"--namespace",
136+
"mydb"
93137
]
94138
}
95139
}
@@ -102,7 +146,7 @@ Here is an example connection for the movie database with Movie, Person (Actor,
102146
"mcpServers": {
103147
"movies-neo4j": {
104148
"command": "uvx",
105-
"args": ["[email protected].2",
149+
"args": ["[email protected].3",
106150
"--db-url", "neo4j+s://demo.neo4jlabs.com",
107151
"--user", "recommendations",
108152
"--password", "recommendations",
@@ -125,6 +169,7 @@ Here is an example connection for the movie database with Movie, Person (Actor,
125169
"-e", "NEO4J_URI=bolt://host.docker.internal:7687",
126170
"-e", "NEO4J_USERNAME=neo4j",
127171
"-e", "NEO4J_PASSWORD=<your-password>",
172+
"-e", "NEO4J_NAMESPACE=mydb",
128173
"mcp/neo4j-cypher:latest"
129174
]
130175
}
@@ -177,7 +222,7 @@ uv pip install -e ".[dev]"
177222
"command": "uv",
178223
"args": [
179224
"--directory", "parent_of_servers_repo/servers/mcp-neo4j-cypher/src",
180-
"run", "mcp-neo4j-cypher", "--transport", "stdio"],
225+
"run", "mcp-neo4j-cypher", "--transport", "stdio", "--namespace", "dev"],
181226
"env": {
182227
"NEO4J_URI": "bolt://localhost",
183228
"NEO4J_USERNAME": "neo4j",
@@ -200,6 +245,7 @@ docker build -t mcp/neo4j-cypher:latest .
200245
docker run -e NEO4J_URI="bolt://host.docker.internal:7687" \
201246
-e NEO4J_USERNAME="neo4j" \
202247
-e NEO4J_PASSWORD="your-password" \
248+
-e NEO4J_NAMESPACE="mydb" \
203249
mcp/neo4j-cypher:latest
204250
```
205251

servers/mcp-neo4j-cypher/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "mcp-neo4j-cypher"
3-
version = "0.2.2"
3+
version = "0.2.3"
44
description = "A simple Neo4j MCP server"
55
readme = "README.md"
66
requires-python = ">=3.10"

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ def main():
1212
parser.add_argument("--username", default=None, help="Neo4j username")
1313
parser.add_argument("--password", default=None, help="Neo4j password")
1414
parser.add_argument("--database", default=None, help="Neo4j database name")
15-
parser.add_argument("--transport", default="stdio", help="Transport type")
15+
parser.add_argument("--transport", default=None, help="Transport type")
16+
parser.add_argument("--namespace", default=None, help="Tool namespace")
1617

1718
args = parser.parse_args()
1819
asyncio.run(
@@ -21,7 +22,8 @@ def main():
2122
args.username or os.getenv("NEO4J_USERNAME", "neo4j"),
2223
args.password or os.getenv("NEO4J_PASSWORD", "password"),
2324
args.database or os.getenv("NEO4J_DATABASE", "neo4j"),
24-
args.transport,
25+
args.transport or os.getenv("NEO4J_TRANSPORT", "stdio"),
26+
args.namespace or os.getenv("NEO4J_NAMESPACE", ""),
2527
)
2628
)
2729

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919

2020
logger = logging.getLogger("mcp_neo4j_cypher")
2121

22+
def _format_namespace(namespace: str) -> str:
23+
if namespace:
24+
if namespace.endswith("-"):
25+
return namespace
26+
else:
27+
return namespace + "-"
28+
else:
29+
return ""
2230

2331
async def _read(tx: AsyncTransaction, query: str, params: dict[str, Any]) -> str:
2432
raw_results = await tx.run(query, params)
@@ -41,7 +49,7 @@ def _is_write_query(query: str) -> bool:
4149
)
4250

4351

44-
def create_mcp_server(neo4j_driver: AsyncDriver, database: str = "neo4j") -> FastMCP:
52+
def create_mcp_server(neo4j_driver: AsyncDriver, database: str = "neo4j", namespace: str = "") -> FastMCP:
4553
mcp: FastMCP = FastMCP("mcp-neo4j-cypher", dependencies=["neo4j", "pydantic"])
4654

4755
async def get_neo4j_schema() -> list[types.TextContent]:
@@ -126,9 +134,11 @@ async def write_neo4j_cypher(
126134
types.TextContent(type="text", text=f"Error: {e}\n{query}\n{params}")
127135
]
128136

129-
mcp.add_tool(get_neo4j_schema)
130-
mcp.add_tool(read_neo4j_cypher)
131-
mcp.add_tool(write_neo4j_cypher)
137+
namespace_prefix = _format_namespace(namespace)
138+
139+
mcp.add_tool(get_neo4j_schema, name=namespace_prefix+"get_neo4j_schema")
140+
mcp.add_tool(read_neo4j_cypher, name=namespace_prefix+"read_neo4j_cypher")
141+
mcp.add_tool(write_neo4j_cypher, name=namespace_prefix+"write_neo4j_cypher")
132142

133143
return mcp
134144

@@ -139,6 +149,7 @@ async def main(
139149
password: str,
140150
database: str,
141151
transport: Literal["stdio", "sse"] = "stdio",
152+
namespace: str = "",
142153
) -> None:
143154
logger.info("Starting MCP neo4j Server")
144155

@@ -150,7 +161,7 @@ async def main(
150161
),
151162
)
152163

153-
mcp = create_mcp_server(neo4j_driver, database)
164+
mcp = create_mcp_server(neo4j_driver, database, namespace)
154165

155166
match transport:
156167
case "stdio":

servers/mcp-neo4j-cypher/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)