mcpField
D
db-gateway

db-gateway

ローカル
github.com/GuardBeeセキュリティ11 日前に更新

db-gateway について

db-gateway は LLM とデータベースの間に置く MCP サーバーです。データベースアクセスを管理したいチーム向けに、PII の自動マスキング、ロール別ルール、レート制限、クエリ監査を備えています。

主な機能

  1. 01PII の自動マスキング
  2. 02ロール別のテーブル・フィールドアクセス制御
  3. 03全体およびテーブル別のレート制限
  4. 04監査出力とクエリ履歴
  5. 05Prisma、SQL データベース、MongoDB 用アダプター
  6. 06任意で有効にする書き込み操作

活用シーン

  1. 01データベース結果の機密フィールドをマスキング
  2. 02エージェントのアクセス先を許可済みテーブルに限定
  3. 03拒否・実行済みのデータベースクエリを確認
  4. 04制御下でのデータ挿入・更新・削除

MCP 対応

MCP クライアントにデータベースのクエリ、スキーマ、状態、監査ログ用ツールを公開します。書き込みを有効にすると、挿入・更新・削除用ツールも利用できます。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"4hmetuyar-db-gateway": {
"command": "npx",
"args": [
"-y",
"@guardbee/mcp-db-gateway"
]
}
}
}
起動コマンドnpx -y @guardbee/mcp-db-gateway

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

パッケージ
npm@guardbee/mcp-db-gateway0.3.5

ツール

5

掲載時のツール一覧 · 2 週間前に更新

パラメーター型必須説明
limitintegerいいえゲートウェイの上限を適用する前に取得する最大行数(デフォルト:50)
tablestringはいクエリ対象のテーブル名
filterobjectいいえキーと値のフィルターペア。例:{ status: 'active' }

詳細

@guardbee/mcp-db-gateway

🇬🇧 英語 | 🇹🇷 トルコ語 | 🇨🇳 中国語 | 🇯🇵 日本語 | 🇰🇷 韓国語 | 🇧🇷 ポルトガル語 | 🇪🇸 スペイン語 | 🇩🇪 ドイツ語

npm version npm downloads License: MIT Smithery

KVKK / GDPR に準拠した MCP(Model Context Protocol)サーバーです。LLM とデータベースの間にセキュリティレイヤーを追加します。

データベースに直接クエリを実行する代わりに、Claude(またはその他の LLM)はこのゲートウェイを経由します。機密フィールドは自動的にマスキングされ、テーブルへのアクセスはロールによって制御され、すべてのクエリが監査ログに記録されます。

テレメトリーはデフォルトでオフです。GUARDBEE_TELEMETRY=1 を設定すると、サーバー、ツール、成功の有無、処理時間、およびファイルパスなどの短いパラメーター値が送信されます。content、token、password などの長い文字列やフィールドはプレースホルダーに置き換えられます。詳しくは @guardbee/mcp-telemetry をご覧ください。

Claude ──► MCP Gateway ──► Database
              │
              ├─ PII masking     (tcKimlik → [REDACTED])
              ├─ Role check      (ai-agent can only reach the products table)
              ├─ Rate limiting   (max 100 queries/minute)
              └─ Audit log       (every query is recorded)

機能

  • PII のマスキング — トルコの国民識別番号、IBAN、メールアドレス、電話番号、パスワードハッシュなどを自動的にマスキングします
  • ロールベースのアクセス制御(RBAC) — ロールごとのテーブル許可/拒否リストとフィールドルール
  • レート制限 — グローバルおよびテーブルごとのリクエストウィンドウ
  • 監査ログ — コンソール、ファイル、HTTP ウェブフックに書き込み可能です
  • Prisma / Postgres / MySQL / SQLite / MongoDB アダプター — 既存の PrismaClient、pg の Pool、mysql2 の Pool、better-sqlite3 の Database、または MongoDB の Db を直接接続できます
  • 書き込みのサポート(オプション) — insert/update/delete に対応します。デフォルトでは無効で、テーブルごとおよびロールごとの権限で制御され、保護対象フィールドのガードと「テーブル全体を変更しない」ためのセーフティーネットで保護されます
  • ユニットテスト 195 件 — マスキング、パイプライン、RBAC、レートリミッター、監査ログ、すべてのアダプター(読み取り+書き込み)を網羅しています

最近の変更(2026-09-15)

このパッケージの AI Gateway 拡張に関する取り組みに、3 つの新しいステップが追加されました。

1. query_audit_log ツール

