name: develop-neo4j-graph
description: Develop Neo4j graphs end-to-end: analyze source data, design data models, ingest CSV and/or PDF data, extract entities, and validate with queries. Use when importing data to Neo4j, designing graph data models, creating knowledge graphs, or building chatbots or analytical applications backed by Neo4j.
Develop Neo4j Graph
Pre-flight: Confirm Models
Before starting, read .env and report the configured models:
EMBEDDING_MODEL — used by embed_chunks
EXTRACTION_MODEL — used by extract_entities
Never substitute, correct, or override these values. Model names in .env are user-configured and may include models you don't recognize (recently released models, LiteLLM aliases, custom endpoints). If a name looks unfamiliar, that is intentional — use it as-is.
If extraction or embedding fails with a model error, report the exact error and stop. Do not silently switch to a different model.
Progress Checklist
Copy this checklist to track progress:
- [ ] Step 1: Discovery — read source data, identify entities
- [ ] Step 2: Use case discussion → determine MODE (CHATBOT or ANALYTICAL)
- [ ] Step 3: Graph data model
- [ ] Step 4: Ingest data (CSV and/or PDF)
- [ ] Step 4.5: Verify ingestion counts
- [ ] Step 5 [PDF only]: Export schema and review validators
- [ ] Step 6 [PDF only]: Extract entities
- [ ] Step 7 [PDF only]: Verify extraction results
- [ ] Step 8: Output [MODE-SPECIFIC]
Step 1: Discovery
Read source data samples to understand content and structure. Do not use MCP tools at this stage.
CSV data: Read samples from data/csv/. Reference HANDLE_STRUCTURED_DATA.md for discovery guidance, including the cross-file ID consistency check.
PDF data: List files in data/pdf/ (and subfolders) using Glob. For each PDF, use the Read tool with pages: "1-2" to sample content. Reference the Parse Mode Guide in HANDLE_UNSTRUCTURED_DATA.md to identify the appropriate parse mode for each document type.
Summarize what you found: data types present, content domain, entity types visible, structural observations.
Step 2: Use Case Discussion → Mode Selection
Ask the user what they want to accomplish with the data. Do not ask them to choose a mode explicitly.
To determine the mode, ask yourself: does the user describe how someone will interact with the application (natural language Q&A), or what the data should reveal (patterns, aggregations, cohort analysis)?
-
CHATBOT mode signals: user mentions asking questions, a chatbot, a search interface, natural language queries, or retrieving answers on demand. The interaction is the point.
-
ANALYTICAL mode signals: user mentions tracking, identifying patterns, correlations, treatment outcomes, cohort comparisons, monitoring, or surfacing insights across the dataset. The findings are the point — even if the result will power an application.
When ambiguous (e.g. "building an application" without specifying how users interact with it, or "connect X with Y" which could be retrieval or analysis), ask one clarifying question:
"Will users primarily explore the data through natural language questions, or should the application surface structured patterns and reports from the data?"
Set MODE = CHATBOT or ANALYTICAL. State it clearly. You will return to this at Step 8.
Step 3: Graph Data Model
Reference GRAPH_DATA_MODELING_MCP.md for the full modeling process using the neo4j-data-modeling MCP server.
If handling both CSV and PDF data, design four distinct sub-models, each visualized separately with get_mermaid_config_str:
- Structured data model — nodes and relationships derived from CSV only
- Entity extraction model — focused subset of nodes to extract from PDFs via LLM; must partially overlap with the structured model via bridge nodes (merged on a shared key property such as
name)
- Lexical graph model —
Document → Chunk, created by neo4j-lexical-graph; no design needed, provided by the server
- Unified model — all three layers combined; show explicitly how extracted entities connect to structured nodes (bridge nodes + MERGE key)
[CHATBOT mode] Map each confirmed target question to the nodes/relationships that will answer it. Flag any questions the current model cannot address.
Save the final model JSON to outputs/data_models/<topic>_data_model.json.
Step 4: Ingest Data
CSV data — neo4j-ingest
Reference HANDLE_STRUCTURED_DATA.md for ingestion details.
Always use absolute paths. Use ingest_csv_into_neo4j.
PDF data — neo4j-lexical-graph
Load the mode-specific reference file for the exact tool sequence:
Quick reference (all modes):
| Step | Tool | pymupdf | docling | page_image | vlm_blocks |
|---|
| 1 | create_lexical_graph | ✓ | ✓ | ✓ | ✓ |
| 2 | chunk_lexical_graph | ✗ skip | ✓ | ✓ | ✓ |
| 3 | list_documents | ✓ | ✓ | ✓ | ✓ |
| 4 | verify_lexical_graph | optional | optional | ✗ never | optional |
| 5 | assign_section_hierarchy | ✗ skip | optional | ✗ skip | optional |
| 6 | generate_chunk_descriptions | if images/tables | if images/tables | required | if images/tables |
| 7 | embed_chunks | ✓ | ✓ | ✓ | ✓ |
generate_chunk_descriptions — call without document_id to run for all active documents at once.
embed_chunks — call with no parameters. Auto-detects textDescription and applies the right embedding strategy (VLM descriptions for Table/Image/Page nodes, raw text for others — all in one unified index).
Step 4.5: Verify Ingestion Counts
After all ingestion is complete, run count checks for every node label and key relationship type using read_neo4j_cypher from neo4j-graphrag:
MATCH (n:NodeLabel) RETURN COUNT(n) AS count
For CSV nodes: verify counts match source row counts (accounting for deduplication).
Check for orphan nodes:
MATCH (n:NodeLabel) WHERE NOT (n)--() RETURN COUNT(n) AS orphans
If orphans are found, check for cross-file ID mismatches before proceeding.
Step 5 [PDF only]: Export Schema and Review Validators
Use convert_schema from neo4j-entity-graph — not export_to_pydantic_models from the data-modeling server.
- Input: the entity extraction sub-model (not the full unified model)
- Set
output_path to outputs/schemas/<topic>_schema.json
- Output:
<topic>_schema.json (extraction config) + <topic>_schema.json.py (Pydantic models)
Review the Pydantic .py file. For each node's key property, verify or add a normalizing validator:
@field_validator('name')
@classmethod
def normalize_name(cls, v: str) -> str:
return v.strip().lower()
This prevents duplicate nodes from minor text variations (e.g. "Aspirin" vs "aspirin "). Present the validators to the user and confirm before proceeding.
Step 6 [PDF only]: Extract Entities
Use extract_entities from neo4j-entity-graph:
- Pass the schema JSON path from Step 5
- Extraction is async — poll with
check_extraction_status until complete
- Report progress to the user: chunks processed, entities found so far
Step 7 [PDF only]: Verify Extraction Results
Use read_neo4j_cypher from neo4j-graphrag:
-- Count per label
MATCH (n:NodeLabel) RETURN count(n) as count
-- Check for duplicates on key property
MATCH (n:NodeLabel)
WITH n.keyProp as key, count(*) as cnt
WHERE cnt > 1
RETURN key, cnt ORDER BY cnt DESC LIMIT 10
-- Verify entity-chunk links
MATCH (n)-[:EXTRACTED_FROM]->(c:Chunk) RETURN count(*) as entity_chunk_links
If CSV data is also present, run entity reconciliation to check for name mismatches between extracted and structured nodes. See HANDLE_UNSTRUCTURED_DATA.md.
If significant duplicates: document them for next iteration. Do not re-run extraction.
Step 8: Output [MODE-SPECIFIC]
Reminder — current MODE: CHATBOT or ANALYTICAL (set in Step 2).
[CHATBOT mode] → Load CHATBOT_MODE.md:
Answer each confirmed target question using neo4j-graphrag tools (vector search, fulltext search, Cypher, read_node_image), then generate the chatbot report saved to outputs/reports/<topic>_chatbot_report.md.
[ANALYTICAL mode] → Load ANALYTICAL_MODE.md:
Generate Cypher queries per use case in YAML format, validate them against the graph, then generate the analytical report saved to outputs/reports/<topic>_report.md.
MCP Server Quick Reference
| Server | Steps | Key Tools |
|---|
neo4j-data-modeling | 3 | list_example_data_models, get_example_data_model, get_mermaid_config_str, validate_data_model |
neo4j-ingest | 4 | ingest_csv_into_neo4j |
neo4j-lexical-graph | 4 | create_lexical_graph, chunk_lexical_graph, list_documents, generate_chunk_descriptions, embed_chunks, check_processing_status, verify_lexical_graph (spot-check, single doc only), assign_section_hierarchy (optional) |
neo4j-entity-graph | 5–6 | convert_schema, extract_entities, check_extraction_status |
neo4j-graphrag | 4.5–8 | read_neo4j_cypher, write_neo4j_cypher, get_neo4j_schema_and_indexes, vector_search, fulltext_search, search_cypher_query, read_node_image |