mcpField
M
mapsql-mcp

mapsql-mcp

ローカル
github.com/mveyseldelibasデータベース14 日前に更新

mapsql-mcp について

mapsql-mcpは、PostGISまたはOracle Spatialを扱うGIS開発者、アナリスト、研究者向けのMCPサーバーです。空間クエリ用ツールを備え、結果を地図で返します。読み取り専用トランザクション、行数上限、タイムアウトでクエリを制限します。

主な機能

  1. 01PostGISとOracle Spatialに対応
  2. 02一般的な空間分析ツール
  3. 03地図画像とLeafletのインタラクティブ地図
  4. 04行数と実行時間を制限した読み取り専用クエリ
  5. 05SQLクエリとレイヤー検出

活用シーン

  1. 01メートル単位の距離で周辺の地物を検索
  2. 02地区ごとの件数を比較して地図化
  3. 03地点に近い病院を検索

MCP 対応

MCPクライアントに、空間データベースの探索、クエリ、分析、地図描画のツールを提供します。stdioとStreamable HTTPに対応します。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"mveyseldelibas-mapsql": {
"command": "uvx",
"args": [
"mapsql-mcp"
],
"env": {
"DATABASE_URL": "<DATABASE_URL>"
}
}
}
}
起動コマンドuvx mapsql-mcp
設定が必要な環境変数
DATABASE_URLシークレットConnection string, e.g. postgresql://readonly:secret@host:5432/gis. Use a read-only user.

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

パッケージ
pypimapsql-mcp0.2.0

ツール

14

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

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

詳細

mapsql-mcp

PostGIS または Oracle Spatial データベースについて平易な英語で質問し、地図で回答を受け取れます。

mapsql-mcp は、AI アシスタント(Claude Desktop、Claude Code、Cursor、その他あらゆる MCP クライアント)が PostGIS または Oracle Spatial(SDO_GEOMETRY)データベースを安全に探索、クエリ、分析し、チャット内で直接レンダリングされた地図で回答できるModel Context Protocol サーバーです。

PyPI mapsql-mcp MCP server License: MIT Python MCP status PostGIS Oracle Spatial

Kizilay から 500 m 以内の薬局

「Kızılay 広場から 500 m 以内にある薬局はどこですか?」 - モデルがレイヤーを見つけ、within_distance(テーブルの SRID にかかわらず測地距離のメートル単位)を呼び出し、続いて render_map を実行します。上の画像は、同梱のデモデータベースでこれら 2 つのツール呼び出しを実行した結果そのものです。

mapsql-mcp のデモ:質問、ツール呼び出し、地図

この GIF は、デモデータベース(PostGIS と Oracle)で実行した実際のツール出力から scripts/make_demo_video.py によって作成されています。

トルコ語: 以下の使用ガイド · 対象ユーザー/手順: 使用方法

PostGIS/Postgres/Oracle 用の MCP サーバーがもう一つ必要な理由

汎用の Postgres または Oracle MCP サーバーは空間データに対応していません。そのためモデルは PostGIS/SDO_* SQL を手書きしなければならず、SRID、geography キャスト、単位、ST_DWithin/SDO_WITHIN_DISTANCE の引数を微妙に間違えてしまいます。さらに、結果を表示することもできません。mapsql-mcp は次の 3 つの考え方を中心に構築されています。

  1. 設計上、安全です。 すべてのクエリは解析され(PostgreSQL:実際の PostgreSQL パーサー、Oracle:Oracle モードの sqlglot)、タイムアウトと行数上限を設定した READ ONLY トランザクションで実行されます。シークレットがモデルに渡ることはありません。書き込みは、要求がない限り無効です(PostGIS のみ)。
  2. SQL を推測する代わりに、空間ツールを使います。 within_distance、nearest、buffer、spatial_filter、spatial_join、aggregate、bbox_of ... が、SRID、メートル単位、インデックスを処理します。両方のデータベースで同じ 14 個のツールを利用できます。通常の run_sql も引き続き使えます。
  3. 回答は地図です。 render_map は MCP の画像コンテンツとして PNG(OpenStreetMap のベースマップ、コロプレスマップ、ラベル)を返し、インタラクティブな Leaflet HTML ファイルを書き出すこともできます。

また、モデルには推測せずに質問するよう指示されています。サーバーの指示、プロンプト、各ツールは、「近くの薬局」(何の近くですか?)や、10 個の地物に一致する地名について、処理を進めないようにします。

クイックスタート

Python 3.10 以降と、PostGIS または Oracle Spatial データベースが必要です。読み取り専用のデータベースロール/ユーザーを使用してください(SECURITY.md を参照)。バックエンドは接続文字列から選択されます。

pip install mapsql-mcp            # or: pipx install mapsql-mcp   |   uvx mapsql-mcp
export DATABASE_URL=postgresql://readonly:secret@localhost:5432/gis
mapsql-mcp --check                # prints PostgreSQL/PostGIS versions and exits

# Oracle Spatial instead (python-oracledb thin mode: no Oracle Client install needed) - see "Oracle Spatial" below
pip install "mapsql-mcp[oracle]"
export DATABASE_URL="oracle://MAPSQL_RO:secret@dbhost:1521/ORCLPDB1"
mapsql-mcp --check
Claude Desktop

