I’m thrilled to announce SwiftMCP, a Swift macro-based framework that elegantly exposes your Swift features 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 normal Swift documentation straight 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 features, together with documentation enclosed in triple quotes. One thing comparable 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 sort, and extra. This opens up astonishing potentialities:
- Extracting detailed metadata straight out of your current Swift documentation feedback.
- Routinely producing further supply code that captures and shops this metadata.
- Dynamically creating perform wrappers that simplify invocation with versatile arguments.
As an instance, contemplate 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 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 like Goal-C’s NSInvocation, enabling your features 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 fallacious.
The ultimate magic occurs on the server stage with @MCPServer, which features a common tool-invocation methodology:
public func callTool(_ identify: String, arguments: [String: Sendable]) async throws -> (Codable & Sendable) {
guard let software = mcpTools.first(the place: { $0.identify == identify }) else {
throw MCPToolError.unknownTool(identify: identify)
}
let enrichedArguments = strive software.enrichArguments(arguments, forObject: self)
change identify {
case "add":
return strive await __mcpCall_add(enrichedArguments)
default:
throw MCPToolError.unknownTool(identify: identify)
}
}With this plumbing in place, SwiftMCP effortlessly helps features which might be 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 methodology of serving – through normal IO – is entails the consumer really 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 manner of serving – is through 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) 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 a number of further bells and whistles, like for instance you may restrict entry to purchasers sending a particular bearer token.
When you’ve got your native server working you may 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 fast objective is to combine SwiftMCP with my current 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 further features you can 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 required 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 throwsOne 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 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 comparable options!
SwiftMCP is open-source, actively maintained, and keen on your suggestions and contributions. I’m pleased 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 Bundle Index is internet hosting the documentation.
Associated
Classes: Administrative

