Skip to content

Repository files navigation

cortex-code-neo4j-mcp

A stdio MCP server that lets Snowflake Cortex Code ask natural-language questions to a Neo4j Aura Agent and get back the answer, the Cypher the agent executed, and a preview of the result rows.

Why this exists

Neo4j Aura Agents expose two endpoints for the same agent:

  1. A streamable HTTP MCP endpoint at https://mcp.neo4j.io/agent?.... This endpoint requires an interactive user OAuth flow (openid profile email scopes via authorization_code against a separate aura-mcp.eu.auth0.com tenant). It is well suited to MCP clients that can drive a browser login, such as Claude Desktop or MCP Inspector.
  2. A REST /invoke endpoint at https://api.neo4j.io/v2beta1/.../agents/<id>/invoke. This endpoint accepts service credentials via the standard Aura API OAuth client_credentials grant. It is well suited to headless, automated, and CI environments where no human is present to complete a browser login.

Snowflake Cortex Code's MCP HTTP transport accepts only static headers. It cannot drive an interactive OAuth flow, and per-request token minting is not something the transport will do for you. As a result, plugging Cortex Code directly into the Aura MCP endpoint fails with Unauthorized and there is no combination of static credentials that fixes it.

This project takes the second path: a small local stdio MCP server that uses the REST /invoke endpoint, mints and caches the bearer token internally, and exposes a single MCP tool that Cortex Code can call like any other.

What it does

The server exposes one MCP tool:

Tool Arguments Returns
ask_neo4j_agent question: str, verbose: bool = False Markdown with the answer, executed Cypher, a preview of result rows, and token usage

By default the agent's verbose reasoning trace is suppressed. Pass verbose=true to include it for debugging.

Architecture

+------------------+        stdio (MCP)        +-------------------------+        HTTPS         +---------------------+
|                  | <-----------------------> |                         | <------------------> |                     |
|  Cortex Code     |                           | cortex-code-neo4j-mcp   |   /oauth/token       |   api.neo4j.io      |
|  CLI (MCP host)  |                           | (stdio MCP server)      |   /agents/.../invoke |   (Aura REST API)   |
|                  |                           |                         |                      |                     |
+------------------+                           +-------------------------+                      +---------------------+
                                                      |        ^
                                                      |        |
                                                in-memory token cache
                                                (refresh 60s before expiry)

Three components, each with a single responsibility:

  • config.py validates the environment and produces a typed Settings object. Missing credentials fail at startup rather than silently at first call.
  • aura_client.py owns the OAuth dance, the token cache, and the /invoke call. It retries once on HTTP 401 so that a server-side token rotation does not surface as a transient failure.
  • server.py registers a single MCP tool and renders the Aura Agent's response envelope into a compact, human-readable markdown report.

Install

The recommended path is uvx, which runs the server in an isolated environment without installing anything globally.

# One-time: install uv (https://github.com/astral-sh/uv) if you do not have it.
brew install uv

To run the server directly from this repository:

uvx --from git+https://github.com/neo4j-field/cortex-code-neo4j-mcp cortex-code-neo4j-mcp

Pip-based install works equally well:

pip install git+https://github.com/neo4j-field/cortex-code-neo4j-mcp
cortex-code-neo4j-mcp

Configure

The server reads four required environment variables. All of them come from the Neo4j Aura console.

Variable Where to find it
NEO4J_CLIENT_ID Aura Console -> Project Settings -> API Keys -> Create. The client ID is shown once.
NEO4J_CLIENT_SECRET Same flow as above. The secret is shown once and cannot be retrieved later.
NEO4J_PROJECT_ID Visible in the agent's external endpoint URL: .../projects/<PROJECT_ID>/agents/....
NEO4J_AGENT_ID Visible in the same URL: .../agents/<AGENT_ID>/invoke.

Optional overrides are documented in .env.example.

Do not commit credentials. This repository's .gitignore blocks .env and several conventional credential filenames, but the responsibility for keeping secrets out of source control is yours. Prefer the OS keychain or a secrets manager in any environment you do not personally own.

Wire into Cortex Code

Cortex Code reads MCP servers from ~/.snowflake/cortex/mcp.json. Add this entry, substituting your credentials:

{
  "mcpServers": {
    "neo4j_aura_agent": {
      "type": "stdio",
      "command": "/opt/homebrew/bin/uvx",
      "args": [
        "--from",
        "git+https://github.com/neo4j-field/cortex-code-neo4j-mcp",
        "cortex-code-neo4j-mcp"
      ],
      "env": {
        "NEO4J_CLIENT_ID": "...",
        "NEO4J_CLIENT_SECRET": "...",
        "NEO4J_PROJECT_ID": "...",
        "NEO4J_AGENT_ID": "..."
      }
    }
  }
}

A copy is available in examples/mcp.json. Restart Cortex Code and the neo4j_aura_agent server should appear with one tool, ask_neo4j_agent.

Verify

Once Cortex Code is running, try a simple question. The agent in your Aura instance must be resumed; a paused database returns HTTP 404 from /invoke with a "paused or deleted" message, which the server surfaces back into the tool response.

ask_neo4j_agent("How many nodes are in the graph?")

A successful response includes the executed Cypher (typically MATCH (n) RETURN count(n)), the result, and the final answer.

What it looks like in Cortex Code

