mcpField
S
SwiftMCP

SwiftMCP

ローカル
github.com/Cocoanetics開発ツール165今日更新

SwiftMCP について

SwiftMCP は、JSON-RPC 2.0 に基づく Model Context Protocol の Swift 実装です。stdio、HTTP+SSE、TCP+Bonjour の各トランスポートに対応しています。マクロでツール、リソース、プロンプトを宣言し、Swift で MCP サーバーやクライアントを構築したい開発者を対象としています。SwiftPM のトレイトで必要な機能だけを組み込めます。

主な機能

  1. 01stdio、HTTP+SSE、TCP+Bonjour のトランスポート
  2. 02マクロによるツール、リソース、プロンプトの宣言
  3. 03認可機能と任意の OAuth トークン検証
  4. 04MCP サーバー向けの型付きクライアントプロキシ生成
  5. 05SwiftPM トレイトによる依存関係の選択

活用シーン

  1. 01Swift でコマンドラインから呼び出せる MCP ツールサーバーを作成する
  2. 02Web アプリケーション向けに HTTP+SSE で MCP を提供する
  3. 03リモートの MCP サーバーに接続する Swift クライアントを構築する

MCP 対応

@MCPTool、@MCPResource、@MCPPrompt で宣言したツール、リソース、プロンプトを MCP クライアントに公開する MCP サーバーとして動作します。他の MCP サーバーに接続するためのクライアント MCPServerProxy も含みます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

SwiftMCP

さまざまなトランスポートを介した JSON-RPC 用 MCP(Model Context Protocol)の Swift 実装です。

機能

  • 複数のトランスポートオプション
    • コマンドラインでの使用向けの標準入出力(stdio)
    • Web アプリケーション向けの HTTP+SSE(Server-Sent Events)
    • 生の TCP を介したローカル検出向けの TCP+Bonjour
  • OpenAPI 生成に対応した JSON-RPC 2.0 準拠
  • 認可機能を内蔵し、OAuth 検証にも対応
  • MCP と OpenAPI 向けの透過的な OAuth プロキシモード
  • クロスプラットフォーム対応
サーバーの機能
  • ツール – @MCPTool で関数を公開します
  • リソース – @MCPResource でデータを公開します
  • プロンプト – @MCPPrompt を使用してプロンプトを構築します
  • ユーティリティ
    • RequestContext.current を介した進捗通知
    • Session.current を介してストリーミングされる構造化ログ
    • パラメーターの補完候補(Bool と CaseIterable のデフォルト値)
クライアントの機能
  • ルート – クライアントが通知する動的なファイルシステムルート
  • サンプリング – クライアントのファイルの短いプレビューをリクエストします

インストール

Package.swift に SwiftMCP を依存関係として追加します。

dependencies: [
    .package(url: "https://github.com/Cocoanetics/SwiftMCP.git", branch: "main")
]
パッケージトレイト

SwiftMCP は、オプション機能をSwiftPM パッケージトレイトとして公開しており、すべてデフォルトで有効です。既存の利用者や通常の swift build には影響しません。単一の import SwiftMCP モジュールに変更はありません。

トレイト有効にする機能追加の依存関係
ServerHTTP/SSE および TCP サーバートランスポートswift-nio、swift-crypto、swift-certificates
ClientMCP クライアント(MCPServerProxy)—
OpenAPIOpenAPI/AI プラグインのマニフェストモデルとルート—

ツール/スキーマの基盤である JSONValue、JSONSchema、MCPToolProviding、@MCPTool/@MCPServer マクロ、エラーは常に有効なコア機能であり、トレイトは必要ありません。

Server を無効にすると swift-nio(および swift-crypto/swift-certificates)が完全に除外されるため、パッケージをWindows 上でビルドでき、クライアント/ツールのみを使う利用者は依存関係を軽量化できます。リモート MCP サーバーとの通信のみを行う利用者は、必要なものだけを選択できます(トレイトを選択するには、マニフェストの swift-tools-version が 6.1 以降である必要があります)。

.package(
    url: "https://github.com/Cocoanetics/SwiftMCP.git",
    branch: "main",
    traits: ["Client"]   // tool/schema core + client, no swift-nio
)

