Calíopeのアプリアイコン

MCPサーバとしてのCalíope

MacのAIクライアントに、あなたのデータベースへのクエリーを任せる。読み取り専用、ループバックのみ、初期設定ではオフ。

macOSでは、CalíopeはModel Context Protocol(MCP)サーバとして動くことができます:同じMacで動くAIクライアント—Cursor、Claude Desktop、MCPを話すものなら何でも—が、あなたが公開を選んだ接続に対して、データベースの一覧、テーブルの説明、読み取り専用のクエリーの実行をCalíopeに頼みます。このページでは、そのサーバが何なのか、クライアントがそれを通して何ができるのか、応答する前に何が満たされていなければならないのか、そしてクライアントの接続方法を説明します。ツールの表は、それを提供しているコードから生成しています。

これは何か

Calíopeの中にあるHTTPサーバで、JSON-RPC 2.0を話し、プロトコルのバージョンは2025-06-18で、MCP-Protocol-Versionヘッダで知らせます。待ち受けるのは127.0.0.1だけ—このMacの上だけで、ほかのどこでもありません—で、ポートは変更しないかぎり41500です。ポートは自分で選べますが、アドレスは設定できません。ルートはPOST /mcpの1つで、initialize、ping、tools/list、tools/callに応答します。同じルートへのDELETEでセッションが終わります。

macOSにしかなく、初期設定ではオフで、Calíopeが開いているあいだしか応答しません:アプリを閉じると、もう一度開くまでツールは応答しなくなります。選んだポートをほかのプログラムがすでに使っている場合、Calíopeはそれを伝え、サーバを起動しません。

クライアントにできること

5つのツールだけで、ほかには何もありません。下の表は、サーバがtools/listで提供する配列からスクリプトが書いたもので、説明はクライアントが受け取るとおりの文面—このページが何語であっても英語—です。向こう側のモデルがどのツールを呼ぶかを決めるときに読むのは、その文だからです。パラメータはすべて文字列です。

ツールパラメータ説明
list_connections—Connections the user exposed to MCP. Returns id, name, engine, host.
list_databasesconnectionDatabases visible on a connection.
list_tablesconnection, databaseTables and views in a database.
describe_tableconnection, database, tableColumns, primary key, foreign keys and indexes of a table.
run_queryconnection, sqlRun ONE read-only SQL statement (SELECT/SHOW/EXPLAIN/DESCRIBE) on a connection. Rows are capped at 200.

SQLを実行するツールの背後には読み取り専用のゲートがあり、何かがデータベースサーバに届く前に確認します:

  • 1回の呼び出しに1つの文。2つの文、あるいは文がない場合は拒否します。
  • 読み取りだけ:SELECT、SHOW、EXPLAIN、DESCRIBE。INSERT、UPDATE、DROP、中に書き込みを含むWITH、書き込みを包んだEXPLAIN ANALYZE(サーバはそれを実行します)、SELECT … INTO(PostgreSQLではテーブルを作成します)、そしてサーバにファイルを書く読み取りは拒否します。ゲートは各文をMySQLとPostgreSQLの両方の規則で読み、どちらかが書き込みを見つければ拒否します。
  • ロックを取るものはなし。SELECT … FOR UPDATEとLOCK IN SHARE MODEは読み取りではありますが、トランザクションが終わるまでロックを保持するので、これも拒否します。
  • 最大200行。応答には、列、行、実際のrowCount、そして上限で切り捨てたときはtruncated: trueが入ります。上限は設定できません。
  • MongoDB、Redis、Valkey、Cassandra、ScyllaDBの接続は公開しません。ゲートで読むSQLがないからです:チェックできる接続の中に出てこず、ツールはMCPでは使えないと応答します。

ゲートはCalíopeの中にある構文上の許可リストで、文がサーバに届く前に確認します。読み取り専用のトランザクションではありません:副作用のある関数(pg_terminate_backend、setval、GET_LOCK、SLEEP)を呼ぶSELECTは通ってしまいます。だから、公開する接続は、書き込み権限も管理権限も持たないデータベースユーザのものにしてください。

データベースユーザに書き込み権限も管理権限もない接続を公開してください:MySQLとMariaDBではGRANT SELECT, SHOW VIEW ON *.* TO 'ai'@'%'、PostgreSQLでは見せたいスキーマへのSELECTだけを持ち、ほかには何も持たないロール、SQL Serverでは各データベースのユーザがdb_datareaderロールだけを持つログイン、ClickHouseではSELECTの権限とreadonly = 1の設定だけを持つユーザ、Oracle DatabaseではCREATE SESSIONと、見てよいテーブルへのREADだけを持つユーザです。

MCPで実行したものはすべて、自分で入力したものと同じように、接続と結果とともにCalíopeのクエリーログに残ります。ゲートが拒否したものはサーバに届かず、行も残しません。

クライアントを接続する

スイッチをオンにし、接続をチェックし、「設定をコピー」を押して、クライアントに必要なブロックをそのファイルに貼り付け、クライアントを再起動します。クリップボードには、実際のポートとキーがすでに入った2つのブロックが入ります—ここに<port>と<token>をプレースホルダとして示した2つと同じものです。

CursorはHTTPサーバを直接読みます。そのブロックは~/.cursor/mcp.jsonに入れます:

// Cursor — ~/.cursor/mcp.json
{
  "mcpServers": {
    "caliope": {
      "url": "http://127.0.0.1:<port>/mcp",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}

Claude DesktopはHTTPではなく標準入出力でしか話さないので、そのブロックではmcp-remoteを橋渡しに使います—そこでnpxがしているのはそれです。~/Library/Application Support/Claude/claude_desktop_config.jsonに入れます:

// Claude Desktop — claude_desktop_config.json
{
  "mcpServers": {
    "caliope": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://127.0.0.1:<port>/mcp",
               "--header", "Authorization:${AUTH}"],
      "env": { "AUTH": "Bearer <token>" }
    }
  }
}

クライアントは起動時に設定を読むので、新しいキーや新しいポートにしたら、もう一度貼り付けて再起動してください。

さらに詳しく

これについてはヘルプに3つのトピックがあり、アプリが表示するのと同じ文です:

そしてCalíopeの作り方では、このサーバをほかの構成要素と並べて位置づけています。