claude_desktop_config.json を編集します(macOS は ~/Library/Application Support/Claude/、Windows は %APPDATA%\Claude\)。

{
  "mcpServers": {
    "postgis": {
      "command": "uvx",
      "args": ["mapsql-mcp"],
      "env": { "DATABASE_URL": "postgresql://readonly:secret@localhost:5432/gis" }
    }
  }
}
Claude Code
claude mcp add postgis -e DATABASE_URL=postgresql://readonly:secret@localhost:5432/gis -- uvx mapsql-mcp
Cursor(.cursor/mcp.json)/Windsurf
{
  "mcpServers": {
    "postgis": {
      "command": "uvx",
      "args": ["mapsql-mcp", "--schemas", "public,osm"],
      "env": { "DATABASE_URL": "postgresql://readonly:secret@localhost:5432/gis" }
    }
  }
}
VS Code(.vscode/mcp.json、Agent モードの Copilot Chat)

VS Code では servers キーを使用し、パスワードをファイルに保存する代わりに入力を求めることができます。

{
  "inputs": [
    { "id": "pg-url", "type": "promptString", "description": "PostGIS connection URL", "password": true }
  ],
  "servers": {
    "postgis": {
      "type": "stdio",
      "command": "uvx",
      "args": ["mapsql-mcp", "--schemas", "public,osm"],
      "env": { "DATABASE_URL": "${input:pg-url}" }
    }
  }
}
その他の MCP クライアント(ChatGPT 互換、リモート)

ストリーム可能な HTTP トランスポートを実行し、クライアントを http://127.0.0.1:8000/mcp に接続します。

mapsql-mcp --transport streamable-http --host 127.0.0.1 --port 8000

HTTP トランスポートには認証がありません。ループバック上で使用するか、独自の認証機能付きリバースプロキシ/トンネルの背後に配置してください。クローンからインストールした場合は、"command": "python", "args": ["-m", "mapsql_mcp"] を使用します。

使い方:ステップごとに説明

対象ユーザー。 すでに AI アシスタント(Claude Code、 Claude Desktop、Cursor、VS Code + Copilot)を使用しており、PostGIS または Oracle Spatial に空間データを持つ GIS 開発者、データベース担当者、アナリスト、研究者向けです。これはアシスタントの構成要素であり、エンドユーザー向けアプリではありません。独自の Web UI はなく、チャットウィンドウが UI です。

1. インストール:

pipx install "mapsql-mcp[oracle]"     # or: pip install "mapsql-mcp[oracle]"

2. 読み取り専用ユーザーでデータベースに接続し、接続を確認します。

export DATABASE_URL=postgresql://readonly:secret@localhost:5432/gis      # or oracle://USER:PASS@host:1521/service
mapsql-mcp --check

すぐに使えるデータベースがありませんか? 次のセクションを参照し、同梱のデモ(Natural Earth + OpenStreetMap Ankara)を 2 分で構築できます。

3. アシスタントに登録します。 Quickstart の JSON ブロックのいずれかを、クライアントの設定ファイルに追加します (Claude Code の場合は .mcp.json、VS Code の場合は .vscode/mcp.json、Cursor の場合は .cursor/mcp.json、Claude Desktop の場合は claude_desktop_config.json)。VS Code ではサーバーエントリの上にある Start をクリックします。Claude Code では /mcp を実行し、connected と表示されることを確認します。14 個のツールが表示されるはずです。

4. 普通の言葉で質問します。 例:

  • 「どのレイヤーがありますか? 要約してください。」
  • 「Kızılay(39.9208, 32.8541)から 500 m 以内にある薬局はどこですか? 地図に表示してください。」
  • 「カフェが最も多い地区はどこですか? 件数に応じて地区を色分けしてください。」
  • 「この地点に最も近い病院を 5 件、距離とともに表示してください。」
  • 「近くの薬局を探してください。」 - 優れたアシスタントなら推測するのではなく、何の近くですか? と尋ねます。

5. 地図を確認します。 render_map は PNG をアシスタントに返し、~/mapsql-mcp-output に保存します(オプションでインタラクティブな Leaflet HTML も保存します)。一部のクライアント(例:VS Code 内の Claude Code パネル)では、ツールの画像が表示されません。その場合は、サーバーの env に MAPSQL_OPEN_MAPS=1(または --open-maps)を追加すると、すべての地図が既定のビューアーで開きます。

知っておくとよいこと。 アシスタントのプロバイダー(Anthropic、OpenAI など)には、ツールが返す行が送信されます。そのため、組織外に持ち出してはならない内容を含むデータベースには接続しないでください。必要なデータだけを公開するには --schemas / --layers を使用し、データベースユーザーは読み取り専用にしてください。

デモデータベースで試す(2 分)

デモデータは、Natural Earth(世界の国、州・省、都市、河川、湖沼 - パブリックドメイン)と、中央 Ankara の OpenStreetMap 抽出データ(POI、道路、公園、105 地区 - ODbL)で構成されています。固定されたスナップショットが demo/data に含まれているため(2.8 MB)、オフラインでも構築できます。

docker run -d --name pg -p 55432:5432 -e POSTGRES_PASSWORD=pw postgis/postgis:16-3.4
pip install -e .
python demo/build_demo_db.py --database-url postgresql://postgres:pw@localhost:55432/postgres
export DATABASE_URL=postgresql://postgres:pw@localhost:55432/postgres