AppIntents ブリッジ(@MCPAppIntentTool、AppShortcuts の検出)はトレイトではありません。すでに #if canImport(AppIntents) で制御されているため、AppIntents のないプラットフォーム(Linux、Windows、Android)では自動的に除外されます。

使用方法

コマンドラインのデモ

付属のデモアプリケーションでは、SwiftMCP をさまざまなトランスポートオプションで使用する方法を紹介しています。

# Using stdio transport
SwiftMCPDemo stdio

# Using HTTP+SSE transport
SwiftMCPDemo httpsse --port 8080

# Using HTTP+SSE with authorization
SwiftMCPDemo httpsse --port 8080 --token your-secret-token

# Using HTTP+SSE with OpenAPI support
SwiftMCPDemo httpsse --port 8080 --openapi

# Using HTTP+SSE with authorization and OpenAPI support
SwiftMCPDemo httpsse --port 8080 --token your-secret-token --openapi

# Using HTTP+SSE with OAuth (JSON config)
SwiftMCPDemo httpsse --port 8080 --oauth oauth-config-example.json

# Using TCP+Bonjour transport
SwiftMCPDemo tcp --name "SwiftMCP Demo"

# Using HTTP+SSE plus TCP+Bonjour in parallel
SwiftMCPDemo httpsse --port 8080 --tcp

--token オプションを指定して HTTP+SSE トランスポートを使用する場合、クライアントはリクエストに Authorization ヘッダーを含める必要があります。

Authorization: Bearer your-secret-token

OpenAPI のサポート

--openapi オプションを指定すると、AI プラグインとの連携向けの OpenAPI エンドポイントが有効になります。このオプションを使用すると、サーバーは /openapi.json に OpenAPI 仕様を、/.well-known/ai-plugin.json に AI プラグインのマニフェストを提供します。これにより、AI モデルや OpenAPI をサポートするその他のツールと簡単に連携できます。

OAuth のサポート

HTTPSSETransport に OAuthConfiguration を設定すると、トランスポートは設定された OAuth プロバイダーを通じて、受信したベアラートークンを検証します。 検証には、イントロスペクションエンドポイントを使用する方法と、イントロスペクションを利用できない場合にプロバイダーの JWKS に照らして JWT クレームを確認する方法があります。また、クライアントによる検出用に、トランスポートは /.well-known/oauth-authorization-server と /.well-known/oauth-protected-resource でメタデータも提供します。

進捗、ログ、ルート、サンプリング

SwiftMCP は、ツールの実行中に進捗状況を送信し、接続されたクライアントに構造化ログメッセージをストリーミングし、クライアントが通知する動的なファイルシステムルートを処理して、プレビュー用の短いデータサンプルをリクエストできます。これらの機能の簡単な実装例については、デモサーバーを参照してください。doc:ServerCapabilities と doc:Sampling の記事では、API について詳しく説明しています。

カスタムサーバーの実装

独自の MCP サーバーを実装するには:

  1. クラスやアクターなどの参照型に @MCPServer マクロを付けます
  2. @MCPTool 属性を使ってツールを定義します
  3. トランスポート(stdio、HTTP+SSE、TCP+Bonjour)を選択して設定します

例:

@MCPServer
class MyServer {
    @MCPTool
    func add(a: Int, b: Int) -> Int {
        return a + b
    }
}

// Using HTTP+SSE transport with authorization
let server = MyServer()
let transport = HTTPSSETransport(server: server, port: 8080)

// Optional: Add authorization
transport.authorizationHandler = { token in
    guard let token = token, token == "your-secret-token" else {
        return .unauthorized("Invalid token")
    }
    return .authorized
}

// Or configure OAuth validation
transport.oauthConfiguration = OAuthConfiguration(
    issuer: URL(string: "https://example.com")!,
    authorizationEndpoint: URL(string: "https://example.com/authorize")!,
    tokenEndpoint: URL(string: "https://example.com/oauth/token")!,
    introspectionEndpoint: URL(string: "https://example.com/oauth/introspect")!,
    jwksEndpoint: URL(string: "https://example.com/.well-known/jwks.json")!,
    audience: "your-api-identifier",
    clientID: "client",
    clientSecret: "secret"
)

try transport.run()

代わりに TCP+Bonjour で提供するには:

let server = MyServer()
let tcpTransport = TCPBonjourTransport(server: server)
try await tcpTransport.run()

型付きクライアントプロキシ

