termal.in

← ブログ

Claude Code と Cursor からデータベースを(安全に)クエリする:MCP 設定ガイド

· Termalin Team claude-codecursormcpdatabasetutorial

データベースを読めるエージェントは、本来なら SQL エディターを開いて調べるような問いに答えます。「火曜日になぜサインアップが落ちたのか?」「1 時間以上 pending で止まっている注文はどれか?」「events テーブルには実際に何が入っているのか?」クエリの能力があれば、モデルは数秒で答えます。なければ推測します。役に立つのは SQL そのものではありません。Claude Code も Cursor も SQL は問題なく書けます。役に立つのは、エージェントに、認証情報を渡さずに読み取りを実行する手段を与えることです。その受け渡しこそが摩擦のすべてで、この記事では両方のツールについてそれを順に見ていきます。

なぜデータベースの接続文字列をエージェントに貼り付けるのは取り消せない一手なのか(英語)については、別の記事で書きました。その資格情報は bearer アクセス(持っているだけで使える)で、読み取りだけでなく書き込みも削除もでき、いったんモデルのコンテキストを通ってしまうと「共有をなかったこと」にはできません。安全性のモデルはそちらを読んでください。ここではそれを前提として、配線を済ませます。短く言えば、クライアントが資格情報を保持し、エージェントはスコープされた、既定で読み取り専用の依頼を得ます。

必要なもの

  • Termalin——デスクトップアプリで、Free プランで十分です。MCP サーバーを内蔵した SSH・データベースクライアントで、あなたのエージェントが話す相手はこのローカルサーバーです。
  • Termalin の Data クライアントに保存したデータベース接続を少なくとも 1 つ——Postgres、MySQL、SQLite、SQL Server、ClickHouse、MongoDB、Redis など。最初の実行には、失っても困らないものを選びます。分析用のレプリカ、ステージングのデータベース、コピーなどです。
  • アプリと同じマシン上の Claude Code または Cursor。データベースのツールは稼働中のデスクトップアプリを動かすので、エージェントとアプリは 1 台のマシンを共有します。

1 つ前提を揃えておきます。Claude Code と Cursor では、データベースアクセスはローカルの stdio MCP サーバーを通るので、エージェントはアンロック済みのデスクトップアプリと同じマシンにいる必要があります。(ホスト型の経路もあります。ホスト型の MCP サーバー——claude.ai、ChatGPT、Claude Code、Cursor 向けにサインインする termal.in/mcp、または API キーを使う termal.in/api/v1/mcp——は、登録済みサーバーのデータベースを、サーバー自身のローカルなデータベースの信頼を使ってパスワードなしでクエリでき、デスクトップアプリを動かす必要もありません。デスクトップアプリの Data クライアントに保存した接続については、欲しいのはローカルのサーバーのほうです。)

ステップ 1:エージェントのデータアクセスを有効化する

これは既定でオフで、意図的にそうしています。設定 → エージェントを開いて、「Let agents query your databases」(エージェントにデータベースへのクエリを許可) を有効化します。サブタイトルがその方針を明記しています:既定ではオフ。接続側がフルアクセスを許可しない限り、読み取り専用のままです。 有効にするまで、どのデータベースツールも database access for agents is off — enable it in Settings → Agent を返して、それで終わりです。

先へ進む前に、身につけておく価値のある既定値が 2 つあります:

  • これは、稼働中のアプリの上に重ねる、2 つ目のオプトインです。 サーバーへのエージェントアクセスを有効にしても、データベースアクセスは有効になりません。これは独立したスイッチです。あなたが決断するまで、何も公開されません。
  • どの接続も、エージェントにとっては読み取り専用です。 マスタースイッチをオンにしても、各クエリは実行前にチェックされます。書き込みが通るのは、その特定の接続のエージェントポリシーをフルアクセスに上げた場合だけで、これは接続ごとの選択であって、全体に効くものではありません。いまは読み取り専用のままにしておきます。

資格情報そのものは一切動きません。接続のホスト・ポート・パスワードはアプリのボールトの中にとどまり、エージェントができるのは、稼働中のアプリにクエリの実行と行の返却を依頼することだけです。エージェント(あるいはプロンプトインジェクション)が読める接続文字列は、設定ファイルのどこにもありません。

ステップ 2:ローカルの MCP サーバーを登録する

Claude Code——コマンド 1 つ:

claude mcp add termalin -- <path>/termalin-mcp

<path> は、termalin-mcp バイナリの場所に置き換えます(アプリがその場所を案内してくれます)。Claude Code を再起動すると、ツールを拾います。

Cursor——Cursor は MCP サーバーを JSON ファイルから読みます。そのプロジェクト限定ならプロジェクトルートの .cursor/mcp.json、どこでもサーバーを使えるようにするなら ~/.cursor/mcp.json です。ローカルの stdio サーバーの場合、エントリはコマンドとその引数です:

{
  "mcpServers": {
    "termalin": {
      "command": "<path>/termalin-mcp",
      "args": []
    }
  }
}

グローバルのファイルが妥当な選択です。データベースアクセスはリポジトリごとの関心事ではありません。Cursor を再起動(または設定内で MCP の一覧を再読み込み)し、サーバーが実行中と表示されることを確認します。これは、Cursor の SSH ウォークスルーや Claude Code のそれ(英語)で使うのと同じ登録です。サーバーは 1 つで、いまやそれが SSH のツールと並んでデータベースのツールも運びます。

ステップ 3:ツールと、最初の本物のタスク

サーバーを登録し、スイッチをオンにすると、エージェントには 4 つのデータベースツールが見えます:

