mcpField
M
macos-mcp-server

macos-mcp-server

ローカル
github.com/cyanheads生産性41 週間前に更新

macos-mcp-server について

ローカルの Mac を操作する MCP サーバーです。アプリやウィンドウ、システム設定などを管理するエージェント向けで、オーディオ、ディスプレイ、スクリーンショット、Finder、通知、集中モードにも対応します。ホストには macOS が必要です。

主な機能

  1. 01アプリの起動、終了、非表示、表示
  2. 02ウィンドウの一覧表示、フォーカス、配置
  3. 03オーディオ設定の確認と変更
  4. 04ディスプレイと外観の管理
  5. 05スクリーンショットの撮影と Finder の操作
  6. 06通知の送信と集中モードの設定

活用シーン

  1. 01デスクトップのワークフローでアプリのウィンドウを配置
  2. 02オーディオデバイスの切り替えやシステム音量の調整
  3. 03ディスプレイ、アプリウィンドウ、画面領域を撮影
  4. 04システム情報の確認と集中モードの操作

MCP 対応

MCP クライアント向けに 13 個のツールと 3 つのリソースを公開し、STDIO または Streamable HTTP に対応します。ローカルの macOS ホストを操作するため、実用上は STDIO でのローカル実行を想定しています。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"cyanheads-macos": {
"command": "npx",
"args": [
"-y",
"@cyanheads/macos-mcp-server"
],
"env": {
"MACOS_SCREENSHOT_DIR": "<MACOS_SCREENSHOT_DIR>",
"MACOS_DISPLAY_LAYOUTS": "<MACOS_DISPLAY_LAYOUTS>",
"MCP_LOG_LEVEL": "<MCP_LOG_LEVEL>",
"MCP_TRANSPORT_TYPE": "<MCP_TRANSPORT_TYPE>",
"MCP_HTTP_HOST": "<MCP_HTTP_HOST>",
"MCP_HTTP_PORT": "<MCP_HTTP_PORT>",
"MCP_HTTP_ENDPOINT_PATH": "<MCP_HTTP_ENDPOINT_PATH>",
"MCP_AUTH_MODE": "<MCP_AUTH_MODE>"
}
}
}
}
起動コマンドnpx -y @cyanheads/macos-mcp-server
設定が必要な環境変数
MACOS_SCREENSHOT_DIRDefault directory for screenshot files. Defaults to ~/Desktop when empty.
MACOS_DISPLAY_LAYOUTSJSON object mapping layout names to displayplacer argument strings for apply_layout.
MCP_LOG_LEVELMinimum log level for output: debug, info, notice, warning, error.
MCP_TRANSPORT_TYPESelects the HTTP transport.
MCP_HTTP_HOSTThe hostname for the HTTP server.
MCP_HTTP_PORTThe port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHThe endpoint path for the MCP server.
MCP_AUTH_MODEシークレットAuthentication mode: none, jwt, or oauth.

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npm@cyanheads/macos-mcp-server0.4.0

ツール

13

掲載時のツール一覧 · 今日に更新

このツールにパラメーターはありません。

詳細

@cyanheads/macos-mcp-server

MCP を介して macOS のシステム設定、アプリ、ウィンドウ、オーディオ、ディスプレイ、スクリーンショット、集中モードを操作します。STDIO または Streamable HTTP に対応しています。

13 個のツール • 3 個のリソース

Version License MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

macOS 専用です。 このサーバーはローカルの macOS システムを操作するため、ホストマシンで macOS が実行されている必要があります。HTTP トランスポートにも対応していますが、実用上は stdio での利用を想定しています。ローカルで実行し、MCP クライアントから接続してください。


概要

エージェントから Mac を操作できます。アプリやウィンドウの起動、終了、配置、オーディオやディスプレイデバイスの切り替え、スクリーンショットの撮影、Finder の操作、通知の送信、集中モードの切り替えが可能です。

ツール
ツール説明
macos_get_infoシステムのスナップショット:バッテリー残量と充電状態、電源、Wi-Fi の接続状態とネットワーク名、ホスト名、macOS のバージョン、稼働時間、ディスプレイ数を取得します。プローブに失敗した場合、そのフィールドは null となり、unavailable に名前が記載されます
macos_check_permissionsApple のプロンプト不要のチェックを使って、呼び出し元プロセスのアクセシビリティ、画面収録、オートメーション > Finder の状態を報告します。チェックで判定できない場合は、理由とともに null を返します
macos_manage_apps実行中のアプリを一覧表示し、最前面のアプリを取得し、アプリケーションの起動、終了、強制終了、非表示、表示を行います
macos_manage_windows表示中のすべてのアプリのウィンドウを一覧表示、フォーカス、移動、サイズ変更、移動とサイズ変更、最小化、フルスクリーン表示、または閉じます
macos_control_volumeシステムの出力音量(0~100)とミュート状態を取得または設定します
macos_control_audioオーディオデバイスを一覧表示し、現在のデフォルトを取得するか、デフォルトの入力/出力デバイスを切り替えます
macos_control_appearanceダーク/ライトモードを取得または設定します
macos_control_system画面をロックするか、ディスプレイをスリープ状態にします
macos_take_screenshotメインディスプレイ、display_index で指定したディスプレイ、名前を指定したアプリのウィンドウ、またはピクセル領域をキャプチャします。overwrite が true の場合を除き、既存のファイルを置き換えずに PNG を保存します。JPEG プレビューは任意です
macos_manage_displays接続されたディスプレイ(それぞれの index を含む)と設定済みレイアウト名を一覧表示し、名前を指定したディスプレイレイアウトのプリセットを適用します
macos_send_notificationmacOS の通知センターに通知を送信します
macos_manage_focusおやすみモード/集中モードを取得または設定します
macos_manage_finder最前面のパス、現在の選択項目の取得、表示、アプリで開く、またはゴミ箱への移動を行います
リソース
リソース説明
macos://system/info現在の macOS システムのスナップショット:バッテリー、電源、Wi-Fi の接続状態とネットワーク名、ホスト名、バージョン、稼働時間、ディスプレイ数を取得します。プローブに失敗した場合、そのフィールドは null となり、unavailable に名前が記載されます
macos://audio/devices現在のデフォルトデバイスを含む、すべてのオーディオ入力・出力デバイス。SwitchAudioSource CLI が必要です。
macos://displays永続 ID、インデックス(macos_take_screenshot と macos_manage_windows が使用する display_index)、種類、解像度、原点、回転、スケーリング、有効状態を含む、接続されたディスプレイの一覧。displayplacer CLI が必要です。

リソースのデータは、macos_get_info、macos_control_audio(action=list)、macos_manage_displays(action=list)からも取得できます。

機能リファレンス

macos_get_info tool
  • バッテリー残量(0~100)、充電状態、電源(AC、Battery、UPS)。バッテリーのないデスクトップでは null です。バッテリーが充電上限で維持されている場合(「AC 接続中、充電していません」)、charging は false になり、充電完了に向けて充電中の場合は true になります
  • Wi-Fi デバイスのリンク状態から Wi-Fi の接続状態を取得します。macOS がネットワーク名の取得を制限している場合、接続中でもネットワーク名は null になります(取得にはホストアプリで位置情報サービスへのアクセスが必要です)。名前は content[] 内でコードスパンとして表示されるため、名前に含まれる Markdown 文字もそのまま読み取れます
  • ホスト名と稼働時間(Node の os モジュールから取得)、macOS のバージョン文字列(例:"15.1")
  • 接続されたディスプレイ数(ヘッドレス Mac では 0)
  • プローブに失敗した場合、そのフィールドは null となり、unavailable に名前が記載されます。値が battery: null で、unavailable に battery が含まれていない場合、その Mac にバッテリーはありません
  • 権限は不要です
macos_check_permissions ツール
  • Apple のプロンプトを表示しないチェック、AXIsProcessTrusted、CGPreflightScreenCaptureAccess、およびプロンプト表示を無効にした AEDeterminePermissionToAutomateTarget を使用して、アクセシビリティ(list を含むすべての macos_manage_windows アクション、macos_manage_apps の hide と show、window_title の frontmost 読み取り、およびスクリーンセーバーにフォールバックする前に ⌃⌘Q キーストロークを送信する macos_control_system の lock)、画面収録(ウィンドウのスクリーンショット)、および オートメーション > Finder(macos_manage_finder の frontmost_path、get_selection、trash)の権限を報告します
  • 各フィールドは true、false、またはチェックで判定できない場合は null です。unknown_reasons には、各 null が不明である理由が示されます。macOS が同意を求めるまでは、また Finder が起動していない間は、オートメーション > Finder の値は null です。通知は常に null です。macOS にはプロンプトを表示しないチェック方法がありません
  • 呼び出し元のプロセス名(例:"ghostty"、"node")を返すため、どのプロセスに権限を付与すべきかがわかります
  • 読み取り専用です。チェックによって他のアプリに Apple イベントが送信されたり、画面がキャプチャされたり、権限プロンプトが表示されたりすることはありません
  • 他のツールが失敗する原因をデバッグする際は、まずこれを実行してください

