Skip to content

Windsurf support #131

Closed
Closed
@glaciotech

Description

@glaciotech

I'm trying to get the MCP server to work with Windsurf. I'm not sure if this is an issue with how i'm creating the server or something to do with how Windsurf expects MCP servers to respond. So starting out with a question.

I can get Windsurf to detect the MCP server and it sees the tools listed, but at the same time it's showing 0 tools available and if i try and get Cascade to invoke any of the tools it doesn't think it has any. It's possible from looking at the Firecrawl MCP source and doing some inference that Windsurf expects the tools to be listed as resources as well, but if anyone has any guidance or experience here it would be a great help?

Below is the quick code i threw together to test this from Windsurf along with a screenshot of what i'm seeing in Windsurf.

Thanks

final class App: Sendable {
    
    let logger = Logger(label: "com.example.mcp-server")
    let server: Server

    init() async {

        let server = Server(name: "TestMCPServer", version: "1.0", capabilities: .init(logging: Server.Capabilities.Logging(),
            resources: .init(subscribe: true, listChanged: true),
            tools: .init(listChanged: true)
        ))
    
        
        await server.withMethodHandler(ListResources.self) { _ in
            let resources = [
                Resource(name: "Tools", uri: "www.glacio.tech", description: "List of available tools for MCP")
            ]
            return .init(resources: resources)
        }
        
        //// Register a tool list handler
        await server.withMethodHandler(ListTools.self) { _ in
            let tools = [
                Tool(
                    name: "weather",
                    description: "Get current weather for a location",
                    inputSchema: .object([
                        "location": .string("City name or coordinates"),
                        "units": .string("Units of measurement, e.g., metric, imperial")
                    ]),
                ),
                Tool(
                    name: "calculator",
                    description: "Perform calculations",
                    inputSchema: .object([
                        "expression": .string("Mathematical expression to evaluate")
                    ])
                )
            ]
            return .init(tools: tools)
        }
        
        //// Register a tool call handler
        await server.withMethodHandler(CallTool.self) { params in
            switch params.name {
            case "weather":
                let location = params.arguments?["location"]?.stringValue ?? "Unknown"
                let units = params.arguments?["units"]?.stringValue ?? "metric"
                let weatherData = getWeatherData(location: location, units: units) // Your implementation
                return .init(
                    content: [.text("Weather for \(location): \(weatherData.temperature)°, \(weatherData.conditions)")],
                    isError: false
                )
                
            case "calculator":
                if let expression = params.arguments?["expression"]?.stringValue {
                    let result = evaluateExpression(expression) // Your implementation
                    return .init(content: [.text("\(result)")], isError: false)
                } else {
                    return .init(content: [.text("Missing expression parameter")], isError: true)
                }
                
            default:
                return .init(content: [.text("Unknown tool")], isError: true)
            }
        }
        
        self.server = server
    }
    
    func start() async throws {
        
        print("CLI app has exited.")
        
        // Create MCP service and other services
        let transport = StdioTransport(logger: logger)
        let mcpService = MCPService(server: server, transport: transport)

        // Create service group with signal handling
        let serviceGroup = ServiceGroup(
            services: [mcpService],
            configuration: .init(gracefulShutdownSignals: [.sigterm, .sigint]), logger: logger
        )
        
            
        // Run the service group - this blocks until shutdown
        try await serviceGroup.run()
    }
}

try! await App().start()
struct MCPService: Service {
    
    let server: Server
    let transport: StdioTransport
    
    init(server: Server, transport: StdioTransport) {
        self.server = server
        self.transport = transport
    }
    
    func run() async throws {
        // Start the server
        try await server.start(transport: transport)

        // Keep running until external cancellation
        try await Task.sleep(for: .seconds(10000)) 
    }

    func shutdown() async throws {
        // Gracefully shutdown the server
        await server.stop()
    }
}

struct WeatherDataType {
    var temperature: Double
    var conditions: String
}

func getWeatherData(location: String, units: String) -> WeatherDataType {
    return WeatherDataType(temperature: 80, conditions: "Sunny")
}

func evaluateExpression(_ expression: String) -> String {
    "Evaluated \(expression)"
}
Image

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