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 all the time dreamed of: turning commonplace Swift documentation instantly 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 unimaginable potential of Swift Macros.
Macros in Swift have full entry to the syntax tree of your supply code, together with each documentation remark, parameter kind, and extra. This opens up astonishing prospects:
- Extracting detailed metadata instantly out of your current Swift documentation feedback.
- Routinely producing extra supply code that captures and shops this metadata.
- Dynamically creating perform wrappers that simplify invocation with versatile arguments.
As an instance, take into account this straightforward 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 similar to Goal-C’s NSInvocation
, enabling your capabilities to just 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 improper.
The ultimate magic occurs on the server stage with @MCPServer
, which features a common tool-invocation methodology:
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 kind. You possibly can serve your MCP instruments both through commonplace IO or as an HTTP+SSE server, permitting seamless integration into numerous workflows.
The easier methodology of serving – through commonplace IO – is includes the shopper really launching your app after which speaking or not it’s sending single-line JSONRPC requests to stdin and receiving JSONRPC responses through stdout. If you wish to ship an error, then it’s best to ship that to stderr.
let transport = StdioTransport(server: calculator)
strive await transport.run()
The opposite – extra subtle means 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 distributed to the endpoint, the reply for it (with matching id) will probably 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 further bells and whistles, like for instance you may restrict entry to purchasers sending a particular bearer token.
When you have your native server working you may expose it through an OpenAPI scheme to customized GPTs, in order that even these can work together along with your native instruments.
What’s Subsequent?
My fast aim is to combine SwiftMCP with my current libraries akin to SwiftMail, enabling my brokers to work together with e-mail through IMAP and SMTP, deal with notifications, and manipulate calendar occasions through EventKit. There are various extra capabilities which you could thus make out there to agentic coders like Cursor.
I’ve began a mission to do exactly 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 pc:
/// 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: Non-compulsory subtitle for the notification
@MCPTool
func sendNotification(title: String,
physique: String,
subtitle: String? = nil
) async throws
One other concept 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 observed the NSHipster article about iMCP showing in my feed, highlighting the broader neighborhood’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 blissful to listen to from you ways you intend to make use of it or to assist including lacking options.
Test it out on GitHub: SwiftMCP, Swift Bundle Index is internet hosting the documentation.