Skip to content

Conversation

a-s-g93
Copy link
Collaborator

@a-s-g93 a-s-g93 commented Apr 16, 2025

  • Pull out common functions from the Cypher MCP into a common package to be used by all MCP servers
  • write IT for common
  • Update Cypher MCP server with changes
  • Test Common and Neo4j Cypher MCP

@a-s-g93 a-s-g93 requested a review from jexp April 16, 2025 20:55
@a-s-g93
Copy link
Collaborator Author

a-s-g93 commented Apr 16, 2025

this builds on PR #18 and should be merged after.

time.sleep(initial_delay)
print("\nWaiting for Neo4j to Start...\n", file=sys.stderr)

while not success and attempts < max_attempts:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't that more like a test issue than a runtime issue? at runtime the neo4j db should be up and running

should be handled in test infrastructure instead that waits that a server is up (like testcontainers does internally)

raw_results = await tx.run(query, params)
eager_results = await raw_results.to_eager_result()

return [r.data() for r in eager_results.records]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use a result transformer

A list of dictionaries containing the results of the query or error messages.
"""
try:
async with neo4j_driver.session(database=database) as session:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use driver.execute_query which handles retries internally and automatically

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for sessions

A list of dictionaries containing the results of the query or error messages.
"""
try:
async with neo4j_driver.session(database=database) as session:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here retries would actually be important, but they are also handled by driver.execute_query

environment:
NEO4J_AUTH: neo4j/testingpassword
NEO4J_ACCEPT_LICENSE_AGREEMENT: "eval"
NEO4J_PLUGINS: "[\"apoc\"]" No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if possible we shouldn't require apoc or enterprise

from typing import Any

@pytest.mark.asyncio(loop_scope="session")
async def test_execute_read_query_with_parameters(async_neo4j_driver: AsyncDriver, healthcheck: Any, init_data: Any):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be good if fixture and use of fixture data were together in the same file


3. Run Integration Tests

**CLOSE ANY LOCAL NEO4J DATABASES BEFORE RUNNING TESTS**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not require that, but instead use a safe way of running databases that doesn't conflict with existing db's

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too dangerous otherwise

"--directory", "parent_of_servers_repo/servers/mcp-neo4j-cypher/src",
"run", "mcp-neo4j-cypher"],
"env": {
"NEO4J_URL": "bolt://localhost",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

raw_results = await session.execute_write(_write, query, params)
counters_json_str = json.dumps(raw_results._summary.counters.__dict__, default=str)
result = await execute_write_query(
neo4j_driver, query, params, database, logger, False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are usually loggers passed to functions in python?
the false should be a named parameter, otherwise the reader doesn't know what it does

) -> None:
logger.info("Starting MCP neo4j Server")

neo4j_driver = AsyncGraphDatabase.driver(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this use the common infra ...

@a-s-g93 a-s-g93 closed this Apr 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants