福岡Rubyist会議05 のキーノートで yancya さんの最新 SQLQL の話を聞いて、そのあとのビアバーでも議論を深めた夜がありました。そこで受け取った考え方が、わたしが Claude に自分のデータを渡すときの設計である chiebukuro-mcp の土台になっています。
書き上がっているコードを手元に置いたまま、改めて最新のキーノート資料を読み直して、何が同じで、どこがコンテキスト差からずれているのかを自分のために整理しておきたくなりました。yancya さん、ありがとうございます。
同じなのは抽象的な設計思想
chiebukuro-mcp が SQLQL から受け取ったのは、次の5点で、yancya さんの論の中にあったものを、SQLite + MCP の文脈に載せ替えを行いました。
1. SQLそのまま
「SQL をそのまま送らせる」という設計思想。「要するに GraphQL っぽいことを SQL でやりたい」という本質定義は、chiebukuro-mcp の設計意図とそのまま一致しています。MCP ツール経由で Claude が自分で SQL を組み立てて送る、という使い方は、SQL を API 言語として扱う SQLQL の発想の延長にあります。
2. 何を認めるかの保証
「read-only をサーバー側で保証する」。SELECT と WITH のみ通して、他を拒否します。改竄不可能性をサーバー側に握らせるところです。
3. 責務分離
CQRS の思想です。SQLQL では CQRS (Command Query Responsibility Segregation) が読み書き分離の実装パターンとして明示的に据えられていました。chiebukuro-mcp はこの Query 側に完全に寄った実装で、書き込みは別系統のパイプラインに任せて、MCP サーバーは純粋に読み取り窓口として振る舞います。SQLQL 全体の読み側を特化して引き受ける、という位置づけに自然に収まっていました。
4. 事前定義をクライアントが活用
「サーバー側が事前に書いた SQL をクライアントが呼び出す」という枠。SQLQL ではストアドプロシージャ + SECURITY DEFINER で実現されていて、chiebukuro-mcp では recipes という形で実装しています。_sqlite_mcp_meta に recipe_sql テンプレート(:key プレースホルダ付き)を置いて、MCP ツール経由で named parameter を埋めて実行します。SECURITY DEFINER そのものは SQLite にはありませんが、「サーバー側が書いたクエリをクライアントが呼ぶ」という発想は同じ枠です。
5. 防御手段
DB 層を防御の第1層に置く考え方。SQLQL は DB ユーザーに SELECT 権限のみ付与して副作用を DB 層でも弾く設計で、chiebukuro-mcp は SQLite の read-only 接続モード (?mode=ro) に寄せる方向で育てています。アプリ層より下にも層を置いておく、という発想は同じです。
コンテキスト差で違ってくるところ
一方で、デプロイメントコンテキストの違いから、必要な設計が変わるところもあります。前提が違うところで読み替えが必要になる、というだけの話です。
| 軸 | SQLQL | chiebukuro-mcp |
|---|---|---|
| デプロイ先 | (おそらく)HTTP、不特定多数のクライアント | stdio、ローカルの自分の Claude |
| クエリ作者 | 人間、フロントエンドシステム | LLM (Claude) |
| 防御の層数 | Web的な多層防衛 | SELECT/WITH 入口判定 + 読み取り専用オープン |
| 分散 | Webシステムとしての各種方式 | なし。ローカルの SQLite ファイル群に分かれているだけ |
chiebukuro-mcpはローカルMCPのためネットワーク境界を越えないため、一般公開のWeb的な多層防衛までは盛り込んでいません。クエリを書くのが 自分が使うLLM だから、DBを読み取り専用で開いて破損・改ざんだけシンプルにガードしようという判断になっています。
関連付け
yancya さんのスライドで「腹の底にネタを持ってると、なんでもそれに関連づけて考える」という話がありました。このSQLQLの話はそうして受け取り、わたしにとっての「腹の底のネタ」として持っていたのでしょう。