macos_manage_apps ツール
  • list — 実行中のユーザー向けアプリを、名前、バンドル ID、PID、表示状態、最前面フラグとともに一覧表示します
  • frontmost — アクティブなアプリの名前、バンドル ID、PID、最前面ウィンドウのタイトル
  • launch — app_name または bundle_id でアプリを開く、またはアクティブ化します。hidden=true を指定するとバックグラウンドで起動します
  • quit(AppleScript による正常終了)と force_quit(SIGKILL による終了。保存プロンプトは表示されません)
  • hide / show — 表示状態を切り替えます。アクセシビリティが必要です
  • quit、force_quit、hide、show は、まずアプリが実行中かどうかを確認します。アプリケーション名は tell application と同じ方法で解決され("Visual Studio Code" から Code プロセスが見つかります)、アプリは起動しません。実行中でない場合は not_running を返します
  • 型付きエラー:app_not_found(インストールされていないアプリに対する launch)、no_frontmost_app(System Events が最前面のプロセスを報告しない場合)、not_running、accessibility_required

macos_manage_windows tool
  • list — アプリ全体で表示されているすべてのウィンドウを、位置、サイズ、minimized と fullscreen の状態(それぞれウィンドウの AXMinimized/AXFullScreen 属性から読み取り、読み取れない場合は null)、および display_index(ウィンドウと最も重なるディスプレイ。インデックスは macos_manage_displays action=list が報告するもの。ディスプレイのフレームを読み取れない場合、またはウィンドウと重なるディスプレイがない場合は null)とともに一覧表示します。同じタイトルのウィンドウや、同じ名前の2つのプロセスが所有するウィンドウは、それぞれ個別に一覧表示されます
  • focus、move、resize、move_resize、minimize、fullscreen、close — window_title(大文字と小文字を区別しない完全一致で、すべてのアプリが対象。同じアプリに同じタイトルのウィンドウが2つある場合は、手前にあるウィンドウ)または app_name(そのアプリの手前にあるウィンドウ)で対象を指定します。window_title が優先され、その場合 app_name は無視されます
  • app_name は、アプリケーション名("Visual Studio Code")、ローカライズ名("Code")、またはプロセス名("firefox")で、実行中のアプリに大文字と小文字を区別せずに一致します。実行中のアプリ一覧から解決されるため、アプリの検索時にアプリを起動したり、Apple イベントを送信したりすることはありません
  • move には x/y が必要です。resize には width/height(どちらも 0 より大きい値)が必要です。move_resize には4つすべてが必要です
  • minimize — minimized: true(デフォルト)で最小化し、false で復元します。ウィンドウがすでにその状態にある場合は AXMinimized 属性を書き込まず、読み戻した状態が指定された状態になった場合にのみ成功します
  • fullscreen — fullscreen: true で全画面表示にし、false で解除します。省略するとウィンドウの現在の状態を切り替えます。状態が異なる場合は、focus と同様に対象のウィンドウを前面に表示し、その AXFullScreen 属性を設定します(キー入力は行わないため、キーボードフォーカスがあったウィンドウが切り替わることはありません)。ウィンドウの状態が指定された状態に読み戻されるまで、最大4秒待ちます
  • list を含むすべてのアクションは System Events をスクリプトで操作し、アクセシビリティの許可が必要です。許可されていない場合は accessibility_required を返し、「ウィンドウなし」として読み取ることはありません。focus はウィンドウを前面に表示し、そのアプリを最前面にします。どのアクションもアプリを起動しません
  • 各書き込み処理では、1つのスクリプト内で同じウィンドウを見つけ、変更し、読み戻します。window.app はウィンドウが見つかったプロセスです。close はウィンドウを返しません
  • 型付きエラー:not_running(app_name に指定された名前のアプリが実行されていない)、window_not_found、accessibility_required、minimize_unsupported、fullscreen_unsupported(ウィンドウの AXMinimized/AXFullScreen 属性が存在しない、設定できない、または4秒以内に指定された状態にならなかった場合)。osascript のタイムアウトまたは失敗は、window_not_found として読み替えず、固有のエラーを維持します

