Add MCP Server and Proxy for CtrEditor with LLM Integration

- Implemented MCPServer class for TCP communication, allowing remote control of CtrEditor simulations.
- Added JSON-RPC methods for object management, simulation control, and screenshot functionality.
- Created a comprehensive LLM usage guide in MCP_LLM_Guide.md for interacting with the MCP server.
- Developed start_mcp_proxy.bat and start_mcp_proxy.py scripts to facilitate connection between GitHub Copilot and the MCP server.
- Enhanced error handling and logging throughout the MCP server and proxy scripts.
This commit is contained in:
Miguel 2025-09-06 17:05:59 +02:00
parent af839f4201
commit f07e7895f6
10 changed files with 1750 additions and 1 deletions

14
.vscode/mcp_config.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
"mcpServers": {
"ctreditor": {
"command": "C:/Users/migue/miniconda3/envs/mcp_proxy/python.exe",
"args": [
"d:/Proyectos/Scripts/MCP_Proxy/mcp_proxy.py",
"--host", "localhost",
"--port", "5006",
"--name", "CtrEditor",
"--description", "CtrEditor WPF Application MCP Server for debugging and testing"
]
}
}
}

24
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,24 @@
{
"github.copilot.chat.experimental.models": {
"gpt-4": {
"vendor": "Copilot",
"family": "gpt-4",
"version": "gpt-4",
"maxRequestLength": 8192,
"id": "gpt-4"
}
},
"github.copilot.advanced": {
"debug.overrideProxyUrl": "http://localhost:8080",
"debug.overrideProxyAuthorization": ""
},
"github.copilot.chat.experimental.mcpServers": {
"ctreditor": {
"command": "C:/Users/migue/miniconda3/envs/mcp_proxy/python.exe",
"args": [
"d:/Proyectos/Scripts/MCP_Proxy/mcp_proxy.py",
"5006"
]
}
}
}

View File

@ -8,7 +8,26 @@
},
{
"path": "../Librerias/bepuphysics2-master"
},
{
"path": "../../Scripts/MCP_Proxy"
}
],
"settings": {}
"settings": {
"mcp": {
"servers": {
"ctreditor": {
"command": "C:/Users/migue/miniconda3/envs/mcp_proxy/python.exe",
"args": [
"d:/Proyectos/Scripts/MCP_Proxy/mcp_proxy.py",
"--host", "localhost",
"--port", "5006",
"--name", "CtrEditor",
"--description", "CtrEditor WPF Application MCP Server for debugging and testing"
]
}
},
"inputs": []
}
}
}

170
Documentation/MCP.md Normal file
View File

