I’m thrilled to announce SwiftMCP, a Swift macro-based framework that elegantly exposes your Swift capabilities as highly effective Mannequin Context Protocol (MCP) instruments for AI assistants. After months of cautious refinement, SwiftMCP now delivers the expertise I’ve at all times dreamed of: turning normal Swift documentation immediately into AI-integrable instruments—effortlessly.
Behind the Scenes
For a very long time, I watched with envy as builders in languages like Python effortlessly created instruments for AI brokers by merely including decorators to their capabilities, together with documentation enclosed in triple quotes. One thing related felt painfully out of attain for Swift builders—till I noticed the unbelievable potential of Swift Macros.
Macros in Swift have full entry to the syntax tree of your supply code, together with each documentation remark, parameter sort, and extra. This opens up astonishing potentialities:
- Extracting detailed metadata immediately out of your present Swift documentation feedback.
- Routinely producing extra supply code that captures and shops this metadata.
- Dynamically creating perform wrappers that simplify invocation with versatile arguments.
For instance, think about this easy Swift perform:
/// Provides two integers and returns their sum
/// - Parameter a: First quantity so as to add
/// - Parameter b: Second quantity so as to add
/// - Returns: The sum of a and b
@MCPTool
func add(a: Int, b: Int) -> Int {
return a + b
}
Utilizing SwiftMCP’s @MCPTool
macro, the above perform robotically generates metadata like this:
/// autogenerated
let __mcpMetadata_add = MCPToolMetadata(
title: "add",
description: "Provides two integers and returns their sum",
parameters: [MCPToolParameterInfo(name: "a", label: "a", type: "Int", description: "First number to add", defaultValue: nil), MCPToolParameterInfo(name: "b", label: "b", type: "Int", description: "Second number to add", defaultValue: nil)],
returnType: "Int",
returnTypeDescription: "The sum of a and b",
isAsync: false,
isThrowing: false
)
Moreover, SwiftMCP generates a versatile invocation wrapper, very like Goal-C’s NSInvocation
, enabling your capabilities to simply accept parameters as dictionaries:
/// Autogenerated wrapper for add that takes a dictionary of parameters
func __mcpCall_add(_ params: [String: Sendable]) async throws -> (Codable & Sendable) {
let a = strive params.extractInt(named: "a")
let b = strive params.extractInt(named: "b")
return add(a: a, b: b)
}
This wrapper intelligently validates and parses incoming parameters, robotically dealing with conversions and offering informative error messages if something goes incorrect.
The ultimate magic occurs on the server degree with @MCPServer
, which features a common tool-invocation technique:
public func callTool(_ title: String, arguments: [String: Sendable]) async throws -> (Codable & Sendable) {
guard let software = mcpTools.first(the place: { $0.title == title }) else {
throw MCPToolError.unknownTool(title: title)
}
let enrichedArguments = strive software.enrichArguments(arguments, forObject: self)
change title {
case "add":
return strive await __mcpCall_add(enrichedArguments)
default:
throw MCPToolError.unknownTool(title: title)
}
}
With this plumbing in place, SwiftMCP effortlessly helps capabilities which are async, throwing, returning void, or returning any Codable sort. You’ll be able to serve your MCP instruments both through normal IO or as an HTTP+SSE server, permitting seamless integration into numerous workflows.
The easier technique of serving – through normal IO – is entails the shopper truly launching your app after which speaking it’s sending single-line JSONRPC requests to stdin and receiving JSONRPC responses through stdout. If you wish to ship an error, then you need to ship that to stderr.
let transport = StdioTransport(server: calculator)
strive await transport.run()
The opposite – extra subtle method of serving – is through a HTTP-SSE server. Right here the shopper makes a GET request to /sse and retains the connection open. It’s knowledgeable of an endpoint to POST JSONRPC requests to. When a message is shipped to the endpoint, the reply for it (with matching id) will likely be despatched through the SSE channel.
let transport = HTTPSSETransport(server: calculator, port: 8080)
strive await transport.run()
SwiftMCP helps each strategies. On the HTTP+SSE transport it has just a few additional bells and whistles, like for instance you possibly can restrict entry to shoppers sending a selected bearer token.
When you have your native server operating you possibly can expose it through an OpenAPI scheme to customized GPTs, in order that even these can work together together with your native instruments.
What’s Subsequent?
My speedy objective is to combine SwiftMCP with my present libraries corresponding to SwiftMail, enabling my brokers to work together with electronic mail through IMAP and SMTP, deal with notifications, and manipulate calendar occasions through EventKit. There are lots of extra capabilities which you can thus make obtainable to agentic coders like Cursor.
I’ve began a mission to just do that. For now it simply lets me begin an MCP Server and authorize location notifications.

This exposes the perform to ship native notifications to my laptop:
/// Sends a notification with the desired title and physique
/// - Parameters:
/// - title: The title of the notification
/// - physique: The physique textual content of the notification
/// - subtitle: Elective subtitle for the notification
@MCPTool
func sendNotification(title: String,
physique: String,
subtitle: String? = nil
) async throws
One other thought is to have some primary workflow issues that Cursor is lacking however Xcode gives, like launching an app in Simulator, or a wrapper for xcode-build
and swift
for constructing and testing.
Conclusion
Shortly after beginning SwiftMCP, I seen the NSHipster article about iMCP showing in my feed, highlighting the broader group’s rising curiosity in MCP. Shortly thereafter, I additionally discovered one other Swift MCP implementation by Compiler-Inc. It’s thrilling to see others exploring related options!
SwiftMCP is open-source, actively maintained, and keen in your suggestions and contributions. I’m comfortable to listen to from you the way you propose to make use of it or to assist including lacking options.
Test it out on GitHub: SwiftMCP, Swift Package deal Index is internet hosting the documentation.
Associated
Classes: Administrative