Skip to main content
Glama
plan.md5.59 kB
# Implementation Plan: Advanced Facets (Classification, Material, PartOf) **Branch**: `claude/006-advanced-facets` | **Date**: 2025-11-01 | **Spec**: [DESIGN_SPECIFICATION.md](../../DESIGN_SPECIFICATION.md) ## Summary Implement MCP tools for the three advanced IDS facets: Classification (classification systems), Material (material assignments), and PartOf (spatial relationships). These facets enable complex requirements for classification codes, material specifications, and structural hierarchy validation. ## Technical Context **Language/Version**: Python 3.8+ **Primary Dependencies**: - `fastmcp` - MCP tools - `ifctester` - `ids.Classification`, `ids.Material`, `ids.PartOf` classes **Performance Goals**: Facet creation <5ms **Constraints**: - PartOf requires nested entity specification - Classification systems must support URIs - Material supports both names and URIs **Scale/Scope**: Support 20+ advanced facets per specification ## Project Structure ```text specs/006-advanced-facets/ └── plan.md src/ids_mcp_server/tools/ └── advanced_facets.py # Classification, Material, PartOf tools tests/ ├── unit/tools/ │ └── test_advanced_facet_tools.py └── integration/ └── test_advanced_facet_workflow.py ``` ## Phase 1: Design ### Tool Contracts ```python @mcp.tool async def add_classification_facet( spec_id: str, location: str, classification_value: str, ctx: Context, classification_system: str = None, cardinality: str = "required" ) -> dict: """ Add classification facet. Args: classification_value: Classification code or URI classification_system: Optional system name or URI Contract: - MUST create ids.Classification object - MUST support both simple codes and URIs """ @mcp.tool async def add_material_facet( spec_id: str, location: str, material_value: str, ctx: Context, cardinality: str = "required" ) -> dict: """ Add material facet. Args: material_value: Material name or URI Contract: - MUST create ids.Material object - MUST support material URIs (e.g., from bSDD) """ @mcp.tool async def add_partof_facet( spec_id: str, location: str, relation: str, parent_entity: str, ctx: Context, parent_predefined_type: str = None, cardinality: str = "required" ) -> dict: """ Add partOf facet for spatial relationships. Args: relation: IFC relationship type (e.g., "IFCRELCONTAINEDINSPATIALSTRUCTURE") parent_entity: Parent entity name parent_predefined_type: Optional parent type Contract: - MUST create ids.Entity for parent - MUST create ids.PartOf with entity reference - MUST support common relations """ ``` ## Phase 2: Test-Driven Implementation ### Classification Facet Tests ```python @pytest.mark.asyncio async def test_add_classification_facet(): """Test adding classification with system.""" mcp = create_test_server() async with Client(mcp) as client: await setup_test_spec(client) await client.call_tool("add_classification_facet", { "spec_id": "S1", "location": "requirements", "classification_value": "EF_25_10_25", "classification_system": "Uniclass 2015", "cardinality": "required" }) # Validate with IfcTester session_data = _session_storage.get(client.session_id) classif = session_data.ids_obj.specifications[0].requirements[0] assert isinstance(classif, ids.Classification) assert classif.value == "EF_25_10_25" assert classif.system == "Uniclass 2015" ``` ### Material Facet Tests ```python @pytest.mark.asyncio async def test_add_material_facet(): """Test adding material facet.""" mcp = create_test_server() async with Client(mcp) as client: await setup_test_spec(client) await client.call_tool("add_material_facet", { "spec_id": "S1", "location": "requirements", "material_value": "Concrete", "cardinality": "required" }) # Validate session_data = _session_storage.get(client.session_id) material = session_data.ids_obj.specifications[0].requirements[0] assert isinstance(material, ids.Material) assert material.value == "Concrete" ``` ### PartOf Facet Tests ```python @pytest.mark.asyncio async def test_add_partof_facet(): """Test adding partOf facet for spatial containment.""" mcp = create_test_server() async with Client(mcp) as client: await setup_test_spec(client) await client.call_tool("add_partof_facet", { "spec_id": "S1", "location": "requirements", "relation": "IFCRELCONTAINEDINSPATIALSTRUCTURE", "parent_entity": "IFCSPACE", "cardinality": "required" }) # Validate session_data = _session_storage.get(client.session_id) partof = session_data.ids_obj.specifications[0].requirements[0] assert isinstance(partof, ids.PartOf) assert partof.relation == "IFCRELCONTAINEDINSPATIALSTRUCTURE" assert partof.entity.name == "IFCSPACE" ``` ## Success Metrics - ✅ All three advanced facets implemented - ✅ PartOf correctly creates nested entity - ✅ Test coverage ≥ 95% ## Next Steps After Phase 006: 1. Proceed to **007-restrictions** - Implement value restrictions (enumeration, pattern, bounds)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vinnividivicci/ifc-ids-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server