macos_control_volume tool
  • get — デフォルト出力の現在の音量(0~100)とミュート状態を取得します。ソフトウェアで音量を制御できない出力(多くの HDMI および DisplayPort ディスプレイなど)では、level と muted は null になり、output_device にデバイス名が入ります(識別できない場合は null)
  • set — level(0~100)、muted、またはその両方が必要です。level=0 ではミュートになりません。要求された値をソフトウェアで制御できない出力の場合、デバイス名を示す volume_unsupported で失敗し、変更は行いません
  • action をそのまま含め、常に現在の状態を返します
  • 型付きエラー:volume_unsupported。呼び出しがキャンセルされた場合、デバイスの検索を停止してキャンセルとして終了し、output_device: null にはなりません

macos_control_audio tool
  • list — すべての入力/出力デバイスを is_default フラグ付きで一覧表示します。type で絞り込めます
  • current — デフォルトの入力デバイス名と出力デバイス名を取得します
  • switch_output/switch_input — 大文字と小文字を区別しない部分一致で名前を指定します("MacBook" は "MacBook Pro Microphone" に一致します)
  • 音量レベルは別のツールで制御します(macos_control_volume)
  • SwitchAudioSource CLI が必要です(brew install switchaudio-osx)。型付きエラー:device_not_found、switchaudio_unavailable

macos_control_appearance ツール
  • get — dark_mode: true/false を返し、action もそのまま返します
  • set には mode: "dark" | "light" | "toggle" が必要です — dark/light は冪等で、toggle は呼び出すたびに切り替わります
  • System Events をスクリプトで操作します。Automation > System Events が拒否されると、型付きエラー accessibility_required が発生します

macos_control_system ツール
  • lock — アクセシビリティ経由で ⌃⌘Q を実行します。アクセシビリティが許可されていない場合は、ScreenSaverEngine バイナリにフォールバックします(キャンセルされた呼び出しはフォールバックしません)
  • sleep_display — pmset displaysleepnow を実行します。権限は不要です
  • どちらの操作も即座に実行され、任意の入力(スリープ解除/ロック解除)で元に戻せます

macos_take_screenshot ツール
  • target:screen(メニューバーがあるメインディスプレイのみ)、display(0 始まりの整数 display_index。デフォルトは 0。macos_manage_displays action=list が報告する index)、region(ピクセル単位の矩形。width/height は 0 より大きい値)では、画面収録の許可は不要です。window(app_name で指定。macos_manage_windows と同様に、大文字と小文字を区別せず、アプリケーション名、ローカライズされた名前、またはプロセス名で照合し、そのアプリの画面上で最前面にあるウィンドウをキャプチャします)には画面収録の許可が必要です。画面収録の確認で判定できない場合もウィンドウのキャプチャは実行され、理由が notice に記載されます
  • 常にフル解像度の PNG を保存します。path を省略する(または "" を渡す)と、MACOS_SCREENSHOT_DIR(未設定の場合は ~/Desktop)に新しい screenshot-<timestamp>.png を保存します。既存ファイルは置き換えず、代わりに -2、-3、…を付加します。カスタムの path は .png で終わる必要があります(大文字と小文字は区別しません)。~/ はホームディレクトリに展開されます。ディレクトリは存在している必要があり、シンボリックリンクを解決した後の場所が MACOS_SCREENSHOT_DIR、/tmp、またはホームディレクトリのいずれかの配下でなければなりません。返される path は解決済みのパスです(/tmp のパスは /private/tmp 配下として報告されます)
  • 既存のエントリは置き換えません。パスがすでに存在する場合、overwrite: true が指定されていない限り path_exists エラーになります。overwrite: true が指定されている場合も、呼び出し時の確認で path に見つかった通常の .png ファイルのみを置き換えます(シンボリックリンクやディレクトリは置き換えません)。確認後に path に作成されたエントリや、そのファイルの代わりに置かれたエントリは置き換えず、path_exists エラーになります
  • すべての呼び出しは、開始から 55 秒以内に完了します。app_name の検索時間も含まれます。超過した場合はタイムアウト(-32004)として失敗し、何も書き込みません。キャンセルされたリクエストも何も書き込みません
  • include_data=true を指定すると、長辺が最大 1024 px(キャプチャがそれより小さい場合は元のサイズ)の JPEG プレビューを品質 70 で返します。これは最初の content[] ブロック(image/jpeg)として返され、structuredContent 内では base64 の preview と preview_width/preview_height としても返されます
  • width/height(およびプレビューの寸法)は、画像ファイルのヘッダーから読み取られます
  • 型付きエラー:screen_recording_required、window_not_found(アプリが起動していない場合、または画面上にウィンドウがない場合。ウィンドウ検索中に osascript がタイムアウトまたは失敗した場合は、独自のエラーが維持されます)、display_not_found、path_not_writable(解決または検索できないディレクトリも含みます。パスが長すぎる場合も含みます)、path_exists。.png で終わらない path、U+0000 を含む path、またはファイル名や解決後のフルパスがファイルシステムの上限(名前あたり 255 バイト、パス全体で 1024 バイト)を超える path は、理由 invalid_arguments を伴う -32602 として拒否されます
