{"id":26710575,"url":"https://github.com/compiler-inc/swiftmcp","last_synced_at":"2025-03-27T09:28:55.160Z","repository":{"id":283588395,"uuid":"952232474","full_name":"Compiler-Inc/SwiftMCP","owner":"Compiler-Inc","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-21T02:53:38.000Z","size":22,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-21T03:21:37.363Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Compiler-Inc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-21T00:17:36.000Z","updated_at":"2025-03-21T02:03:19.000Z","dependencies_parsed_at":"2025-03-21T03:21:40.254Z","dependency_job_id":null,"html_url":"https://github.com/Compiler-Inc/SwiftMCP","commit_stats":null,"previous_names":["compiler-inc/swiftmcp"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Compiler-Inc%2FSwiftMCP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Compiler-Inc%2FSwiftMCP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Compiler-Inc%2FSwiftMCP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Compiler-Inc%2FSwiftMCP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Compiler-Inc","download_url":"https://codeload.github.com/Compiler-Inc/SwiftMCP/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245816897,"owners_count":20677161,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-27T09:28:54.665Z","updated_at":"2025-03-27T09:28:55.147Z","avatar_url":"https://github.com/Compiler-Inc.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SwiftMCP\n\nA Swift Package that implements an MCP (Model Context Protocol) client for iOS and macOS, enabling native API integration through a JSON-RPC interface. The package also includes an OpenAI-compatible function calling bridge.\n\n## Features\n\n- Open source function definitions for Apple's native APIs like HealthKit\n- JSON-RPC 2.0 compliant interface\n- Some test coverage\n\n## Requirements\n\n- iOS 15.0+ / macOS 12.0+\n- Swift 6.0+\n- Xcode 15.0+\n\n## Installation\n\n### Swift Package Manager\n\nAdd the following dependency to your `Package.swift` file:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/compiler-inc/SwiftMCP.git\", from: \"1.0.0\")\n]\n```\n\n### Architecture\n\n[![](https://mermaid.ink/img/pako:eNqFVE1zmzAU_CsaXWt7jBPAcGgmxXWnnXHiiXNJwQcVnm0mIFF9tHFt__dK4sNMnEy4aPW0u9qHEAecsgxwiDcF-5vuCJfocZZQpB-hfm05qXYowSuQqkpwXTfPbVU58RNT3KA1Gg4_owfY5kLyffzIWNFO1mdJW2rJhibiugoc2WlDB5rV4CJIxOgf4ILInFE015FfhZq8CnVfAb39rjeJa_ROto5mRd9AzmAjYj02KzYd0sWc5mZr0dM2bKtc6eRLzspKxgaiGqNPF3okWWPdczqrrZnRRKQoDk2GBXkGUTuZ8s3prDyjVmQcjnfsiOY5JbplUcUWIQN1AFh_qH4CcUT1C5dxM5rcP1b3d8OHZaStfisQsufUskz8RbSMihyojDvUY3Y1y_36AqnZOzZASbBBeux2vTW2_eixn-WirYZnNU0wq-u10j_d1gHNGS_JG111ZuacvpD0uT7jGZHk3eM0NKvpjuGt194tWqr5jLt7gAe4BJ0nz_QdPZhyguUOSkhwqGEGG6IKaW7BSVOJkmy1pykOJVcwwJyp7Q6HG1IIPVNVRiTMcqJvU9lVK0J_Mla2Eshyyfii_inYf4Ol4PCAX3B45Y9Hnht4zjSY-I7r-u4A73HoT0au73jTwL2aekEQ-KcB_mdNx6Ppted77tTxJo7jj8fXp_9SZmEl?type=png)](https://mermaid.live/edit#pako:eNqFVE1zmzAU_CsaXWt7jBPAcGgmxXWnnXHiiXNJwQcVnm0mIFF9tHFt__dK4sNMnEy4aPW0u9qHEAecsgxwiDcF-5vuCJfocZZQpB-hfm05qXYowSuQqkpwXTfPbVU58RNT3KA1Gg4_owfY5kLyffzIWNFO1mdJW2rJhibiugoc2WlDB5rV4CJIxOgf4ILInFE015FfhZq8CnVfAb39rjeJa_ROto5mRd9AzmAjYj02KzYd0sWc5mZr0dM2bKtc6eRLzspKxgaiGqNPF3okWWPdczqrrZnRRKQoDk2GBXkGUTuZ8s3prDyjVmQcjnfsiOY5JbplUcUWIQN1AFh_qH4CcUT1C5dxM5rcP1b3d8OHZaStfisQsufUskz8RbSMihyojDvUY3Y1y_36AqnZOzZASbBBeux2vTW2_eixn-WirYZnNU0wq-u10j_d1gHNGS_JG111ZuacvpD0uT7jGZHk3eM0NKvpjuGt194tWqr5jLt7gAe4BJ0nz_QdPZhyguUOSkhwqGEGG6IKaW7BSVOJkmy1pykOJVcwwJyp7Q6HG1IIPVNVRiTMcqJvU9lVK0J_Mla2Eshyyfii_inYf4Ol4PCAX3B45Y9Hnht4zjSY-I7r-u4A73HoT0au73jTwL2aekEQ-KcB_mdNx6Ppted77tTxJo7jj8fXp_9SZmEl)\n\n## Usage\n\n### Basic Setup\n\n```swift\nimport SwiftMCP\n\n// Create a tool registry\nlet registry = ToolRegistry()\n\n// Create an MCP client with a response handler\nlet client = MCPClient(toolRegistry: registry) { response in\n    print(\"Received response: \\(response)\")\n}\n\n// Register tools\ndo {\n    let healthKitTool = try HealthKitTool()\n    registry.register(tool: healthKitTool)\n} catch {\n    print(\"Failed to initialize HealthKit tool: \\(error)\")\n}\n```\n\n### OpenAI Integration\n\nThis example demonstrates:\n\n1. Setting up the MCP client with HealthKit tool\n2. Creating an OpenAI bridge and registering the tool schema\n3. Converting MCP tools to OpenAI function definitions\n4. Sending an initial request to OpenAI\n5. Processing any tool calls through MCP\n6. Sending the tool results back to OpenAI for final summarization\n\nThe flow allows OpenAI to:\n\n- Request step count data using the HealthKit `getData` action\n- Request workout data using the HealthKit `getWorkouts` action\n- Receive the actual health and workout data through MCP\n- Provide a natural language summary of the data\n\n```swift\nimport SwiftMCP\nimport OpenAI\n\n// 1. Set up MCP client and tools\nlet registry = ToolRegistry()\nlet client = MCPClient(toolRegistry: registry) { response in\n    print(\"Received response: \\(response)\")\n}\n\n// Initialize HealthKit tool\nlet healthKitTool = try HealthKitTool()\nregistry.register(tool: healthKitTool)\n\n// 2. Set up OpenAI bridge\nlet openAIRegistry = OpenAIToolRegistry()\nlet healthKitSchema = JSONSchema(\n    type: .object,\n    properties: [\n        \"action\": .init(type: .string, enum: [\"getData\", \"getWorkouts\"]),\n        \"dataType\": .init(type: .string, description: \"Type of health data to retrieve (e.g., stepCount, heartRate)\"),\n        \"timeRange\": .init(type: .string, enum: [\"today\", \"yesterday\", \"this_week\", \"last_week\"]),\n        \"workoutType\": .init(type: .string, enum: [\"running\", \"cycling\", \"walking\"]),\n        \"includeRoutes\": .init(type: .boolean)\n    ],\n    required: [\"action\"]\n)\n\n// Register the HealthKit tool with its schema\nopenAIRegistry.registerTool(healthKitTool, schema: healthKitSchema)\n\n// 3. Get OpenAI function definitions\nlet functions = try openAIRegistry.getOpenAIFunctions()\n\n// 4. Create OpenAI client and chat request\nlet openAI = OpenAI(apiToken: \"your-api-key\")\nlet query = \"What was my step count today and how many calories did I burn in my last run?\"\n\nlet chatRequest = ChatRequest(\n    model: .gpt4o,\n    messages: [\n        .init(role: .user, content: query)\n    ],\n    functions: functions,\n    functionCall: \"auto\"\n)\n\n// 5. Send request to OpenAI\nlet result = try await openAI.chat(request: chatRequest)\n\n// 6. Handle any tool calls from OpenAI\nif let toolCalls = result.choices.first?.message.toolCalls {\n    // Process each tool call through MCP\n    let toolResponses = try await openAIRegistry.handleToolCalls(toolCalls)\n\n    // 7. Send follow-up request to OpenAI with tool results\n    let followUpRequest = ChatRequest(\n        model: .gpt4,\n        messages: [\n            .init(role: .user, content: query),\n            result.choices.first!.message,\n            .init(role: .assistant, content: nil, toolCalls: toolResponses)\n        ]\n    )\n\n    // 8. Get final summarized response\n    let finalResult = try await openAI.chat(request: followUpRequest)\n    print(finalResult.choices.first?.message.content ?? \"No response\")\n}\n```\n\nNote: Make sure to handle errors appropriately and replace \"your-api-key\" with your actual OpenAI API key.\n\n### OpenAI Function Calling Bridge\n\n```swift\n// Create and set up the OpenAI bridge\nlet openAIRegistry = OpenAIToolRegistry()\n\n// Register your MCP tools with their schemas\nopenAIRegistry.registerTool(healthKitTool, schema: healthKitToolSchema)\n\n// Get OpenAI function definitions\nlet functions = try openAIRegistry.getOpenAIFunctions()\n\n// Handle OpenAI tool calls\nlet toolCalls: [OpenAIBridge.ToolCall] = ... // from OpenAI response\nlet toolResponses = try await openAIRegistry.handleToolCalls(toolCalls)\n```\n\n### Handling JSON-RPC Requests\n\n```swift\n// Example JSON-RPC request for health data\nlet request = JSONRPCRequest(\n    jsonrpc: \"2.0\",\n    method: \"healthKit\",\n    params: [\n        \"action\": .string(\"getData\"),\n        \"dataType\": .string(\"stepCount\"),\n        \"timeRange\": .string(\"today\")\n    ],\n    id: \"1\"\n)\n\n// Example JSON-RPC request for workouts\nlet workoutRequest = JSONRPCRequest(\n    jsonrpc: \"2.0\",\n    method: \"healthKit\",\n    params: [\n        \"action\": .string(\"getWorkouts\"),\n        \"workoutType\": .string(\"running\"),\n        \"includeRoutes\": .bool(true),\n        \"timeRange\": .string(\"last_week\")\n    ],\n    id: \"2\"\n)\n\nif let data = try? JSONEncoder().encode(request) {\n    try await client.handleIncomingMessage(data: data)\n}\n```\n\n### Creating Custom Tools\n\n```swift\nclass CustomTool: MCPTool {\n    let methodName = \"custom/method\"\n\n    func handle(params: [String: JSON]) async throws -\u003e [String: JSON] {\n        // Implement your custom functionality here\n        return [\n            \"status\": .string(\"success\"),\n            \"result\": .object([\"data\": .string(\"your data here\")])\n        ]\n    }\n}\n```\n\n## Available Tools\n\n### HealthKitTool\n\nProvides comprehensive access to HealthKit data through the MCP interface.\n\n#### Methods\n\n- `healthKit`\n\n  - Actions:\n\n    - `getData`: Retrieve health metrics\n\n      - Parameters:\n        - `dataType`: Type of health data to retrieve (e.g., \"stepCount\", \"heartRate\")\n        - `timeRange` (optional): Predefined range (\"today\", \"yesterday\", \"this_week\", etc.)\n        - `duration` (optional): ISO 8601 duration string (e.g., \"P7D\" for 7 days)\n      - Returns:\n        - `dataType`: The type of data retrieved\n        - `unit`: The unit of measurement\n        - `samples`: Array of data points with values and timestamps\n\n    - `getWorkouts`: Retrieve workout data\n      - Parameters:\n        - `workoutType` (optional): Type of workout to filter by (e.g., \"running\", \"cycling\")\n        - `includeRoutes` (optional): Boolean to include GPS route data\n        - `timeRange` (optional): Predefined range\n        - `duration` (optional): ISO 8601 duration string\n      - Returns:\n        - `workouts`: Array of workout data including:\n          - `type`: Workout type\n          - `startDate`: Start timestamp\n          - `endDate`: End timestamp\n          - `duration`: Duration in seconds\n          - `distance` (optional): Distance in meters\n          - `calories` (optional): Energy burned in kilocalories\n          - `route` (optional): Array of GPS coordinates with timestamps\n\n## Error Handling\n\nThe package uses the `MCPError` type for error handling, which includes:\n\n- `toolNotFound`: When the requested method doesn't exist\n- `invalidParams`: When the request parameters are invalid\n- `toolError`: Generic error case for tool-specific errors with a descriptive message\n- `jsonParsingError`: When JSON parsing fails\n- `invalidRequest`: When the JSON-RPC request format is invalid\n\n## Contributing\n\nI want to add as many iOS APIs as possible to this repo. The goal is to create a comprehensive collection of MCP-compatible tools for iOS development.\n\nAny contributions are welcome! Please feel free to submit a PR.\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## MLX Swift Integration\n\n### Overview\n\nSwiftMCP now includes support for function calling (tool use) with MLX models running locally on-device. This feature allows you to leverage the power of local large language models with tool use capabilities without relying on external API services.\n\n### Setup\n\nTo use MLX Swift function calling, first add the MLX Swift dependency to your project:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/compiler-inc/SwiftMCP.git\", from: \"1.0.0\")\n    .package(url: \"https://github.com/ml-explore/mlx-swift\", from: \"0.21.0\")\n]\n```\n\n### Basic Usage\n\nThis example demonstrates:\n\n1. Setting up the MLX tool registry\n2. Loading and initializing an MLX model\n3. Registering tools with the MLX bridge\n4. Generating text with tool calling capabilities\n\n```swift\nimport SwiftMCP\nimport MLX\n\n// 1. Set up MLX Tool Registry\nlet mlxRegistry = MLXToolRegistry()\n\n// 2. Register tools\nlet weatherTool = WeatherTool()\nmlxRegistry.registerTool(weatherTool, schema: WeatherTool.getJSONSchema())\n\n// 3. Create model handler and load model\nlet modelType = MLXModelFactory.detectModelType(from: modelURL)\nlet modelHandler = MLXModelFactory.createModelHandler(\n    modelType: modelType,\n    toolRegistry: mlxRegistry\n)\n\ntry await modelHandler.loadModel(from: modelURL)\n\n// 4. Generate text with function calling\nlet prompt = \"What's the weather like in San Francisco?\"\nlet response = try await modelHandler.generateWithFunctionCalling(\n    prompt: prompt,\n    systemPrompt: \"You are a helpful assistant with access to weather information.\",\n    parameters: [\n        \"temperature\": 0.7,\n        \"max_tokens\": 1024\n    ]\n)\n\nprint(response)\n```\n\n### Supported Models\n\nThe MLX integration currently supports the following model architectures:\n\n- Mistral (7B, 8x7B)\n- Llama (2, 3)\n- Phi\n\n### Model Loading\n\nModels need to be in the MLX format, which can be obtained by converting models from Hugging Face using the MLX conversion tools. For detailed instructions, visit the [MLX repository](https://github.com/ml-explore/mlx-swift).\n\n### Creating Custom Tools for MLX Models\n\nCreating tools for MLX models follows the same pattern as other tools in SwiftMCP:\n\n```swift\nclass CustomTool: MCPTool {\n    let methodName = \"custom/method\"\n\n    func handle(params: [String: JSON]) async throws -\u003e [String: JSON] {\n        // Implement your custom functionality here\n        return [\n            \"status\": .string(\"success\"),\n            \"result\": .object([\"data\": .string(\"your data here\")])\n        ]\n    }\n\n    static func getJSONSchema() -\u003e String {\n        return \"\"\"\n        {\n            \"type\": \"function\",\n            \"function\": {\n                \"name\": \"custom_method\",\n                \"description\": \"Performs a custom operation\",\n                \"parameters\": {\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"param1\": {\n                            \"type\": \"string\",\n                            \"description\": \"First parameter\"\n                        },\n                        \"param2\": {\n                            \"type\": \"number\",\n                            \"description\": \"Second parameter\"\n                        }\n                    },\n                    \"required\": [\"param1\"]\n                }\n            }\n        }\n        \"\"\"\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompiler-inc%2Fswiftmcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcompiler-inc%2Fswiftmcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompiler-inc%2Fswiftmcp/lists"}