# πŸ”Œ Graph Pipeline Phase 5: MCP μ„œλ²„ 톡합 및 μ‹œμŠ€ν…œ μ•„ν‚€ν…μ²˜ (MCP Integration) 이 λ¬Έμ„œλŠ” μ•žμ„œ μ„€κ³„ν•œ 1~4λ‹¨κ³„μ˜ Graph Pipeline을 ν˜„μž¬ ν”„λ‘œμ νŠΈμ˜ **Unified MCP Server (`mcp-server/server.py`)**에 ν†΅ν•©ν•˜λŠ” λ°©μ•ˆκ³Ό μ΅œμ’… ν”„λ‘œκ·Έλž¨ ꡬ쑰λ₯Ό λ‹€λ£Ήλ‹ˆλ‹€. 이λ₯Ό 톡해 C# 메인 μ„œλ²„μ™€ LLM, 그리고 도면 뢄석 엔진이 ν•˜λ‚˜μ˜ μƒνƒœκ³„μ—μ„œ 유기적으둜 λ™μž‘ν•˜κ²Œ ν•©λ‹ˆλ‹€. --- ## πŸ—οΈ 1. 톡합 μ•„ν‚€ν…μ²˜ 섀계 ### 1.1 전체 데이터 흐름 (End-to-End Flow) `Frontend (UI)` $\rightarrow$ `C# Server (API)` $\rightarrow$ `MCP Server (Python)` $\rightarrow$ `Graph Pipeline Engine` $\rightarrow$ `Experion DB/OPC UA` 1. **μš”μ²­:** μ‚¬μš©μžκ°€ UIμ—μ„œ "P-101 νŽŒν”„μ˜ 영ν–₯도 뢄석" μš”μ²­. 2. **쀑계:** C# μ„œλ²„κ°€ `McpClient`λ₯Ό 톡해 MCP μ„œλ²„μ˜ `analyze_pid_impact` 툴 호좜. 3. **뢄석:** MCP μ„œλ²„λŠ” λ‚΄λΆ€μ μœΌλ‘œ `NetworkX` κ·Έλž˜ν”„λ₯Ό λ‘œλ“œν•˜μ—¬ ν•˜λ₯˜ λ…Έλ“œλ₯Ό 계산. 4. **응닡:** 뢄석 κ²°κ³Ό(λ…Έλ“œ 리슀트)λ₯Ό JSON으둜 λ°˜ν™˜ $\rightarrow$ C# μ„œλ²„ $\rightarrow$ UI ν•˜μ΄λΌμ΄νŠΈ. ### 1.2 MCP μ„œλ²„ λ‚΄ μ—­ν•  λΆ„λ‹΄ ν˜„μž¬ `server.py`λŠ” RAG, NL2SQL, λ‹¨μˆœ νƒœκ·Έ μΆ”μΆœ κΈ°λŠ₯을 κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€. 여기에 **Graph Pipeline μ „μš© 도ꡬ μ„ΈνŠΈ**λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€. | κΈ°μ‘΄ κΈ°λŠ₯ | 좔가될 Graph Pipeline κΈ°λŠ₯ | μ—­ν•  | |---|---|---| | `parse_pid_dxf` | `build_pid_graph` | DXF $\rightarrow$ κΈ°ν•˜ μΆ”μΆœ $\rightarrow$ μœ„μƒ κ·Έλž˜ν”„ 생성 및 μ €μž₯ | | `match_pid_tags` | `resolve_graph_tags` | κ·Έλž˜ν”„ λ§₯락을 λ°˜μ˜ν•œ μ§€λŠ₯ν˜• νƒœκ·Έ λ§€ν•‘ | | (μ‹ κ·œ) | `analyze_pid_impact` | νŠΉμ • λ…Έλ“œ κΈ°μ€€ 영ν–₯도 뢄석 (Downstream 탐색) | | (μ‹ κ·œ) | `get_graph_topology` | μ‹œκ°ν™”λ₯Ό μœ„ν•œ λ…Έλ“œ-μ—£μ§€ 리슀트 λ°˜ν™˜ | --- ## πŸ’» 2. MCP μ„œλ²„ 톡합 κ΅¬ν˜„ κ°€μ΄λ“œ ### 2.1 MCP Tool μΊ‘μŠν™” 섀계 `mcp-server/server.py`에 λ‹€μŒκ³Ό 같은 ν˜•νƒœλ‘œ νˆ΄μ„ μΆ”κ°€ν•©λ‹ˆλ‹€. ```python # mcp-server/server.py 에 좔가될 λ‚΄μš© (κ°œλ… μ½”λ“œ) @mcp.tool() def build_pid_graph(filepath: str) -> str: """ P&ID 도면을 λΆ„μ„ν•˜μ—¬ μœ„μƒ κ·Έλž˜ν”„λ₯Ό μƒμ„±ν•˜κ³  μ €μž₯ν•©λ‹ˆλ‹€. Phase 1(κΈ°ν•˜ μΆ”μΆœ) + Phase 2(μœ„μƒ λͺ¨λΈλ§) 톡합 μ‹€ν–‰. """ # 1. Phase 1: Geometric Extraction extractor = PidGeometricExtractor(filepath) geo_data = extractor.extract_all() # 2. Phase 2: Topology Modeling builder = PidTopologyBuilder(geo_data) builder.build_graph() # 3. κ·Έλž˜ν”„ μ €μž₯ (GraphML λ˜λŠ” JSON) graph_id = os.path.basename(filepath).replace(".dxf", "_graph.json") nx.write_graphml(builder.G, f"storage/{graph_id}") return json.dumps({"success": True, "graph_id": graph_id, "nodes": builder.G.number_of_nodes()}) @mcp.tool() def analyze_pid_impact(graph_id: str, start_node_id: str) -> str: """ νŠΉμ • μ„€λΉ„μ˜ μž₯μ•  μ‹œ 영ν–₯을 λ°›λŠ” ν•˜λ₯˜ μ„€λΉ„ 리슀트λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. """ # κ·Έλž˜ν”„ λ‘œλ“œ G = nx.read_graphml(f"storage/{graph_id}") # 영ν–₯도 뢄석 (Phase 4 둜직) impacted = nx.descendants(G, start_node_id) return json.dumps({ "success": True, "start_node": start_node_id, "impacted_nodes": list(impacted) }) ``` ### 2.2 C# μ„œλ²„μ™€μ˜ μΈν„°νŽ˜μ΄μŠ€ (`McpClient` ν™œμš©) C# μ„œλ²„λŠ” `src/Infrastructure/Mcp/McpClient.cs`λ₯Ό 톡해 μœ„ νˆ΄λ“€μ„ ν˜ΈμΆœν•©λ‹ˆλ‹€. ```csharp // src/Core/Application/Services/PidGraphService.cs (μ‹ κ·œ μ„œλΉ„μŠ€) public async Task GetImpactAnalysisAsync(string graphId, string nodeId) { var request = new McpToolRequest { ToolName = "analyze_pid_impact", Arguments = new { graph_id = graphId, start_node_id = nodeId } }; var jsonResponse = await _mcpClient.CallToolAsync(request); return JsonSerializer.Deserialize(jsonResponse); } ``` --- ## πŸ› οΈ 3. ν”„λ‘œκ·Έλž¨ ꡬ성 및 배포 μ „λž΅ ### 3.1 디렉토리 ꡬ쑰 ν™•μž₯ ```text mcp-server/ β”œβ”€β”€ server.py # MCP 메인 μ„œλ²„ (툴 μ •μ˜) β”œβ”€β”€ pipeline/ # Graph Pipeline 핡심 둜직 (Phase 1~4) β”‚ β”œβ”€β”€ __init__.py β”‚ β”œβ”€β”€ extractor.py # Phase 1: Geometric Extraction β”‚ β”œβ”€β”€ topology.py # Phase 2: Topology Modeling β”‚ β”œβ”€β”€ mapper.py # Phase 3: Intelligent Mapping β”‚ └── analyzer.py # Phase 4: Impact Analysis └── storage/ # μƒμ„±λœ κ·Έλž˜ν”„ 파일 (.graphml) μ €μž₯μ†Œ ``` ### 3.2 μ‹€ν–‰ ν”„λ‘œμ„ΈμŠ€ 1. **MCP μ„œλ²„ 기동:** `python mcp-server/server.py --http` (포트 5001) 2. **C# μ„œλ²„ 기동:** `dotnet run` (포트 5000) 3. **톡신:** C# μ„œλ²„ $\xrightarrow{HTTP/JSON}$ MCP μ„œλ²„ $\xrightarrow{Python\ Libs}$ κ²°κ³Ό λ°˜ν™˜. --- ## πŸš€ 4. μ΅œμ’… μ™„λ£Œ κΈ°μ€€ (Definition of Done) - [ ] `mcp-server/server.py`에 `build_pid_graph`, `analyze_pid_impact` λ“± 핡심 툴이 μ •μ˜λ˜μ—ˆλŠ”κ°€? - [ ] Phase 1~4의 Python 둜직이 `mcp-server/pipeline/` λͺ¨λ“ˆλ‘œ κ΅¬μ‘°ν™”λ˜μ–΄ ν†΅ν•©λ˜μ—ˆλŠ”κ°€? - [ ] C# `McpClient`λ₯Ό 톡해 MCP μ„œλ²„μ˜ κ·Έλž˜ν”„ 뢄석 νˆ΄μ„ ν˜ΈμΆœν•˜κ³  κ²°κ³Όλ₯Ό μˆ˜μ‹ ν•  수 μžˆλŠ”κ°€? - [ ] 도면 μ—…λ‘œλ“œ $\rightarrow$ κ·Έλž˜ν”„ 생성 $\rightarrow$ νƒœκ·Έ λ§€ν•‘ $\rightarrow$ 영ν–₯도 λΆ„μ„μœΌλ‘œ μ΄μ–΄μ§€λŠ” **End-to-End νŒŒμ΄ν”„λΌμΈ**이 μ™„μ„±λ˜μ—ˆλŠ”κ°€? - [ ] λͺ¨λ“  과정이 `json_response=True` 및 `stateless_http=True` μ„€μ • ν•˜μ— μ•ˆμ •μ μœΌλ‘œ λ™μž‘ν•˜λŠ”κ°€?