Once the wrapper is registered and Cortex Code is restarted, the MCP server status panel reports the bridge as connected with one tool available:

Cortex Code MCP server status showing neo4j_aura_agent connected over stdio with one tool

From the chat prompt, you ask a natural-language question. The example below is one of the synthetic-identity questions from the next section: "Find clusters of customers who share the same Device, Email, or Phone but have different names. List up to 5 clusters with their members."

Cortex Code chat prompt with the synthetic-identity question being entered

The agent translates the question to Cypher, runs it against the Aura instance, and returns a structured answer. Cortex Code renders the markdown directly in the chat surface:

Agent response listing customer clusters that share a Device across different names, with an offer to extend the analysis to shared Email or Phone

This is the practical value of pointing Cortex Code at a graph: a question that would require recursive joins in a relational store becomes one sentence of natural language and a clean, explained answer in seconds.

Additional screenshots, including the Cortex Code home screen and the tool-details panel, are available in docs/screenshots/.

Sample questions to try

These are written for a financial-crimes graph with labels such as Customer, Account, Transaction, Card, Device, Beneficiary, Merchant, Address, Email, Phone, and RiskRating. Adjust the nouns for your own schema.

Warm-up

  1. "What node labels exist in the graph, and how many of each?"
  2. "What relationship types exist, and which are the most common?"
  3. "Give me one example of each relationship pattern, formatted as (:Source)-[:REL]->(:Target)."

Multi-hop patterns (this is where graphs earn their keep)

  1. "Find the top 10 chains of three or more transactions, starting from any customer flagged HIGH risk, where each hop is at least $10,000 and the total path value exceeds $100,000."
  2. "Show me customers who are connected to a HIGH risk customer within three hops via shared accounts or beneficiaries."
  3. "Identify round-trip transaction paths: where money leaves a customer's account and returns to the same customer within five hops."

Shared-attribute and synthetic-identity detection

  1. "Find clusters of customers who share the same Device, Email, or Phone but have different names. List up to 20 clusters with their members."
  2. "Which addresses are tied to the highest number of distinct customers, and how many high-value accounts hang off each?"
  3. "Find pairs of customers that share at least two of: address, phone, email, employer. Return them with the count of shared attributes."

Community and ring detection

  1. "Surface the top 10 merchants by transaction volume, and for each list the customers who accounted for more than five percent of that volume."
  2. "Identify groups of three or more customers who all transact with the same beneficiary and the same merchant within the same month."

Risk propagation

  1. "For every customer connected to a RiskRating of HIGH or CRITICAL, summarise their account count, transaction volume, and the average path length to the nearest high-risk neighbour."
  2. "Rank countries by the total transaction value flowing into them from accounts owned by customers flagged HIGH risk."

Anomalies and velocity

  1. "List devices used by more than five distinct customers in the last 24 hours. Include the customer names and their risk ratings."
  2. "Find customers whose number of distinct sessions in the last seven days is more than three standard deviations above their 90-day mean."

The agent will translate each question into Cypher, run it against your Aura instance, and return the answer along with the query. Use the verbose=true argument on any call to see the agent's reasoning trace.

Design notes and trade-offs

Why the REST endpoint and not the MCP endpoint? The MCP endpoint at mcp.neo4j.io/agent is gated by user-bound OAuth (verified via the WWW-Authenticate: Bearer resource_metadata=... header it returns on unauthenticated requests, with required scopes openid profile email). Cortex Code's MCP HTTP transport supports static headers only. The REST endpoint accepts service credentials and is therefore reachable from a headless agent.

Why a wrapper and not a direct HTTP entry in mcp.json? Cortex Code's HTTP MCP transport does not mint or refresh OAuth tokens per request. A static Bearer in mcp.json works for at most one hour, after which it fails until manually rotated. A local stdio process can refresh tokens on its own without any user interaction.

Why one tool and not many? The Aura Agent already plans, tools, and executes internally. Exposing many MCP tools that all delegate to the same agent would only confuse the upstream model. One tool, one mental model.

Why hide the reasoning trace by default? The agent's thinking blocks are useful for debugging but verbose enough to drown the answer in chat clients. The verbose=True flag is available when you want it.

Security

  • Credentials are read from environment variables only. They are never written to disk, logged, or echoed in tool responses.
  • The token cache is in-memory and lives only for the lifetime of the process. There is no on-disk token cache to leak.
  • The server only reaches api.neo4j.io over TLS. No other outbound calls are made.
  • Aura API credentials grant access to the agent and to project metadata. Scope the credentials to the minimum project required, and rotate them if they are ever exposed.
  • See SECURITY.md for how to report vulnerabilities.

Development

git clone https://github.com/neo4j-field/cortex-code-neo4j-mcp.git
cd cortex-code-neo4j-mcp
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
pytest
ruff check src tests

The test suite uses httpx.MockTransport and does not require network access. Running it does not incur Aura API calls or token charges.

Prompts

The full prompt history that produced this implementation is preserved in prompts/ so the design decisions are reproducible and reviewable. See prompts/initial_design.md for the original conversation and prompts/final_prompt.md for the consolidated spec.

License

Apache License 2.0. See LICENSE.

About

Snowflake Cortex Code MCP server that connects Cortex agents to Neo4j Aura via the Aura REST API for graph-backed enterprise AI workflows.

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages