mapsql-mcp について
mapsql-mcpは、PostGISまたはOracle Spatialを扱うGIS開発者、アナリスト、研究者向けのMCPサーバーです。空間クエリ用ツールを備え、結果を地図で返します。読み取り専用トランザクション、行数上限、タイムアウトでクエリを制限します。
主な機能
- 01PostGISとOracle Spatialに対応
- 02一般的な空間分析ツール
- 03地図画像とLeafletのインタラクティブ地図
- 04行数と実行時間を制限した読み取り専用クエリ
- 05SQLクエリとレイヤー検出
活用シーン
- 01メートル単位の距離で周辺の地物を検索
- 02地区ごとの件数を比較して地図化
- 03地点に近い病院を検索
MCP 対応
MCPクライアントに、空間データベースの探索、クエリ、分析、地図描画のツールを提供します。stdioとStreamable HTTPに対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
14掲載時のツール一覧 · 4 日前に更新
このツールにパラメーターはありません。
詳細
mapsql-mcp
PostGIS または Oracle Spatial データベースについて平易な英語で質問し、地図で回答を受け取れます。
mapsql-mcp は、AI アシスタント(Claude Desktop、Claude Code、Cursor、その他あらゆる MCP クライアント)が PostGIS または Oracle Spatial(SDO_GEOMETRY)データベースを安全に探索、クエリ、分析し、チャット内で直接レンダリングされた地図で回答できるModel Context Protocol サーバーです。

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

この 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 つの考え方を中心に構築されています。
- 設計上、安全です。 すべてのクエリは解析され(PostgreSQL:実際の PostgreSQL パーサー、Oracle:Oracle モードの
sqlglot)、タイムアウトと行数上限を設定したREAD ONLYトランザクションで実行されます。シークレットがモデルに渡ることはありません。書き込みは、要求がない限り無効です(PostGIS のみ)。 - SQL を推測する代わりに、空間ツールを使います。
within_distance、nearest、buffer、spatial_filter、spatial_join、aggregate、bbox_of... が、SRID、メートル単位、インデックスを処理します。両方のデータベースで同じ 14 個のツールを利用できます。通常のrun_sqlも引き続き使えます。 - 回答は地図です。
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 など)でも利用できます。

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 |
|---|---|
![]() | ![]() |
ツールと Oracle Spatial の対応
| ツール | Oracle での実装 |
|---|---|
list_layers / describe_layer | ALL_SDO_GEOM_METADATA(およびアクセス可能なテーブル/ビューの、未登録の SDO_GEOMETRY 列)、SRID、許容誤差、SDO_GTYPE によるジオメトリタイプ、ALL_INDEXES による空間インデックスの有無/有効性、MDSYS.SDO_COORD_REF_SYS / CS_SRS による CRS の種類/名前 |
within_distance | SDO_WITHIN_DISTANCE(geom, ref, 'distance=N unit=M')、距離は SDO_GEOM.SDO_DISTANCE(..., 'unit=M') で計算 |
nearest | SDO_NN + SDO_NN_DISTANCE(属性フィルターがある場合は sdo_batch_size を使用し、近傍が順次取得される間にフィルターを適用) |
buffer | SDO_GEOM.SDO_BUFFER(..., 'unit=M arc_tolerance=...')、SDO_AGGR_UNION で溶解、SDO_AREA(..., 'unit=SQ_KM') で面積を計算 |
spatial_filter / spatial_join | SDO_RELATE マスク(ANYINTERACT、INSIDE+COVEREDBY+EQUAL、CONTAINS+COVERS+EQUAL、TOUCH、OVERLAPBDYDISJOINT+OVERLAPBDYINTERSECT)、dwithin には SDO_WITHIN_DISTANCE を使用。結合は ROWID でグループ化したセットベースの空間結合として実行 |
bbox_of | SDO_CS.TRANSFORM(geom, 4326) に対する SDO_AGGR_MBR |
aggregate | SDO_GEOM.SDO_AREA(... 'unit=SQ_KM') / SDO_LENGTH(... 'unit=KM') |
| GeoJSON | SDO_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_distance | lon/lat の地点または他の地物から N メートル以内にある地物。lon/lat データには測地線距離、メートル単位の CRS には平面距離を使用し、フィートなどの単位は換算します。distance_m を追加します |
nearest | distance_m を伴う k 最近傍(大規模なテーブルでは GiST KNN による事前選択) |
buffer | 点または(フィルターを適用した)レイヤーの測地線バッファー。必要に応じてディゾルブし、area_km2 を付加します |
spatial_filter | 別のレイヤー、bbox、または GeoJSON ジオメトリに対する intersects/within/contains/touches/crosses/overlaps/disjoint |
aggregate | count、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_map | MCP の画像コンテンツとしての 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_PASSWORD | Oracle:DSN/TNS 記述子と認証情報(URL の代替) | ||
MAPSQL_ORACLE_WALLET_DIR, MAPSQL_ORACLE_WALLET_PASSWORD | Oracle:mTLS ウォレット(任意) | ||
MAPSQL_BACKEND | --backend | 自動 | postgis または oracle |
MAPSQL_SCHEMAS | --schemas | すべて | カンマ区切りのスキーマ許可リスト(Oracle:所有者) |
MAPSQL_LAYERS | --layers | すべて | カンマ区切りのテーブル/レイヤーパターン(schema.table、schema.*、table) |
MAPSQL_STATEMENT_TIMEOUT_MS | --statement-timeout-ms | 15000 | クエリごとのタイムアウト |
MAPSQL_MAX_ROWS / MAPSQL_DEFAULT_LIMIT | --max-rows | 5000 / 100 | 行数の上限/デフォルトの limit |
MAPSQL_ALLOW_WRITE | --allow-write | オフ | execute_sql を有効化(PostGIS のみ) |
MAPSQL_BASEMAP | --no-basemap | osm | osm、none、または {z}/{x}/{y} を含むタイル URL テンプレート |
MAPSQL_OUTPUT_DIR | --output-dir | ~/mapsql-mcp-output | render_map が PNG/HTML を保存する場所(タイルキャッシュを含む) |
MAPSQL_OPEN_MAPS | --open-maps | オフ | レンダリングした各地図をデフォルトのビューアーで開きます(ローカルでの使用向け。Claude Code の VS Code パネルなど、ツール画像を表示しないクライアント向け) |
MAPSQL_LOG_LEVEL | WARNING | ログは 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)、および
mcp1.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 ベースマップを使って描画された地図には、必須の帰属表示が含まれます。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。



