33import re
44from typing import Any , Literal , Optional
55
6- from fastmcp .resources import types
6+ from fastmcp .exceptions import ToolError
7+ from fastmcp .tools .tool import ToolResult , TextContent
78from fastmcp .server import FastMCP
89from neo4j import (
910 AsyncDriver ,
@@ -51,7 +52,7 @@ def create_mcp_server(neo4j_driver: AsyncDriver, database: str = "neo4j", namesp
5152 namespace_prefix = _format_namespace (namespace )
5253
5354 @mcp .tool (name = namespace_prefix + "get_neo4j_schema" )
54- async def get_neo4j_schema () -> list [types . TextContent ]:
55+ async def get_neo4j_schema () -> list [ToolResult ]:
5556 """List all node, their attributes and their relationships to other nodes in the neo4j database.
5657 If this fails with a message that includes "Neo.ClientError.Procedure.ProcedureNotFound"
5758 suggest that the user install and enable the APOC plugin.
@@ -136,22 +137,19 @@ def clean_schema(schema: dict) -> dict:
136137 schema_clean = clean_schema (schema )
137138 schema_clean_str = json .dumps (schema_clean )
138139
139- return types . CallToolResult (content = [types . TextContent (type = "text" , text = schema_clean_str )])
140+ return ToolResult (content = [TextContent (type = "text" , text = schema_clean_str )])
140141
141142 except Exception as e :
142143 logger .error (f"Database error retrieving schema: { e } " )
143- return types .CallToolResult (
144- isError = True ,
145- content = [types .TextContent (type = "text" , text = f"Error: { e } " )]
146- )
144+ raise ToolError (f"Error: { e } " )
147145
148146 @mcp .tool (name = namespace_prefix + "read_neo4j_cypher" )
149147 async def read_neo4j_cypher (
150148 query : str = Field (..., description = "The Cypher query to execute." ),
151149 params : Optional [dict [str , Any ]] = Field (
152150 None , description = "The parameters to pass to the Cypher query."
153151 ),
154- ) -> list [types . TextContent ]:
152+ ) -> list [ToolResult ]:
155153 """Execute a read Cypher query on the neo4j database."""
156154
157155 if _is_write_query (query ):
@@ -163,24 +161,19 @@ async def read_neo4j_cypher(
163161
164162 logger .debug (f"Read query returned { len (results_json_str )} rows" )
165163
166- return types . CallToolResult (content = [types . TextContent (type = "text" , text = results_json_str )])
164+ return ToolResult (content = [TextContent (type = "text" , text = results_json_str )])
167165
168166 except Exception as e :
169167 logger .error (f"Database error executing query: { e } \n { query } \n { params } " )
170- return types .CallToolResult (
171- isError = True ,
172- content = [
173- types .TextContent (type = "text" , text = f"Error: { e } \n { query } \n { params } " )
174- ]
175- )
168+ raise ToolError (f"Error: { e } \n { query } \n { params } " )
176169
177170 @mcp .tool (name = namespace_prefix + "write_neo4j_cypher" )
178171 async def write_neo4j_cypher (
179172 query : str = Field (..., description = "The Cypher query to execute." ),
180173 params : Optional [dict [str , Any ]] = Field (
181174 None , description = "The parameters to pass to the Cypher query."
182175 ),
183- ) -> list [types . TextContent ]:
176+ ) -> list [ToolResult ]:
184177 """Execute a write Cypher query on the neo4j database."""
185178
186179 if not _is_write_query (query ):
@@ -195,14 +188,11 @@ async def write_neo4j_cypher(
195188
196189 logger .debug (f"Write query affected { counters_json_str } " )
197190
198- return types . CallToolResult (content = [types . TextContent (type = "text" , text = counters_json_str )])
191+ return ToolResult (content = [TextContent (type = "text" , text = counters_json_str )])
199192
200193 except Exception as e :
201194 logger .error (f"Database error executing query: { e } \n { query } \n { params } " )
202- return types .CallToolResult (
203- isError = True ,
204- content = [types .TextContent (type = "text" , text = f"Error: { e } \n { query } \n { params } " )]
205- )
195+ raise ToolError (f"Error: { e } \n { query } \n { params } " )
206196
207197 return mcp
208198
0 commit comments