macos_manage_displays ツール
  • list — ディスプレイごとに、index(NSScreen.screens 内の0始まりの位置。macos_take_screenshot と macos_manage_windows が使用する display_index。無効化されたディスプレイなど、NSScreen エントリーがない場合は null)、永続 ID、種類("MacBook built in screen" または "<N> inch external screen")、解像度、リフレッシュレート(macOS が報告しない場合は "N/A")、原点、回転、スケーリング、有効状態(別のディスプレイをミラーリングしている場合も true)を返します。さらに、現在の配置を再現する displayplacer コマンドである current_config と、MACOS_DISPLAY_LAYOUTS で設定された名前(設定がない場合は [])を示す layouts も返します。MACOS_DISPLAY_LAYOUTS が無効な場合でも list は成功し、layouts を省略して、notice に変数名を示します。NSScreen の読み取りに失敗した場合は index を省略し、その理由を notice に示します。これには、並行する System Events の列挙が完了するまで15秒待機した読み取りも含まれます
  • apply_layout — MACOS_DISPLAY_LAYOUTS の名前付きプリセットを有効にします(list が layouts として返す名前のいずれか)。呼び出し元から displayplacer の生の引数を受け付けることはありません。MACOS_DISPLAY_LAYOUTS が無効な場合、apply_layout は layouts_invalid(ConfigurationError)として失敗し、layout_not_found にはなりません
  • displayplacer CLI が必要です(brew install displayplacer)。型付きエラー:displayplacer_not_found、displayplacer_output_unrecognized、layout_not_found、layouts_invalid
  • displayplacer の実行に失敗した場合(終了コードが0以外、シグナル、タイムアウト)、出力内容を返すのではなく呼び出しが失敗します。ディスプレイブロックに、一覧表示で値を返す項目の行が欠けている場合、または一覧表示に配置コマンドがない場合は、displayplacer_output_unrecognized として失敗します。displayplacer 1.3.0 と 1.4.0 の両方を読み取ります

macos_send_notification ツール
  • title は必須です。body、subtitle、および sound=true(デフォルトの通知音)は任意です
  • 呼び出すたびに新しい通知が作成されます(冪等ではありません)
  • 通知の投稿に権限は必要ありません。おやすみモードなどの集中モードが有効な場合、そのモードで投稿アプリが許可されていない限り通知は無音になります

