Skip to main content
Glama
http_integration.rs6.61 kB
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpStream; use serde_json::{json, Value}; use std::time::Duration; /// Helper function to start the HTTP MCP server in the background for testing async fn start_test_server(port: u16) -> tokio::task::JoinHandle<()> { tokio::spawn(async move { // Simulate starting the server on the given port // In a real scenario, you would import and call your server's start function let addr = format!("127.0.0.1:{}", port); let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); // Accept one connection for testing let (stream, _) = listener.accept().await.unwrap(); // Simple echo server for now - this will be replaced with actual MCP handling let (mut reader, mut writer) = tokio::io::split(stream); let mut buf = vec![0u8; 4096]; loop { match reader.read(&mut buf).await { Ok(0) => break, Ok(n) => { if let Err(_) = writer.write_all(&buf[..n]).await { break; } } Err(_) => break, } } }) } /// Test basic HTTP connection to the server #[tokio::test] async fn test_http_connection() { let port = 9876; let _server = start_test_server(port).await; // Give server time to start tokio::time::sleep(Duration::from_millis(100)).await; // Connect to the server let result = TcpStream::connect(format!("127.0.0.1:{}", port)).await; assert!(result.is_ok(), "Should be able to connect to the test server"); } /// Test HTTP upgrade request #[tokio::test] async fn test_http_upgrade_request() { let port = 9877; let _server = start_test_server(port).await; // Give server time to start tokio::time::sleep(Duration::from_millis(100)).await; let mut stream = TcpStream::connect(format!("127.0.0.1:{}", port)) .await .expect("Failed to connect"); // Send HTTP upgrade request let request = "GET / HTTP/1.1\r\n\ Host: localhost\r\n\ Upgrade: mcp\r\n\ Connection: Upgrade\r\n\ \r\n"; stream.write_all(request.as_bytes()).await.expect("Failed to write request"); // Read response let mut buf = vec![0u8; 1024]; let n = stream.read(&mut buf).await.expect("Failed to read response"); let response = String::from_utf8_lossy(&buf[..n]); // Verify we got a response assert!(!response.is_empty(), "Should receive a response"); } /// Test MCP initialize message #[tokio::test] async fn test_mcp_initialize() { // Create a test initialize request let initialize_request = json!({ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": { "name": "test-client", "version": "1.0.0" } } }); // Verify the request is properly formatted JSON-RPC assert_eq!(initialize_request["jsonrpc"], "2.0"); assert_eq!(initialize_request["method"], "initialize"); assert!(initialize_request["params"].is_object()); } /// Test MCP tool call (run_js) #[tokio::test] async fn test_mcp_tool_call_format() { // Create a test tool call request let tool_call_request = json!({ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "run_js", "arguments": { "code": "1 + 1", "heap": "test-heap" } } }); // Verify the request is properly formatted assert_eq!(tool_call_request["jsonrpc"], "2.0"); assert_eq!(tool_call_request["method"], "tools/call"); assert_eq!(tool_call_request["params"]["name"], "run_js"); assert!(tool_call_request["params"]["arguments"].is_object()); } /// Test JavaScript code execution scenarios #[tokio::test] async fn test_javascript_execution_scenarios() { // Test simple arithmetic let code1 = "1 + 1"; assert!(!code1.is_empty()); // Test variable assignment with persistence let code2 = "let x = 5; x"; assert!(code2.contains("let")); // Test accessing previously set variable let code3 = "x + 10"; assert!(!code3.is_empty()); // All test code snippets are valid assert!(true); } /// Test heap storage naming #[tokio::test] async fn test_heap_naming() { let heap_names = vec![ "test-heap", "user-session-123", "calculation-workspace", ]; // Verify heap names are valid strings for name in heap_names { assert!(!name.is_empty()); assert!(!name.contains('/')); // No path separators } } /// Test error handling for invalid JavaScript #[tokio::test] async fn test_invalid_javascript_handling() { // Examples of invalid JavaScript that should be caught let invalid_codes = vec![ "this is not javascript", "let x = ;", "undefined.method()", ]; for code in invalid_codes { // These should be handled gracefully by the server let request = json!({ "code": code, "heap": "test-heap" }); assert!(request.is_object()); } } /// Test concurrent connections #[tokio::test] async fn test_concurrent_connections() { let port = 9878; // Try to create multiple connection attempts let tasks: Vec<_> = (0..3).map(|_| { tokio::spawn(async move { // Each task attempts to connect let addr = format!("127.0.0.1:{}", port); // Connection may fail since server isn't running, but we test the logic let _ = tokio::time::timeout( Duration::from_millis(100), TcpStream::connect(addr) ).await; }) }).collect(); // Wait for all tasks to complete for task in tasks { task.await.expect("Task should complete"); } } /// Test JSON-RPC error response format #[tokio::test] async fn test_jsonrpc_error_format() { let error_response = json!({ "jsonrpc": "2.0", "id": 1, "error": { "code": -32600, "message": "Invalid Request" } }); assert_eq!(error_response["jsonrpc"], "2.0"); assert!(error_response["error"].is_object()); assert!(error_response["error"]["code"].is_number()); assert!(error_response["error"]["message"].is_string()); }

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/r33drichards/mcp-js'

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