以前、ゲートウェイの監査ログは書き込み専用でした。console/file/http シンクのいずれかに記録されるだけで、Claude 自身が「たった今何が起きたのか、どの呼び出しが拒否されたのか」を振り返って確認する方法はありませんでした。現在は確認できます。

// Tool called from the Claude side:
query_audit_log({ table: "orders", deniedOnly: true, limit: 20 })
  • 仕組み: AuditLogger に、設定されたシンク(audit.bufferSize、デフォルトは 200)から完全に独立した、常時有効のインメモリーリングバッファが追加されました。シンクが "http"(送信後の応答を待たない Webhook)の場合でも、このバッファを通じて履歴をクエリできます。プロセスが再起動するとバッファはリセットされ、audit.enabled: false の場合はデータが格納されません。
  • フィルター: table、tool(MCP ツール名。例:"delete_row")、operation(read/insert/update/delete)、deniedOnly(拒否された呼び出しのみ)、since(ISO 8601 タイムスタンプ)、limit(デフォルトは 50、最大 200)。結果は新しい順に返されます。
  • 合わせて修正した実際のバグ: registerDbTools(読み取りツール)と registerWriteTools(書き込みツール)は、それぞれ独自の GatewayPipeline/AuditLogger インスタンスを作成していました。そのため、insert_row/update_row/delete_row の呼び出しによる監査イベントは、query_audit_log が読み取るバッファには一度も記録されませんでした。互いを認識しない別々のバッファが二つ存在していたためです。現在、server.ts は単一の GatewayPipeline インスタンスを作成し、両方のツールグループで共有します。
  • テスト: src/__tests__/audit-logger.test.ts(10 件のテスト:バッファの上限、各フィルター、リングバッファの動作)に加え、pipeline.test.ts に 3 件のテストを追加しました(読み取りと書き込みが同じバッファに記録されること、deniedOnly と table フィルターが組み合わせて機能すること、audit.enabled: false の場合にバッファが空のままであることを検証)。
2. SQLite アダプター

ゲートウェイが Prisma/Postgres/MySQL に加えて better-sqlite3 でも動作するようになりました。

import Database from "better-sqlite3";
import { createServer, createSqliteAdapter } from "@guardbee/mcp-db-gateway";

