Skip to content

Commit 9db1b7d

Browse files
rfrneo4ja-s-g93
andauthored
data modeling - feat: Add comprehensive example data models as MCP resources (#122)
* feat: Add comprehensive example data models as MCP resources - Add DataModel.from_dict() class method for JSON to DataModel conversion - Add 7 new example data models as MCP resources: * resource://examples/patient_journey_model (14 nodes, 21 relationships) * resource://examples/supply_chain_model (14 nodes, 23 relationships) * resource://examples/software_dependency_model (14 nodes, 17 relationships) * resource://examples/oil_gas_monitoring_model (12 nodes, 26 relationships) * resource://examples/customer_360_model (30 nodes, 35 relationships) * resource://examples/fraud_aml_model (15 nodes, 24 relationships) * resource://examples/health_insurance_fraud_model (14 nodes, 16 relationships) - Add new MCP tools: * list_example_data_models: Lists all available examples with descriptions * load_example_data_model: Loads any example as DataModel object - Remove CBRE_WORK_ORDER_MODEL (accidentally added) - Remove Google references from Supply Chain model - Fix server startup with asyncio.run(main()) - Add comprehensive test coverage for new tools and resources - Ensure MCP resources return JSON strings, tools return DataModel objects All 56 tests passing (43 unit + 13 integration) * refactor: improve template and test organization - Update DATA_MODELING_TEMPLATE to include example data in property descriptions - Remove unnecessary template fields (Direction, Integration Needs, Compliance) - Move server tools and MCP resources tests to dedicated test_server.py file - Use pytest fixture for MCP server to avoid duplication - All 43 tests passing with comprehensive coverage * replace .to_dict with built in functions, update example unit tests and get_example model_tool to return viz config too * update get_example_data_model tests need to parse data model from response since we now include the viz config * Added description field to static data models and removed data model prompt * Fix duplicate relationship validation to allow multiple relationships with same pattern * update readme and changelog * Update CHANGELOG.md --------- Co-authored-by: runfourestrun <[email protected]> Co-authored-by: alex <[email protected]>
1 parent 6a0e7da commit 9db1b7d

File tree

10 files changed

+3531
-15
lines changed

10 files changed

+3531
-15
lines changed

servers/mcp-neo4j-data-modeling/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
### Added
99
* Update PR workflow to iterate over Python 3.10 to 3.13
10+
* Add example data model resources
11+
* Add tools to list and retrieve example data models and their Mermaid configurations
1012

1113
## v0.2.0
1214

servers/mcp-neo4j-data-modeling/README.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ A Model Context Protocol (MCP) server implementation that provides tools for cre
1010

1111
The server provides these resources:
1212

13+
#### Schema
14+
1315
- `resource://schema/node`
1416
- Get the JSON schema for a Node object
1517
- Returns: JSON schema defining the structure of a Node
@@ -25,7 +27,40 @@ The server provides these resources:
2527
- `resource://schema/data_model`
2628
- Get the JSON schema for a DataModel object
2729
- Returns: JSON schema defining the structure of a DataModel
28-
30+
31+
#### Example Data Models
32+
33+
- `resource://examples/patient_journey_model`
34+
- Get a real-world Patient Journey healthcare data model in JSON format
35+
- Returns: JSON DataModel for tracking patient encounters, conditions, medications, and care plans
36+
37+
- `resource://examples/supply_chain_model`
38+
- Get a real-world Supply Chain data model in JSON format
39+
- Returns: JSON DataModel for tracking products, orders, inventory, and locations
40+
41+
- `resource://examples/software_dependency_model`
42+
- Get a real-world Software Dependency Graph data model in JSON format
43+
- Returns: JSON DataModel for software dependency tracking with security vulnerabilities, commits, and contributor analysis
44+
45+
- `resource://examples/oil_gas_monitoring_model`
46+
- Get a real-world Oil and Gas Equipment Monitoring data model in JSON format
47+
- Returns: JSON DataModel for industrial monitoring of oil and gas equipment, sensors, alerts, and maintenance
48+
49+
- `resource://examples/customer_360_model`
50+
- Get a real-world Customer 360 data model in JSON format
51+
- Returns: JSON DataModel for customer relationship management with accounts, contacts, orders, tickets, and surveys
52+
53+
- `resource://examples/fraud_aml_model`
54+
- Get a real-world Fraud & AML data model in JSON format
55+
- Returns: JSON DataModel for financial fraud detection and anti-money laundering with customers, transactions, alerts, and compliance
56+
57+
- `resource://examples/health_insurance_fraud_model`
58+
- Get a real-world Health Insurance Fraud Detection data model in JSON format
59+
- Returns: JSON DataModel for healthcare fraud detection tracking investigations, prescriptions, executions, and beneficiary relationships
60+
61+
62+
#### Ingest
63+
2964
- `resource://neo4j_data_ingest_process`
3065
- Get a detailed explanation of the recommended process for ingesting data into Neo4j using the data model
3166
- Returns: Markdown document explaining the ingest process
@@ -77,6 +112,21 @@ These tools provide integration with **[Arrows](https://arrows.app/)** - a graph
77112
- `data_model` (DataModel): The data model to export
78113
- Returns: JSON string compatible with Arrows app
79114

115+
#### 📚 Example Data Model Tools
116+
117+
These tools provide access to pre-built example data models for common use cases and domains.
118+
119+
- `list_example_data_models`
120+
- List all available example data models with descriptions
121+
- Input: None
122+
- Returns: Dictionary with example names, descriptions, node/relationship counts, and usage instructions
123+
124+
- `get_example_data_model`
125+
- Get an example graph data model from the available templates
126+
- Input:
127+
- `example_name` (str): Name of the example to load ('patient_journey', 'supply_chain', 'software_dependency', 'oil_gas_monitoring', 'customer_360', 'fraud_aml', or 'health_insurance_fraud')
128+
- Returns: ExampleDataModelResponse containing DataModel object and Mermaid visualization configuration
129+
80130
#### 📝 Cypher Ingest Tools
81131

82132
These tools may be used to create Cypher ingest queries based on the data model. These queries may then be used by other MCP servers or applications to load data into Neo4j.

servers/mcp-neo4j-data-modeling/src/mcp_neo4j_data_modeling/data_model.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -414,14 +414,6 @@ def validate_relationships(
414414
) -> list[Relationship]:
415415
"Validate the relationships."
416416

417-
# check for duplicate relationships
418-
counts = Counter([r.pattern for r in relationships])
419-
for pattern, count in counts.items():
420-
if count > 1:
421-
raise ValueError(
422-
f"Relationship with pattern {pattern} appears {count} times in data model"
423-
)
424-
425417
# ensure source and target nodes exist
426418
for relationship in relationships:
427419
if relationship.start_node_label not in [
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from pydantic import BaseModel, Field
2+
from .data_model import DataModel
3+
4+
class ExampleDataModelResponse(BaseModel):
5+
"""Response model for the `get_example_data_model` tool."""
6+
7+
data_model: DataModel = Field(description="The example graph data model.")
8+
mermaid_config: str = Field(description="The Mermaid visualization configuration for the example graph data model.")

servers/mcp-neo4j-data-modeling/src/mcp_neo4j_data_modeling/server.py

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import logging
23
from typing import Any, Literal
34

@@ -10,7 +11,17 @@
1011
Property,
1112
Relationship,
1213
)
13-
from .static import DATA_INGEST_PROCESS
14+
from .models import ExampleDataModelResponse
15+
from .static import (
16+
DATA_INGEST_PROCESS,
17+
PATIENT_JOURNEY_MODEL,
18+
SUPPLY_CHAIN_MODEL,
19+
SOFTWARE_DEPENDENCY_MODEL,
20+
OIL_GAS_MONITORING_MODEL,
21+
CUSTOMER_360_MODEL,
22+
FRAUD_AML_MODEL,
23+
HEALTH_INSURANCE_FRAUD_MODEL,
24+
)
1425

1526
logger = logging.getLogger("mcp_neo4j_data_modeling")
1627

@@ -52,6 +63,48 @@ def neo4j_data_ingest_process() -> str:
5263
logger.info("Getting the process for ingesting data into a Neo4j database.")
5364
return DATA_INGEST_PROCESS
5465

66+
@mcp.resource("resource://examples/patient_journey_model")
67+
def example_patient_journey_model() -> str:
68+
"""Get a real-world Patient Journey healthcare data model in JSON format."""
69+
logger.info("Getting the Patient Journey healthcare data model.")
70+
return json.dumps(PATIENT_JOURNEY_MODEL, indent=2)
71+
72+
@mcp.resource("resource://examples/supply_chain_model")
73+
def example_supply_chain_model() -> str:
74+
"""Get a real-world Supply Chain data model in JSON format."""
75+
logger.info("Getting the Supply Chain data model.")
76+
return json.dumps(SUPPLY_CHAIN_MODEL, indent=2)
77+
78+
@mcp.resource("resource://examples/software_dependency_model")
79+
def example_software_dependency_model() -> str:
80+
"""Get a real-world Software Dependency Graph data model in JSON format."""
81+
logger.info("Getting the Software Dependency Graph data model.")
82+
return json.dumps(SOFTWARE_DEPENDENCY_MODEL, indent=2)
83+
84+
@mcp.resource("resource://examples/oil_gas_monitoring_model")
85+
def example_oil_gas_monitoring_model() -> str:
86+
"""Get a real-world Oil and Gas Equipment Monitoring data model in JSON format."""
87+
logger.info("Getting the Oil and Gas Equipment Monitoring data model.")
88+
return json.dumps(OIL_GAS_MONITORING_MODEL, indent=2)
89+
90+
@mcp.resource("resource://examples/customer_360_model")
91+
def example_customer_360_model() -> str:
92+
"""Get a real-world Customer 360 data model in JSON format."""
93+
logger.info("Getting the Customer 360 data model.")
94+
return json.dumps(CUSTOMER_360_MODEL, indent=2)
95+
96+
@mcp.resource("resource://examples/fraud_aml_model")
97+
def example_fraud_aml_model() -> str:
98+
"""Get a real-world Fraud & AML data model in JSON format."""
99+
logger.info("Getting the Fraud & AML data model.")
100+
return json.dumps(FRAUD_AML_MODEL, indent=2)
101+
102+
@mcp.resource("resource://examples/health_insurance_fraud_model")
103+
def example_health_insurance_fraud_model() -> str:
104+
"""Get a real-world Health Insurance Fraud Detection data model in JSON format."""
105+
logger.info("Getting the Health Insurance Fraud Detection data model.")
106+
return json.dumps(HEALTH_INSURANCE_FRAUD_MODEL, indent=2)
107+
55108
@mcp.tool()
56109
def validate_node(
57110
node: Node, return_validated: bool = False
@@ -180,6 +233,96 @@ def get_constraints_cypher_queries(data_model: DataModel) -> list[str]:
180233
)
181234
return data_model.get_cypher_constraints_query()
182235

236+
@mcp.tool()
237+
def get_example_data_model(
238+
example_name: str = Field(
239+
...,
240+
description="Name of the example to load: 'patient_journey', 'supply_chain', 'software_dependency', 'oil_gas_monitoring', 'customer_360', 'fraud_aml', or 'health_insurance_fraud'",
241+
),
242+
) -> ExampleDataModelResponse:
243+
"""Get an example graph data model from the available templates. Returns a DataModel object and the Mermaid visualization configuration for the example graph data model."""
244+
logger.info(f"Getting example data model: {example_name}")
245+
246+
example_map = {
247+
"patient_journey": PATIENT_JOURNEY_MODEL,
248+
"supply_chain": SUPPLY_CHAIN_MODEL,
249+
"software_dependency": SOFTWARE_DEPENDENCY_MODEL,
250+
"oil_gas_monitoring": OIL_GAS_MONITORING_MODEL,
251+
"customer_360": CUSTOMER_360_MODEL,
252+
"fraud_aml": FRAUD_AML_MODEL,
253+
"health_insurance_fraud": HEALTH_INSURANCE_FRAUD_MODEL,
254+
}
255+
256+
if example_name not in example_map:
257+
raise ValueError(
258+
f"Unknown example: {example_name}. Available examples: {list(example_map.keys())}"
259+
)
260+
261+
example_data = example_map[example_name]
262+
263+
validated_data_model = DataModel.model_validate(example_data)
264+
265+
return ExampleDataModelResponse(
266+
data_model=validated_data_model,
267+
mermaid_config=validated_data_model.get_mermaid_config_str(),
268+
)
269+
270+
@mcp.tool()
271+
def list_example_data_models() -> dict[str, Any]:
272+
"""List all available example data models with descriptions. Returns a dictionary with example names and their descriptions."""
273+
logger.info("Listing available example data models.")
274+
275+
examples = {
276+
"patient_journey": {
277+
"name": "Patient Journey",
278+
"description": "Healthcare data model for tracking patient encounters, conditions, medications, and care plans",
279+
"nodes": len(PATIENT_JOURNEY_MODEL["nodes"]),
280+
"relationships": len(PATIENT_JOURNEY_MODEL["relationships"]),
281+
},
282+
"supply_chain": {
283+
"name": "Supply Chain",
284+
"description": "Supply chain management data model for tracking products, orders, inventory, and locations",
285+
"nodes": len(SUPPLY_CHAIN_MODEL["nodes"]),
286+
"relationships": len(SUPPLY_CHAIN_MODEL["relationships"]),
287+
},
288+
"software_dependency": {
289+
"name": "Software Dependency Graph",
290+
"description": "Software dependency tracking with security vulnerabilities, commits, and contributor analysis",
291+
"nodes": len(SOFTWARE_DEPENDENCY_MODEL["nodes"]),
292+
"relationships": len(SOFTWARE_DEPENDENCY_MODEL["relationships"]),
293+
},
294+
"oil_gas_monitoring": {
295+
"name": "Oil & Gas Equipment Monitoring",
296+
"description": "Industrial monitoring data model for oil and gas equipment, sensors, alerts, and maintenance",
297+
"nodes": len(OIL_GAS_MONITORING_MODEL["nodes"]),
298+
"relationships": len(OIL_GAS_MONITORING_MODEL["relationships"]),
299+
},
300+
"customer_360": {
301+
"name": "Customer 360",
302+
"description": "Customer relationship management data model for accounts, contacts, orders, tickets, and surveys",
303+
"nodes": len(CUSTOMER_360_MODEL["nodes"]),
304+
"relationships": len(CUSTOMER_360_MODEL["relationships"]),
305+
},
306+
"fraud_aml": {
307+
"name": "Fraud & AML",
308+
"description": "Financial fraud detection and anti-money laundering data model for customers, transactions, alerts, and compliance",
309+
"nodes": len(FRAUD_AML_MODEL["nodes"]),
310+
"relationships": len(FRAUD_AML_MODEL["relationships"]),
311+
},
312+
"health_insurance_fraud": {
313+
"name": "Health Insurance Fraud Detection",
314+
"description": "Healthcare fraud detection data model for tracking investigations, prescriptions, executions, and beneficiary relationships",
315+
"nodes": len(HEALTH_INSURANCE_FRAUD_MODEL["nodes"]),
316+
"relationships": len(HEALTH_INSURANCE_FRAUD_MODEL["relationships"]),
317+
},
318+
}
319+
320+
return {
321+
"available_examples": examples,
322+
"total_examples": len(examples),
323+
"usage": "Use the get_example_data_model tool with any of the example names above to get a specific data model",
324+
}
325+
183326
return mcp
184327

185328

0 commit comments

Comments
 (0)