macos_manage_focus ツール
  • get — ベストエフォートで、~/Library/DoNotDisturb/DB/Assertions.json を読み取り、status: "active" | "inactive" | "unknown" を返します。このファイルを読み取れない、または解析できない場合(サーバープロセスに読み取りが許可されていない場合など)は、reason を伴う unknown を返します。キャンセルされた呼び出しはキャンセルとして処理され、unknown にはなりません
  • set — Shortcuts ライブラリから "Set Focus" という名前のショートカットを実行し、JSON 入力として {"mode": …, "enabled": …} を渡します。このショートカットは組み込みではありません。Get Dictionary from Input の出力を Set Focus アクションにつなぐショートカットを作成してください。mode は設定済みの集中モード名と大文字小文字も含めて完全に一致する必要があります(例:"Do Not Disturb"、"Work")。enabled のデフォルトは true です。結果には mode と enabled がそのまま返されます。success: true はショートカットがエラーなく完了したことを意味します(集中モードの状態は再読み取りされません)
  • 型付きエラー:shortcuts_unavailable(shortcuts CLI が見つからない、または "Set Focus" という名前のショートカットがない)、shortcut_failed(ショートカットがエラーで終了し、エラーテキストを含む)。ショートカットの実行が15秒を過ぎても続いている場合は停止され、Timeout エラーとして報告されます。呼び出しがキャンセルされた場合は実行を停止し、キャンセルとして処理されます

macos_manage_finder ツール
  • frontmost_path — アクティブな Finder ウィンドウの POSIX パス。ウィンドウが開いていない場合は null です。キャンセルされた呼び出しはキャンセルとして処理され、null にはなりません
  • get_selection — 選択した項目の POSIX パス
  • reveal(open -R)、open_with(open -a <App>、または app_name を省略した場合はデフォルトのアプリ)、trash(ゴミ箱に移動します。復元可能で、完全に削除されることはありません)
  • open_with と trash は、open または Finder を呼び出す前にパスの存在を確認します
  • frontmost_path、get_selection、trash は Finder をスクリプトで操作するため、Automation > Finder の権限が必要です。reveal と open_with は権限を必要としません
  • 型付きエラー:finder_not_open、path_not_found、app_not_found(open_with で指定したアプリが不明)、trash_refused(Finder が既存の項目を拒否した場合。ロック中、使用中、またはボリュームにゴミ箱がないなど)、accessibility_required

macos://system/info リソース
  • 現在の macOS システムスナップショットを application/json で返します。バッテリー、電源、Wi-Fi 接続とネットワーク名、ホスト名、バージョン、稼働時間、ディスプレイ数、unavailable が含まれます
  • 同じデータは macos_get_info からも取得できます

macos://audio/devices リソース
  • 現在のデフォルトデバイスを含む、すべてのオーディオ入力・出力デバイスを application/json で返します
  • SwitchAudioSource CLI が必要です
  • 同じデータは macos_control_audio(action=list)からも取得できます

macos://displays リソース
  • 接続されているディスプレイの一覧を application/json で返します。index、永続 ID、タイプ、解像度、原点、回転、スケーリング、有効状態、current_config が含まれます。NSScreen の読み取りに失敗した場合は、notice(および index なし)が含まれます
  • displayplacer CLI が必要です
  • 同じデータは macos_manage_displays(action=list)からも取得できます

機能

@cyanheads/mcp-ts-core を基盤としています。stdio および Streamable HTTP トランスポート、プラグイン可能な認証(none/jwt/oauth)、切り替え可能なストレージ(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1)、オプションの OpenTelemetry トレーシングに対応した構造化ロギングを備えています。

macOS 固有の機能:

  • osascript サービスは、設定可能なタイムアウトで JXA(runJxa)と AppleScript(runAppleScript)の両方を実行します
  • SwitchAudioSource と displayplacer の連携はオプションの依存関係です。呼び出しごとに PATH、/opt/homebrew/bin、または /usr/local/bin から検出されます。CLI が見つからない場所では、該当ツールはインストール手順とともに ServiceUnavailable を返します
  • macOS のシステムバイナリ(osascript、screencapture、sips、pmset、networksetup、system_profiler など)は絶対パスで実行されるため、ホストの PATH によって実行されるバイナリが変わることはありません
  • screencapture は保存先の隣にある非公開ディレクトリにファイルを書き込み、この呼び出しで確認していないファイルを置き換えることなく PNG を配置します。sips は JPEG プレビューを作成し、画像サイズは PNG/JPEG ヘッダーから取得します
  • バッテリー情報には pmset、Wi-Fi には networksetup と ifconfig、バージョンには sw_vers、ディスプレイには system_profiler -json SPDisplaysDataType、ホスト名と稼働時間には Node の os を使用します
  • 権限を優先する設計です。ツールが Forbidden を返す前に、macos_check_permissions が、どのプロセスにどの権限が必要なのかを正確に報告します

