Skip to main content
Glama

Runnywhere(ランニングウェア)— どこでもランニングコース作成!

カカオ PlayMCP Agentic Player 10 コンテスト出品作品。AIチャットに "市庁から5km、上り坂なし、クジラの形で" と言えば、ソウルの歩行道路網上に走れるコースを生成します。 ソウル市の傾斜度(標高・等高線)、歩行者用信号機、街灯位置データをランニング親和度スコア(RFS)に反映し、平地優先・夜間安心コースを提供します。ソウル市の公衆トイレとOSMコンビニデータも反映し、"トイレ・コンビニを通るように" といったリクエストをコース候補選択に活用します。 PRD: ../runart-mcp-prd/PRD.md

実行

python3 -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'
python -m runart.server           # http://localhost:8000/mcp (Streamable HTTP, JSON)
pytest                            # 테스트 (시나리오 수용 테스트 포함)
python scripts/loadtest.py 1000 10 # 콜드 미스 포함 부하 테스트 (평균 100ms / p99 3s)

PlayMCP 審査用 JSON レポートは次のように保存します。

RUNART_LOADTEST_REPORT=artifacts/playmcp-loadtest.json python scripts/loadtest.py 1000 10

アドレス検索、再試行、コース生成を含む MCP Tool 全体の応答には2.85秒の上限を適用し、内部のコース生成と外部のジオコーディングもより短い同じデッドラインを共有します。

環境変数: HOST(ローカルデフォルト 127.0.0.1、コンテナ 0.0.0.0) · PORT(デフォルト 8000) · RUNART_BASE_URL(プレビューリンクのドメイン) · RUNART_RELEASE_SHA(デプロイ用 Git SHA、Docker ビルド引数と連携) · KAKAO_JAVASCRIPT_KEY(カカオマップ Web API、必須) · KAKAO_REST_API_KEY(ジオコーディング、オプション) · RUNART_TOKEN_SECRET(32文字以上の図鑑・リレートークン署名キー、運用環境では必須) · RUNART_LEGAL_CONTACT(ポリシー問い合わせメール、公開配布時は必須) · WEB_CONCURRENCY(Webワーカー数、デフォルト1) · RUNART_POOL_WORKERS(コース探索プロセス数、デフォルト2) · RATE_LIMIT_RPS(IPあたり、デフォルト20) · RUNART_MAX_BODY_BYTES(MCPリクエスト本文、デフォルト65,536) · RUNART_MAX_CONCURRENT_MCP(同時 MCP HTTP リクエスト、デフォルト4) · RUNART_ROUTE_EDIT(コース編集、デフォルト1) · RUNART_MAX_CONCURRENT_ROUTE_EDITS(同時編集再計算、デフォルト1) · RUNART_ETL_LOCAL_ONLY=1(既存の OSM 属性は保持し、ローカルの傾斜度・信号機・街灯のみ再反映)

実グラフ(data/seoul_graph.pkl)がない場合は ソウル市庁周辺のデモグリッド で動作します(パイプライン全体の動作確認用)。コンテスト提出前に必ずETLを実行:

pip install -e '.[etl]'
python etl/build_graph.py         # OSM 서울 전역 보행망 -> data/seoul_graph.pkl
python scripts/build_animal_presets.py --workers 2 --fresh  # 고유 역 좌표 × 동물 4종 품질 우선 사전 계산
RUNART_ETL_LOCAL_ONLY=1 python etl/build_rfs.py
# 로컬 서울시 경사도 + 보행자 신호등 + 가로등 위치 + 공중화장실을 반영

現在のスナップショット(data/snapshot.json、2026-07-11): ソウル全域の歩行グラフ 163,848 ノード / 232,006 エッジに対して、傾斜度 232,006 エッジ、歩行者用信号機 26,769 ポイントベースの横断スコア、街灯 19,316 ポイントベースの照明スコアを反映しています。施設はコンビニ 6,693、トイレ 4,985、公園 2,237、水飲み場 213 が含まれています。

pickle 形式のグラフ・施設・インフラファイルは読み込み前に src/runart/data_integrity.py の SHA-256 と照合します。ETL でこれら3ファイルを再作成する場合のみ RUNART_ALLOW_UNVERIFIED_DATA=1 で検証を一時的に解除し、検収後に新しいチェックサムをコードに反映する必要があります。運用環境では検証解除変数を設定しません。

動物コースのプリセットは stations.py の289行を同一座標基準で結合し、犬・猫・クジラ・ウサギをそれぞれ11kmまで全距離探索します。ランタイムの3秒制限や早期終了は適用せず、参照シルエット類似度を最優先で選択し、類似度が近い場合のみより短いコースを選びます。結果は data/animal_station_presets.json.gz に保存され、適切なコースがない組み合わせも明示的に保存してランタイムの再探索を防ぎます。グラフが変更されると fingerprint が変わり、既存のプリセットは自動無効化されます。

ランタイムではリクエスト地点の正確なプリセットを優先して使用し、ない場合は同じ動物の検証済みコースを周辺2kmから探して実際の出発駅・移動距離・徒歩時間を明示します。品質ゲートを下げずに駅×動物の即時推奨範囲を421から905の組み合わせに拡大します。

Related MCP server: Strava Coach MCP Server

構造

パス

役割 (PRD マッピング)

src/runart/server.py

MCP ツール6個 + プレビュー/GPX/共有ルート (§5.1, §5.6)

src/runart/course.py

RFS 重み付け巡回コース生成、±5% 距離許容 (§5.3)

src/runart/shapes.py

動物形状テンプレート・スナッピング・類似度ゲート 0.7 (§5.4)

src/runart/rfs.py

ランニング親和度スコア — 基本/夜間加重プロファイル (§5.7)

src/runart/facilities.py

コース10m半径内施設 (§5.5)

src/runart/models.py

自己完結型 course_id — ステートレス (§5.1)

etl/

オフラインデータパイプライン — ルート生成中にデータ API 呼び出しなし (§5.7)

ルート・安全・施設データはコンテナにあらかじめロードされており、ランタイムに外部へ問い合わせません。ただし、ユーザーが入力した任意のソウル住所を座標に変換するジオコーディングは KAKAO_REST_API_KEY が設定されている場合に Kakao Local API をオプションで使用し、地下鉄駅289駅と主要地名はネットワークなしで解釈します。

ツール(7個、すべてステートレス・べき等)

create_seoul_running_course · list_available_shapes · find_facilities_near_course · refine_course · get_course_status · record_animal_completion · extend_shape_relay

ソウル動物地図(/animals)では検証済み421個のGPSアートを1画面で探索できます。完走記録はサーバDBやログインの代わりに自己完結型の passport_token で引き継がれ、4種の図鑑・地域別4種のバッジ・週間最接近未発見動物を提供します。Shape Relay(/relay/{token})も最大8つの地域の同じ動物 course_id を自己完結型トークンに格納し、並べて比較し、共同GPS作品として重ねて表示します。したがって PlayMCP 推奨のステートレス/セッションレス構造を維持します。

デプロイ(PlayMCP in KC)

docker build --build-arg RUNART_RELEASE_SHA=$(git rev-parse HEAD) -t runnywhere .
docker run -p 8000:8000 -e RUNART_BASE_URL=https://<kc-endpoint> runnywhere

MCP Endpoint: https://<kc-endpoint>/mcp — PlayMCP 登録前に MCP Inspector で検証してください。

ライセンス・データ・安全

ソースコードは MIT License で配布します。OSM 派生 DB は ODbL 1.0、ソウル市の傾斜度 OA-22241・街灯 OA-22205・歩行者用信号機 OA-22356・公衆トイレ OA-22586・ソウル交通公社の駅住所は公共ヌリ1類型で利用します。駅座標はソウル交通公社1~8号線座標公共データ(利用許諾制限なし)を基準とします。NASA SRTM 30m を高度フォールバックとして使用します。安心イー CCTV ポイントはサービス終了のため使用せず、OSM surveillance タグのみ使用します。

詳細な出典・加工・再配布条件は DATA_LICENSES.md、依存関係の通知は THIRD_PARTY_NOTICES.md を参照してください。Web UI の /terms、/privacy、/data-licenses で利用・安全、情報処理、出典を確認できます。コースはリアルタイムナビゲーションではなく参考用であり、ユーザーが現場の通行・工事・天候・健康状態を確認する必要があります。

Related MCP Connectors

Related MCP Servers