SwiftMCP は、任意のサーバー向けに型付きクライアントプロキシを生成できます。このプロキシは @MCPTool、@MCPResource、@MCPPrompt のシグネチャを反映し、呼び出しを MCPServerProxy 経由で転送します。サーバーマクロに generateClient: true を指定して有効にします。

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

let url = URL(string: "http://localhost:8080/mcp")!
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)

TCP+Bonjour の検出の場合:

let config = MCPServerConfig.tcp(config: MCPServerTcpConfig(instanceName: "SwiftMCP Demo"))
let proxy = MCPServerProxy(config: config)
try await proxy.connect()
検出スコープ

すべての MCP サービスは、単一のサービスタイプ _mcp._tcp でアドバタイズされます。識別情報は Bonjour の インスタンス名に含まれ、その名前をどこまで届かせるかは、1 つの設定で決まります:

スコープ到達範囲ベース名 Post のアドバタイズ名
.localUser (デフォルト)ループバック、ユーザー名で修飾Post (oliver)
.localMachineループバック、修飾なしPost
.localNetwork接続されているリンク、修飾なしPost

名前に修飾が付くのは .localUser だけです。クライアントとサーバーが同じマシン上の同じユーザーであり、両側で修飾を導出できるためです。ホスト名による修飾はありません。DNS-SD はすでにサービスを宛先ホストに解決し、マシン名を変更するとホスト名も変わるためです。同じ名前をアドバタイズする 2 台のマシンは mDNS によって区別され、2 台目の名前は Post (2) に変更されます。

スコープはバインド、アドバタイズ、ブラウジングをまとめて制御するため、サービスが提供される範囲を超えてアドバタイズされることはありません。クライアントとサーバーには同じベース名を渡し、残りはスコープに導出させます:

// server
let transport = TCPBonjourTransport(server: server)               // .localUser
// client
let config = MCPServerTcpConfig(instanceName: server.serverName)  // .localUser

インスタンス名はマシン全体で共有されるため、.localUser がデフォルトです。同じサーバーを実行する 2 つのアカウントは、そうでなければ名前が衝突し、2 つ目のユーザーのクライアントが気付かないまま 1 つ目のユーザーのプロセスに接続してしまいます。.localUser はこの誤ったバインドを防ぎますが、ループバックソケットはマシン上のすべてのアカウントから見えるため、アクセス境界ではありません。必要であれば認証を行ってください。

.localNetwork は明示的に選択する必要があります。TCP トランスポートには認可フックがないため、独自のレイヤーを追加しない限り、そこから到達可能なものには認証なしでアクセスできます。

検出を利用できない場合は、直接接続して検出をスキップします:

let config = MCPServerTcpConfig(host: "127.0.0.1", port: 8181)

注:

  • クライアント生成はオプトインです(generateClient のデフォルトは false です)。
  • クライアントメソッドは常に throw し、トランスポートまたはサーバーのエラーを表面化します。
  • 新しいクライアントには Streamable HTTP /mcp エンドポイントを使用してください。レガシーの /sse エンドポイントも、後方互換性のため引き続き利用できます。

クライアント通知ハンドラー

MCPServerProxy は、サーバーからの型付き JSON-RPC 通知を表面化することもできます。 カスタムのアプリ/ドメインイベントには setNotificationHandler(_:as:handler:) を使い、 組み込みの便利な処理には setLogNotificationHandler(_:)/setProgressNotificationHandler(_:) を使います。

struct RunStatusUpdate: Codable, Sendable {
    let runID: String
    let status: String
}

await proxy.setNotificationHandler("notifications/runStatusChanged", as: RunStatusUpdate.self) { update in
    print("Run \(update.runID) is now \(update.status)")
}

SwiftMCPUtility プロキシ生成

SwiftMCPUtility generate-proxy を使うと、SwiftMCP 以外のサーバーも含め、任意の MCP サーバー向けに クライアントプロキシを作成できます。生成されたプロキシは内部で MCPServerProxy を呼び出し、 MCP ツールスキーマから型付きツールメソッドを生成します。また、サーバーがそれらの機能をアドバタイズする場合は、 リソース/プロンプト用の便利な API も標準で追加します。 入力パラメーターはサーバーのツールスキーマから推論され、date-time、uri、uuid、byte などの文字列形式のみが ネイティブ型(Date、URL、UUID、Data)にマッピングされます。