エージェントに適した出力:

  • 権限エラーには accessibility_required 理由と、実際に拒否された権限に対応する付与手順が含まれます。対象は Privacy & Security > Accessibility、または名前が示されたアプリの Privacy & Security > Automation です
  • アクションごとの必須引数が不足している場合(mode を指定しない set、app_name を指定しない quit)、または AppleScript リテラルで表現できないテキスト(U+0000、対応するサロゲートのないサロゲート)がある場合は、何も実行される前に拒否されます。この場合は -32602、理由 invalid_arguments、送信すべき内容を示すヒントが返されます。各複数アクションツールの inputSchema には、アクションごとの要件が示されています
  • エラーには失敗したプログラム自身のエラーテキストが含まれ、コマンドラインやスクリプトソースは含まれません
  • オプションの CLI 依存関係がない場合、必要な brew install コマンドを正確に示した ServiceUnavailable が返されます
  • macos_manage_windows は各ウィンドウに display_index を報告します。これはウィンドウが最も大きく重なっているディスプレイを示し、不明な場合は null となります。これにより、エージェントは複数ディスプレイのレイアウトを把握できます
  • macos_take_screenshot は、フル解像度でのディスクへの書き込みとオプションのプレビューを分けています。プレビューは画像コンテンツブロックとして送信され、structuredContent には base64 として含まれるため、どちらの出力にも含まれます

はじめに

このサーバーはローカル専用で、実行されている macOS システムを操作します。MCP クライアントでは STDIO トランスポートを使用してください。

以下を MCP クライアントの設定ファイルに追加します。