続いて、アシスタントに次のように質問します。

  • 「どのレイヤーがありますか? Ankara のデータを要約してください。」
  • 「薬局が最も多い地区はどこですか? 地図に表示してください。」
  • 「Kızılay(緯度 39.9208、経度 32.8541)から 300 m 以内のカフェを地図に表示してください。」
  • 「近くの薬局を探してください。」 → どこかを尋ねるはずです。
地区ごとのカフェ数(spatial_join + コロプレス)最寄りの病院 5 件(nearest)
カフェ病院

地図データ © OpenStreetMap contributors(ODbL)。 そのうち 2 つのインタラクティブ版:docs/images/*.html(ブラウザーで開いてください)。

Oracle Spatial

v0.2 の新機能:同じツール、同じ安全性モデル、同じマップを、python-oracledb の thin モード(Oracle Client ライブラリは不要)で Oracle Database with Spatial(19c、21c、23ai / 26ai、Autonomous Database など)でも利用できます。

Kizilay から 500 m 以内の薬局、Oracle Spatial

PostGIS と同じ質問、同じ回答(薬局 20 件)です。今回は Autonomous Database 上で SDO_WITHIN_DISTANCE(... 'distance=500 unit=M') を使用しています。地図データの著作権は OpenStreetMap contributors(ODbL)に帰属します。

インストールと接続
pip install "mapsql-mcp[oracle]"        # adds oracledb + sqlglot
変数説明
DATABASE_URL=oracle://USER:PASS@host:1521/service_name簡易形式です。パスワード内の特殊文字はパーセントエンコードしてください(@ -> %40)。TLS を使用するには ?protocol=tcps(または ?tls=true)を追加します。それ以外の ?key=value ペアは Easy Connect パラメーターとして渡されます(例:ssl_server_dn_match=yes)。
MAPSQL_ORACLE_DSN + MAPSQL_ORACLE_USER + MAPSQL_ORACLE_PASSWORD長い TNS 記述子、tcps://host:1522/service 形式の文字列、または tnsnames.ora の別名(TNS_ADMIN を使用)向けです。DSN は oracle:// URL のホスト部分を上書きします。ここで指定したユーザー名/パスワードは URL 内の値を上書きします。パスワードを URL に含めないことで、引用符の問題を避けられます。
MAPSQL_ORACLE_WALLET_DIR、MAPSQL_ORACLE_WALLET_PASSWORD相互 TLS(ウォレット)接続専用です。たとえば、「mTLS required」の Autonomous Database で使用します。
MAPSQL_BACKEND=postgis|oracle / --backendバックエンドを強制的に指定します。デフォルトでは DATABASE_URL のスキームから判定されます。MAPSQL_ORACLE_DSN のみが設定されている場合は Oracle が選択されます。

その他の設定(MAPSQL_SCHEMAS、MAPSQL_LAYERS、MAPSQL_STATEMENT_TIMEOUT_MS、MAPSQL_MAX_ROWS など)は変更なく動作します。 タイムアウトは接続の call_timeout として適用され、スキーマは Oracle の 所有者 です。

Autonomous Database(TLS、ウォレットなし)。 コンソールで Database connection を開き、TLS authentication: TLS(mTLS ではなく、接続元 IP アドレスを許可するアクセス制御リストが必要)を選択して、Low/Medium の接続文字列をコピーします。記述子は次のようになります:(description=(address=(protocol=tcps)(port=1522)(host=...))(connect_data=(service_name=...))(security=(ssl_server_dn_match=yes)))。 長く、括弧を含むため URL には適さないので、MAPSQL_ORACLE_DSN に設定してください。サーバー証明書はオペレーティングシステムの信頼ストアを使って検証されます。読み取り専用の専用ユーザーを使用し、ADMIN は決して使用しないでください。

export MAPSQL_ORACLE_DSN='(description=(retry_count=3)(address=(protocol=tcps)(port=1522)(host=adb.<region>.oraclecloud.com))(connect_data=(service_name=xxxx_mydb_low.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))'
export MAPSQL_ORACLE_USER=MAPSQL_RO MAPSQL_ORACLE_PASSWORD='...'
mapsql-mcp --check
読み取り専用ユーザー

scripts/oracle_readonly_user.sql は readonly_role.sql に相当する Oracle 用スクリプトです。アシスタントが参照できるテーブルに対して、CREATE SESSION と SELECT のみが許可されたユーザーを作成します。空間メタデータビュー、MDSYS.CS_SRS、SDO_* 演算子はすべてのユーザーが利用できるため、それ以外の設定は不要です。

Claude Desktop / Claude Code / Cursor / VS Code
{
  "mcpServers": {
    "oracle-spatial": {
      "command": "uvx",
      "args": ["--from", "mapsql-mcp[oracle]", "mapsql-mcp", "--schemas", "GIS"],
      "env": { "DATABASE_URL": "oracle://MAPSQL_RO:secret@dbhost:1521/ORCLPDB1" }
    }
  }
}
claude mcp add oracle-spatial -e DATABASE_URL=oracle://MAPSQL_RO:secret@dbhost:1521/ORCLPDB1 -- uvx --from "mapsql-mcp[oracle]" mapsql-mcp --schemas GIS

VS Code(.vscode/mcp.json)では、パスワードの入力が求められ、ファイルには保存されません。TNS 記述子は MAPSQL_ORACLE_DSN に設定します:

{
  "inputs": [
    { "id": "ora-pw", "type": "promptString", "description": "Oracle password for MAPSQL_RO", "password": true }
  ],
  "servers": {
    "oracle-spatial": {
      "type": "stdio",
      "command": "uvx",
      "args": ["--from", "mapsql-mcp[oracle]", "mapsql-mcp", "--schemas", "GIS", "--no-basemap"],
      "env": {
        "MAPSQL_ORACLE_DSN": "dbhost:1521/ORCLPDB1",
        "MAPSQL_ORACLE_USER": "MAPSQL_RO",
        "MAPSQL_ORACLE_PASSWORD": "${input:ora-pw}"
      }
    }
  }
}
Oracle デモスキーマ(3 分)

scripts/oracle_demo_db.py は、PostGIS デモと同じ Natural Earth と OpenStreetMap-Ankara のデータをスキーマ MAPSQL_DEMO に読み込みます(WORLD_COUNTRIES、WORLD_CITIES、ANKARA_POIS、ANKARA_NEIGHBOURHOODS など。Oracle には world.countries のようなデータベース内スキーマの規約がないため、PostGIS のスキーマ名をテーブル名のプレフィックスとして使用します)。USER_SDO_GEOM_METADATA を登録し、空間インデックスを作成して、投影座標系を試せるようにアンカラの 2 つのレイヤーの TUREF TM30(EPSG:5254、メートル単位) コピーを追加し、読み取り専用ユーザー MAPSQL_RO を作成します。管理者ログイン情報を、Git で無視される ini ファイルに設定する必要があります。

; oracle-test.ini
[oracle]
user = ADMIN
password = ...
dsn = (description=...)    ; or host:1521/service
python scripts/oracle_demo_db.py          # creates MAPSQL_DEMO + MAPSQL_RO (random passwords are written to the same ini file)
python scripts/make_oracle_demo_maps.py --ini oracle-test.ini     # the maps in docs/images/oracle_*.png
近隣地域ごとのカフェ数(spatial_join + コロプレス図)投影レイヤー:TUREF TM30、SRID 5254
カフェtm30
ツールと Oracle Spatial の対応
ツールOracle での実装
list_layers / describe_layerALL_SDO_GEOM_METADATA(およびアクセス可能なテーブル/ビューの、未登録の SDO_GEOMETRY 列)、SRID、許容誤差、SDO_GTYPE によるジオメトリタイプ、ALL_INDEXES による空間インデックスの有無/有効性、MDSYS.SDO_COORD_REF_SYS / CS_SRS による CRS の種類/名前
within_distanceSDO_WITHIN_DISTANCE(geom, ref, 'distance=N unit=M')、距離は SDO_GEOM.SDO_DISTANCE(..., 'unit=M') で計算
nearestSDO_NN + SDO_NN_DISTANCE(属性フィルターがある場合は sdo_batch_size を使用し、近傍が順次取得される間にフィルターを適用)
bufferSDO_GEOM.SDO_BUFFER(..., 'unit=M arc_tolerance=...')、SDO_AGGR_UNION で溶解、SDO_AREA(..., 'unit=SQ_KM') で面積を計算
spatial_filter / spatial_joinSDO_RELATE マスク(ANYINTERACT、INSIDE+COVEREDBY+EQUAL、CONTAINS+COVERS+EQUAL、TOUCH、OVERLAPBDYDISJOINT+OVERLAPBDYINTERSECT)、dwithin には SDO_WITHIN_DISTANCE を使用。結合は ROWID でグループ化したセットベースの空間結合として実行
bbox_ofSDO_CS.TRANSFORM(geom, 4326) に対する SDO_AGGR_MBR
aggregateSDO_GEOM.SDO_AREA(... 'unit=SQ_KM') / SDO_LENGTH(... 'unit=KM')
GeoJSONSDO_CS.TRANSFORM(geom, 4326) で変換したジオメトリに対する SDO_UTIL.TO_GEOJSON。Python で簡略化/丸め処理
run_sqlガード付き Oracle SQL。すべての SDO_GEOMETRY 列を GeoJSON(WGS84)として返します

測地系レイヤー(EPSG:4326 および Oracle の旧式 SRID 8307。楕円体上の測地線距離)でも、投影レイヤー(投影上の平面距離を unit=M で変換)でも、メートル単位は正確です。値には常にバインド変数を使用し、識別子はカタログから取得します。

PostGIS との違いについて
  • SDO_* 演算子には空間インデックスが必要です。 有効な空間インデックスがないレイヤーは、インデックスを使用しない SDO_GEOM.* 関数でクエリされます(レスポンスにその旨が示され、describe_layer が警告します)。速度を上げるには、インデックスを作成し(CREATE INDEX ... INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2)、レイヤーを USER_SDO_GEOM_METADATA に登録してください。
  • crosses に忠実に対応する Oracle のマスクはありません。spatial_filter は、誤った結果を返す可能性がある処理を行わず、理由を説明して拒否します(intersects/touches/overlaps を使用するか、独自の SDO_RELATE マスクで run_sql を使用してください)。within/contains は境界での接触(COVEREDBY/COVERS)と EQUAL を含みます。overlaps は OVERLAPBDYDISJOINT+OVERLAPBDYINTERSECT です。
  • このバージョンでは、Oracle の書き込みモードは利用できません(起動時に --allow-write が拒否されます)。
  • 識別子が通常の大文字の Oracle 名である場合、小文字で表示されます(mapsql_demo.ankara_pois、列 name)。SQL では引用符なしで引き続き有効です。引用符付きの大文字小文字混在の名前はそのまま表示され、run_sql では引用符で囲む必要があります。
  • Oracle では空文字列は NULL として保存されます。EQ '' フィルターは IS NULL に変換されます。
  • PostGIS との数値のわずかな違い(デモデータで確認済み):測地系レイヤーの距離は 0.1 m 以内、面積/長さは約 0.01% 以内です。ポリゴンの dwithin 結合では、境界上の地物が異なる場合があります。バッファーの面積はポリゴン近似によって異なります。投影レイヤーの距離はその投影上の平面距離です(TM30 では、中央子午線付近の測地距離との差は 1 km あたり約 1 m 以内です)。
  • GeoJSON 変換は円弧/複合曲線に対応していません(投影データのバッファーは先に高密度化されます)。Oracle がシリアライズできないジオメトリがあると、ツールは明示的なデータベースエラーを返して失敗します。
  • list_layers は SDO_AGGR_MBR を使って範囲を報告します(500 000 行を超えるレイヤーでは省略されます)。SDO_TUNE.EXTENT_OF は READ ONLY トランザクション内では実行できません。

ツール

ツール機能
server_infoデータベース/PostGIS または Oracle Spatial のバージョン、バックエンド、モード、制限、許可リスト
list_layersジオメトリタイプ、SRID、行数の推定値、範囲、列(検索可能)を含む空間レイヤー
describe_layer列/型、正確な件数と範囲、テキスト列の上位値、数値範囲
sample_features実際の地物をいくつか取得
find_features属性フィルター(= != < > like ilike contains in between is_null …)、並べ替え、列の選択
within_distancelon/lat の地点または他の地物から N メートル以内にある地物。lon/lat データには測地線距離、メートル単位の CRS には平面距離を使用し、フィートなどの単位は換算します。distance_m を追加します
nearestdistance_m を伴う k 最近傍(大規模なテーブルでは GiST KNN による事前選択)
buffer点または(フィルターを適用した)レイヤーの測地線バッファー。必要に応じてディゾルブし、area_km2 を付加します
spatial_filter別のレイヤー、bbox、または GeoJSON ジオメトリに対する intersects/within/contains/touches/crosses/overlaps/disjoint
aggregatecount、count_distinct、sum、avg、min、max、測地線による area_km2/length_km。グループ化にも対応
spatial_join左側の各地物について、関連する右側の地物の count/sum/avg/付加(intersects、within、contains、dwithin)
bbox_ofレイヤーまたはそのサブセットのバウンディングボックスと中心
run_sqlガード付きの読み取り専用 SQL(PostgreSQL または Oracle の方言)。ジオメトリ列は GeoJSON として返されます
render_mapMCP の画像コンテンツとしての PNG 地図(ファイルも保存)。オプションで Leaflet HTML を生成します。result_id、GeoJSON、または SQL のレイヤーに対応。ラベルとコロプレス(value_property)も利用できます
execute_sql--allow-write が指定されている場合のみ、PostGIS のみ:INSERT/UPDATE/DELETE(WHERE が必須)/CREATE TABLE|INDEX|VIEW/ALTER TABLE ADD COLUMN を 1 つ実行

すべての座標は WGS84 の lon/lat、距離はメートル、面積は km² です。ジオメトリを返すすべてのツールは、完全な(簡略化された)結果をサーバー側に保存し、result_id を返すため、render_map(result_ids=[...]) でモデルが大きな GeoJSON をコピーする必要はありません。応答は小さく保たれます。頂点数が予算を超えるジオメトリは、geometry="full" を指定しない限り、代表点として返されます(注記付き)。

プロンプト:gis_assistant、spatial_question、explore_database。リソース:mapsql://guide、mapsql://layers。

推測せずに質問する

within_distance で地点も参照地物も指定されていない場合、位置を推測せず、*"参照先がありません:何の近くですか?…質問してください"*というエラーになります。参照先に複数の地物が一致した場合は、候補を返して、どれを指しているのか尋ねます。同様に、距離が指定されていない場合、レイヤー名が曖昧な場合、数値フィルターにテキストが指定された場合、lon/lat の順序が入れ替わっている場合なども同様です。サーバーの指示(接続時に送信)では、モデルにまず簡潔な確認質問を 1 つするよう伝えています。この方針は、情報不足の認識率がモデルによって 0% から 98% まで異なった、著者の TR-CBS-Komut ベンチマークをきっかけに採用されました。

安全モデル

多層防御 — どの層も単独では信頼しません(脅威モデルの全容は SECURITY.md をご覧ください)。

層役割
SQL の解析PostgreSQL:pglast(実際の PostgreSQL パーサー)。Oracle:sqlglot(Oracle 方言)と独立したトークン検査を併用します。ステートメントは厳密に 1 つだけで、通常の SELECT/WITH/集合演算のみを許可します。DML/DDL/MERGE、PL/SQL ブロック、EXECUTE IMMEDIATE、FOR UPDATE、データベースリンク(@)、DBMS_*/UTL_*/CTX_* パッケージ、SYS/DBA_*/V$* オブジェクト、シーケンス、URL/XML 関数は拒否します。解析できないものもすべて拒否します(詳しくは SECURITY.md をご覧ください)。PostgreSQL の詳細:ステートメントは厳密に 1 つだけで、通常の SELECT である必要があります(CTE/UNION/VALUES は許可されます)。DDL/DML/COPY/DO/SET/トランザクション制御、SELECT INTO、FOR UPDATE、データ変更を伴う CTE、pg_read_file、lo_*、dblink*、pg_sleep、set_config、nextval、query_to_xml、少数の無害な関数を除くすべての pg_* 関数、認証情報やアクティビティに関するリレーション(pg_authid、pg_shadow、pg_stat_activity、pg_settings など)を拒否します。540 件以上のテストケースがあります。
読み取り専用トランザクションPostgreSQL:すべてのクエリは statement_timeout を指定して BEGIN READ ONLY 内で実行し、必ずロールバックします。書き込みを試みる SELECT my_volatile_function() は PostgreSQL によって阻止されます(テスト済み)。Oracle:call_timeout を指定して SET TRANSACTION READ ONLY を実行し、必ずロールバックします(書き込み可能なユーザーでテスト済みの ORA-01456 が書き込みを阻止します)。
行数上限サーバー側カーソル/FETCH FIRST とハード上限(MAPSQL_MAX_ROWS、デフォルトは 5000)を使用します。サーバーが巨大な結果をメモリ上に展開することはありません。
許可リスト--schemas public,osm および/または --layers 'osm.*,public.cities' を指定すると、対象はあらゆる場所(カタログツール、SQL ガード、search_path)から非表示になります。
出力にシークレットを含めないエラーは主要なメッセージに書き換えます。DSN、パスワード、ホスト名を除去し、接続文字列は決して返しません。
書き込みはデフォルトで無効--allow-write を指定すると、より厳格なガードを適用した独立のツールが 1 つ追加されます(DROP/TRUNCATE/GRANT は不可、WHERE のない UPDATE/DELETE は不可)。
データベースロール最も強力な層です。アシスタントに表示を許可する対象に対してのみ SELECT 権限を持つロール/ユーザーで接続してください(scripts/readonly_role.sql、scripts/oracle_readonly_user.sql)。

