MCP Server
JetGraph exposes 14 Model Context Protocol (MCP) tools and the investigate prompt so AI agents (Cursor, Claude, OpenAI Agents SDK, and custom runtimes) can inspect schema semantics, explore relationships, read time-windowed behavior, run guarded Cypher, and author live segments.
On this page
Two ways to run MCP
Both deployment modes expose the exact same 14 tools and investigate prompt:
| Mode | Transport & endpoint | When to use |
|---|---|---|
Built into jetgraph-engine |
Streamable HTTP on port 8080 at /mcp (alias /api/mcp) |
Default for Docker and server deployments — zero extra processes to run. |
Standalone jetgraph-mcp binary |
stdio by default, or Streamable HTTP with --listen <addr> / JETGRAPH_MCP_ADDR (exposes /mcp, /api/mcp, /health) |
When you need a local stdio MCP command in a desktop client or want MCP on a separate host/port (source in RustGraphClient/jetgraph-mcp). |
Client configuration
For Cursor (.cursor/mcp.json) or any Streamable HTTP MCP client connecting to the engine:
When running the standalone jetgraph-mcp binary over stdio (pointing at the engine's gRPC, HTTP, and segment-evaluator ports):
Or run the standalone binary as an HTTP server on a separate port (--http binds 0.0.0.0:8090):
Tool reference (14 tools)
Agents are instructed to call get_schema before naming any node type, edge type, or property so queries align with registered description and business_meaning metadata.
| Tool | Arguments | Behavior & limits |
|---|---|---|
get_schema |
None | Returns schema_version, node_types (name, description, business_meaning, external_id kind, properties), edge_types (direction, description, business_meaning, symmetric, minimal_payload, state_ttl_secs, activity_tick_secs, activity_horizon_secs, bool_property, tracked_property, bin_boundaries, node_histogram, ingest properties), feature_schemas, and transaction_profiles. |
get_neighbors |
node_type, external_id, edge_type, direction (out|in, default out), limit, cursor |
Returns one page of neighbor external IDs plus has_more and next_cursor. Default limit 25, maximum 100 (0 is rejected). |
get_neighbor_count |
node_type, external_id, edge_type |
Returns neighbor count and approximate flag (HyperLogLog estimate when enabled). |
get_last_neighbor |
node_type, external_id, edge_type |
Returns the outgoing (from → to) neighbor with the latest last_seen_secs. For inbound recency on a to node, use an anchored cypher_read with ORDER BY r.last_seen DESC LIMIT 1. |
get_edge_state |
edge_type, src_type, src_id, dst_type, dst_id, activity_windows_secs |
Returns pair summary: found (false means first-time interaction), tx_count, approx_sum, last_seen_secs, bool_flag, and activity_counts. Accepts up to 4 positive window values (in seconds) within activity_horizon_secs. |
get_histogram |
node_type, external_id, edge_type, window_hours OR window_days |
Returns node-level total_events, 8-bucket bin_counts, and window_covered_secs for a source (from) node. Pass either window_hours (1..=1440) or window_days (1..=365), never both. |
get_feature_vector |
node_type, external_id |
Reads the stored 32-slot vector (only valid when get_schema.feature_schemas has enabled: true for that node type). Returns confidence, age_secs, quality_flags, and active slots (raw, effective, support, used_fallback). |
find_similar |
node_type, external_id, edge_weights ([{edge_type, weight}]), required_edge_types, k, min_similarity |
Computes weighted shared-neighbor Jaccard overlap on the fly without writing SIMILAR_TO edges. Default k 10, maximum 25. |
cypher_read |
query, parameters |
Executes one read-only Cypher statement and returns columns, rows, elapsed_us, and truncated. See guardrails below. |
list_signals |
None | Lists signal definitions stored by segment-evaluator. |
list_segments |
None | Lists segment definitions stored by segment-evaluator. |
create_signal |
name, query, value_kind (number|epoch_secs), time_sensitive |
Stores or replaces a signal definition in segment-evaluator (does not mutate graph edges or nodes). |
create_segment |
name, label, entity_type, logic (all|any|weighted), min_confidence, conditions |
Stores or replaces a segment rule over existing signals. Membership appears in list_segment_members once the evaluator processes nodes. |
list_segment_members |
name, limit, cursor |
Lists entities linked to a segment (external_id, node_id, confidence, last_seen_secs). Default limit 25, maximum 100. |
Read-only Cypher guard & limits
cypher_read enforces read-only, bounded execution before planning any query:
- Single statement only: multi-statement queries separated by semicolons are rejected.
- Write keywords blocked:
CREATE,MERGE,DELETE,DETACH,SET,REMOVE,DROP,FOREACH, andLOADare rejected. Pass string filter values viaparameters($val) so literals containing those words are not rejected. - Procedure allowlist:
CALLis restricted toCALL graph.*procedures (graph.histogram,graph.lastNeighbor,graph.neighborCount,graph.edgeState,graph.segmentContext,graph.fraudContext,graph.findSimilar). - Row limit cap: literal
LIMITmust be1..=100. ParameterizedLIMIT $kis rejected, and a missingLIMITautomatically appendsLIMIT 100. - Compact edge fields in Cypher: edge ingest properties are inputs only; filter and project stored fields via
r.tx_count,r.approx_sum(aliasr.amount),r.last_seen,r.bool_flag, andr.bins.
Authoring signals & segments
Agents can promote investigative patterns into continuous segments in segment-evaluator:
- Signal queries must be read-only Cypher binding
$node(internal node ID) and returning one column namedvalue(e.g.,MATCH (n) WHERE id(n) = $node RETURN n.prop_name AS valueorCALL graph.histogram($node, 'EDGE', 24, null) YIELD total_events RETURN total_events AS value). epoch_secsthresholds: whenvalue_kindisepoch_secs, the evaluator converts the timestamp to elapsed days ((now_secs - value) / 86400; null maps to infinity) before comparing against condition thresholds — soop: "gt", threshold: 30means inactive for more than 30 days.- Segment logic: combine conditions with
all,any, orweighted(each condition takessignal,opingt|lt|gte|lte|eq|between,threshold, optionalthreshold_max,weight, andreasonsupporting{value},{threshold},{delta},{pct}).
The investigate prompt
The server exposes an MCP prompt named investigate ("How to investigate a JetGraph question with these tools") alongside server instructions. It guides agents to call get_schema first, interpret compact per-pair edges accurately (distinguishing count(r) distinct counterparties from sum(r.tx_count) total events), pair node histograms with edge state to distinguish concentration vs fan-out, and keep Top-K Cypher aggregations in a single RETURN ... ORDER BY ... LIMIT k block.
Environment variables
| Variable | Applies to | Purpose |
|---|---|---|
JETGRAPH_MCP_ALLOWED_HOSTS |
Built-in /mcp & standalone HTTP |
Comma-separated Host header allowlist for DNS-rebinding protection. When unset, host checking is disabled. |
JETGRAPH_GRPC_URL |
Built-in /mcp & standalone binary |
Engine gRPC endpoint used by MCP tools (built-in defaults to http://127.0.0.1:<grpc_port>). |
JETGRAPH_SEGMENTS_URL |
Built-in /mcp & standalone binary |
Base URL for segment-evaluator (defaults to trying http://127.0.0.1:8081, then http://segment-evaluator:8081). |
JETGRAPH_HTTP_URL |
Standalone jetgraph-mcp |
Engine HTTP endpoint for cypher_read (defaults to http://127.0.0.1:8080). |
JETGRAPH_MCP_ADDR / MCP_LISTEN_ADDR |
Standalone jetgraph-mcp |
Listen address for Streamable HTTP mode when --listen is not passed. |
Related: MCP for AI agents (overview), security notes, Segment Evaluator docs, Cypher manual.