Skip to main content
Glama

Visum Thinker MCP Server

MIT License
enhanced-visum-mcp.mjs26.3 kB
#!/usr/bin/env node // Enhanced Working MCP Server for Claude's Visum Access with Network Analysis import { createInterface } from 'readline'; import { spawn } from 'child_process'; console.error("Enhanced Visum MCP Server for Claude - starting..."); const rl = createInterface({ input: process.stdin, output: process.stdout, terminal: false }); // Launch Visum if not running async function launchVisum() { return new Promise((resolve) => { const script = ` try { # Check if Visum is already running $visumProcess = Get-Process -Name "Visum250" -ErrorAction SilentlyContinue if ($visumProcess) { @{ success = $true message = "Visum already running" processId = $visumProcess.Id alreadyRunning = $true } | ConvertTo-Json } else { # Start Visum visibly Write-Host "Starting Visum visibly..." $visumPath = "H:\\Program Files\\PTV Vision\\PTV Visum 2025\\Exe\\Visum250.exe" if (Test-Path $visumPath) { # Force Visum to start visibly with WindowStyle Normal $process = Start-Process -FilePath $visumPath -WindowStyle Normal -PassThru Start-Sleep -Seconds 8 # Wait longer for Visum to fully load @{ success = $true message = "Visum started successfully" processId = $process.Id alreadyRunning = $false } | ConvertTo-Json } else { @{ success = $false error = "Visum executable not found at expected path" } | ConvertTo-Json } } } catch { @{ success = $false error = $_.Exception.Message } | ConvertTo-Json } `; const powershell = spawn('powershell', ['-ExecutionPolicy', 'Bypass', '-Command', script]); let output = ''; powershell.stdout.on('data', (data) => { output += data.toString(); }); powershell.on('close', () => { try { const result = JSON.parse(output.trim()); resolve(result); } catch { resolve({ success: false, error: 'Failed to parse PowerShell output' }); } }); }); } // Enhanced Visum COM test function async function testVisum() { return new Promise((resolve) => { const script = ` try { $visum = New-Object -ComObject "Visum.Visum" $version = $visum.VersionNumber $net = $visum.Net $netAvailable = ($net -ne $null) @{ success = $true version = $version netAvailable = $netAvailable path = "H:\\Program Files\\PTV Vision\\PTV Visum 2025\\Exe\\Visum250.exe" } | ConvertTo-Json [System.Runtime.InteropServices.Marshal]::ReleaseComObject($visum) | Out-Null } catch { @{ success = $false error = $_.Exception.Message } | ConvertTo-Json } `; const powershell = spawn('powershell', ['-ExecutionPolicy', 'Bypass', '-Command', script]); let output = ''; powershell.stdout.on('data', (data) => { output += data.toString(); }); powershell.on('close', () => { try { const result = JSON.parse(output.trim()); resolve(result); } catch { resolve({ success: false, error: 'Failed to parse PowerShell output' }); } }); }); } // Initialize Visum with stability async function initializeVisum() { return new Promise((resolve) => { const script = ` try { Write-Host "Initializing Visum COM with enhanced stability..." # Create Visum object $visum = New-Object -ComObject "Visum.Visum" # Test basic functionality $version = $visum.VersionNumber $net = $visum.Net if ($version -and ($net -ne $null)) { @{ success = $true message = "Visum initialized successfully" version = $version ready = $true } | ConvertTo-Json } else { @{ success = $false error = "Visum object created but not fully functional" } | ConvertTo-Json } } catch { @{ success = $false error = $_.Exception.Message } | ConvertTo-Json } `; const powershell = spawn('powershell', ['-ExecutionPolicy', 'Bypass', '-Command', script]); let output = ''; powershell.stdout.on('data', (data) => { output += data.toString(); }); powershell.on('close', () => { try { const result = JSON.parse(output.trim()); resolve(result); } catch { resolve({ success: false, error: 'Failed to initialize Visum' }); } }); }); } // Analyze network function async function analyzeNetwork() { return new Promise((resolve) => { const script = ` try { Write-Host "Analyzing Visum network..." # Create Visum object $visum = New-Object -ComObject "Visum.Visum" # Get network statistics $net = $visum.Net if ($net -ne $null) { $nodeCount = 0 $linkCount = 0 $zoneCount = 0 try { $nodeCount = $net.Nodes.Count } catch { $nodeCount = "Unknown" } try { $linkCount = $net.Links.Count } catch { $linkCount = "Unknown" } try { $zoneCount = $net.Zones.Count } catch { $zoneCount = "Unknown" } @{ success = $true analysis = @{ nodes = $nodeCount links = $linkCount zones = $zoneCount networkLoaded = $true analysisDate = (Get-Date).ToString() } } | ConvertTo-Json -Depth 3 } else { @{ success = $false error = "No network loaded in Visum" } | ConvertTo-Json } [System.Runtime.InteropServices.Marshal]::ReleaseComObject($visum) | Out-Null } catch { @{ success = $false error = $_.Exception.Message } | ConvertTo-Json } `; const powershell = spawn('powershell', ['-ExecutionPolicy', 'Bypass', '-Command', script]); let output = ''; powershell.stdout.on('data', (data) => { output += data.toString(); }); powershell.on('close', () => { try { const result = JSON.parse(output.trim()); resolve(result); } catch { resolve({ success: false, error: 'Failed to analyze network' }); } }); }); } // Get network statistics async function getNetworkStats() { return new Promise((resolve) => { const script = ` try { $visum = New-Object -ComObject "Visum.Visum" $net = $visum.Net if ($net -ne $null) { $stats = @{ nodes = try { $net.Nodes.Count } catch { 0 } links = try { $net.Links.Count } catch { 0 } zones = try { $net.Zones.Count } catch { 0 } lines = try { $net.Lines.Count } catch { 0 } stops = try { $net.Stops.Count } catch { 0 } timeProfiles = try { $net.TimeProfiles.Count } catch { 0 } vehicleJourneys = try { $net.VehicleJourneys.Count } catch { 0 } networkFile = try { $visum.GetAttValue("VersionFile") } catch { "Not loaded" } } @{ success = $true stats = $stats } | ConvertTo-Json -Depth 3 } else { @{ success = $false error = "No network available" } | ConvertTo-Json } [System.Runtime.InteropServices.Marshal]::ReleaseComObject($visum) | Out-Null } catch { @{ success = $false error = $_.Exception.Message } | ConvertTo-Json } `; const powershell = spawn('powershell', ['-ExecutionPolicy', 'Bypass', '-Command', script]); let output = ''; powershell.stdout.on('data', (data) => { output += data.toString(); }); powershell.on('close', () => { try { const result = JSON.parse(output.trim()); resolve(result); } catch { resolve({ success: false, error: 'Failed to get network stats' }); } }); }); } // Open Visum project (FIXED VERSION) async function openProject(projectPath) { return new Promise((resolve) => { const script = ` try { Write-Host "Opening Visum project: ${projectPath}" # Check if file exists first if (-not (Test-Path "${projectPath}")) { @{ success = $false error = "Project file not found: ${projectPath}" } | ConvertTo-Json return } # Use New-Object (works better than GetActiveObject for Visum) Write-Host "Creating Visum COM object..." $visum = New-Object -ComObject "Visum.Visum" # Load the project Write-Host "Loading project file..." $visum.LoadVersion("${projectPath}") # Get network statistics Write-Host "Analyzing network..." $net = $visum.Net $nodeCount = try { $net.Nodes.Count } catch { 0 } $linkCount = try { $net.Links.Count } catch { 0 } $zoneCount = try { $net.Zones.Count } catch { 0 } Write-Host "Project loaded successfully! Nodes: $nodeCount" @{ success = $true message = "Project opened successfully via COM" projectPath = "${projectPath}" networkStats = @{ nodes = $nodeCount links = $linkCount zones = $zoneCount } } | ConvertTo-Json -Depth 3 # Clean up COM object [System.Runtime.InteropServices.Marshal]::ReleaseComObject($visum) | Out-Null } catch { @{ success = $false error = $_.Exception.Message } | ConvertTo-Json } `; const powershell = spawn('powershell', ['-ExecutionPolicy', 'Bypass', '-Command', script]); let output = ''; powershell.stdout.on('data', (data) => { output += data.toString(); }); powershell.on('close', () => { try { const result = JSON.parse(output.trim()); resolve(result); } catch { resolve({ success: false, error: 'Failed to parse PowerShell output' }); } }); }); } // Handle MCP requests rl.on('line', async (line) => { try { console.error(`Received request: ${line}`); const request = JSON.parse(line); let response = { jsonrpc: "2.0", id: request.id }; // Handle tools/list if (request.method === 'tools/list') { response.result = { tools: [ { name: "launch_visum", description: "Launch PTV Visum if not already running", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "open_project", description: "Open a Visum project file (.ver)", inputSchema: { type: "object", properties: { projectPath: { type: "string", description: "Full path to the Visum project file (.ver)" } }, required: ["projectPath"] } }, { name: "check_visum", description: "Check if PTV Visum is installed and accessible", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "initialize_visum", description: "Initialize Visum COM connection for automation", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "get_visum_status", description: "Get current Visum status and configuration", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "analyze_network", description: "Analyze the current Visum network and get basic statistics", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "get_network_stats", description: "Get detailed network statistics from Visum", inputSchema: { type: "object", properties: {}, required: [] } } ] }; } // Handle tools/call else if (request.method === 'tools/call') { const toolName = request.params.name; const args = request.params.arguments || {}; if (toolName === 'launch_visum') { const launchResult = await launchVisum(); if (launchResult.success) { response.result = { content: [ { type: "text", text: `✅ **Visum Launch ${launchResult.alreadyRunning ? 'Status' : 'Successful'}**\n\n` + `**Process Details:**\n` + `• **Status:** ${launchResult.message}\n` + `• **Process ID:** ${launchResult.processId}\n` + `• **Already Running:** ${launchResult.alreadyRunning ? 'Yes' : 'No'}\n\n` + `**Next Steps:**\n` + `• Visum is now ready for COM automation\n` + `• You can now use check_visum or analyze_network\n` + `• Load a network model for analysis\n\n` + `*Visum application is active and ready for transportation modeling.*` } ] }; } else { response.result = { content: [ { type: "text", text: `❌ **Visum Launch Failed**\n\n` + `**Error:** ${launchResult.error}\n\n` + `**Troubleshooting:**\n` + `• Verify Visum installation path\n` + `• Check if Visum license is available\n` + `• Run as Administrator if needed\n` + `• Ensure no other Visum instances are stuck\n\n` + `*Could not start Visum application.*` } ] }; } } else if (toolName === 'check_visum') { const visumTest = await testVisum(); if (visumTest.success) { response.result = { content: [ { type: "text", text: `✅ **Visum Available and Working**\n\n` + `**Installation Details:**\n` + `• **Version:** ${visumTest.version}\n` + `• **Path:** ${visumTest.path}\n` + `• **Network Object:** ${visumTest.netAvailable ? 'Available' : 'Not Available'}\n` + `• **COM Interface:** Functional\n\n` + `**Status:** Ready for transportation modeling and analysis\n\n` + `*Visum is properly installed and COM automation is working correctly.*` } ] }; } else { response.result = { content: [ { type: "text", text: `❌ **Visum Not Available**\n\n` + `**Error:** ${visumTest.error}\n\n` + `**Troubleshooting:**\n` + `• Verify Visum is installed\n` + `• Check COM registration\n` + `• Run Visum once as Administrator\n` + `• Ensure license is valid\n\n` + `*Contact system administrator if issues persist.*` } ] }; } } else if (toolName === 'initialize_visum') { const initResult = await initializeVisum(); if (initResult.success) { response.result = { content: [ { type: "text", text: `✅ **Visum Initialized Successfully**\n\n` + `**Connection Details:**\n` + `• **Version:** ${initResult.version}\n` + `• **Status:** ${initResult.message}\n` + `• **COM Object:** Active and responsive\n\n` + `**Ready for Operations:**\n` + `• Load transportation models\n` + `• Execute procedures and analyses\n` + `• Access network data\n\n` + `*Visum automation is now active and ready for use.*` } ] }; } else { response.result = { content: [ { type: "text", text: `❌ **Initialization Failed**\n\n` + `**Error:** ${initResult.error}\n\n` + `**Suggestions:**\n` + `• Restart Visum manually\n` + `• Check for running Visum processes\n` + `• Verify COM permissions\n` + `• Try running as Administrator\n\n` + `*Visum COM automation could not be established.*` } ] }; } } else if (toolName === 'get_visum_status') { const statusTest = await testVisum(); response.result = { content: [ { type: "text", text: `📊 **Current Visum Status**\n\n` + `**Availability:** ${statusTest.success ? '✅ Available' : '❌ Not Available'}\n` + `**COM Interface:** ${statusTest.success ? 'Working' : 'Failed'}\n` + `**Installation Path:** H:\\Program Files\\PTV Vision\\PTV Visum 2025\\Exe\\Visum250.exe\n` + `**Version:** ${statusTest.version || 'Unknown'}\n\n` + `**MCP Server:** ✅ Running and responsive\n` + `**Communication:** ✅ STDIO protocol working\n` + `**Last Check:** ${new Date().toLocaleString()}\n\n` + `*This MCP server is working correctly for Claude integration.*` } ] }; } else if (toolName === 'analyze_network') { const analysisResult = await analyzeNetwork(); if (analysisResult.success) { const analysis = analysisResult.analysis; response.result = { content: [ { type: "text", text: `📊 **Network Analysis Results**\n\n` + `**Network Components:**\n` + `• **Nodes:** ${analysis.nodes}\n` + `• **Links:** ${analysis.links}\n` + `• **Zones:** ${analysis.zones}\n\n` + `**Analysis Status:**\n` + `• **Network Loaded:** ${analysis.networkLoaded ? '✅ Yes' : '❌ No'}\n` + `• **Analysis Date:** ${analysis.analysisDate}\n\n` + `**Network Summary:**\n` + `The current Visum network contains ${analysis.nodes} nodes connected by ${analysis.links} links, ` + `with ${analysis.zones} traffic analysis zones defined.\n\n` + `*Network analysis completed successfully.*` } ] }; } else { response.result = { content: [ { type: "text", text: `❌ **Network Analysis Failed**\n\n` + `**Error:** ${analysisResult.error}\n\n` + `**Possible Causes:**\n` + `• No network model loaded in Visum\n` + `• Visum COM connection lost\n` + `• Insufficient permissions\n\n` + `**Suggestions:**\n` + `• Load a network model in Visum first\n` + `• Check Visum connection status\n` + `• Try reinitializing Visum\n\n` + `*Please ensure a network is loaded before analysis.*` } ] }; } } else if (toolName === 'get_network_stats') { const statsResult = await getNetworkStats(); if (statsResult.success) { const stats = statsResult.stats; response.result = { content: [ { type: "text", text: `📈 **Detailed Network Statistics**\n\n` + `**Basic Network Elements:**\n` + `• **Nodes:** ${stats.nodes}\n` + `• **Links:** ${stats.links}\n` + `• **Zones:** ${stats.zones}\n\n` + `**Public Transport Elements:**\n` + `• **Lines:** ${stats.lines}\n` + `• **Stops:** ${stats.stops}\n` + `• **Time Profiles:** ${stats.timeProfiles}\n` + `• **Vehicle Journeys:** ${stats.vehicleJourneys}\n\n` + `**Network File:**\n` + `• **Source:** ${stats.networkFile}\n\n` + `**Network Connectivity:**\n` + `Average links per node: ${stats.nodes > 0 ? (stats.links / stats.nodes * 2).toFixed(2) : 'N/A'}\n\n` + `*Detailed network statistics retrieved successfully.*` } ] }; } else { response.result = { content: [ { type: "text", text: `❌ **Statistics Retrieval Failed**\n\n` + `**Error:** ${statsResult.error}\n\n` + `*Could not retrieve detailed network statistics.*` } ] }; } } else if (toolName === 'open_project') { const projectPath = args.projectPath; const openResult = await openProject(projectPath); if (openResult.success) { response.result = { content: [ { type: "text", text: `✅ **Project Opened Successfully**\n\n` + `**File:** ${projectPath}\n` + `**Status:** Project loaded in Visum\n` + `**Size:** ${openResult.size || 'Unknown'}\n\n` + `**Network Details:**\n` + `• **Type:** ${openResult.fileType || 'Visum Version'}\n` + `• **Loaded:** ${new Date().toLocaleString()}\n\n` + `**Next Steps:**\n` + `• Use analyze_network to inspect the network\n` + `• Use get_network_stats for detailed statistics\n` + `• Perform transportation analysis\n\n` + `*The project is now ready for analysis in Visum.*` } ] }; } else { response.result = { content: [ { type: "text", text: `❌ **Project Opening Failed**\n\n` + `**File:** ${projectPath}\n` + `**Error:** ${openResult.error}\n\n` + `**Possible Causes:**\n` + `• File not found or inaccessible\n` + `• Invalid Visum project format\n` + `• Visum not properly connected\n` + `• File permissions issue\n\n` + `**Suggestions:**\n` + `• Verify the file path is correct\n` + `• Check file exists and is readable\n` + `• Ensure Visum is running (use launch_visum)\n` + `• Try absolute path format\n\n` + `*Could not load the specified project file.*` } ] }; } } else { response.error = { code: -32601, message: `Unknown tool: ${toolName}` }; } } // Handle initialize else if (request.method === 'initialize') { response.result = { protocolVersion: "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "enhanced-visum-mcp", version: "1.0.0" } }; } else { response.error = { code: -32601, message: `Unknown method: ${request.method}` }; } // Send response console.log(JSON.stringify(response)); console.error(`Sent response for ${request.method}`); } catch (error) { console.error(`Error processing request: ${error.message}`); // Send error response const errorResponse = { jsonrpc: "2.0", id: 1, error: { code: -32603, message: error.message } }; console.log(JSON.stringify(errorResponse)); } }); rl.on('close', () => { console.error('Enhanced MCP server connection closed'); process.exit(0); }); console.error("Enhanced Visum MCP Server ready for Claude with network analysis!");

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/multiluca2020/visum-thinker-mcp-server'

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