設定

環境変数CLI フラグデフォルト意味
DATABASE_URL(--database-url, avoid)必須postgresql://... または oracle://USER:PASS@host:1521/service_name
MAPSQL_ORACLE_DSN, MAPSQL_ORACLE_USER, MAPSQL_ORACLE_PASSWORDOracle:DSN/TNS 記述子と認証情報(URL の代替)
MAPSQL_ORACLE_WALLET_DIR, MAPSQL_ORACLE_WALLET_PASSWORDOracle:mTLS ウォレット(任意)
MAPSQL_BACKEND--backend自動postgis または oracle
MAPSQL_SCHEMAS--schemasすべてカンマ区切りのスキーマ許可リスト(Oracle:所有者)
MAPSQL_LAYERS--layersすべてカンマ区切りのテーブル/レイヤーパターン(schema.table、schema.*、table)
MAPSQL_STATEMENT_TIMEOUT_MS--statement-timeout-ms15000クエリごとのタイムアウト
MAPSQL_MAX_ROWS / MAPSQL_DEFAULT_LIMIT--max-rows5000 / 100行数の上限/デフォルトの limit
MAPSQL_ALLOW_WRITE--allow-writeオフexecute_sql を有効化(PostGIS のみ)
MAPSQL_BASEMAP--no-basemaposmosm、none、または {z}/{x}/{y} を含むタイル URL テンプレート
MAPSQL_OUTPUT_DIR--output-dir~/mapsql-mcp-outputrender_map が PNG/HTML を保存する場所(タイルキャッシュを含む)
MAPSQL_OPEN_MAPS--open-mapsオフレンダリングした各地図をデフォルトのビューアーで開きます(ローカルでの使用向け。Claude Code の VS Code パネルなど、ツール画像を表示しないクライアント向け)
MAPSQL_LOG_LEVELWARNINGログは stderr のみに出力されます

