← All courses ← Course home

Lesson 05 of 05

Plug in a tool without rewriting chat

Register one new MCP method, refresh the tool list, and send the same user text through session.respond.

Agent brief (llms.md)

The point of the bridge is a boring change. You register a new MCP tool. You do not touch the SwiftUI chat view or the respond call.

RegisterNew MCPTool
ListClient refresh
ChatSame respond
let lookup = MCPTool(
    name: "lookup_order",
    description: "Return the local order status for an id the user already has.",
    inputSchema: [
        "type": "object",
        "properties": [
            "orderId": ["type": "string", "description": "Order id from the user"]
        ],
        "required": ["orderId"]
    ],
    run: { arguments in
        let orderId = arguments["orderId"] as? String ?? ""
        let status = OrderStore.shared.status(for: orderId)
        return ["orderId": orderId, "status": status]
    }
)

await server.register(lookup)
let session = try await makeSession(client: client)
let reply = try await session.respond(to: prompt)

The view still sends user text into respond. The model sees lookup_order because tools/list returned it. If you need a second tool tomorrow, add another MCPTool. Leave the view alone.

UIText field and send
Loopsession.respond
New workServer register

Checklist

  1. Target iOS 27 or macOS 27, and Xcode 27.
  2. Keep the MCP server free of Foundation Models imports.
  3. Speak raw JSON-RPC for initialize, tools/list, and tools/call.
  4. Map listed tools with a runtime schema, not a new compiled Tool per method.
  5. Create or refresh the session after the list changes. Do not edit tools while isResponding is true.
  6. Put file, network, and private-data tools through the sandbox and guardrail courses before you ship them.

Primary sources: MCP specification, Foundation Models, and WWDC26 session 242.

Related courses: Run tools in a safe box, Stop prompt attacks and leaks, and Core AI vs Core ML vs MLX.

Short form. MCP adds tools at runtime. Foundation Models still runs the chat. Your bridge is the only join.

Key concepts

  • Register a new MCP tool on the server, refresh the list, and keep the same respond call.
  • The view still sends user text into respond.
  • Do not edit tools while the session is responding.
  • Put file, network, and private-data tools through sandbox and guardrail courses before shipping.

Takeaways

  • Add another MCP tool tomorrow and leave the SwiftUI chat view alone.
  • The model sees the new tool because tools/list returned it.
  • MCP adds tools at runtime. Your bridge is the join.