{
  "mcpServers": {
    "macos-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/macos-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

または npx を使用します(Bun は不要です)。

{
  "mcpServers": {
    "macos-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/macos-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Streamable HTTP を使用する場合は、トランスポートを設定してサーバーを起動します。

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
前提条件
  • macOS 13(Ventura)以降。
  • Bun v1.4.0 以降(または Node.js v24 以降)。
  • 任意:オーディオルーティング用の SwitchAudioSource(brew install switchaudio-osx)。
  • 任意:ディスプレイ管理用の displayplacer 1.3.0 または 1.4.0(brew install displayplacer)。

どちらの任意の CLI も、Apple Silicon(/opt/homebrew/bin)または Intel(/usr/local/bin)の Homebrew から、あるいは PATH 上の任意の場所から使用できます。

一部のツールでは、ターミナルまたは MCP ホストアプリに macOS のアクセス許可が付与されている必要があります。

アクセス許可必要とする機能
アクセシビリティmacos_manage_windows(list を含むすべてのアクション)、macos_manage_apps(非表示/表示。frontmost はこれを使って window_title を読み取ります)、macos_control_system(ロックのキー入力。許可がない場合はスクリーンセーバーにフォールバックします)
画面収録target=window を指定した macos_take_screenshot
オートメーション > Finderaction=frontmost_path、get_selection、または trash を指定した macos_manage_finder

アクセス許可が必要な操作を実行する前に、macos_check_permissions で現在の状態を確認してください。

インストール
  1. リポジトリをクローンします:
git clone https://github.com/cyanheads/macos-mcp-server.git
  1. ディレクトリに移動します:
cd macos-mcp-server
  1. 依存関係をインストールします:
bun install
  1. 環境を設定します:
cp .env.example .env
# edit .env if you want to set MACOS_SCREENSHOT_DIR or MACOS_DISPLAY_LAYOUTS

設定

変数説明デフォルト
MACOS_SCREENSHOT_DIRスクリーンショットファイルのデフォルトディレクトリ、およびカスタムの path が解決される可能性のあるディレクトリの一つです(/tmp とホームディレクトリも対象です)。~ とシンボリックリンクは解決されます。~/Desktop
MACOS_DISPLAY_LAYOUTSレイアウト名を、空でない displayplacer 引数文字列に対応付ける JSON オブジェクトです。macos_manage_displays action=apply_layout で使用されます。action=list は名前を layouts として返します。値が無効な場合、apply_layout のみが失敗します。{}
MCP_TRANSPORT_TYPEトランスポート:stdio または http。stdio
MCP_HTTP_PORTHTTP サーバーのポート。3010
MCP_AUTH_MODE認証モード:none、jwt、または oauth。none
MCP_LOG_LEVELログレベル。info
MCP_SESSION_MODEセッションストレージ:auto、stateful、または stateless(HTTP のみ)。このサーバーはセッションごとの状態を保持しないため、.env.example では stateless を明示的に設定しています。stateless(src/index.ts で宣言)
OTEL_ENABLEDOpenTelemetry の計装を有効にします。false

オプションの上書き設定の全一覧については、.env.example を参照してください。

ディスプレイレイアウトの例:

# Get the current displayplacer command for your setup:
displayplacer list

# Then configure named layouts in your env:
MACOS_DISPLAY_LAYOUTS='{"office":"\"id:1234 res:2560x1440 hz:60 color_depth:8 scaling:on origin:(0,0) degree:0\" \"id:5678 res:1920x1080 hz:60 color_depth:8 scaling:on origin:(2560,0) degree:0\""}'

各画面には、displayplacer list が配置を出力する形式の、引用符で囲まれた個別のセグメントが割り当てられます。レイアウト値に引用符で囲まれたセグメントがない場合、単一の引数として displayplacer に渡されます。macos_manage_displays action=list は、同じ画面ごとの引用符付きセグメントを含む current_config を返し、設定済みの名前を layouts として返します。

サーバーの実行

ローカル開発
# One-time build
bun run rebuild

# Run the built server
bun run start:stdio

# Run checks
bun run devcheck   # Lint, format, typecheck, security, changelog sync
bun run test       # Vitest test suite
bun run lint:mcp   # Validate MCP definitions against spec

プロジェクト構成

ディレクトリ用途
src/index.tscreateApp() のエントリーポイント — ツール/リソースを登録し、サービスを初期化します
src/config/server-config.tsMACOS_SCREENSHOT_DIR と MACOS_DISPLAY_LAYOUTS の環境変数を解析します
src/mcp-server/tools/definitions/13 個のツール定義(macos-*.tool.ts)
src/mcp-server/tools/action-requirements.tsアクションごとの引数要件 — 入力スキーマで適用され、inputSchema で通知されます
src/mcp-server/resources/definitions/3 個のリソース定義(macos-*.resource.ts)
src/services/osascript/タイムアウト設定と権限拒否の分類に対応した osascript JXA および AppleScript ランナー、呼び出し元のテキスト用 AppleScript 文字列リテラル、実行中のアプリ名の解決機能
src/utils/exec-failure.tsCLI 呼び出し失敗時に呼び出し元へ返す安全なエラーテキスト(コマンドラインは含めません)
src/services/binaries/binary-paths.tsmacOS システムバイナリの絶対パス、および呼び出しごとの PATH と displayplacer、SwitchAudioSource の Homebrew 検索
src/services/permissions/プロンプトを表示しないアクセシビリティ、画面収録、オートメーション > Finder のチェック
src/services/audio/SwitchAudioSource によるデバイス一覧表示と切り替え
src/services/display/displayplacer の一覧表示とレイアウト適用、および各ディスプレイのインデックスを取得する JXA NSScreen 読み取り
src/services/screencapture/screencapture による PNG キャプチャ、パスチェックと上書きしない配置、sips による JPEG プレビュー
src/services/system-info/pmset/networksetup/ifconfig/sw_vers/system_profiler によるバッテリー、Wi-Fi、バージョン、ディスプレイ数の取得、node:os によるホスト名と稼働時間の取得
tests/tools/ツール定義に対応するツールテスト

開発ガイド

開発ガイドラインとアーキテクチャ上のルールについては、CLAUDE.md を参照してください。概要は次のとおりです。

  • ハンドラーは例外をスローし、フレームワークが捕捉します — ツールのロジック内で try/catch を使用しません
  • リクエスト単位のログには ctx.log を使用し、console は呼び出しません
  • 実際のシステム/CLI の状態を読み取り、決して捏造しません — OS が回答できない場合(デスクトップでのバッテリー情報や、Focus の状態ファイルを読み取れない場合の Focus の状態など)は推測せず、null または unknown を返します
  • サービスは createApp() でシングルトンとして初期化され、get*Service() アクセサーからアクセスします

貢献

Issue を歓迎します。提出前にチェックとテストを実行してください。

bun run devcheck
bun run test

ライセンス

Apache-2.0 — 詳細は LICENSE を参照してください。

コメント

MCP は初めてですか?

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

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