Mirror of https://github.com/modelcontextprotocol/swift-sdk — The official Swift SDK for Model Context Protocol servers and clients.
  • Swift 99.8%
  • Shell 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Sash Zats c63a872a69
Fix client parsing (#8)
* Allow decoding Decodable type directly from Value

Summary: I noticed we are not converting value associated with response to the strong types requests recorded
This change will help to decode the value type later once we support the rest of plumbing (next commit)

* Store and pass original request when response arrives

Summary: Looks like there were multiple issues with parsing response:
1. It appears that we would mistakenly pass response both for response and request arguments in the private func handleResponse(_ response: Response<AnyMethod>, for request: Any)
2. Later I couldn't figure out how to win against swift type system, so ended up creating a type-erased request to store in the pendingRequests instead of original type under Any (that wouldn't allow to downcast original type later)

Test Plan:

1. Standup iMCP client from https://github.com/loopwork-ai/iMCP
2. Create a dummy project setting up MCP client against "/private/var/folders/26/8gncz37x7slbfrr95d9jcr400000gn/T/AppTranslocation/62ADEC4D-3545-4E98-A612-0E6DF52CE525/d/iMCP.app/Contents/MacOS/imcp-server" and call initialize

Note response is being parsed correctly and client.initialize() does not hang indefinitely

* Fix warning: 'Cast from Client.AnyPendingRequest to unrelated type Client.PendingRequest<Any> always fails'

* Fix warning: 'Conditional cast from NWError to NWError always succeeds'

* Uncomment code in RoundtripTests

* Formatting

* Reorganize declarations

* Inline JSONDecoder extension

* Expand roundtrip tests

---------

Co-authored-by: Sash Zats sash@zats.io <>
Co-authored-by: Mattt Zmuda <mattt@loopwork.com>
2025-03-13 11:39:46 -07:00
.github/workflows Add CI workflow (#1) 2025-02-11 15:26:39 -08:00
.vscode Initial implementation 2025-02-11 15:22:35 -08:00
Sources/MCP Fix client parsing (#8) 2025-03-13 11:39:46 -07:00
Tests/MCPTests Fix client parsing (#8) 2025-03-13 11:39:46 -07:00
.gitignore Initial commit 2025-02-05 11:13:57 -08:00
LICENSE Initial implementation 2025-02-11 15:22:35 -08:00
Package.resolved Initial implementation 2025-02-11 15:22:35 -08:00
Package.swift Initial implementation 2025-02-11 15:22:35 -08:00
README.md Add link to iMCP in README 2025-03-06 06:51:34 -08:00

MCP Swift SDK

Swift implementation of the Model Context Protocol (MCP).

Tip

To see it in action, check out the iMCP app.

Requirements

  • Swift 6.0+ / Xcode 16+
  • macOS 14.0+ (Sonoma)
  • iOS 17.0+

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/loopwork-ai/mcp-swift-sdk.git", from: "0.3.0")
]

Usage

Basic Client Setup

import MCP

// Initialize the client
let client = Client(name: "MyApp", version: "1.0.0")

// Create a transport and connect
let transport = StdioTransport()
try await client.connect(transport: transport)

// Initialize the connection
let result = try await client.initialize()

Basic Server Setup

import MCP

// Initialize the server with capabilities
let server = Server(
    name: "MyServer", 
    version: "1.0.0",
    capabilities: .init(
        resources: .init(
            list: true,
            read: true,
            subscribe: true
        )
    )
)

// Create transport and start server
let transport = StdioTransport()
try await server.start(transport: transport)

// Register method handlers
server.withMethodHandler(ReadResource.self) { params in
    // Handle resource read request
    let uri = params.uri
    let content = [Resource.Content.text("Example content")]
    return .init(contents: content)
}

// Register notification handlers
server.onNotification(ResourceUpdatedNotification.self) { message in
    // Handle resource update notification
}

// Stop the server when done
await server.stop()

Working with Tools

// List available tools
let tools = try await client.listTools()

// Call a tool
let (content, isError) = try await client.callTool(
    name: "example-tool", 
    arguments: ["key": "value"]
)

// Handle tool content
for item in content {
    switch item {
    case .text(let text):
        print(text)
    case .image(let data, let mimeType, let metadata):
        // Handle image data
    }
}

Working with Resources

// List available resources
let (resources, nextCursor) = try await client.listResources()

// Read a resource
let contents = try await client.readResource(uri: "resource://example")

// Subscribe to resource updates
try await client.subscribeToResource(uri: "resource://example")

// Handle resource updates
await client.onNotification(ResourceUpdatedNotification.self) { message in
    let uri = message.params.uri
    let content = message.params.content
    // Handle the update
}

Working with Prompts

// List available prompts
let (prompts, nextCursor) = try await client.listPrompts()

// Get a prompt with arguments
let (description, messages) = try await client.getPrompt(
    name: "example-prompt",
    arguments: ["key": "value"]
)

License

This project is licensed under the Apache License, Version 2.0.