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 comparable felt painfully out of attain for Swift builders—till I spotted 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 prospects:
- Extracting detailed metadata immediately out of your present Swift documentation feedback.
- Routinely producing further supply code that captures and shops this metadata.
- Dynamically creating perform wrappers that simplify invocation with versatile arguments.
For instance, think about 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 mechanically generates metadata like this:
/// autogenerated
let __mcpMetadata_add = MCPToolMetadata(
identify: "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, mechanically 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 methodology:
public func callTool(_ identify: String, arguments: [String: Sendable]) async throws -> (Codable & Sendable) {
guard let device = mcpTools.first(the place: { $0.identify == identify }) else {
throw MCPToolError.unknownTool(identify: identify)
}
let enrichedArguments = strive device.enrichArguments(arguments, forObject: self)
swap identify {
case "add":
return strive await __mcpCall_add(enrichedArguments)
default:
throw MCPToolError.unknownTool(identify: identify)
}
}
With this plumbing in place, SwiftMCP effortlessly helps capabilities which can be async, throwing, returning void, or returning any Codable sort. You’ll be able to serve your MCP instruments both by way of normal IO or as an HTTP+SSE server, permitting seamless integration into varied workflows.
The easier methodology of serving – by way of normal IO – is includes the consumer really launching your app after which speaking it’s sending single-line JSONRPC requests to stdin and receiving JSONRPC responses by way of 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 refined method of serving – is by way of a HTTP-SSE server. Right here the consumer 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) shall be despatched by way of 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 purchasers sending a particular bearer token.
In case you have your native server operating you possibly can expose it by way of an OpenAPI scheme to customized GPTs, in order that even these can work together along with your native instruments.
What’s Subsequent?
My rapid objective is to combine SwiftMCP with my present libraries akin to SwiftMail, enabling my brokers to work together with electronic mail by way of IMAP and SMTP, deal with notifications, and manipulate calendar occasions by way of EventKit. There are various further capabilities that you would be able to thus make accessible to agentic coders like Cursor.
I’ve began a challenge 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 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 thought is to have some fundamental 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 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 comparable options!
SwiftMCP is open-source, actively maintained, and keen on your suggestions and contributions. I’m comfortable to listen to from you ways 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