Skip to content

Commit c6e6717

Browse files
committed
add namespacing for tools, tested
tested with claude desktop and 4 different namespaced Cypher MCP servers
1 parent 78c890e commit c6e6717

File tree

3 files changed

+22
-7
lines changed

3 files changed

+22
-7
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/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":

0 commit comments

Comments
 (0)