Close Menu
geekfence.comgeekfence.com
    What's Hot

    Designing trust & safety (T&S) in customer experience management (CXM): why T&S is becoming core to CXM operating model 

    January 24, 2026

    iPhone 18 Series Could Finally Bring Back Touch ID

    January 24, 2026

    The Visual Haystacks Benchmark! – The Berkeley Artificial Intelligence Research Blog

    January 24, 2026
    Facebook X (Twitter) Instagram
    • About Us
    • Contact Us
    Facebook Instagram
    geekfence.comgeekfence.com
    • Home
    • UK Tech News
    • AI
    • Big Data
    • Cyber Security
      • Cloud Computing
      • iOS Development
    • IoT
    • Mobile
    • Software
      • Software Development
      • Software Engineering
    • Technology
      • Green Technology
      • Nanotechnology
    • Telecom
    geekfence.comgeekfence.com
    Home»iOS Development»SwiftMCP Client | Cocoanetics
    iOS Development

    SwiftMCP Client | Cocoanetics

    AdminBy AdminJanuary 11, 2026No Comments7 Mins Read1 Views
    Facebook Twitter Pinterest LinkedIn Telegram Tumblr Email
    SwiftMCP Client | Cocoanetics
    Share
    Facebook Twitter LinkedIn Pinterest Email


    It’s 5 months since the release of SwiftMCP 1.0 and I’ve been slow cooking some enhancements for it. It was rewarding to see a bit of interested in this package, judging by issues and forks I could see on GitHub. Today, I’m revealing the work for the client-side I’ve done during this time.

    The first version of SwiftMCP naturally focussed entirely on the server-side. You can annotate any class or actor with @MCPServer and that would expose its functions with the @MCPTool attribute via MCP. Metadata is gleaned from the documentation comments for the function and parameters. This means – as a developer – you don’t have to spend any extra effort to expose tools for your app via MCP. You only have to think what API surface you wish to expose and then design the functions such that they have easy to understand and documented prototypes.

    SwiftMCP takes the metadata it derives directly from your code via macros and generates API responses. The initialize response contains all MCP tool descriptions, and their input schemas. Because of where MCP comes from – providing text input to LLMs – no thought seems to have been given to the idea that there could be structured responses. Therefore MCP spec is missing output schemas.

    In contrast the OpenAPI spec does have output schemas as well as a degree of support for error responses. This will become relevant further down.

    The Case for the Client

    Despite this limitation MCP has become the de factor standard for JSON RPC function calling. If you are designing an API for an LLM, why not also call those tools from your own programs?

    Before today, if you wanted to call into any MCP Server you would have to construct JSON messages and send these off to your server. Maybe some open source framework would make this slightly less bothersome, but it’s still not very “Swift-y”.

    Having said that, it is worth mentioning that SwiftMCP also will serve the tools via OpenAPI JSON RPC function calling, if you enable this feature. You could then use a proxy generator what builds you Swift types and functions. Then you could conveniently interact with this local code.

    That got me thinking: I do have all meta information within the @MCPServer macro. So at least for the code that you control you could generate the client-side proxy. For arbitrary other MCP Servers you could at least generate client code with the JSON types from the input schemas.

    Several common types get mapped to JSON strings which an additional format specifier. For example Date gets mapped to String with format date-time. So for MCP Servers that tell us the format we can derive the native Swift types from this. Other types with similar treatment are URL, UUID and Data.

    At this time the only way to get the native output/return types is to have a matching OpenAPI spec for the MCP Server and “steal” the types from there. Static types for custom errors are much harder to pull off, so that was out-of-scope for now.

    Scenario 1 – You Control the Code for Server and Client

    If you control both sides of the equation, then you are most lucky. The @MCPServer macro has gained a new ability to generat client-code for you. You awake the sleeper agent by adding `generateClient: true` to the macro. This causes it to generated a nested Client type within the type.

    @MCPServer(generateClient: true)
    actor Calculator {
        @MCPTool
        func add(a: Int, b: Int) -> Int {
            a + b
        }
    }

    Then to connect to the client proxy, you specify a configuration for the transport and instantiate a proxy.

    let url = URL(string: "
    let config = MCPServerConfig.sse(config: MCPServerSseConfig(url: url))
    let proxy = MCPServerProxy(config: config)
    try await proxy.connect()
    
    let client = Calculator.Client(proxy: proxy)
    let result = try await client.add(a: 2, b: 3)

    The client API surface will exactly match the original functions with one exception: All functions are now throws because a problem could occur on the client with communicating with the server.

    This path will retain all types, including Int and Double (which both get sent as number in JSON) and also struct. All types that are Codable and Sendable can be used.

    This opens up the use case that you have your MCP code in a shared package to allow you importing the MCPServer both from your servers and clients, including structs you want to use as input or output.

    Scenario 2 – You Control Only the Client Code

    This is harder, but I got you covered nevertheless. To generate local proxy code for any arbitrary MCP Server there’s now a CLI tool. This connects to a server (over network or STDIO) and gets the tools schemas. You can compile the utility and call it as shown, or alternatively you can precede it with swift run from the project folder.

    SwiftMCPUtility generate-proxy --sse -o ToolsProxy.swift

    This will generate the code for the local proxy. As stated above the limitation here is that certain types can only be modeled as native types if the inputSchema for string values has format information. Without extra information return types all have to be string.

    If the server also serves an OpenAPI spec, then this can supplement the type information for output types.

    SwiftMCPUtility generate-proxy \
      --sse  \
      --openapi  \
      -o ToolsProxy.swift

    The proxy generator also creates nested struct declarations. Let’s look at one of those generated proxy functions in the ProxyDemoCLI demo.

    /**
      Custom description: Performs addition of two numbers
      - Parameter a: First number to add
      - Parameter b: Second number to add
      - Returns: The sum of a and b
      */
     public func add(a: Double, b: Double) async throws -> Double {
         var arguments: [String: any Sendable] = [:]
         arguments["a"] = a
         arguments["b"] = b
         let text = try await proxy.callTool("add", arguments: arguments)
         return try MCPClientResultDecoder.decode(Double.self, from: text)
     } 

    You can see how the arguments are put into the arguments dictionary and then the proxy’s callTool functions is called for the “add” command. This takes care of the type conversion as well as the JSON-RPC messaging. The response then gets converted back to the native type of Double.

    Here’s another example from the demo that returns a custom struct.

    public actor SwiftMCPDemoProxy {
        
        /// A resource content implementation for files in the file system
        public struct RandomFileResponseItem: Codable, Sendable {
            /// The binary content of the resource (if it's a binary resource)
            public let blob: Data?
            /// The MIME type of the resource
            public let mimeType: String?
            /// The text content of the resource (if it's a text resource)
            public let text: String?
            /// The URI of the resource
            public let uri: URL?
        }
    
        /**
         A function returning a random file
         - Returns: A multiple simple text files
         */
        public func randomFile() async throws -> [RandomFileResponseItem] {
            let text = try await proxy.callTool("randomFile")
            return try MCPClientResultDecoder.decode([RandomFileResponseItem].self, from: text)
        }

    Here you can see that the proxy generator created a struct for the return type. The function randomFile decodes an array of this type from the JSON response. This way you get a statically typed Swift struct instead of a dictionary of arbitrary value types.

    Since this is generated code you can actually further customize it and for example use your own struct declarations. You just have to replace the generated type with your own and this will work as long as it matches the JSON.

    By contrast the same function as mentioned in scenario 1 is able to reference a public type and therefore no extra type declaration is necessary.

    Conclusion

    Please note that there might still be some rough edges as this functionality is brand new. If you find a problem or have a suggestion please let me know in the GitHub issues. How do you use SwiftMCP?

    Like this:

    Like Loading…

    Related


    Categories: Administrative



    Source link

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email

    Related Posts

    A Deep Dive into SwiftData migrations – Donny Wals

    January 24, 2026

    AI, find me some work…

    January 23, 2026

    Swift adapter design pattern – The.Swift.Dev.

    January 22, 2026

    Text is not visible when the button is in disabled state

    January 21, 2026

    What’s New in SwiftUI for iOS 18

    January 19, 2026

    WWDC 2023: A Reflection on Apple’s “Spatial Computing” Journey

    January 17, 2026
    Top Posts

    Understanding U-Net Architecture in Deep Learning

    November 25, 202511 Views

    Hard-braking events as indicators of road segment crash risk

    January 14, 20269 Views

    Microsoft 365 Copilot now enables you to build apps and workflows

    October 29, 20258 Views
    Don't Miss

    Designing trust & safety (T&S) in customer experience management (CXM): why T&S is becoming core to CXM operating model 

    January 24, 2026

    Customer Experience (CX) now sits at the intersection of Artificial Intelligence (AI)-enabled automation, identity and access journeys, AI-generated content…

    iPhone 18 Series Could Finally Bring Back Touch ID

    January 24, 2026

    The Visual Haystacks Benchmark! – The Berkeley Artificial Intelligence Research Blog

    January 24, 2026

    Data and Analytics Leaders Think They’re AI-Ready. They’re Probably Not. 

    January 24, 2026
    Stay In Touch
    • Facebook
    • Instagram
    About Us

    At GeekFence, we are a team of tech-enthusiasts, industry watchers and content creators who believe that technology isn’t just about gadgets—it’s about how innovation transforms our lives, work and society. We’ve come together to build a place where readers, thinkers and industry insiders can converge to explore what’s next in tech.

    Our Picks

    Designing trust & safety (T&S) in customer experience management (CXM): why T&S is becoming core to CXM operating model 

    January 24, 2026

    iPhone 18 Series Could Finally Bring Back Touch ID

    January 24, 2026

    Subscribe to Updates

    Please enable JavaScript in your browser to complete this form.
    Loading
    • About Us
    • Contact Us
    • Disclaimer
    • Privacy Policy
    • Terms and Conditions
    © 2026 Geekfence.All Rigt Reserved.

    Type above and press Enter to search. Press Esc to cancel.