@ -0,0 +1,170 @@
# CtrEditor MCP Server Documentation
## 🎯 Overview
The CtrEditor MCP (Model Context Protocol) Server transforms the CtrEditor WPF application into a programmable automation platform for debugging, testing, and simulation control. This server enables remote control of all major application features through JSON-RPC style communication.
## 🚀 Architecture
### Communication Flow
```
LLM/Client ↔ MCP Proxy (Python) ↔ CtrEditor MCP Server (C#) ↔ WPF Application
```
### Connection Setup
- **Protocol**: TCP Socket on port 5006
- **Format**: JSON-RPC style messages
- **Proxy**: Python proxy for VS Code Copilot integration
### VS Code Configuration
```json
"ctreditor": {
"command": "C:/Users/migue/miniconda3/envs/mcp_proxy/python.exe",
"args": [
"d:/Proyectos/Scripts/MCP_Proxy/mcp_proxy.py",
"--host", "localhost",
"--port", "5006",
"--name", "CtrEditor",
"--description", "CtrEditor WPF Application MCP Server for debugging and testing"
]
}
```
## 📋 Available Tools
### 🔧 Object Management
#### `list_objects`
**Description**: Get complete list of all simulation objects
**Parameters**: None
**Returns**: Array of objects with full metadata (ID, name, type, position, properties)
#### `create_object`
**Description**: Create a new simulation object
**Parameters**:
- `type` (string): Object type (e.g., "osHydTank", "osHydPump")
- `x` (number): X position in meters
- `y` (number): Y position in meters
#### `update_object`
**Description**: Modify properties of existing object
**Parameters**:
- `id` (string): Object ID
- `properties` (object): JSON object with properties to update
#### `delete_objects`
**Description**: Remove objects from simulation
**Parameters**:
- `ids` (array): Array of object IDs to delete
#### `list_object_types`
**Description**: Get list of all creatable object types
**Parameters**: None
### ⚙️ Simulation Control
#### `start_simulation`
**Description**: Start the physics simulation
**Parameters**: None
#### `stop_simulation`
**Description**: Stop the physics simulation
**Parameters**: None
#### `get_simulation_status`
**Description**: Get current simulation state
**Parameters**: None
**Returns**: Status info (running, object count, etc.)
### 🔌 PLC Integration
#### `get_plc_status`
**Description**: Get PLC connection status
**Parameters**: None
**Returns**: Connection state and status information
### 📸 Visual Documentation
#### `take_screenshot`
**Description**: Capture canvas screenshot with high resolution
**Parameters** (all optional):
- `x` (number): X position in meters for partial capture
- `y` (number): Y position in meters for partial capture
- `width` (number): Width in meters for partial capture
- `height` (number): Height in meters for partial capture
- `include_background` (boolean): Include canvas background (default: false)
**Features**:
- **High Resolution**: 2x scale for full canvas, 3x for partial captures
- **Auto-Directory**: Saves to `/screenshots/` subdirectory
- **Detailed Response**: File size, dimensions, timestamps, paths
### 💾 Project Management
#### `save_project`
**Description**: Save current project state
**Parameters**: None
## 🎨 Key Features
### 📊 Rich Object Information
- **Complete Properties**: All object properties in JSON format
- **Simulation Data**: Real-time physics and hydraulic states
- **Coordinate System**: All positions in engineering meters
- **Type Safety**: Full .NET type information preserved
### 🖼️ Advanced Screenshots
- **Meter-Based Coordinates**: Natural engineering units
- **High Resolution**: Anti-aliased, print-quality images
- **Flexible Areas**: Full canvas or custom rectangular regions
- **Background Control**: With/without canvas background
### 🔄 Real-Time Monitoring
- **Live Updates**: Monitor simulation state changes
- **Property Tracking**: Observe dynamic property changes during simulation
- **Performance Data**: Track flow rates, pressures, speeds, etc.
### 🛡️ Error Handling
- **Detailed Errors**: Comprehensive error messages with context
- **Safe Operations**: Thread-safe UI operations via Dispatcher
- **Graceful Degradation**: Handles connection issues and timeouts
## 🎯 Use Cases
### 🔬 Simulation Debugging
1. **Pre-Simulation**: Inspect object configurations and positions
2. **Runtime Monitoring**: Track dynamic properties during simulation
3. **Post-Analysis**: Compare before/after states
4. **Visual Verification**: Screenshot specific areas for documentation
### 🤖 Automated Testing
- **Regression Testing**: Verify simulation behavior consistency
- **Performance Benchmarking**: Monitor simulation performance metrics
- **Configuration Validation**: Ensure proper object setup
- **Visual Regression**: Compare screenshots across versions
### 📚 Documentation Generation
- **Auto-Documentation**: Extract object configurations automatically
- **Visual Documentation**: Generate annotated screenshots
- **State Reports**: Create detailed simulation state reports
- **Training Materials**: Generate step-by-step simulation guides
## 🔧 Technical Implementation
### Core Components
- **MCPServer.cs**: Main TCP server with JSON-RPC handling
- **Tool Handlers**: Specialized handlers for each operation type
- **Thread Safety**: UI operations via WPF Dispatcher
- **Error Management**: Comprehensive exception handling
### Performance Optimizations
- **Lazy Connection**: Connect only when needed
- **Efficient Serialization**: Optimized JSON generation
- **Memory Management**: Proper resource cleanup
- **High-Resolution Rendering**: Optimized screenshot generation
### Security Considerations
- **Local-Only**: Bound to localhost for security
- **No File System Access**: Limited to application operations
- **Controlled Operations**: No dangerous system operations
- **Sandboxed**: Isolated from system configuration

View File