const db = new Database("./app.db");
const server = createServer({}, createSqliteAdapter(db));
  • pg/mysql と同じセキュリティパターン: テーブル名とカラム名はパラメーター化できないため、SQL に埋め込む前に検証します。ここでは information_schema の代わりに SQLite の PRAGMA table_info(table) を使用します。形式チェックに失敗する名前(例:users"; DROP TABLE users;--)や、実際のスキーマに存在しない名前は、クエリが SQLite に送られる前に拒否されます。
  • better-sqlite3 はオプションの peerDependency に限られます。 ネイティブバインディングが必要なため、パッケージ自身の devDependencies には追加していません。実際のパッケージをインポートせず、pg/mysql のテストと同様に、SqliteQueryable インターフェースに一致するシンプルなモックオブジェクトを使ってテストを作成しました。
  • 挿入では RETURNING の代わりに lastInsertRowid を使用: SQLite の RETURNING のサポート状況はバージョンによって異なるため、MySQL アダプターの insertId と同じ方法を採用しています。テーブルに id カラムがあり、それがすでに data に含まれていない場合は、挿入された行に lastInsertRowid が付与されます。
  • 追加の修正: AuditEvent/AuditQueryFilter 型は、パッケージのルート(index.ts)からエクスポートされていませんでした。GatewayPipeline.queryAuditLog() の呼び出しを独自に型付けしたい利用者向けに、エクスポートを追加しました。
  • テスト: src/__tests__/sqlite-adapter.test.ts(21 件のテスト)。pg-adapter.test.ts と同じシナリオ一式をカバーします。テーブル一覧表示、フィルターあり/なしのクエリ、上限数、未知のテーブル/カラムの拒否、インジェクションの試みの拒否、挿入(ID の割り当てを含む)、更新、削除です。
3. MongoDB アダプター

ゲートウェイは、mongodb ドライバーの Db インスタンスにも対応するようになりました。

import { MongoClient } from "mongodb";
import { createServer, createMongoAdapter } from "@guardbee/mcp-db-gateway";

const client = new MongoClient(process.env.DATABASE_URL!);
await client.connect();
const server = createServer({}, createMongoAdapter(client.db("mydb")));
  • 異なる種類のリスクです。SQL インジェクションではなく、オペレーターインジェクションです。 pg/mysql/sqlite では、テーブル名やカラム名が SQL に埋め込まれるリスクがありました。MongoDB では識別子が埋め込まれることはありませんが、filter/data のキーが $where/$ne のような Mongo オペレーターの場合や、値が { $ne: null } のようなオペレーターオブジェクトの場合、ツールが宣言する「単純なキーと値の等価フィルター」が、気づかないうちに任意のクエリーに変わる可能性があります。このアダプターでは、以下をすべて事前に拒否します。
    • $ で始まるキー(filter と data の両方)
    • . を含むキー(ドット区切りのパス。例:"passwordHash.reset"。オペレーターに似たリスクがあるほか、findProtectedWriteFields の完全一致による照合を回避する手段にもなります(その glob 対応範囲外の場合))
    • スカラーでない(オブジェクト/配列)フィルター値。{ status: { $ne: "active" } } のようなオペレーターオブジェクトによる回避の試みも含みます
  • mongodb はオプションの peerDependency にすぎません。 SQLite アダプターと同様に、実際のパッケージをインポートせず、MongoDatabase インターフェースに合致するモックオブジェクトを使ってテストを作成しました。
  • 「テーブル」はコレクションを指します。 tables() は listCollections() に対応します。挿入時には、返される行に _id(ドライバーの insertedId)を付加します。更新では { $set: data } を指定して updateMany を実行し、削除では deleteMany を実行します。
  • テスト: src/__tests__/mongo-adapter.test.ts(19 件のテスト)。コレクション一覧、フィルターあり/なしのクエリー、上限、3 つのオペレーターインジェクションのケース($ で始まるキー、ドットを含むキー、オペレーターオブジェクトの値)、挿入/更新/削除をテストします。

クイックスタート

1. Smithery 経由でワンクリック接続

Smithery 経由でワンクリックで Claude Desktop に追加できます。

2. グローバルインストールで Claude Desktop に接続
npm install -g @guardbee/mcp-db-gateway

macOS の場合、~/Library/Application Support/Claude/claude_desktop_config.json に追加します。

{
  "mcpServers": {
    "guardbee-db-gateway": {
      "command": "guardbee-gateway",
      "env": {
        "DATABASE_URL": "postgresql://user:pass@localhost:5432/mydb"
      }
    }
  }
}

Windows: %APPDATA%\Claude\claude_desktop_config.json Linux: ~/.config/Claude/claude_desktop_config.json

Claude Desktop を再起動します。デモデータベースが自動的に読み込まれ、PII マスキングが有効になります。

3. プロジェクトで使用(Prisma)
npm install @guardbee/mcp-db-gateway
import { PrismaClient } from "@prisma/client";
import { createServer, createPrismaAdapter } from "@guardbee/mcp-db-gateway";

const prisma = new PrismaClient();

const server = createServer(
  {
    audit: { enabled: true, sink: "file", filePath: "./audit.jsonl" },
  },
  createPrismaAdapter(prisma)
);

Prisma を使用していない場合は、pg または mysql2 の接続を直接渡すこともできます。

// Postgres
import { Pool } from "pg";
import { createServer, createPgAdapter } from "@guardbee/mcp-db-gateway";

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const server = createServer({}, createPgAdapter(pool /*, { schema: "public" } */));
// MySQL
import mysql from "mysql2/promise";
import { createServer, createMysqlAdapter } from "@guardbee/mcp-db-gateway";

const pool = mysql.createPool(process.env.DATABASE_URL!);
const server = createServer({}, createMysqlAdapter(pool /*, { database: "shop" } */));
// SQLite
import Database from "better-sqlite3";
import { createServer, createSqliteAdapter } from "@guardbee/mcp-db-gateway";

const db = new Database("./app.db");
const server = createServer({}, createSqliteAdapter(db));
// MongoDB
import { MongoClient } from "mongodb";
import { createServer, createMongoAdapter } from "@guardbee/mcp-db-gateway";

const client = new MongoClient(process.env.DATABASE_URL!);
await client.connect();
const server = createServer({}, createMongoAdapter(client.db("mydb")));

セキュリティに関する注意: Prisma アダプターとは異なり、pg/mysql2/better-sqlite3 アダプターは生の SQL を生成します。テーブル名とカラム名はパラメーター化できないため、クエリーごとにライブスキーマ(information_schema、SQLite の場合は PRAGMA table_info)と照合して検証します。スキーマに存在しないテーブル名/カラム名(インジェクションの試みなど)は、SQL に渡される前に拒否されます。MongoDB アダプターは別のリスク(SQL ではなく「オペレーターインジェクション」)を防ぎます。詳しくは最近の変更をご覧ください。


MCP ツール

ゲートウェイは、常に以下の 5 つの読み取りツールを Claude に公開します。

ツール説明
query_tableテーブルの行をクエリーします(PII は自動的にマスキングされます)
list_tablesアクセス可能なテーブルを一覧表示します(ロールの制限が適用されます)
describe_tableテーブルのスキーマとマスキングポリシーを表示します
query_audit_logゲートウェイ自身の監査履歴をクエリーします(テーブル/ツール/操作/deniedOnly/since でフィルター可能)。メモリ内に保持され、audit.bufferSize が上限です。プロセスの再起動時にリセットされます
gateway_status有効な設定、ロール、レート制限の状態を表示します

writesEnabled: true の場合(書き込みのサポートを参照)、さらに 3 つの書き込みツールが追加されます。

ツール説明
insert_row新しい行を挿入します
update_rowフィルターに一致する行を更新します(空のフィルターは拒否されます)
delete_rowフィルターに一致する行を削除します(空のフィルターは拒否されます)

設定

createServer({
  // PII field rules (the first match applies)
  fieldRules: [
    { field: "tcKimlik",     strategy: "redact" }, // [REDACTED]
    { field: "iban",         strategy: "mask"   }, // TR32***890
    { field: "email",        strategy: "mask"   }, // ah***@example.com
    { field: "passwordHash", strategy: "redact" },
    { field: "*Token*",      strategy: "redact" }, // glob pattern
  ],

  // Table access rules
  tableRules: [
    { table: "audit_logs", access: "deny"  },
    { table: "users",      access: "allow", maxRows: 25 },
    // write: if unspecified, that table has no write permission at all (off by default)
    { table: "orders",     access: "allow", write: { insert: true, update: true, delete: false } },
  ],

  // Turn on the write tools (insert_row/update_row/delete_row) — false by default.
  // While false, these tools are never visible to Claude.
  writesEnabled: true,

  // How many rows update_row/delete_row may affect via one filter.
  // If exceeded, the operation is rejected before touching the database ("narrow your filter").
  maxAffectedRowsPerWrite: 10,

  // Default max rows
  defaultMaxRows: 50,

  // Rate limiting
  rateLimit: {
    enabled: true,
    windowMs: 60_000,          // 1 minute
    maxRequests: 100,           // global limit
    maxRequestsPerTable: 20,    // per table
  },

  // Audit log
  audit: {
    enabled: true,
    sink: "file",              // "console" | "file" | "http"
    filePath: "./audit.jsonl",
    // webhookUrl: "https://..."  (for sink: "http")
    bufferSize: 200,           // size of the in-memory history the `query_audit_log` tool reads
  },

  // Roles
  roles: [
    {
      name: "ai-agent",
      allowTables: ["products", "orders"],  // only these tables
      maxRows: 10,
      // If a role doesn't define write (undefined), write is COMPLETELY off for that role,
      // even if the table allows it. To permit writes, state it explicitly on the role too:
      write: { insert: true, update: true, delete: false },
    },
    {
      name: "analyst",
      denyTables: ["audit_logs"],           // this table is blocked
      fieldRules: [
        { field: "email", strategy: "allow" }, // email unmasked
      ],
      // write not defined → analyst can write nothing
    },
  ],

  // Active role (can also be set via the GATEWAY_ROLE env var)
  activeRole: "ai-agent",
});

マスキング戦略

戦略説明例
redactフィールド全体を削除します[REDACTED]
mask値の中央部分をアスタリスクで置き換えますah***@example.com / 530***67
hashSHA-256(先頭16文字)a665a45920422f9d
allow変更せずにそのまま通します[email protected]

Glob パターンに対応しています:*Password*、*Token*、*Secret*

テキスト列内の PII(piiScan)

フィールドルールは列名に基づいて適用されるため、自由記述のテキスト列(notes、description)にメールアドレス、TC kimlik、API キーが含まれることがあります。デフォルトでオフの piiScan は、フィールドルールが適用されないすべてのテキストフィールドで、値に基づいてこれらをマスキングします。ネストされたオブジェクトや配列も対象です。allow ルールを設定すると、そのフィールドでは無効になります。preset / enable / disable で検出器を選択します。セキュリティプロキシと同じプリセットを使用できます:ALL(デフォルト)、KVKK、IDENTITY、IDENTIFIERS、SECRETS。

createServer({ piiScan: { enabled: true, preset: "KVKK", disable: ["address"] } }, adapter);

CLI からは、GATEWAY_PII_SCAN=true(デフォルトのすべての検出器)または GATEWAY_PII_SCAN=KVKK(プリセット)を指定します。不明なプリセット名または検出器名を指定すると、起動時に失敗します。

piiScan.blockPatterns と piiScan.allowPatterns を使うと、セキュリティプロキシと同様に独自のパターンを追加できます。block は ID を <CATEGORY_n> としてマスキングし、allow は検出された値のテキスト全体が一致する場合にそのまま通します。block パターンが100 msの制限時間を超えると、マスキングされていない可能性のある行を返さず、クエリが失敗します。

createServer({ piiScan: { enabled: true, blockPatterns: [{ pattern: "CL-\\d{6}", category: "CLIENT_NO" }], allowPatterns: ["destek@acme\\.com\\.tr"] } }, adapter);

ロールベースアクセス制御(RBAC)

ロールはサーバーの起動時に、GATEWAY_ROLE 環境変数または config.activeRole を使って設定します。 Claude Desktop の各プロファイルまたはデプロイメントは、異なるロールで実行できます。

GATEWAY_ROLE=analyst node dist/cli.js

ルールの優先順位(高い順):

  1. グローバル tableRules の deny
  2. ロールの denyTables
  3. ロールの allowTables(ホワイトリスト。設定されている場合、テーブルはこのリストに含まれている必要があります)
  4. ロールの fieldRules → グローバル fieldRules

書き込みサポート(書き込み/挿入/更新/削除)

ゲートウェイはデフォルトで完全な読み取り専用です。LLM にデータの変更を許可するには、いくつかのゲートを意図的に解除する必要があります。

  1. writesEnabled: true — グローバルなキルスイッチです。false(デフォルト)の場合、insert_row/update_row/delete_row は Claude に一切表示されません。
  2. テーブル権限 — tableRules[].write.{insert,update,delete} — テーブルごとに設定します。すべてのテーブルでデフォルトはオフです。
  3. ロール権限(ロールが有効な場合)— roles[].write.{insert,update,delete}。ロールで write が一度も定義されていない(未定義)場合、そのロールでは書き込みが完全にオフになります。テーブルで許可されていても同様です。書き込みを許可するには、テーブルとロールの両方で明示的に true を指定する必要があります(AND ロジック。マスキングルールで使われる「ロールによる上書き」ロジックより意図的に厳格です)。

この3つのゲートに加えて、無効化できない保護機能が2つあります。

  • 保護フィールドのガード — LLM は fieldRules で redact/mask/hash に指定されたフィールド(例:tcKimlik、passwordHash)に値を書き込めません。insert_row/update_row の data にそのようなフィールドが含まれている場合、リクエスト全体が拒否されます。
  • maxAffectedRowsPerWrite — update_row/delete_row の実行前に、まずフィルターを読み取りクエリとして試します。該当する行数がこの上限(デフォルトは10)を超える場合、何も変更する前に操作が拒否されます。update_row/delete_row は空のフィルターも常に拒否します。このゲートウェイを通して「テーブル全体を更新/削除」することはできません。

すべての書き込み試行(許可・拒否を問わず)は監査ログに記録されます。ログには書き込まれたフィールドのみが記録され、data 自体は記録されません(監査ログ自体が PII の漏えい箇所になることはありません)。

createServer({
  writesEnabled: true,
  maxAffectedRowsPerWrite: 10,
  tableRules: [
    { table: "orders", access: "allow", write: { insert: true, update: true, delete: false } },
  ],
  roles: [
    { name: "ai-agent", allowTables: ["orders"], write: { insert: true, update: true, delete: false } },
  ],
  activeRole: "ai-agent",
});

Prisma アダプター

PrismaClient を直接渡すと、テーブル名からモデルへのマッピングが自動的に行われます。

クエリのテーブルPrisma モデル
"users"prisma.user
"audit_logs"prisma.auditLog
"orders"prisma.order
"orderItems"prisma.orderItem

開発

npm run dev          # dev mode via tsx
npm run build        # TypeScript compile
npm test             # 195 unit tests
npm run test:watch   # watch mode
npm run type-check   # type-check only

ライセンス

MIT — GuardBee

フィードバック

ご質問やアイデア、誤検知がありましたら、GitHub Discussionsでスレッドを開始するか、issue を作成してください。GuardBee が役に立った場合は、リポジトリに ⭐ を付けていただくと、ほかの方にも見つけてもらいやすくなります。

コメント

MCP は初めてですか?

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

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