ベースマップのタイルは、帰属表示、内容を説明する User-Agent、地図ごとのタイル上限(16 枚以下)、ディスク上のキャッシュを設定して tile.openstreetmap.org から取得します。OSM タイル利用ポリシーを遵守してください。大量に利用する場合は、MAPSQL_BASEMAP を独自のタイルサーバーに設定するか、none を使用してください(完全にオフラインで動作します)。

ベンチマーク:mapsql-bench

bench/ には、デモデータベースを対象とした 英語の GIS 質問 60 件(回答可能な質問 52 件と、確認の質問で答える必要がある質問 8 件)が収録されています。8 つのカテゴリ(属性、距離、空間、集計、結合、バッファー、bbox、曖昧)に分類され、手書きの SQL で正解を算出しています。また、stdio 経由でこのサーバーのツールを呼び出すエージェントループで、OpenAI 互換モデル(OpenAI、OpenRouter、vLLM、Ollama、LM Studio など)を任意に評価するランナーも含まれています。

python bench/run_bench.py --oracle                  # no LLM: replays one reference tool call per question
python bench/run_bench.py --validate-gold           # re-checks gold answers against the database
python bench/run_bench.py --model gpt-4o-mini --api-key-env OPENAI_API_KEY
python bench/run_bench.py --model qwen2.5:7b --base-url http://localhost:11434/v1

