Skip to content

Feature Request: Native HTTP Transport Support for MCP ServersΒ #897

@jief123

Description

@jief123

Summary

Add native HTTP transport support to smithy-java MCP server implementation, similar to the existing StdIO transport. This would enable MCP servers to be deployed as HTTP services without requiring custom transport layer implementations.

Motivation

Currently, smithy-java provides excellent support for StdIO-based MCP servers via McpServer.builder().stdio(), but lacks native HTTP transport support. The MCP specification defines HTTP as a standard transport mechanism, yet developers must implement their own HTTP layer.

This creates several issues:

  1. Duplication: Every project reimplements HTTP transport logic
  2. Inconsistency: Different implementations may handle protocol details differently
  3. Maintenance burden: Protocol updates require changes across multiple projects
  4. Error-prone: Easy to miss protocol requirements (e.g., returning 202 for notifications)
  5. Barrier to adoption: Increases complexity for new MCP server developers

Current Workaround

After PR: #893, Developers currently can implement custom HTTP servers that wrap McpService:

// Current approach - custom HTTP server required
public class HttpMCPServer {
    private final McpService mcpService;
    private HttpServer httpServer;
    
    public HttpMCPServer(String host, int port, String serverName) {
        var service = BillingAnalyticsService.builder()
            .addOperation(new MyOperationImpl())
            .build();
            
        this.mcpService = McpService.builder()
            .services(Map.of("billing", service))
            .name(serverName)
            .build();
    }
    
    public void start() throws IOException {
        httpServer = HttpServer.create(new InetSocketAddress(host, port), 0);
        httpServer.createContext("/mcp", new McpHandler());
        httpServer.start();
    }
    
    private class McpHandler implements HttpHandler {
        public void handle(HttpExchange exchange) throws IOException {
            // Handle CORS, Origin validation, method routing
            // Parse JSON-RPC request
            // Delegate to mcpService.handleRequest()
            // Return 202 for notifications, 200 for requests
            // Handle errors appropriately
        }
    }
}

This requires ~200+ lines of boilerplate code per project.

Proposed Solution

Add HTTP transport support to McpServer.Builder, making it as simple as StdIO:

// Proposed API - consistent with StdIO
var server = McpServer.builder()
    .http("0.0.0.0", 8000)  // Simple HTTP transport
    .name("my-mcp-server")
    .addService("billing", service)
    .build();

server.start();

Advanced Configuration

For production deployments, provide configuration options:

var server = McpServer.builder()
    .http(HttpTransportConfig.builder()
        .host("0.0.0.0")
        .port(8000)
        .path("/mcp")
        .enableSSE(true)  // Server-Sent Events for streaming
        .cors(CorsConfig.builder()
            .allowedOrigins("https://example.com")
            .allowedMethods("POST", "GET", "DELETE")
            .build())
        .security(SecurityConfig.builder()
            .validateOrigin(true)
            .allowedOrigins("http://localhost:*", "https://*.example.com")
            .build())
        .build())
    .name("my-mcp-server")
    .addService("billing", service)
    .build();

Smithy Trait Representation

HTTP transport configuration could be represented as a Smithy trait:

namespace smithy.mcp

/// Configures HTTP transport for an MCP service
@trait(selector: "service")
structure httpTransport {
    /// Host to bind to (default: "0.0.0.0")
    host: String
    
    /// Port to listen on (default: 8000)
    port: Integer
    
    /// HTTP path for MCP endpoint (default: "/mcp")
    path: String
    
    /// Enable Server-Sent Events for streaming (default: false)
    enableSSE: Boolean
    
    /// CORS configuration
    cors: CorsConfiguration
    
    /// Security configuration
    security: SecurityConfiguration
}

structure CorsConfiguration {
    /// Allowed origins (default: "*")
    allowedOrigins: StringList
    
    /// Allowed HTTP methods
    allowedMethods: StringList
    
    /// Allowed headers
    allowedHeaders: StringList
}

structure SecurityConfiguration {
    /// Validate Origin header to prevent DNS rebinding
    validateOrigin: Boolean
    
    /// Allowed origin patterns
    allowedOrigins: StringList
}

Usage in service definition:

@httpTransport(
    host: "0.0.0.0"
    port: 8000
    path: "/mcp"
    enableSSE: true
    cors: {
        allowedOrigins: ["https://example.com"]
        allowedMethods: ["POST", "GET", "DELETE"]
    }
)
service BillingAnalyticsService {
    operations: [GetCostByService, GetCostByRegion]
}

The code generator would then automatically configure HTTP transport based on these traits.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions