[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-79862":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":9,"totalLinesOfCode":9,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":9,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":9,"rankLanguage":9,"license":9,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":27,"readmeContent":28,"aiSummary":29,"trendingCount":16,"starSnapshotCount":16,"syncStatus":30,"lastSyncTime":31,"discoverSource":32},79862,"swift-sdk","modelcontextprotocol\u002Fswift-sdk","modelcontextprotocol","The official Swift SDK for Model Context Protocol servers and clients.",null,"https:\u002F\u002Fgithub.com\u002Fmodelcontextprotocol\u002Fswift-sdk","Swift",1406,194,20,56,0,5,6,9,15,65.77,false,"main",[25,26],"mcp","swift","2026-06-12 04:01:25","# MCP Swift SDK\n\nOfficial Swift SDK for the [Model Context Protocol][mcp] (MCP).\n\n## Overview\n\nThe Model Context Protocol (MCP) defines a standardized way\nfor applications to communicate with AI and ML models.\nThis Swift SDK implements both client and server components\naccording to the [2025-11-25][mcp-spec-2025-11-25] (latest) version\nof the MCP specification.\n\n## Table of contents\n\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Client Usage](#client-usage)\n  - [Basic Client Setup](#basic-client-setup)\n  - [Transport Options for Clients](#transport-options-for-clients)\n  - [Tools](#tools)\n  - [Resources](#resources)\n  - [Prompts](#prompts)\n  - [Completions](#completions)\n  - [Sampling](#sampling)\n  - [Elicitation](#elicitation)\n  - [Roots](#roots)\n  - [Logging](#logging)\n  - [Error Handling](#error-handling)\n  - [Cancellation](#cancellation)\n  - [Progress Tracking](#progress-tracking)\n  - [Advanced Client Features](#advanced-client-features)\n- [Server Usage](#server-usage)\n  - [Basic Server Setup](#basic-server-setup)\n  - [Tools](#tools-1)\n  - [Resources](#resources-1)\n  - [Prompts](#prompts-1)\n  - [Completions](#completions-1)\n  - [Sampling](#sampling-1)\n  - [Elicitations](#elicitations)\n  - [Roots](#roots-1)\n  - [Logging](#logging-1)\n  - [Progress Tracking](#progress-tracking-1)\n  - [Initialize Hook](#initialize-hook)\n  - [HTTP Request Context in Handlers](#http-request-context-in-handlers)\n  - [Graceful Shutdown](#graceful-shutdown)\n- [Transports](#transports)\n- [Authentication](#authentication)\n  - [Client: Client Credentials Flow](#client-client-credentials-flow)\n  - [Client: Authorization Code Flow](#client-authorization-code-flow)\n  - [Client: Custom Token Provider](#client-custom-token-provider)\n  - [Client: Custom Token Storage](#client-custom-token-storage)\n  - [Client: private\\_key\\_jwt Authentication](#client-private_key_jwt-authentication)\n  - [Client: Endpoint Overrides](#client-endpoint-overrides)\n  - [Server: Serving Protected Resource Metadata](#server-serving-protected-resource-metadata)\n  - [Server: Validating Bearer Tokens](#server-validating-bearer-tokens)\n- [Platform Availability](#platform-availability)\n- [Debugging and Logging](#debugging-and-logging)\n- [Additional Resources](#additional-resources)\n- [Changelog](#changelog)\n- [License](#license)\n\n## Requirements\n\n- Swift 6.0+ (Xcode 16+)\n\nSee the [Platform Availability](#platform-availability) section below\nfor platform-specific requirements.\n\n## Installation\n\n### Swift Package Manager\n\nAdd the following to your `Package.swift` file:\n\n```swift\ndependencies: [\n    .package(url: \"https:\u002F\u002Fgithub.com\u002Fmodelcontextprotocol\u002Fswift-sdk.git\", from: \"0.11.0\")\n]\n```\n\nThen add the dependency to your target:\n\n```swift\n.target(\n    name: \"YourTarget\",\n    dependencies: [\n        .product(name: \"MCP\", package: \"swift-sdk\")\n    ]\n)\n```\n\n## Client Usage\n\nThe client component allows your application to connect to MCP servers.\n\n### Basic Client Setup\n\n```swift\nimport MCP\n\n\u002F\u002F Initialize the client\nlet client = Client(name: \"MyApp\", version: \"1.0.0\")\n\n\u002F\u002F Create a transport and connect\nlet transport = StdioTransport()\nlet result = try await client.connect(transport: transport)\n\n\u002F\u002F Check server capabilities\nif result.capabilities.tools != nil {\n    \u002F\u002F Server supports tools (implicitly including tool calling if the 'tools' capability object is present)\n}\n```\n\n> [!NOTE]\n> The `Client.connect(transport:)` method returns the initialization result.\n> This return value is discardable, \n> so you can ignore it if you don't need to check server capabilities.\n\n### Transport Options for Clients\n\n#### Stdio Transport\n\nFor local subprocess communication:\n\n```swift\n\u002F\u002F Create a stdio transport (simplest option)\nlet transport = StdioTransport()\ntry await client.connect(transport: transport)\n```\n\n#### HTTP Transport\n\nFor remote server communication:\n\n```swift\n\u002F\u002F Create a streaming HTTP transport\nlet transport = HTTPClientTransport(\n    endpoint: URL(string: \"http:\u002F\u002Flocalhost:8080\")!,\n    streaming: true  \u002F\u002F Enable Server-Sent Events for real-time updates\n)\ntry await client.connect(transport: transport)\n```\n\n### Tools\n\nTools represent functions that can be called by the client:\n\n```swift\n\u002F\u002F List available tools\nlet (tools, cursor) = try await client.listTools()\nprint(\"Available tools: \\(tools.map { $0.name }.joined(separator: \", \"))\")\n\n\u002F\u002F Call a tool with arguments and get the result\nlet (content, isError) = try await client.callTool(\n    name: \"image-generator\",\n    arguments: [\n        \"prompt\": \"A serene mountain landscape at sunset\",\n        \"style\": \"photorealistic\",\n        \"width\": 1024,\n        \"height\": 768\n    ]\n)\n\n\u002F\u002F Handle tool content\nfor item in content {\n    switch item {\n    case .text(let text):\n        print(\"Generated text: \\(text)\")\n    case .image(let data, let mimeType, let metadata):\n        if let width = metadata?[\"width\"] as? Int,\n           let height = metadata?[\"height\"] as? Int {\n            print(\"Generated \\(width)x\\(height) image of type \\(mimeType)\")\n            \u002F\u002F Save or display the image data\n        }\n    case .audio(let data, let mimeType):\n        print(\"Received audio data of type \\(mimeType)\")\n    case .resource(let resource, _, _):\n        print(\"Received embedded resource: \\(resource)\")\n    case .resourceLink(let uri, let name, _, _, let mimeType, _):\n        print(\"Resource link: \\(name) at \\(uri), type: \\(mimeType ?? \"unknown\")\")\n    }\n}\n```\n\n### Resources\n\nResources represent data that can be accessed and potentially subscribed to:\n\n```swift\n\u002F\u002F List available resources\nlet (resources, nextCursor) = try await client.listResources()\nprint(\"Available resources: \\(resources.map { $0.uri }.joined(separator: \", \"))\")\n\n\u002F\u002F Read a resource\nlet contents = try await client.readResource(uri: \"resource:\u002F\u002Fexample\")\nprint(\"Resource content: \\(contents)\")\n\n\u002F\u002F Subscribe to resource updates if supported\nif result.capabilities.resources?.subscribe == true {\n    try await client.subscribeToResource(uri: \"resource:\u002F\u002Fexample\")\n\n    \u002F\u002F Register notification handler\n    await client.onNotification(ResourceUpdatedNotification.self) { message in\n        let uri = message.params.uri\n        print(\"Resource \\(uri) updated with new content\")\n\n        \u002F\u002F Fetch the updated resource content\n        let updatedContents = try await client.readResource(uri: uri)\n        print(\"Updated resource content received\")\n    }\n}\n```\n\n### Prompts\n\nPrompts represent templated conversation starters:\n\n```swift\n\u002F\u002F List available prompts\nlet (prompts, nextCursor) = try await client.listPrompts()\nprint(\"Available prompts: \\(prompts.map { $0.name }.joined(separator: \", \"))\")\n\n\u002F\u002F Get a prompt with arguments\nlet (description, messages) = try await client.getPrompt(\n    name: \"customer-service\",\n    arguments: [\n        \"customerName\": \"Alice\",\n        \"orderNumber\": \"ORD-12345\",\n        \"issue\": \"delivery delay\"\n    ]\n)\n\n\u002F\u002F Use the prompt messages in your application\nprint(\"Prompt description: \\(description)\")\nfor message in messages {\n    if case .text(text: let text) = message.content {\n        print(\"\\(message.role): \\(text)\")\n    }\n}\n```\n\n### Completions\n\nCompletions allow servers to provide autocompletion suggestions for prompt and resource template arguments as users type:\n\n```swift\n\u002F\u002F Request completions for a prompt argument\nlet completion = try await client.complete(\n    promptName: \"code_review\",\n    argumentName: \"language\",\n    argumentValue: \"py\"\n)\n\n\u002F\u002F Display suggestions to the user\nfor value in completion.values {\n    print(\"Suggestion: \\(value)\")\n}\n\nif completion.hasMore == true {\n    print(\"More suggestions available (total: \\(completion.total ?? 0))\")\n}\n```\n\nYou can also provide context with already-resolved arguments:\n\n```swift\n\u002F\u002F First, user selects a language\nlet languageCompletion = try await client.complete(\n    promptName: \"code_review\",\n    argumentName: \"language\",\n    argumentValue: \"py\"\n)\n\u002F\u002F User selects \"python\"\n\n\u002F\u002F Then get framework suggestions based on the selected language\nlet frameworkCompletion = try await client.complete(\n    promptName: \"code_review\",\n    argumentName: \"framework\",\n    argumentValue: \"fla\",\n    context: [\"language\": .string(\"python\")]\n)\n\u002F\u002F Returns: [\"flask\"]\n```\n\nCompletions work for resource templates as well:\n\n```swift\n\u002F\u002F Get path completions for a resource URI template\nlet pathCompletion = try await client.complete(\n    resourceURI: \"file:\u002F\u002F\u002F{path}\",\n    argumentName: \"path\",\n    argumentValue: \"\u002Fusr\u002F\"\n)\n\u002F\u002F Returns: [\"\u002Fusr\u002Fbin\", \"\u002Fusr\u002Flib\", \"\u002Fusr\u002Flocal\"]\n```\n\n### Sampling\n\nSampling allows servers to request LLM completions through the client, \nenabling agentic behaviors while maintaining human-in-the-loop control. \nClients register a handler to process incoming sampling requests from servers.\n\n> [!TIP]\n> Sampling requests flow from **server to client**, \n> not client to server. \n> This enables servers to request AI assistance \n> while clients maintain control over model access and user approval.\n\n```swift\n\u002F\u002F Register a sampling handler in the client\nawait client.withSamplingHandler { parameters in\n    \u002F\u002F Review the sampling request (human-in-the-loop step 1)\n    print(\"Server requests completion for: \\(parameters.messages)\")\n    \n    \u002F\u002F Optionally modify the request based on user input\n    var messages = parameters.messages\n    if let systemPrompt = parameters.systemPrompt {\n        print(\"System prompt: \\(systemPrompt)\")\n    }\n    \n    \u002F\u002F Sample from your LLM (this is where you'd call your AI service)\n    let completion = try await callYourLLMService(\n        messages: messages,\n        maxTokens: parameters.maxTokens,\n        temperature: parameters.temperature\n    )\n    \n    \u002F\u002F Review the completion (human-in-the-loop step 2)\n    print(\"LLM generated: \\(completion)\")\n    \u002F\u002F User can approve, modify, or reject the completion here\n    \n    \u002F\u002F Return the result to the server\n    return CreateSamplingMessage.Result(\n        model: \"your-model-name\",\n        stopReason: .endTurn,\n        role: .assistant,\n        content: .text(completion)\n    )\n}\n```\n\n### Elicitation\n\nElicitation allows servers to request structured information directly from users through the client. \nThis is useful when servers need user input that wasn't provided in the original request, \nsuch as credentials, configuration choices, or approval for sensitive operations.\n\n> [!TIP]\n> Elicitation requests flow from **server to client**, \n> similar to sampling. \n> Clients must register a handler to respond to elicitation requests from servers.\n\n#### Client-Side: Handling Elicitation Requests\n\nRegister an elicitation handler to respond to server requests:\n\n```swift\n\u002F\u002F Register an elicitation handler in the client\nawait client.withElicitationHandler { parameters in\n    switch parameters {\n    case .form(let form):\n        \u002F\u002F Display the request to the user\n        print(\"Server requests: \\(form.message)\")\n\n        \u002F\u002F If a schema was provided, inspect it\n        if let schema = form.requestedSchema {\n            print(\"Required fields: \\(schema.required ?? [])\")\n            print(\"Schema: \\(schema.properties)\")\n        }\n\n        \u002F\u002F Present UI to collect user input\n        let userResponse = presentElicitationUI(form)\n\n        \u002F\u002F Return the user's response\n        if userResponse.accepted {\n            return CreateElicitation.Result(\n                action: .accept,\n                content: userResponse.data\n            )\n        } else if userResponse.canceled {\n            return CreateElicitation.Result(action: .cancel)\n        } else {\n            return CreateElicitation.Result(action: .decline)\n        }\n\n    case .url(let url):\n        \u002F\u002F Direct the user to an external URL (e.g., for OAuth)\n        openURL(url.url)\n        return CreateElicitation.Result(action: .accept)\n    }\n}\n```\n\nCommon use cases for elicitation:\n\n- **Authentication**: Request credentials when needed rather than upfront\n- **Confirmation**: Ask for user approval before sensitive operations\n- **Configuration**: Collect preferences or settings during operation\n- **Missing information**: Request additional details not provided initially\n\n### Roots\n\nRoots define the filesystem boundaries that a client exposes to servers. Servers discover roots by sending a `roots\u002Flist` request to the client; clients notify servers when the list changes.\n\n> [!TIP]\n> To use roots, declare the `roots` capability when creating the client.\n\n```swift\nlet client = Client(\n    name: \"MyApp\",\n    version: \"1.0.0\",\n    capabilities: .init(\n        roots: .init(listChanged: true)\n    )\n)\n\n\u002F\u002F Register a handler for roots\u002Flist requests from servers\nawait client.withRootsHandler {\n    return [\n        Root(uri: \"file:\u002F\u002F\u002FUsers\u002Fuser\u002Fprojects\", name: \"Projects\"),\n        Root(uri: \"file:\u002F\u002F\u002FUsers\u002Fuser\u002Fdocuments\", name: \"Documents\")\n    ]\n}\n\n\u002F\u002F Notify connected servers whenever roots change\ntry await client.notifyRootsChanged()\n```\n\n### Logging\n\nClients can control server logging levels and receive structured log messages:\n\n```swift\n\u002F\u002F Set the minimum logging level\ntry await client.setLoggingLevel(.warning)\n\n\u002F\u002F Register a handler for log messages from the server\nawait client.onNotification(LogMessageNotification.self) { message in\n    let level = message.params.level        \u002F\u002F LogLevel (debug, info, warning, etc.)\n    let logger = message.params.logger      \u002F\u002F Optional logger name\n    let data = message.params.data          \u002F\u002F Arbitrary JSON data\n\n    \u002F\u002F Display log message based on level\n    switch level {\n    case .error, .critical, .alert, .emergency:\n        print(\"❌ [\\(logger ?? \"server\")] \\(data)\")\n    case .warning:\n        print(\"⚠️ [\\(logger ?? \"server\")] \\(data)\")\n    default:\n        print(\"ℹ️ [\\(logger ?? \"server\")] \\(data)\")\n    }\n}\n```\n\nLog levels follow the standard syslog severity levels (RFC 5424):\n\n- **debug**: Detailed debugging information\n- **info**: General informational messages\n- **notice**: Normal but significant events\n- **warning**: Warning conditions\n- **error**: Error conditions\n- **critical**: Critical conditions\n- **alert**: Action must be taken immediately\n- **emergency**: System is unusable\n\n### Error Handling\n\nHandle common client errors:\n\n```swift\ndo {\n    try await client.connect(transport: transport)\n    \u002F\u002F Success\n} catch let error as MCPError {\n    print(\"MCP Error: \\(error.localizedDescription)\")\n} catch {\n    print(\"Unexpected error: \\(error)\")\n}\n```\n\n### Cancellation\n\nEither side can cancel an in-progress request and handle incoming cancellations gracefully:\n\n#### Option 1: Convenience Methods with RequestContext Overload\n\nFor common operations like tool calls, use the overloaded method that returns `RequestContext`:\n\n```swift\n\u002F\u002F Call a tool and get a context for cancellation\nlet context = try client.callTool(\n    name: \"long-running-analysis\",\n    arguments: [\"data\": largeDataset]\n)\n\n\u002F\u002F You can cancel the request at any time\ntry await client.cancelRequest(context.requestID, reason: \"User cancelled\")\n\n\u002F\u002F Await the result (will throw CancellationError if cancelled)\ndo {\n    let result = try await context.value\n    print(\"Result: \\(result.content)\")\n} catch is CancellationError {\n    print(\"Request was cancelled\")\n}\n```\n\n#### Option 2: Direct send() for Maximum Flexibility\n\nFor full control or custom requests, use `send()` directly:\n\n```swift\n\u002F\u002F Create any request type\nlet request = CallTool.request(.init(\n    name: \"long-running-analysis\",\n    arguments: [\"data\": largeDataset]\n))\n\n\u002F\u002F Send and get a context for cancellation tracking\nlet context: RequestContext\u003CCallTool.Result> = try client.send(request)\n\n\u002F\u002F Cancel when needed\ntry await client.cancelRequest(context.requestID, reason: \"Timeout\")\n\n\u002F\u002F Get the result\nlet result = try await context.value\nlet content = result.content\nlet isError = result.isError\n```\n\n### Progress tracking\n\nClients can attach a progress token to a request and receive incremental progress updates for long-running operations:\n\n```swift\n\u002F\u002F Call a tool with progress tracking\nlet progressToken = ProgressToken.unique()\n\n\u002F\u002F Register a notification handler to receive progress updates\nawait client.onNotification(ProgressNotification.self) { message in\n    let params = message.params\n    \u002F\u002F Filter by your progress token\n    if params.progressToken == progressToken {\n        print(\"Progress: \\(params.progress)\u002F\\(params.total ?? 0)\")\n        if let message = params.message {\n            print(\"Status: \\(message)\")\n        }\n    }\n}\n\n\u002F\u002F Make the request with the progress token\nlet (content, isError) = try await client.callTool(\n    name: \"long-running-tool\",\n    arguments: [\"input\": \"value\"],\n    meta: Metadata(progressToken: progressToken)\n)\n```\n\n### Advanced Client Features\n\n#### Strict vs Non-Strict Configuration\n\nConfigure client behavior for capability checking:\n\n```swift\n\u002F\u002F Strict configuration - fail fast if a capability is missing\nlet strictClient = Client(\n    name: \"StrictClient\",\n    version: \"1.0.0\",\n    configuration: .strict\n)\n\n\u002F\u002F With strict configuration, calling a method for an unsupported capability\n\u002F\u002F will throw an error immediately without sending a request\ndo {\n    \u002F\u002F This will throw an error if resources.list capability is not available\n    let resources = try await strictClient.listResources()\n} catch let error as MCPError {\n    print(\"Capability not available: \\(error.localizedDescription)\")\n}\n\n\u002F\u002F Default (non-strict) configuration - attempt the request anyway\nlet client = Client(\n    name: \"FlexibleClient\",\n    version: \"1.0.0\",\n    configuration: .default\n)\n\n\u002F\u002F With default configuration, the client will attempt the request\n\u002F\u002F even if the capability wasn't advertised by the server\ndo {\n    let resources = try await client.listResources()\n} catch let error as MCPError {\n    \u002F\u002F Still handle the error if the server rejects the request\n    print(\"Server rejected request: \\(error.localizedDescription)\")\n}\n```\n\n#### Request Batching\n\nImprove performance by sending multiple requests in a single batch:\n\n```swift\n\u002F\u002F Array to hold tool call tasks\nvar toolTasks: [Task\u003CCallTool.Result, Swift.Error>] = []\n\n\u002F\u002F Send a batch of requests\ntry await client.withBatch { batch in\n    \u002F\u002F Add multiple tool calls to the batch\n    for i in 0..\u003C10 {\n        toolTasks.append(\n            try await batch.addRequest(\n                CallTool.request(.init(name: \"square\", arguments: [\"n\": Value(i)]))\n            )\n        )\n    }\n}\n\n\u002F\u002F Process results after the batch is sent\nprint(\"Processing \\(toolTasks.count) tool results...\")\nfor (index, task) in toolTasks.enumerated() {\n    do {\n        let result = try await task.value\n        print(\"\\(index): \\(result.content)\")\n    } catch {\n        print(\"\\(index) failed: \\(error)\")\n    }\n}\n```\n\nYou can also batch different types of requests:\n\n```swift\n\u002F\u002F Declare task variables\nvar pingTask: Task\u003CPing.Result, Error>?\nvar promptTask: Task\u003CGetPrompt.Result, Error>?\n\n\u002F\u002F Send a batch with different request types\ntry await client.withBatch { batch in\n    pingTask = try await batch.addRequest(Ping.request())\n    promptTask = try await batch.addRequest(\n        GetPrompt.request(.init(name: \"greeting\"))\n    )\n}\n\n\u002F\u002F Process individual results\ndo {\n    if let pingTask = pingTask {\n        try await pingTask.value\n        print(\"Ping successful\")\n    }\n\n    if let promptTask = promptTask {\n        let promptResult = try await promptTask.value\n        print(\"Prompt: \\(promptResult.description ?? \"None\")\")\n    }\n} catch {\n    print(\"Error processing batch results: \\(error)\")\n}\n```\n\n> [!NOTE]\n> `Server` automatically handles batch requests from MCP clients.\n\n## Server Usage\n\nThe server component allows your application to host model capabilities and respond to client requests.\n\n### Basic Server Setup\n\n```swift\nimport MCP\n\n\u002F\u002F Create a server with given capabilities\nlet server = Server(\n    name: \"MyModelServer\",\n    version: \"1.0.0\",\n    capabilities: .init(\n        completions: .init(),\n        logging: .init(),\n        prompts: .init(listChanged: true),\n        resources: .init(subscribe: true, listChanged: true),\n        tools: .init(listChanged: true)\n    )\n)\n\n\u002F\u002F Create transport and start server\nlet transport = StdioTransport()\ntry await server.start(transport: transport)\n\n\u002F\u002F Now register handlers for the capabilities you've enabled\n```\n\n### Tools\n\nRegister tool handlers to respond to client tool calls:\n\n```swift\n\u002F\u002F Register a tool list handler\nawait server.withMethodHandler(ListTools.self) { _ in\n    let tools = [\n        Tool(\n            name: \"weather\",\n            description: \"Get current weather for a location\",\n            inputSchema: .object([\n                \"properties\": .object([\n                    \"location\": .string(\"City name or coordinates\"),\n                    \"units\": .string(\"Units of measurement, e.g., metric, imperial\")\n                ])\n            ])\n        ),\n        Tool(\n            name: \"calculator\",\n            description: \"Perform calculations\",\n            inputSchema: .object([\n                \"properties\": .object([\n                    \"expression\": .string(\"Mathematical expression to evaluate\")\n                ])\n            ])\n        )\n    ]\n    return .init(tools: tools)\n}\n\n\u002F\u002F Register a tool call handler\nawait server.withMethodHandler(CallTool.self) { params in\n    switch params.name {\n    case \"weather\":\n        let location = params.arguments?[\"location\"]?.stringValue ?? \"Unknown\"\n        let units = params.arguments?[\"units\"]?.stringValue ?? \"metric\"\n        let weatherData = getWeatherData(location: location, units: units) \u002F\u002F Your implementation\n        return .init(\n            content: [.text(\"Weather for \\(location): \\(weatherData.temperature)°, \\(weatherData.conditions)\")],\n            isError: false\n        )\n\n    case \"calculator\":\n        if let expression = params.arguments?[\"expression\"]?.stringValue {\n            let result = evaluateExpression(expression) \u002F\u002F Your implementation\n            return .init(content: [.text(\"\\(result)\")], isError: false)\n        } else {\n            return .init(content: [.text(\"Missing expression parameter\")], isError: true)\n        }\n\n    default:\n        return .init(content: [.text(\"Unknown tool\")], isError: true)\n    }\n}\n```\n\n### Resources\n\nImplement resource handlers for data access:\n\n```swift\n\u002F\u002F Register a resource list handler\nawait server.withMethodHandler(ListResources.self) { params in\n    let resources = [\n        Resource(\n            name: \"Knowledge Base Articles\",\n            uri: \"resource:\u002F\u002Fknowledge-base\u002Farticles\",\n            description: \"Collection of support articles and documentation\"\n        ),\n        Resource(\n            name: \"System Status\",\n            uri: \"resource:\u002F\u002Fsystem\u002Fstatus\",\n            description: \"Current system operational status\"\n        )\n    ]\n    return .init(resources: resources, nextCursor: nil)\n}\n\n\u002F\u002F Register a resource read handler\nawait server.withMethodHandler(ReadResource.self) { params in\n    switch params.uri {\n    case \"resource:\u002F\u002Fknowledge-base\u002Farticles\":\n        return .init(contents: [Resource.Content.text(\"# Knowledge Base\\n\\nThis is the content of the knowledge base...\", uri: params.uri)])\n\n    case \"resource:\u002F\u002Fsystem\u002Fstatus\":\n        let status = getCurrentSystemStatus() \u002F\u002F Your implementation\n        let statusJson = \"\"\"\n            {\n                \"status\": \"\\(status.overall)\",\n                \"components\": {\n                    \"database\": \"\\(status.database)\",\n                    \"api\": \"\\(status.api)\",\n                    \"model\": \"\\(status.model)\"\n                },\n                \"lastUpdated\": \"\\(status.timestamp)\"\n            }\n            \"\"\"\n        return .init(contents: [Resource.Content.text(statusJson, uri: params.uri, mimeType: \"application\u002Fjson\")])\n\n    default:\n        throw MCPError.invalidParams(\"Unknown resource URI: \\(params.uri)\")\n    }\n}\n\n\u002F\u002F Register a resource subscribe handler\nawait server.withMethodHandler(ResourceSubscribe.self) { params in\n    \u002F\u002F Store subscription for later notifications.\n    \u002F\u002F Client identity for multi-client scenarios needs to be managed by the server application,\n    \u002F\u002F potentially using information from the initialize handshake if the server handles one client post-init.\n    \u002F\u002F addSubscription(clientID: \u002F* some_client_identifier *\u002F, uri: params.uri)\n    print(\"Client subscribed to \\(params.uri). Server needs to implement logic to track this subscription.\")\n    return .init()\n}\n```\n\n### Prompts\n\nImplement prompt handlers:\n\n```swift\n\u002F\u002F Register a prompt list handler\nawait server.withMethodHandler(ListPrompts.self) { params in\n    let prompts = [\n        Prompt(\n            name: \"interview\",\n            description: \"Job interview conversation starter\",\n            arguments: [\n                .init(name: \"position\", description: \"Job position\", required: true),\n                .init(name: \"company\", description: \"Company name\", required: true),\n                .init(name: \"interviewee\", description: \"Candidate name\")\n            ]\n        ),\n        Prompt(\n            name: \"customer-support\",\n            description: \"Customer support conversation starter\",\n            arguments: [\n                .init(name: \"issue\", description: \"Customer issue\", required: true),\n                .init(name: \"product\", description: \"Product name\", required: true)\n            ]\n        )\n    ]\n    return .init(prompts: prompts, nextCursor: nil)\n}\n\n\u002F\u002F Register a prompt get handler\nawait server.withMethodHandler(GetPrompt.self) { params in\n    switch params.name {\n    case \"interview\":\n        let position = params.arguments?[\"position\"]?.stringValue ?? \"Software Engineer\"\n        let company = params.arguments?[\"company\"]?.stringValue ?? \"Acme Corp\"\n        let interviewee = params.arguments?[\"interviewee\"]?.stringValue ?? \"Candidate\"\n\n        let description = \"Job interview for \\(position) position at \\(company)\"\n        let messages: [Prompt.Message] = [\n            .user(.text(text: \"You are an interviewer for the \\(position) position at \\(company).\")),\n            .user(.text(text: \"Hello, I'm \\(interviewee) and I'm here for the \\(position) interview.\")),\n            .assistant(.text(text: \"Hi \\(interviewee), welcome to \\(company)! I'd like to start by asking about your background and experience.\"))\n        ]\n\n        return .init(description: description, messages: messages)\n\n    case \"customer-support\":\n        \u002F\u002F Similar implementation for customer support prompt\n\n    default:\n        throw MCPError.invalidParams(\"Unknown prompt name: \\(params.name)\")\n    }\n}\n```\n\n### Completions\n\nServers can provide autocompletion suggestions for prompt and resource template arguments:\n\n```swift\n\u002F\u002F Enable completions capability\nlet server = Server(\n    name: \"MyServer\",\n    version: \"1.0.0\",\n    capabilities: .init(\n        completions: .init(),\n        prompts: .init(listChanged: true)\n    )\n)\n\n\u002F\u002F Register a completion handler\nawait server.withMethodHandler(Complete.self) { params in\n    \u002F\u002F Get the argument being completed\n    let argumentName = params.argument.name\n    let currentValue = params.argument.value\n\n    \u002F\u002F Check which prompt or resource is being completed\n    switch params.ref {\n    case .prompt(let promptRef):\n        \u002F\u002F Provide completions for a prompt argument\n        if promptRef.name == \"code_review\" && argumentName == \"language\" {\n            \u002F\u002F Simple prefix matching\n            let allLanguages = [\"python\", \"perl\", \"php\", \"javascript\", \"java\", \"swift\"]\n            let matches = allLanguages.filter { $0.hasPrefix(currentValue.lowercased()) }\n\n            return .init(\n                completion: .init(\n                    values: Array(matches.prefix(100)),  \u002F\u002F Max 100 items\n                    total: matches.count,\n                    hasMore: matches.count > 100\n                )\n            )\n        }\n\n    case .resource(let resourceRef):\n        \u002F\u002F Provide completions for a resource template argument\n        if resourceRef.uri == \"file:\u002F\u002F\u002F{path}\" && argumentName == \"path\" {\n            \u002F\u002F Return directory suggestions\n            let suggestions = try getDirectoryCompletions(for: currentValue)\n            return .init(\n                completion: .init(\n                    values: suggestions,\n                    total: suggestions.count,\n                    hasMore: false\n                )\n            )\n        }\n    }\n\n    \u002F\u002F No completions available\n    return .init(completion: .init(values: [], total: 0, hasMore: false))\n}\n```\n\nYou can also use context from already-resolved arguments:\n\n```swift\nawait server.withMethodHandler(Complete.self) { params in\n    \u002F\u002F Access context from previous argument completions\n    if let context = params.context,\n       let language = context.arguments[\"language\"]?.stringValue {\n\n        \u002F\u002F Provide framework suggestions based on selected language\n        if language == \"python\" {\n            let frameworks = [\"flask\", \"django\", \"fastapi\", \"tornado\"]\n            let matches = frameworks.filter {\n                $0.hasPrefix(params.argument.value.lowercased())\n            }\n            return .init(\n                completion: .init(values: matches, total: matches.count, hasMore: false)\n            )\n        }\n    }\n\n    return .init(completion: .init(values: [], total: 0, hasMore: false))\n}\n```\n\n### Sampling\n\nServers can request LLM completions from clients through sampling. This enables agentic behaviors where servers can ask for AI assistance while maintaining human oversight.\n\n```swift\n\u002F\u002F Enable sampling capability in server\nlet server = Server(\n    name: \"MyModelServer\",\n    version: \"1.0.0\",\n    capabilities: .init(\n        sampling: .init(),  \u002F\u002F Enable sampling capability\n        tools: .init(listChanged: true)\n    )\n)\n\n\u002F\u002F Request sampling from the connected client\ndo {\n    let result = try await server.requestSampling(\n        messages: [\n            .user(\"Analyze this data and suggest next steps\")\n        ],\n        systemPrompt: \"You are a helpful data analyst\",\n        temperature: 0.7,\n        maxTokens: 150\n    )\n    \n    \u002F\u002F Use the LLM completion in your server logic\n    print(\"LLM suggested: \\(result.content)\")\n    \n} catch {\n    print(\"Sampling request failed: \\(error)\")\n}\n```\n\nSampling enables powerful agentic workflows:\n\n- **Decision-making**: Ask the LLM to choose between options\n- **Content generation**: Request drafts for user approval\n- **Data analysis**: Get AI insights on complex data\n- **Multi-step reasoning**: Chain AI completions with tool calls\n\n### Elicitations\n\nServers can request information from users through elicitation:\n\n```swift\n\u002F\u002F Ask the user to provide some additional information\nlet schema = Elicitation.RequestSchema(\n    title: \"Additional Information Required\",\n    description: \"Please provide the following details to continue\",\n    properties: [\n        \"name\": .object([\n            \"type\": .string(\"string\"),\n            \"description\": .string(\"Your full name\")\n        ]),\n        \"confirmed\": .object([\n            \"type\": .string(\"boolean\"),\n            \"description\": .string(\"Do you confirm the provided information?\")\n        ])\n    ],\n    required: [\"name\", \"confirmed\"]\n)\n\nlet result = try await server.requestElicitation(\n    message: \"Some details are needed before proceeding\",\n    requestedSchema: schema\n)\n\nswitch result.action {\ncase .accept:\n    if let content = result.content {\n        let name = content[\"name\"]?.stringValue\n        let confirmed = content[\"confirmed\"]?.boolValue\n        \u002F\u002F Use the collected data...\n    }\ncase .decline:\n    throw MCPError.invalidRequest(\"User declined to provide information\")\ncase .cancel:\n    throw MCPError.invalidRequest(\"Operation canceled by user\")\n}\n```\n\nFor URL-based elicitation (e.g., OAuth flows), use the URL overload:\n\n```swift\nlet result = try await server.requestElicitation(\n    message: \"Please sign in to continue\",\n    url: \"https:\u002F\u002Fexample.com\u002Foauth\u002Fauthorize?client_id=...\",\n    elicitationId: UUID().uuidString\n)\n```\n\n### Roots\n\nServers can request the list of filesystem roots that the client has exposed:\n\n```swift\n\u002F\u002F Request roots from the connected client\n\u002F\u002F (requires the client to declare the roots capability)\nlet roots = try await server.listRoots()\nfor root in roots {\n    print(\"Root: \\(root.name ?? root.uri) at \\(root.uri)\")\n}\n\n\u002F\u002F React to root list changes\nawait server.onNotification(RootsListChangedNotification.self) { _ in\n    let updatedRoots = try await server.listRoots()\n    print(\"Roots updated: \\(updatedRoots.map { $0.uri })\")\n}\n```\n\n### Logging\n\nServers can send structured log messages to clients:\n\n```swift\n\u002F\u002F Enable logging capability\nlet server = Server(\n    name: \"MyServer\",\n    version: \"1.0.0\",\n    capabilities: .init(\n        logging: .init(),\n        tools: .init(listChanged: true)\n    )\n)\n\n\u002F\u002F Send log messages at different severity levels\ntry await server.log(\n    level: .info,\n    logger: \"database\",\n    data: Value.object([\n        \"message\": .string(\"Database connected successfully\"),\n        \"host\": .string(\"localhost\"),\n        \"port\": .int(5432)\n    ])\n)\n\ntry await server.log(\n    level: .error,\n    logger: \"api\",\n    data: Value.object([\n        \"message\": .string(\"Request failed\"),\n        \"statusCode\": .int(500),\n        \"error\": .string(\"Internal server error\")\n    ])\n)\n\n\u002F\u002F You can also use codable types directly\nstruct ErrorLog: Codable {\n    let message: String\n    let code: Int\n    let timestamp: String\n}\n\nlet errorLog = ErrorLog(\n    message: \"Operation failed\",\n    code: 500,\n    timestamp: ISO8601DateFormatter().string(from: Date())\n)\n\ntry await server.log(level: .error, logger: \"operations\", data: errorLog)\n```\n\nClients can control which log levels they receive:\n\n```swift\n\u002F\u002F Register a handler for client's logging level preferences\nawait server.withMethodHandler(SetLoggingLevel.self) { params in\n    let minimumLevel = params.level\n\n    \u002F\u002F Store the client's preference and filter log messages accordingly\n    \u002F\u002F (Implementation depends on your server architecture)\n    storeLogLevel(minimumLevel)\n\n    return Empty()\n}\n```\n\n### Progress Tracking\n\nServers can send incremental progress notifications during long-running tool calls by reading the `progressToken` from the request metadata and sending `ProgressNotification` messages:\n\n```swift\nawait server.withMethodHandler(CallTool.self) { params in\n    \u002F\u002F Read the progress token from request metadata\n    guard let token = params._meta?.progressToken else {\n        \u002F\u002F No progress token provided — run without reporting progress\n        return .init(content: [.text(\"Done\")], isError: false)\n    }\n\n    \u002F\u002F Report initial progress\n    let started = ProgressNotification.message(\n        .init(progressToken: token, progress: 0, total: 100)\n    )\n    try await server.notify(started)\n\n    \u002F\u002F ... do work ...\n\n    \u002F\u002F Report intermediate progress\n    let halfway = ProgressNotification.message(\n        .init(progressToken: token, progress: 50, total: 100, message: \"Halfway there\")\n    )\n    try await server.notify(halfway)\n\n    \u002F\u002F ... do more work ...\n\n    \u002F\u002F Report completion\n    let done = ProgressNotification.message(\n        .init(progressToken: token, progress: 100, total: 100, message: \"Complete\")\n    )\n    try await server.notify(done)\n\n    return .init(content: [.text(\"Done\")], isError: false)\n}\n```\n\n#### Initialize Hook\n\nControl client connections with an initialize hook:\n\n```swift\n\u002F\u002F Start the server with an initialize hook\ntry await server.start(transport: transport) { clientInfo, clientCapabilities in\n    \u002F\u002F Validate client info\n    guard clientInfo.name != \"BlockedClient\" else {\n        throw MCPError.invalidRequest(\"This client is not allowed\")\n    }\n\n    \u002F\u002F You can also inspect client capabilities\n    if clientCapabilities.sampling == nil {\n        print(\"Client does not support sampling\")\n    }\n\n    \u002F\u002F Perform any server-side setup based on client info\n    print(\"Client \\(clientInfo.name) v\\(clientInfo.version) connected\")\n\n    \u002F\u002F If the hook completes without throwing, initialization succeeds\n}\n```\n\n### HTTP Request Context in Handlers\n\nWhen a server is connected over `StatefulHTTPServerTransport` or `StatelessHTTPServerTransport`,\nmethod handlers can observe the originating HTTP request (headers, body, path, method) via\n`Server.currentHandlerContext` — a task-local set automatically before each handler runs:\n\n```swift\nawait server.withMethodHandler(CallTool.self) { params in\n    let httpRequest = Server.currentHandlerContext?.httpContext\n    let authHeader = httpRequest?.headers[\"Authorization\"]\n    \u002F\u002F …use the header to scope the response, audit, etc.\n    return .init(content: [.text(\"ok\")], isError: false)\n}\n```\n\n`httpContext` is `nil` for transports that don't carry HTTP context (e.g. `StdioTransport`,\n`InMemoryTransport`) and for handlers reached off the dispatch path.\n\nTask-locals are not inherited by `Task.detached`. If you spawn a detached task from a handler,\ncapture the context up front:\n\n```swift\nlet ctx = Server.currentHandlerContext\nTask.detached { await doWork(with: ctx?.httpContext) }\n```\n\nCustom HTTP transports can opt in by conforming to `HTTPContextProviding` and returning the\n`HTTPRequest` for a given JSON-RPC id while it is in flight.\n\n### Graceful Shutdown\n\nWe recommend using\n[Swift Service Lifecycle](https:\u002F\u002Fgithub.com\u002Fswift-server\u002Fswift-service-lifecycle)\nfor managing startup and shutdown of services.\n\nFirst, add the dependency to your `Package.swift`:\n\n```swift\n.package(url: \"https:\u002F\u002Fgithub.com\u002Fswift-server\u002Fswift-service-lifecycle.git\", from: \"2.3.0\"),\n```\n\nThen implement the MCP server as a `Service`:\n\n```swift\nimport MCP\nimport ServiceLifecycle\nimport Logging\n\nstruct MCPService: Service {\n    let server: Server\n    let transport: Transport\n\n    init(server: Server, transport: Transport) {\n        self.server = server\n        self.transport = transport\n    }\n\n    func run() async throws {\n        \u002F\u002F Start the server\n        try await server.start(transport: transport)\n\n        \u002F\u002F Keep running until external cancellation\n        try await Task.sleep(for: .days(365 * 100))  \u002F\u002F Effectively forever\n    }\n\n    func shutdown() async throws {\n        \u002F\u002F Gracefully shutdown the server\n        await server.stop()\n    }\n}\n```\n\nThen use it in your application:\n\n```swift\nimport MCP\nimport ServiceLifecycle\nimport Logging\n\nlet logger = Logger(label: \"com.example.mcp-server\")\n\n\u002F\u002F Create the MCP server\nlet server = Server(\n    name: \"MyModelServer\",\n    version: \"1.0.0\",\n    capabilities: .init(\n        prompts: .init(listChanged: true),\n        resources: .init(subscribe: true, listChanged: true),\n        tools: .init(listChanged: true)\n    )\n)\n\n\u002F\u002F Add handlers directly to the server\nawait server.withMethodHandler(ListTools.self) { _ in\n    \u002F\u002F Your implementation\n    return .init(tools: [\n        Tool(name: \"example\", description: \"An example tool\")\n    ])\n}\n\nawait server.withMethodHandler(CallTool.self) { params in\n    \u002F\u002F Your implementation\n    return .init(content: [.text(\"Tool result\")], isError: false)\n}\n\n\u002F\u002F Create MCP service and other services\nlet transport = StdioTransport(logger: logger)\nlet mcpService = MCPService(server: server, transport: transport)\nlet databaseService = DatabaseService() \u002F\u002F Your other services\n\n\u002F\u002F Create service group with signal handling\nlet serviceGroup = ServiceGroup(\n    services: [mcpService, databaseService],\n    configuration: .init(\n        gracefulShutdownSignals: [.sigterm, .sigint]\n    ),\n    logger: logger\n)\n\n\u002F\u002F Run the service group - this blocks until shutdown\ntry await serviceGroup.run()\n```\n\nThis approach has several benefits:\n\n- **Signal handling**:\nAutomatically traps SIGINT, SIGTERM and triggers graceful shutdown\n- **Graceful shutdown**:\nProperly shuts down your MCP server and other services\n- **Timeout-based shutdown**:\nConfigurable shutdown timeouts to prevent hanging processes\n- **Advanced service management**:\n`[ServiceLifecycle](https:\u002F\u002Fswiftpackageindex.com\u002Fswift-server\u002Fswift-service-lifecycle\u002Fdocumentation\u002Fservicelifecycle)`\nalso supports service dependencies, conditional services,\nand other useful features.\n\n## Transports\n\nMCP's transport layer handles communication between clients and servers.\nThe Swift SDK provides multiple built-in transports:\n\n\n| Transport | Description | Platforms | Best for |\n| --------- | ----------- | --------- | -------- |\n| [`StdioTransport`](\u002FSources\u002FMCP\u002FBase\u002FTransports\u002FStdioTransport.swift) | Implements [stdio transport](https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2025-06-18\u002Fbasic\u002Ftransports#stdio) using standard input\u002Foutput streams | Apple platforms, Linux with glibc | Local subprocesses, CLI tools |\n| [`HTTPClientTransport`](\u002FSources\u002FMCP\u002FBase\u002FTransports\u002FHTTPClientTransport.swift) | Implements [Streamable HTTP transport](https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2025-06-18\u002Fbasic\u002Ftransports#streamable-http) using Foundation's URL Loading System | All platforms with Foundation | Remote servers, web applications |\n| [`StatelessHTTPServerTransport`](\u002FSources\u002FMCP\u002FBase\u002FTransports\u002FHTTPServer\u002FStatelessHTTPServerTransport.swift) | HTTP server transport with simple request-response semantics; no session management or SSE streaming | All platforms with Foundation | Simple HTTP servers, serverless\u002Fedge functions |\n| [`StatefulHTTPServerTransport`](\u002FSources\u002FMCP\u002FBase\u002FTransports\u002FHTTPServer\u002FStatefulHTTPServerTransport.swift) | HTTP server transport with full session management and SSE streaming for server-initiated messages | All platforms with Foundation | Full-featured HTTP servers, streaming notifications |\n| [`InMemoryTransport`](\u002FSources\u002FMCP\u002FBase\u002FTransports\u002FInMemoryTransport.swift) | Custom in-memory transport for direct communication within the same process | All platforms | Testing, debugging, same-process client-server communication |\n| [`NetworkTransport`](\u002FSources\u002FMCP\u002FBase\u002FTransports\u002FNetworkTransport.swift) | Custom transport using Apple's Network framework for TCP\u002FUDP connections | Apple platforms only | Low-level networking, custom protocols |\n\n\n### Custom Transport Implementation\n\nYou can implement a custom transport by conforming to the `Transport` protocol:\n\n```swift\nimport MCP\nimport Foundation\n\npublic actor MyCustomTransport: Transport {\n    public nonisolated let logger: Logger\n    private var isConnected = false\n    private let messageStream: AsyncThrowingStream\u003CData, any Swift.Error>\n    private let messageContinuation: AsyncThrowingStream\u003CData, any Swift.Error>.Continuation\n\n    public init(logger: Logger? = nil) {\n        self.logger = logger ?? Logger(label: \"my.custom.transport\")\n\n        var continuation: AsyncThrowingStream\u003CData, any Swift.Error>.Continuation!\n        self.messageStream = AsyncThrowingStream { continuation = $0 }\n        self.messageContinuation = continuation\n    }\n\n    public func connect() async throws {\n        \u002F\u002F Implement your connection logic\n        isConnected = true\n    }\n\n    public func disconnect() async {\n        \u002F\u002F Implement your disconnection logic\n        isConnected = false\n        messageContinuation.finish()\n    }\n\n    public func send(_ data: Data) async throws {\n        \u002F\u002F Implement your message sending logic\n    }\n\n    public func receive() -> AsyncThrowingStream\u003CData, any Swift.Error> {\n        return messageStream\n    }\n}\n```\n\n## Authentication\n\n`HTTPClientTransport` supports OAuth 2.1 Bearer token authorization per the\n[MCP authorization specification](https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2025-11-25\u002Fbasic\u002Fauthorization).\nWhen a server returns `401 Unauthorized` or `403 Forbidden`, the transport automatically:\n\n1. Discovers Protected Resource Metadata (RFC 9728) at `\u002F.well-known\u002Foauth-protected-resource`\n2. Discovers Authorization Server Metadata (RFC 8414 \u002F OIDC Discovery 1.0)\n3. Registers the client dynamically (RFC 7591) if needed\n4. Acquires a Bearer token using the configured grant flow (PKCE enforced)\n5. Retries the original request with the token attached\n\nAuthorization is opt-in and disabled by default.\nPass an `OAuthAuthorizer` to `HTTPClientTransport(authorizer:)` to enable it.\n\n### Client: Client Credentials Flow\n\nMachine-to-machine authentication using a pre-shared client secret:\n\n```swift\nlet config = OAuthConfiguration(\n    grantType: .clientCredentials,\n    authentication: .clientSecretBasic(clientID: \"my-app\", clientSecret: \"s3cr3t\")\n)\nlet authorizer = OAuthAuthorizer(configuration: config)\nlet transport = HTTPClientTransport(\n    endpoint: URL(string: \"https:\u002F\u002Fapi.example.com\u002Fmcp\")!,\n    authorizer: authorizer\n)\nlet client = Client(name: \"MyClient\", version: \"1.0.0\")\ntry await client.connect(transport: transport)\n```\n\n### Client: Authorization Code Flow\n\nInteractive, browser-based authentication with PKCE.\nImplement `OAuthAuthorizationDelegate` to open the authorization URL and capture the redirect:\n\n```swift\nstruct MyAuthDelegate: OAuthAuthorizationDelegate {\n    func presentAuthorizationURL(_ url: URL) async throws -> URL {\n        \u002F\u002F Open the URL in a browser\u002Fwebview and wait for the callback redirect URI.\n        \u002F\u002F The returned URL must include the authorization code and state parameters.\n        return try await openBrowserAndWaitForCallback(url)\n    }\n}\n\nlet config = OAuthConfiguration(\n    grantType: .authorizationCode,\n    authentication: .none(clientID: \"my-app\"),\n    authorizationDelegate: MyAuthDelegate()\n)\nlet authorizer = OAuthAuthorizer(configuration: config)\nlet transport = HTTPClientTransport(\n    endpoint: URL(string: \"https:\u002F\u002Fapi.example.com\u002Fmcp\")!,\n    authorizer: authorizer\n)\n```\n\n### Client: Custom Token Provider\n\nSupply an externally acquired token (e.g., from a system credential store) via `accessTokenProvider`.\nThe SDK calls this closure after discovery completes. Return `nil` to fall back to the configured grant flow:\n\n```swift\nlet config = OAuthConfiguration(\n    grantType: .clientCredentials,\n    authentication: .none(clientID: \"my-app\"),\n    accessTokenProvider: { context, session in\n        \u002F\u002F context contains the discovered resource URI, token endpoint, scopes, etc.\n        return try await KeychainTokenStore.shared.loadToken(for: context.resource)\n    }\n)\n```\n\n### Client: Custom Token Storage\n\nBy default, tokens are stored in memory and lost when the process exits.\nTo persist tokens across sessions, implement `TokenStorage` and pass it to `OAuthAuthorizer`:\n\n```swift\nfinal class KeychainTokenStorage: TokenStorage {\n    func save(_ token: OAuthAccessToken) {\n        \u002F\u002F Encode and store token.value in the system Keychain\n    }\n\n    func load() -> OAuthAccessToken? {\n        \u002F\u002F Load and decode token from the Keychain\n        return nil\n    }\n\n    func clear() {\n        \u002F\u002F Delete from the Keychain\n    }\n}\n\nlet authorizer = OAuthAuthorizer(\n    configuration: config,\n    tokenStorage: KeychainTokenStorage()\n)\n```\n\n### Client: `private_key_jwt` Authentication\n\nAuthenticate to the token endpoint using an asymmetric key (RFC 7523).\nThe SDK provides a built-in ES256 helper for P-256 keys:\n\n```swift\nlet config = OAuthConfiguration(\n    grantType: .clientCredentials,\n    authentication: .privateKeyJWT(\n        clientID: \"my-app\",\n        assertionFactory: { tokenEndpoint, clientID in\n            try OAuthConfiguration.makePrivateKeyJWTAssertion(\n                clientID: clientID,\n                tokenEndpoint: tokenEndpoint,\n                privateKeyPEM: myEC256PrivateKeyPEM  \u002F\u002F PEM-encoded P-256 private key\n            )\n        }\n    )\n)\n```\n\n### Client: Endpoint Overrides\n\nSkip automatic discovery by providing explicit endpoint URLs.\nUseful when the server does not publish well-known metadata documents:\n\n```swift\nlet config = OAuthConfiguration(\n    grantType: .clientCredentials,\n    authentication: .clientSecretBasic(clientID: \"app\", clientSecret: \"secret\"),\n    endpointOverrides: OAuthConfiguration.EndpointOverrides(\n        tokenEndpoint: URL(string: \"https:\u002F\u002Fauth.example.com\u002Foauth\u002Ftoken\")!\n    )\n)\n```\n\n### Server: Serving Protected Resource Metadata\n\nPer the MCP authorization specification, servers **MUST** serve Protected Resource Metadata\nat `\u002F.well-known\u002Foauth-protected-resource` so clients can discover authorization server endpoints.\n\nUse `ProtectedResourceMetadataValidator` as the first validator in your pipeline so that\nunauthenticated discovery requests are handled before the bearer token check:\n\n```swift\nlet metadata = OAuthProtectedResourceServerMetadata(\n    resource: \"https:\u002F\u002Fapi.example.com\",\n    authorizationServers: [URL(string: \"https:\u002F\u002Fauth.example.com\")!],\n    scopesSupported: [\"read\", \"write\"]\n)\nlet metadataValidator = ProtectedResourceMetadataValidator(metadata: metadata)\n```\n\n### Server: Validating Bearer Tokens\n\nUse `BearerTokenValidator` to authenticate incoming requests.\nYour `tokenValidator` closure **MUST** verify the token's `aud` claim to prevent\ntoken substitution attacks where a token intended for another resource is replayed against your server:\n\n```swift\nlet resourceIdentifier = URL(string: \"https:\u002F\u002Fapi.example.com\")!\n\nlet bearerValidator = BearerTokenValidator(\n    resourceMetadataURL: URL(string: \"https:\u002F\u002Fapi.example.com\u002F.well-known\u002Foauth-protected-resource\")!,\n    resourceIdentifier: resourceIdentifier,\n    tokenValidator: { token, request, context in\n        guard let claims = try? verifyAndDecodeJWT(token) else {\n            return .invalidToken(errorDescription: \"Token verification failed\")\n        }\n        \u002F\u002F Pass audience and expiry to BearerTokenInfo; the SDK validates the\n        \u002F\u002F audience claim against resourceIdentifier automatically.\n        return .valid(BearerTokenInfo(\n            audience: claims.audience,\n            expiresAt: claims.expiresAt\n        ))\n    }\n)\n\nlet pipeline = StandardValidationPipeline(validators: [\n    metadataValidator,            \u002F\u002F serves \u002F.well-known\u002Foauth-protected-resource unauthenticated\n    bearerValidator,              \u002F\u002F validates Bearer tokens on all other requests\n    AcceptHeaderValidator(mode: .sseRequired),\n    ContentTypeValidator(),\n    SessionValidator(),\n])\n```\n\n## Platform Availability\n\nThe Swift SDK has the following platform requirements:\n\n\n| Platform           | Minimum Version                                                                          |\n| ------------------ | ---------------------------------------------------------------------------------------- |\n| macOS              | 13.0+                                                                                    |\n| iOS \u002F Mac Catalyst | 16.0+                                                                                    |\n| watchOS            | 9.0+                                                                                     |\n| tvOS               | 16.0+                                                                                    |\n| visionOS           | 1.0+                                                                                     |\n| Linux              | Distributions with `glibc` or `musl`, including Ubuntu, Debian, Fedora, and Alpine Linux |\n\n\nWhile the core library works on any platform supporting Swift 6\n(including Linux), running a client or server requires a compatible transport.\n\n## Debugging and Logging\n\nEnable logging to help troubleshoot issues:\n\n```swift\nimport Logging\nimport MCP\n\n\u002F\u002F Configure Logger\nLoggingSystem.bootstrap { label in\n    var handler = StreamLogHandler.standardOutput(label: label)\n    handler.logLevel = .debug\n    return handler\n}\n\n\u002F\u002F Create logger\nlet logger = Logger(label: \"com.example.mcp\")\n\n\u002F\u002F Pass to client\u002Fserver\nlet client = Client(name: \"MyApp\", version: \"1.0.0\")\n\n\u002F\u002F Pass to transport\nlet transport = StdioTransport(logger: logger)\n```\n\n## Additional Resources\n\n- [MCP Specification](https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2025-11-25)\n- [Protocol Documentation](https:\u002F\u002Fmodelcontextprotocol.io)\n- [GitHub Repository](https:\u002F\u002Fgithub.com\u002Fmodelcontextprotocol\u002Fswift-sdk)\n\n## Changelog\n\nThis project follows [Semantic Versioning](https:\u002F\u002Fsemver.org\u002F).\nFor pre-1.0 releases,\nminor version increments (0.X.0) may contain breaking changes.\n\nFor details about changes in each release,\nsee the [GitHub Releases page](https:\u002F\u002Fgithub.com\u002Fmodelcontextprotocol\u002Fswift-sdk\u002Freleases).\n\n## License\n\nThis project is licensed under Apache 2.0 for new contributions, with existing code under MIT. See the [LICENSE](LICENSE) file for details.\n\n[mcp]: https:\u002F\u002Fmodelcontextprotocol.io\n[mcp-spec-2025-11-25]: https:\u002F\u002Fmodelcontextprotocol.io\u002Fspecification\u002F2025-11-25\n","该项目是Model Context Protocol (MCP)的官方Swift SDK，支持客户端和服务器端的实现。核心功能包括基本的客户端和服务端设置、多种传输选项、工具和资源管理、提示与完成处理、采样、引出、根节点管理、日志记录、错误处理、取消操作以及进度跟踪等。此外，它还提供了丰富的认证机制以确保通信安全。该SDK适用于需要通过标准化协议与AI及机器学习模型进行交互的应用场景，特别是那些使用Swift语言开发并希望遵循MCP规范的项目。",2,"2026-06-11 03:58:20","trending"]