スコアリングでは、数値は許容誤差内かどうか、名称は大文字・小文字やアクセントを区別しない集合として評価します。曖昧な質問の場合、モデルは ANSWER: ではなく CLARIFY: で終える必要があります。現在(v0.1)検証済みの内容:正解はデータベースと一致しています(52/52)。また、ツールセットですべての回答可能な質問に回答できます(オラクル 52/52)。LLM の評価結果はまだ公開されていません。ハーネスは準備済みです。bench/RESULTS.md にモデルの結果を追加する PR を歓迎します。

制限事項(v0.2)

  • PostGIS または Oracle Spatial(サーバーごとにデータベースは 1 つ)。テーブル、ビュー、マテリアライズドビュー、外部テーブルの geometry/geography 列(PostGIS)または SDO_GEOMETRY 列(Oracle)に対応します。Oracle 固有の事項については、PostGIS との違いを参照してください(読み取り専用のみ、crosses 非対応、インデックスなしのフォールバック)。
  • 構造化ツールでは、ラスター、トポロジ、3D はサポートしていません(run_sql では引き続きクエリできます)。
  • ベースマップにはインターネット接続が必要です(接続できない場合はプレーンな背景に切り替わります)。OSM 形式のラスタータイルのみをサポートします。
  • render_map はレイヤーごとに単色を描画し、単一変数のコロプレス図にも対応しています。カスタムスタイルにはまだ対応していません。
  • HTTP トランスポートには認証がありません。execute_sql で書き込み可能な範囲は意図的に小さくしています。
  • 異なる CRS 間の結合では左側のジオメトリを変換します。SRID が異なる非常に大規模な dwithin 結合は遅くなる場合があります。
  • PostgreSQL 18/PostGIS 3.6、Oracle Database 26ai(23.26、Spatial 23.7、Autonomous Database Always Free)、および mcp 1.30 と 2.3 でテスト済みです(コードは両方の SDK 世代に対応しています)。CI では PostGIS 3.4/PostgreSQL 16 と Oracle ガードテストを実行します(認証情報がない場合、データベースを使う Oracle テストはスキップされます)。