@ -0,0 +1,214 @@
# CtrEditor MCP Server - LLM Usage Guide
## 🤖 Quick Start for Language Models
This guide provides step-by-step instructions for LLMs to interact with CtrEditor simulations programmatically. The MCP server allows complete control over simulation objects, execution, and monitoring.
## 🚀 Basic Workflow
### 1. Initial Assessment
Start by getting the current state of the simulation:
```
🔍 list_objects - See what's currently in the simulation
🎮 get_simulation_status - Check if simulation is running
🔌 get_plc_status - Check PLC connection state
```
### 2. Object Analysis
For each object found, examine its properties to understand:
- **Position**: `Left`, `Top` coordinates in meters
- **Dimensions**: `Ancho` (width), `Alto` (height) in meters
- **Type-Specific Properties**: Flow rates, pressures, speeds, etc.
- **Connection States**: Which components are connected
- **Simulation Parameters**: Physics and hydraulic settings
### 3. Simulation Control
Control the simulation lifecycle:
- `start_simulation` - Begin physics calculations
- `stop_simulation` - Halt simulation
- Monitor changes with repeated `list_objects` calls
## 📊 Object Property Deep Dive
### Hydraulic Components
#### **osHydTank** (Hydraulic Tank)
Key Properties to Monitor:
- `TankType`: Type of tank (1=standard)
- `CrossSectionalArea`: Tank cross-section in m²
- `MaxLevel`, `MinLevel`: Level limits in meters
- `TankPressure`: Pressure in Pascal
- `IsFixedPressure`: Whether pressure is constant
#### **osHydPump** (Hydraulic Pump)
Key Properties to Monitor:
- `PumpHead`: Pump head in meters
- `MaxFlow`: Maximum flow rate in m³/s
- `SpeedRatio`: Speed ratio (0.0-1.0)
- `IsRunning`: Pump operational state
- `PumpDirection`: Flow direction (1=forward, -1=reverse)
#### **osHydPipe** (Hydraulic Pipe)
Key Properties to Monitor:
- `Length`: Pipe length in meters
- `Diameter`: Internal diameter in meters
- `Roughness`: Surface roughness
- `CurrentFlow`: Current flow rate in m³/s
- `PressureDrop`: Pressure loss across pipe
- `Id_ComponenteA`, `Id_ComponenteB`: Connected components
### Dynamic Properties
During simulation, monitor these changing values:
- Flow rates in pipes (`CurrentFlow`)
- Pressure drops (`PressureDrop`)
- Tank levels (if applicable)
- Pump performance metrics
## 🖼️ Visual Documentation
### Full Canvas Screenshots
```json
take_screenshot()
```
- Captures entire simulation at 2x resolution
- Saves to `/screenshots/` subdirectory
- Returns detailed file information
### Targeted Screenshots
```json
take_screenshot({
"x": 39.0, // Start X in meters
"y": 19.0, // Start Y in meters
"width": 7.0, // Width in meters
"height": 3.0 // Height in meters
})
```
- Captures specific region at 3x resolution (high detail)
- Perfect for component close-ups
- Use object positions to determine coordinates
### Screenshot Use Cases
1. **Component Documentation**: Capture individual components
2. **System Overview**: Full canvas for complete system view
3. **Before/After Comparison**: Screenshots before and after simulation
4. **Issue Investigation**: High-resolution captures of problem areas
## 🔧 Property Modification
### Updating Object Properties
```json
update_object({
"id": "307211",
"properties": {
"PumpHead": 75.0,
"MaxFlow": 0.015,
"IsRunning": true
}
})
```
### Safe Property Modification
- Always check current properties first with `list_objects`
- Modify only relevant properties for the object type
- Use appropriate units (meters, Pascal, m³/s, etc.)
- Verify changes by calling `list_objects` again
## 🎯 Common Debugging Workflows
### 1. Pre-Simulation Analysis
```
1. list_objects - Document initial state
2. take_screenshot() - Visual documentation
3. Analyze object configurations and connections
4. Verify proper component setup
```
### 2. Simulation Monitoring
```
1. start_simulation - Begin simulation
2. get_simulation_status - Confirm running
3. list_objects - Monitor dynamic properties
4. take_screenshot(area) - Capture specific components
5. stop_simulation - End when needed
```
### 3. Performance Investigation
```
1. list_objects - Get baseline measurements
2. start_simulation - Run simulation
3. Wait 5-10 seconds for stabilization
4. list_objects - Compare with baseline
5. take_screenshot() - Document final state
```
### 4. Component Analysis
```
1. take_screenshot(component_area) - High-res component view
2. list_objects - Get detailed properties
3. update_object - Modify parameters if needed
4. start_simulation - Test changes
5. take_screenshot(component_area) - Compare results
```
## 📈 Simulation Data Interpretation
### Flow Analysis
- **Positive Flow**: Normal direction flow
- **Negative Flow**: Reverse flow direction
- **Zero Flow**: No flow (blockage or equilibrium)
### Pressure Analysis
- **High Pressure Drop**: Potential flow restriction
- **Low Pressure Drop**: Free-flowing condition
- **Pressure Patterns**: Indicate system behavior
### Pump Performance
- **SpeedRatio**: Pump operation intensity
- **IsRunning**: Operational state
- **PumpDirection**: Flow direction control
## 🚨 Troubleshooting Guide
### Connection Issues
If MCP commands fail:
1. Check CtrEditor is running
2. Verify MCP server is active on port 5006
3. Use `get_simulation_status` to test connectivity
### Simulation Issues
If simulation behaves unexpectedly:
1. Stop simulation with `stop_simulation`
2. Check object properties with `list_objects`
3. Verify component connections
4. Take screenshots for visual verification
5. Restart simulation with `start_simulation`
### Data Inconsistencies
If properties seem wrong:
1. Get fresh data with `list_objects`
2. Compare with visual evidence via `take_screenshot`
3. Check if simulation is running vs stopped
4. Verify meter-based coordinates
## 💡 Best Practices
### Efficient Monitoring
- Use `get_simulation_status` for quick status checks
- Call `list_objects` only when detailed data is needed
- Take targeted screenshots instead of full canvas when possible
### Data Analysis
- Always compare before/after simulation states
- Monitor key performance indicators for each component type
- Use screenshots to validate data interpretations
### Documentation
- Screenshot key configurations and results
- Document property changes with timestamps
- Maintain clear before/after comparisons
### Safety
- Always stop simulation before making major changes
- Verify property updates with `list_objects`
- Use appropriate units for all parameters

