Post

FastMCP: Build Swift MCP Servers in 3 Lines

A Swift builder pattern that reduces MCP server boilerplate from 50+ lines to just 3.

FastMCP: Build Swift MCP Servers in 3 Lines

Model Context Protocol (MCP) is Anthropic’s open standard for connecting AI assistants to external tools. Building MCP servers with the official Swift SDK requires significant boilerplate.

The Problem

Standard MCP server setup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import MCP

let server = Server(
    name: "My Server",
    version: "1.0.0",
    capabilities: Server.Capabilities(
        prompts: nil,
        resources: nil,
        tools: .init(listChanged: false)
    )
)

await server.withMethodHandler(Tools.self) { _ in
    // Return tool definitions...
}

await server.withMethodHandler(CallTool.self) { params in
    // Handle tool calls...
}

let transport = StdioTransport(logger: logger)
try await server.start(transport: transport)
// Handle shutdown signals...
// Set up logging...

The Solution

1
2
3
4
try await FastMCP.builder()
    .name("My Server")
    .addTools([WeatherTool()])
    .run()

Three lines. Server running.

Building a Tool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import FastMCP

struct WeatherTool: MCPTool {
    let name = "get_weather"
    let description: String? = "Get weather for a location"

    @Schemable
    struct Parameters: Sendable {
        let location: String
        let unit: Unit?
    }

    @Schemable
    enum Unit: String, Sendable {
        case celsius, fahrenheit
    }

    func call(with args: Parameters) async throws(ToolError) -> Content {
        let temp = args.unit == .fahrenheit ? "72°F" : "22°C"
        return [ToolContentItem(text: "Weather in \(args.location): \(temp), Sunny")]
    }
}

@main
struct WeatherServer {
    static func main() async throws {
        try await FastMCP.builder()
            .name("Weather Server")
            .addTools([WeatherTool()])
            .run()
    }
}

The @Schemable macro auto-generates JSON schema for Claude to understand parameters.

Resources

Expose data to AI:

1
2
3
4
5
6
7
8
9
10
11
12
struct ConfigResource: MCPResource {
    let uri = "config://app/settings"
    let name = "App Settings"
    let description: String? = "Application configuration"
    let mimeType: String? = "application/json"

    var content: Content {
        """
        {"theme": "dark", "version": "1.0.0"}
        """
    }
}

Prompts

Reusable conversation templates:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct CodeReviewPrompt: MCPPrompt {
    let name = "code_review"
    let description: String? = "Review code with specific focus"
    let arguments: [Prompt.Argument]? = [
        .init(name: "language", description: "Programming language", required: true),
        .init(name: "focus", description: "Review focus area")
    ]

    func getMessages(arguments: [String: Value]?) async throws -> [Prompt.Message] {
        let lang = arguments?["language"]?.stringValue ?? "Swift"
        let focus = arguments?["focus"]?.stringValue ?? "best practices"

        return [
            .user("Review this \(lang) code focusing on \(focus)."),
            .assistant("I'll review your \(lang) code with attention to \(focus). Please share the code.")
        ]
    }
}

Full Builder API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
try await FastMCP.builder()
    // Identity
    .name("My Awesome Server")
    .version("2.0.0")

    // MCP Capabilities
    .addTools([WeatherTool(), MathTool()])
    .addResources([ConfigResource()])
    .addPrompts([CodeReviewPrompt()])
    .enableSampling()

    // Transport
    .transport(.stdio)  // or .inMemory for testing

    // Configuration
    .logger(myLogger)
    .shutdownSignals([.sigterm, .sigint])

    // Lifecycle Hooks
    .onStart { print("Server started") }
    .onShutdown { print("Server stopped") }

    .run()

Everything has sensible defaults. Configure only what you need.

Claude Desktop Integration

Add to claude_desktop_config.json:

1
2
3
4
5
6
7
{
    "mcpServers": {
        "my-server": {
            "command": "/path/to/my-server"
        }
    }
}

Restart Claude Desktop. Tools appear automatically.

Installation

1
2
3
4
// Package.swift
dependencies: [
    .package(url: "https://github.com/mehmetbaykar/swift-fast-mcp", from: "1.0.0")
]

Requirements: macOS 14+, Swift 6.2+

GitHub: github.com/mehmetbaykar/swift-fast-mcp

☕ Support My Work

If you found this post helpful and want to support more content like this, you can buy me a coffee!

Your support helps me continue creating useful articles and tips for fellow developers. Thank you! 🙏

This post is licensed under CC BY 4.0 by the author.