ロードマップ

  • v0.3:Oracle 書き込みモード(限定的なガード)、Oracle の SDO_JOIN/Spatial Studio の追加機能、HTTP 認証(ベアラートークン)、ツールごとの許可リスト、ベクタータイル/PMTiles のベースマップ、ラスター/H3 のサマリー、explain ツール、ルーティングヘルパー(pgRouting)、結果のエクスポート(GeoJSON/GeoPackage)、より高度なマップスタイリング
  • v0.4:複数データベースプロファイル、確認のための質問に使う MCP エリシテーション(プレーンテキストでの質問の代わり)、カタログキャッシュの調整機能
  • 主要モデルのベンチマーク結果を公開し、パブリックリーダーボードを提供

開発

python -m venv .venv && .venv/bin/pip install -e ".[dev]"
# a throwaway PostGIS (never point the tests at a database you care about):
docker run -d -p 55432:5432 -e POSTGRES_PASSWORD=pw -e POSTGRES_DB=mapsql_test postgis/postgis:16-3.4
export MAPSQL_TEST_DATABASE_URL=postgresql://postgres:pw@localhost:55432/mapsql_test
pytest                      # guard tests need no database; the rest recreate schemas `mt` and `mt_other`

oracle-test.ini([oracle_ro]、上記を参照)または MAPSQL_TEST_ORACLE_URL/ MAPSQL_TEST_ORACLE_DSN+_USER+_PASSWORD が利用可能で、scripts/oracle_demo_db.py を実行済みの場合に、Oracle テスト(pytest -m oracle)が実行されます。それ以外の場合はスキップされます。 Oracle SQL ガードのテストにはデータベースは必要ありません。

CONTRIBUTING.md をご覧ください。ローカルクラスター用の Windows ヘルパー:scripts/dev_cluster.ps1。

日本語