SwiftMCPUtility generate-proxy --sse http://localhost:8080/mcp -o ToolsProxy.swift

生成されるメソッドはすべて async throws で、トランスポートおよびサーバーのエラーが表面化します。

OpenAPI の戻り値の型

MCP サーバーが OpenAPI JSON ドキュメントを公開している場合は、その URL(またはファイルパス)を --openapi に渡すと、戻り値の型を補完できます。ジェネレーターは OpenAPI のレスポンススキーマを MCP ツールリストに重ね合わせ、構造化されたレスポンス用の Codable 構造体/列挙型を生成し、プロキシの戻り値シグネチャでそれらの型を使用します。

SwiftMCPUtility generate-proxy \
  --sse http://localhost:8080/mcp \
  --openapi http://localhost:8080/openapi.json \
  -o ToolsProxy.swift

生成された Codable 型はそのまま使用することも、ローカルに定義がある場合は後から独自のモデルに置き換えることもできます。

ドキュメントの抽出

@MCPServer マクロと @MCPTool マクロは、クラス、パラメーター、戻り値を説明するドキュメントコメントを抽出します。

マクロの機能

このリポジトリのマクロは、SwiftMCP フレームワークでツールとサーバーを定義し、公開する機能を提供します。主な機能は次のとおりです。

  • @MCPServer:このマクロは、クラスまたはアクターを MCP サーバーとして定義するために使用します。ドキュメントコメント(またはオプションの description: オーバーライド)からサーバーの説明を抽出します。使用例は Demos/SwiftMCPDemo/Calculator.swift ファイルで確認できます。ここでは、Calculator アクターに @MCPServer(name: "SwiftMCP Demo") が付与されています。
  • @MCPTool:このマクロは、MCP サーバー内でツールとして呼び出せる関数を定義するために使用します。また、関数、パラメーター、戻り値を説明するドキュメントコメントも抽出します。使用例は Demos/SwiftMCPDemo/Calculator.swift ファイルで確認できます。ここでは、add、subtract、testArray、multiply、divide、greet、ping、noop などのさまざまな関数に @MCPTool が付与されています。
  • @MCPResource:このマクロは、URI テンプレートを通じて読み取り専用データを公開するために使用します。リソースを使用すると、クライアントはパスパラメーターやクエリパラメーターを含む構造化 URI でデータにアクセスできます。このマクロは、URI とテンプレートの照合やパラメーターの抽出に必要なインフラストラクチャを自動生成します。
@MCPResource の使用

@MCPResource マクロを使用すると、URI パターン経由でアクセスできるリソースとして関数を公開できます。

@MCPServer(name: "ResourceServer")
actor ResourceServer {
    /// Get user profile by ID
    @MCPResource("users://{user_id}/profile")
    func getUserProfile(user_id: Int) -> String {
        return "Profile for user \(user_id)"
    }
    
    /// Search users with pagination
    @MCPResource("users://search?q={query}&page={page}", mimeType: "application/json")
    func searchUsers(query: String, page: Int = 1) -> String {
        return """
        {"query": "\(query)", "page": \(page), "results": [...]}
        """
    }
}

主な機能:

  • URI テンプレート:波括弧 {param} のプレースホルダーを含むパターンを定義します
  • パスパラメーター:URI パスから値を抽出します(例:/users/{id})
  • クエリパラメーター:クエリ文字列から値を抽出します(例:?page={page})
  • オプションのパラメーター:オプションのパラメーターにデフォルト値を設定できます
  • MIME タイプ:mimeType パラメーターでコンテンツタイプを任意に指定できます
  • 型安全性:パラメーターは適切な Swift 型に自動変換されます

サーバーは次の機能を自動的に提供します:

  • mcpResourceTemplates によるリソースの検索
  • URI の照合とパラメーターの抽出
  • 型変換と検証
  • パラメーターの欠落または無効な場合のエラー処理

これらのマクロは、MCP サーバーとそのツールに必要なメタデータやドキュメントを自動生成するため、JSON-RPC 通信や AI モデルとの連携に向けた公開を容易にします。

ライセンス

このプロジェクトは BSD 2-clause ライセンスの下でライセンスされています。詳細は LICENSE ファイルを参照してください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。