View File

@ -29,6 +29,7 @@ using CtrEditor.Serialization; // Add this line
using CtrEditor.Controls; // Add this using directive
using System.Linq;
using System.Windows.Media;
using CtrEditor.Services; // Add this for MCP Server
namespace CtrEditor
@ -71,6 +72,12 @@ namespace CtrEditor
// Manager para la visualización 3D
public BEPUVisualization3DManager Visualization3DManager { get; set; }
// Servidor MCP para control remoto
private MCPServer _mcpServer;
[ObservableProperty]
private int mcpServerPort = 5006;
[ObservableProperty]
private bool isConnected;
@ -470,6 +477,9 @@ namespace CtrEditor
// Inicializar configuración del workspace
WorkspaceConfig = new Models.WorkspaceConfiguration();
// Iniciar servidor MCP automáticamente
StartMcpServer();
}
#region Workspace Configuration Management
@ -1243,6 +1253,9 @@ namespace CtrEditor
{
PLCViewModel.Disconnect();
}
// Limpiar servidor MCP
CleanupMcpServer();
}
private List<osBase> objetosSimulablesLlamados = new List<osBase>();
@ -1756,6 +1769,67 @@ namespace CtrEditor
#endregion
#region MCP Server Management
/// <summary>
/// Inicia el servidor MCP
/// </summary>
private async void StartMcpServer()
{
try
{
if (_mcpServer != null)
{
_mcpServer.Dispose();
}
_mcpServer = new MCPServer(this, McpServerPort);
await _mcpServer.StartAsync();
Debug.WriteLine($"[MCP] Servidor MCP iniciado en puerto {McpServerPort}");
}
catch (Exception ex)
{
Debug.WriteLine($"[MCP] Error iniciando servidor MCP: {ex.Message}");
MessageBox.Show($"Error iniciando servidor MCP: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
/// <summary>
/// Detiene el servidor MCP
/// </summary>
private void StopMcpServer()
{
try
{
_mcpServer?.Stop();
Debug.WriteLine("[MCP] Servidor MCP detenido");
}
catch (Exception ex)
{
Debug.WriteLine($"[MCP] Error deteniendo servidor MCP: {ex.Message}");
}
}
/// <summary>
/// Limpia el servidor MCP al cerrar la aplicación
/// </summary>
private void CleanupMcpServer()
{
try
{
_mcpServer?.Dispose();
_mcpServer = null;
}
catch (Exception ex)
{
Debug.WriteLine($"[MCP] Error limpiando servidor MCP: {ex.Message}");
}
}
#endregion
}
public class SimulationData

View File

@ -211,6 +211,9 @@
</StackPanel>
</Button>
<!-- Separador -->
<Separator />
<Button Command="{Binding TBToggle3DUpdateCommand}" ToolTip="Activar/Desactivar actualización Debug 3D para mejorar rendimiento">
<StackPanel>
<Image Source="Icons/app.png" Width="24" Height="24" />

1116
Services/MCPServer.cs Normal file

File diff suppressed because it is too large Load Diff

34
start_mcp_proxy.bat Normal file
View File

@ -0,0 +1,34 @@
@echo off
REM Script para iniciar el proxy MCP para CtrEditor
echo ================================================
echo Proxy MCP para CtrEditor
echo ================================================
echo.
echo Este script inicia el proxy que conecta
echo GitHub Copilot con el servidor MCP de CtrEditor
echo.
echo Asegurate de que:
echo 1. CtrEditor este ejecutandose
echo 2. El servidor MCP este iniciado (puerto 5006)
echo 3. Python este instalado
echo.
echo Presiona Ctrl+C para detener el proxy
echo ================================================
echo.
REM Verificar si Python está disponible
python --version >nul 2>&1
if errorlevel 1 (
echo ERROR: Python no esta instalado o no esta en el PATH
pause
exit /b 1
)
REM Ejecutar el proxy
echo Iniciando proxy MCP...
python "%~dp0start_mcp_proxy.py" --verbose
echo.
echo Proxy detenido.
pause

81
start_mcp_proxy.py Normal file
View File

@ -0,0 +1,81 @@
#!/usr/bin/env python3
"""
Proxy MCP específico para el proyecto CtrEditor
Este script inicia un proxy que conecta GitHub Copilot con el servidor MCP de CtrEditor
"""
import sys
import os
import subprocess
import argparse
import logging
from pathlib import Path
# Configuración de logging
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
def main():
parser = argparse.ArgumentParser(description="Proxy MCP para CtrEditor")
parser.add_argument(
"--ctreditor-host",
default="localhost",
help="Host del servidor MCP de CtrEditor",
)
parser.add_argument(
"--ctreditor-port", default="5006", help="Puerto del servidor MCP de CtrEditor"
)
parser.add_argument(
"--proxy-port", default="8080", help="Puerto del proxy para Copilot"
)
parser.add_argument("--verbose", "-v", action="store_true", help="Modo verbose")
args = parser.parse_args()
if args.verbose:
logging.getLogger().setLevel(logging.DEBUG)
# Ruta al proxy principal
script_dir = Path(__file__).parent
main_proxy_path = script_dir.parent / "Scripts" / "MCP_Proxy" / "mcp_proxy.py"
if not main_proxy_path.exists():
logger.error(f"No se encontró el proxy principal en: {main_proxy_path}")
sys.exit(1)
# Comando para ejecutar el proxy
cmd = [
sys.executable,
str(main_proxy_path),
"--host",
args.ctreditor_host,
"--port",
args.ctreditor_port,
"--proxy-port",
args.proxy_port,
]
if args.verbose:
cmd.append("--verbose")
logger.info(f"Iniciando proxy MCP para CtrEditor...")
logger.info(f"Servidor CtrEditor: {args.ctreditor_host}:{args.ctreditor_port}")
logger.info(f"Proxy para Copilot: localhost:{args.proxy_port}")
logger.info(f"Comando: {' '.join(cmd)}")
try:
# Ejecutar el proxy
subprocess.run(cmd, check=True)
except subprocess.CalledProcessError as e:
logger.error(f"Error al ejecutar el proxy: {e}")
sys.exit(1)
except KeyboardInterrupt:
logger.info("Proxy detenido por el usuario")
sys.exit(0)
if __name__ == "__main__":
main()