mapsql-mcp は、AI アシスタント(Claude Desktop/Code、Cursor、ChatGPT 対応の MCP クライアント)が PostGIS または Oracle Spatial(v0.2)のデータベースを安全にクエリし、空間分析を行い、回答を会話内にマップとして表示できるオープンソースの MCP サーバーです。

  • セキュリティを最優先: すべてのクエリは実際の PostgreSQL パーサー(pglast)で検証されます。単一の SELECT、読み取り専用トランザクション、 タイムアウト、行数制限を適用します。pg_read_file、COPY、dblink、lo_* などはブロックされます。書き込みはデフォルトで無効です (--allow-write)。スキーマ/レイヤーの許可リスト(--schemas、--layers)に対応しており、パスワードや接続文字列が出力に漏れることはありません。
  • 空間ツール: list_layers、describe_layer、within_distance(SRID に依存しないメートル単位)、nearest、 buffer、spatial_filter、aggregate、spatial_join、bbox_of、run_sql、および render_map(OSM 背景地図付き PNG + オプションのインタラクティブな Leaflet HTML、コロプレスマップ)。
  • 不明点があれば質問: 「近くの薬局」のように情報が不足している質問では、モデルが推測する代わりに「何の近くですか?」と 尋ねます(ツールも不足している入力を拒否します)。これは、作者が TR-CBS-Komut ベンチマークから得た教訓です。
  • ベンチマーク: bench/ には、デモデータベース上での英語による GIS の質問 60 件(うち 8 件は「質問すべき」タイプ)、正解データ、および OpenAI 互換モデルを試すための実行ツールが含まれています。

Oracle Spatial: pip install "mapsql-mcp[oracle]" を実行し、DATABASE_URL=oracle://KULLANICI:SIFRE@sunucu:1521/servis_adi を設定します(長い TNS 記述子の場合は MAPSQL_ORACLE_DSN + MAPSQL_ORACLE_USER + MAPSQL_ORACLE_PASSWORD)。同じ 14 個のツールを利用でき、距離は unit=M を指定するとメートル単位になり、地理座標系(4326)と投影座標系(例:TUREF TM30、EPSG:5254)のレイヤーで正確です。クエリは sqlglot (Oracle 方言)で検証されます。SET TRANSACTION READ ONLY と読み取り専用ユーザー(scripts/oracle_readonly_user.sql)の使用を推奨します。 詳細は、上記の Oracle Spatial セクションをご覧ください。

対象ユーザー: 空間データを PostGIS または Oracle Spatial に保存している、AI アシスタント(Claude Code、Claude Desktop、Cursor、VS Code + Copilot)を使用する GIS 開発者、データベースの専門家、アナリスト、研究者向けです。 エンドユーザー向けのアプリケーションではありません。独自の画面はなく、チャットウィンドウ自体がインターフェースです。

手順

1. インストール:

pipx install "mapsql-mcp[oracle]"     # ya da: pip install "mapsql-mcp[oracle]"

2. 読み取り専用ユーザーでデータベースに接続し、接続をテストします:

export DATABASE_URL=postgresql://salt_okunur:sifre@localhost:5432/cbs     # ya da oracle://KULLANICI:SIFRE@sunucu:1521/servis
mapsql-mcp --check

読み取り専用ユーザー用スクリプト:scripts/readonly_role.sql(PostGIS)、scripts/oracle_readonly_user.sql(Oracle)。 データベースがない場合は、上記の デモデータベースで試す セクションを使えば、2分でデモデータベースをセットアップできます (Natural Earth + OpenStreetMap Ankara)。

3. アシスタントに設定します。 クイックスタート セクションの JSON の例から1つを、クライアントの設定ファイルに追加します:Claude Code の場合は .mcp.json、VS Code の場合は .vscode/mcp.json、Cursor の場合は .cursor/mcp.json、Claude Desktop の場合は claude_desktop_config.json。VS Code ではサーバー上部の Start を押します。Claude Code では /mcp と入力し、 connected と表示されることを確認します。14個のツールが一覧表示されます。

4. トルコ語で質問します。 例:

  • 「どのレイヤーがありますか?要約してください。」
  • 「Kızılay(39.9208, 32.8541)から500 m以内の薬局を地図に表示してください。」
  • 「最もカフェの多い地区はどこですか?カフェの数に応じて地区を色分けしてください。」
  • 「この地点に最も近い病院を5か所、距離とともに一覧表示してください。」
  • 「近くの薬局を探してください。」 — 優れたアシスタントは推測せず、「何の近くですか?」 と尋ねます。

5. 地図を表示します。 render_map は地図を PNG としてアシスタントに返し、~/mapsql-mcp-output フォルダーに保存します (必要に応じて、インタラクティブな Leaflet HTML も保存します)。一部のクライアント(例:VS Code の Claude Code パネル)では、ツールの画像が表示されません。サーバーの env 部分に MAPSQL_OPEN_MAPS=1(または --open-maps)を追加すると、各地図が既定のビューアーで開きます。

ご確認ください。 アシスタントのプロバイダー(Anthropic、OpenAI など)は、ツールが返す行を確認できます。組織外に出してはならないデータを含むデータベースは接続しないでください。--schemas / --layers を使って必要なレイヤーだけを有効にし、データベースユーザーは読み取り専用にしてください。デモデータ:Natural Earth(パブリックドメイン)および OpenStreetMap(ODbL)。詳細は demo/ATTRIBUTION.md を参照してください。

作者:Mehmet Veysel Delibaş、GIS ソフトウェアエンジニア(トルコ)。

ライセンスと帰属表示

コード:MIT © 2026 Mehmet Veysel Delibaş。デモデータ:Natural Earth(パブリックドメイン)および OpenStreetMap (© OpenStreetMap の貢献者、ODbL)。demo/ATTRIBUTION.md を参照してください。 OSM ベースマップを使って描画された地図には、必須の帰属表示が含まれます。

コメント

MCP は初めてですか?

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

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