data_list     # your saved connections: id, name, engine, and whether the agent may write
data_tables   # tables / collections / measurements for a connection, with row counts
data_schema   # one table's columns: name, type, nullable, primary key
data_query    # run a query in the connection's own language; default cap 200 rows

これらは、あなたが手でデータベースを探るときの手順を映しています。つながっているものを一覧し、テーブルを見て、テーブルを記述し、クエリを実行する。data_query は、接続が話す言語なら何でも話します。リレーショナルエンジンと ClickHouse には SQL、Neo4j には Cypher、Redis にはそのコマンド、MongoDB には collection {filter} です。そして行を返しますが、呼び出しごとに引き上げられる上限(maxRows)までで、既定は 200 です。これにより、エージェントが誤って 100 万行をコンテキストに引き込むことを防ぎます。

では、デモ用のクエリではなく、実際に尋ねるであろう問いを与えます:

ダッシュボードによると火曜日にサインアップが落ちた。分析用データベースを使って、何が起きたのか突き止めて。

エージェントがツールを順に使う様子を見ましょう:

  1. data_list——analytics の接続を見つけ、エンジンが Postgres であることを確認し、エージェントにとって読み取り専用だと把握します。
  2. data_tables——テーブルを一覧し、signups と signup_events を見つけ、どれをクエリする価値があるか知るために行数を読みます。
  3. signups に対する data_schema——カラム(created_at、source、status など)を把握し、日付別・ソース別に切り分ける方法が分かります。
  4. data_query——SELECT date_trunc('day', created_at) AS day, source, count(*) FROM signups WHERE created_at >= now() - interval '10 days' GROUP BY 1, 2 ORDER BY 1 のようなものを実行し、行を読み戻します。

行が物語を語ります。ある source が火曜日にゼロになった(紹介リンクが壊れていた)のかもしれませんし、合計は保たれたのに status = 'failed' が急増した(プロバイダーの障害)のかもしれません。いずれにせよ、エージェントは推測ではなく実際のスキーマからクエリを組み立て、持っていたのは「尋ねる能力」以上の何物でもありませんでした。結果が 200 行の上限で切り詰められた場合は、その旨を伝え、さらに押し通そうとするのではなくクエリを絞り込みます。

どこに境界があるか

手短にします。安全性の記事(英語)が全体を扱っているからです。ただし、あなたが頼っている既定値は以下のとおりです:

  • 既定で読み取り専用。 SQL 系のエンジンでは、読み取りの動詞だけが通ります——SELECT、SHOW、DESCRIBE、EXPLAIN、WITH、PRAGMA。Redis では読み取りコマンドだけ、MongoDB では $out/$merge を伴う集計がブロックされ、Neo4j では CREATE/MERGE/DELETE/SET/DROP がブロックされます。混乱したり乗っ取られたりしたモデルが得るのは読み取りであって、DROP ではありません。
  • 全体ではなく、接続ごと。 分析用レプリカは、本番のプライマリとは別の決定です。一方をフルの書き込みアクセスに上げても、もう一方には影響しません。
  • トグル 1 つでオフ、そして資格情報を保持するのはアプリです。そもそも何も共有されていないので、オフにしてもコピーは残らず、ローテーションすべきパスワードもありません。

機微なものには、両方を行ってください。Data 接続をリードレプリカか最小権限のデータベースロールに向け、かつエージェントを読み取り専用のままにします。クライアント側のゲートは間違いを捕まえ、データベースの権限付与が上限を定めます。

ツール別の注意

  • Cursor は既定で、ツール呼び出しのたびに確認します。最初の数セッションはこれをオンのままにしてください。すべての data_query を実行前に目にでき、エージェントが提案する SQL を読めます。自動承認は 1 つずつ広げていく便利機能です。data_list と data_schema はまず素通しさせても安全で、data_query は最も長く手動のままにしておくべきものです。
  • Claude Code は、各ツール呼び出しを引数つきでインラインに表示するので、クエリのテキストは実行前にトランスクリプトに出ます。あなたはエージェントの SQL を読んでいるのであって、そのまとめを信用しているのではありません。そしてすべての呼び出しはエージェントに帰属づけられるので、午前 2 時でも「これはそれが読んだ」と「これは自分が読んだ」を見分けられます。

Termalin がどこにはまるか

「エージェントをデータベースにつなぐ」ガイドの多くは、接続文字列を設定ファイルに貼り付けるところで終わっていて、それはエージェントに、あなたのアプリと同じ書き込み・削除の力を静かに与えてしまいます。Termalin の Data クライアントはそれを逆にします。アプリがカストディアンになり、エージェントは稼働中のウィンドウを介して動かされる 4 つのスコープされたツールを得て、その能力全体は、あなたが別の決定を下すまで読み取り専用で、スイッチ 1 つでオフにできます。これは、私たちがエージェントの SSH アクセス(英語)や、MCP サーバーとは実際に何なのか(英語)に適用しているのと同じカストディ(預かり)の考え方です。データベースは、まずい書き込みが行数で測られる版にすぎません。まず 1 つの接続から始め、読み取り専用のままにし、何かを広げることを考える前に、本物の問いを尋ねてみてください。


Termalin は、MCP サーバーを内蔵し、接続ごとのエージェントポリシーを備えた、無料のクロスプラットフォーム SSH・データベースクライアントです。ダウンロードするか、資格情報を安全に扱う仕組みをお読みください。

まずは 1 台のホストで試してみてください。

Termalin は、あなたとあなたのエージェントのための高速な SSH クライアントです。

無料プラン · Pro を 14 日間お試し · 料金