Metadata-Version: 2.5
Name: geoproje-mcp
Version: 0.8.8
Summary: Geoproje Dış API v1 için MCP sunucusu — Claude Code ve Codex etütleri ve modül proje dosyalarını araç olarak görür.
Author: Geoproje
License: Proprietary
Keywords: geoproje,geotechnical,mcp,soil-profile
Requires-Python: >=3.10
Requires-Dist: certifi>=2026.10.19
Requires-Dist: httpx>=0.27
Requires-Dist: jsonschema<5,>=4.23
Requires-Dist: mcp>=2.1.0
Requires-Dist: pypdf<7,>=6
Requires-Dist: python-docx<2,>=1.2
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Provides-Extra: remote
Requires-Dist: cryptography>=42; extra == 'remote'
Requires-Dist: starlette>=0.27; extra == 'remote'
Requires-Dist: uvicorn>=0.31.1; extra == 'remote'
Description-Content-Type: text/markdown

# geoproje-mcp

<!-- mcp-name: tr.com.geoproje/mcp -->

Geoproje Dış API v1'i (`docs/API_V1.md`) ve altı modülün hesap uçlarını bir
**MCP sunucusuna** çevirir. Müşteri anahtarını bir kez girer; sonra kendi
ajanına (Claude Code, Claude Desktop, Codex, Cursor — MCP konuşan herhangi bir
istemci) şunu diyebilir:

> "Etütlerimi listele, SahaB'nin GeoWave dosyasını proje klasörüme yaz, sonra
> OmniPile'da kazık kapasitesini koştur."

Sunucu **stdio** üzerinden konuşur, müşterinin makinesinde çalışır ve yalnız
HTTPS ile `https://api.geoproje.com.tr/api/v1/...` ve
`https://<modül>.geoproje.com.tr/api/...` adreslerine gider. Hub backend'ini
import etmez; sözleşmeye HTTP ile bağlanır.

## Kurulum

Kurulum gerektirmeyen yol (önerilir):

```bash
uvx geoproje-mcp        # paketi indirir ve çalıştırır
```

Kalıcı kurulum:

```bash
pipx install geoproje-mcp     # ya da: pip install geoproje-mcp
```

Depodan (geliştirme):

```bash
pip install mcp/geoproje-mcp
```

Doğrulama (ağa çıkmaz):

```bash
geoproje-mcp --check    # ayarlar ve o an kayıtlı araç/kaynak/prompt'lar
geoproje-mcp --help
```

## Anahtar

Anahtar `app.geoproje.com.tr` > **Profil** > **API Anahtarları** bölümünden
üretilir (aktif ücretli plan gerekir) ve **yalnız bir kez gösterilir**.

Üretirken kapsam seçin:

| Kapsam | Ne açar | Kredi |
|---|---|---|
| `profiles:read` | `hesap_bilgisi`, `araclar`, `etut_listele`, `etut_getir`, `cikarim_tahmin`, `cikarim_durum`, `cikarim_listele` | harcamaz |
| `files:read` | `etut_dosyasi`, `proje_listele`, `proje_getir` | harcamaz |
| `extractions:write` | `cikarim_baslat`, `etut_belge_ekle` | **HARCAR** |
| `assistant:ask` | `asistan_durum`, `asistana_sor` | **HARCAR** |
| `tools:run` | `arac_kos`, `tehlike_spektrumu`, `secim_indirme_listesi`, `secim_gmps_dosyasi`, `secim_spektrum_grafigi`, `secim_proje_dosyasi`, `secim_sonuc_paneli`, `secim_panel_verisi`, `secim_spektrum_sekli` (uydu uçları) | uca göre; hesap koşuları HARCAR |
| `projects:write` | `proje_kaydet`, `proje_sil`, `secim_gmps_dosyasi(hub_kaydet=true)` | harcamaz |

Ajanının yanlışlıkla para harcamasını **imkânsız** kılmak istiyorsan anahtarı
yalnız okuma kapsamlarıyla üret: `extractions:write` ve `assistant:ask`
olmayan bir anahtarla o araçlar sunucudan 403 alır. Kapsam sonradan
EKLENEMEZ, yeni anahtar üretilir.

## Yapılandırma

| Değişken | Zorunlu | Varsayılan | Ne işe yarar |
|---|---|---|---|
| `GEOPROJE_API_KEY` | evet | — | `gp_live_...` anahtarı. Yoksa sunucu **başlarken** hata verip çıkar. |
| `GEOPROJE_API_BASE` | hayır | `https://api.geoproje.com.tr` | Farklı ortam (staging). Eski ad `GEOPROJE_API_URL` de kabul edilir. |
| `GEOPROJE_OUTPUT_DIR` | hayır | `./geoproje` | `etut_dosyasi`, `proje_getir`, `secim_indirme_listesi` ve `secim_gmps_dosyasi` göreli bir yol alırsa dosya bu klasörün altına yazılır. |

### Claude Code

```bash
claude mcp add geoproje -e GEOPROJE_API_KEY=gp_live_... -- uvx geoproje-mcp
```

Proje bazında (`.mcp.json`):

```json
{
  "mcpServers": {
    "geoproje": {
      "command": "uvx",
      "args": ["geoproje-mcp"],
      "env": { "GEOPROJE_API_KEY": "gp_live_..." }
    }
  }
}
```

Anahtarı depoya commitlemeyin: `.mcp.json` yerine `claude mcp add` ile kullanıcı
kapsamında tanımlayın ya da anahtarı ortamdan alın.

### Claude Desktop

`claude_desktop_config.json` (Windows'ta `%APPDATA%\Claude\`, macOS'ta
`~/Library/Application Support/Claude/`):

```json
{
  "mcpServers": {
    "geoproje": {
      "command": "uvx",
      "args": ["geoproje-mcp"],
      "env": { "GEOPROJE_API_KEY": "gp_live_..." }
    }
  }
}
```

### Codex (yerel stdio)

`~/.codex/config.toml` içindeki bu ayrı MCP kaydı, sunucuyu bilgisayarınızda
başlatır; yerel DTA/SÖZDA/geoteknik/YKZE iş deposu bu stdio kipinde çalışır.
Plugin kartındaki uzak `geoproje` bağlantısının yerine otomatik geçmez; aynı
Codex kurulumunda ikisini birlikte kullanabilirsiniz. MCP kılavuzlarında plugin
taşıması ve yerel stdio kaydı ayrı yapılandırma yollarıdır.

API anahtarını TOML dosyasına yazmak yerine işletim sistemi kullanıcı ortamında
`GEOPROJE_API_KEY` olarak tanımlayın. Sonra `~/.codex/config.toml` içine ekleyin:

```toml
[mcp_servers.geoproje-local]
command = "uvx"
args = ["geoproje-mcp"]
env_vars = ["GEOPROJE_API_KEY"]
default_tools_approval_mode = "auto"

[mcp_servers.geoproje-local.tools.arac_kos]
approval_mode = "prompt"

[mcp_servers.geoproje-local.tools.asistana_sor]
approval_mode = "prompt"

[mcp_servers.geoproje-local.tools.cikarim_baslat]
approval_mode = "prompt"

[mcp_servers.geoproje-local.tools.etut_belge_ekle]
approval_mode = "prompt"
```

`uvx` yoksa `command = "geoproje-mcp"` (pipx kurulumu) ya da
`command = "python"`, `args = ["-m", "geoproje_mcp"]` de çalışır.
Bu Codex ayarı ücretli araçların her çağrısında kullanıcı onayı ister. MCP
`destructiveHint` yalnızca bir ipucudur; gerçek onay davranışını kurulumdan sonra
Codex'te deneyin. Onay modları ve yerel MCP ayarları için [Codex MCP rehberine](https://learn.chatgpt.com/docs/extend/mcp)
bakın.

### Cursor

`~/.cursor/mcp.json` (ya da proje içinde `.cursor/mcp.json`):

```json
{
  "mcpServers": {
    "geoproje": {
      "command": "uvx",
      "args": ["geoproje-mcp"],
      "env": { "GEOPROJE_API_KEY": "gp_live_..." }
    }
  }
}
```

## Uzak sunucu

Aynı sunucu, ikinci bir taşımayla **uzaktan** da koşar: `https://mcp.geoproje.com.tr`.
Müşteri hiçbir şey kurmaz, anahtarını kendi istemcisine yazar.

| Kip | Nerede koşar | Anahtar nereden |
|---|---|---|
| `stdio` (varsayılan) | müşterinin makinesinde | `GEOPROJE_API_KEY` |
| `streamable-http` | Geoproje sunucusunda | **her isteğin** `Authorization` başlığı |

Uzak kipte sunucunun kendi anahtarı yoktur; anahtar her istekten okunur ve o
isteğe ait bir istemciyle hub'a gidilir. Bir müşterinin anahtarı başka bir
müşterinin çağrısında **kullanılamaz**.

### Codex (uzak OAuth, önerilen)

```powershell
codex mcp add geoproje --url https://mcp.geoproje.com.tr/mcp
codex mcp login geoproje
```

Tarayıcıda açılan Geoproje onay sayfasında API anahtarınızı girin ve izin verin.
Sonra `codex mcp list` çıktısında `geoproje` satırının `enabled` ve `OAuth`
olduğunu kontrol edin. Uzak sunucu, MCP `serverInfo` metadata’sında Geoproje’nin
ters sarı üçgen ikonunu ve API referans adresini de yayımlar; istemci yeniden
bağlandığında bu metadata’yı okuyabilen istemciler ikonu gösterebilir.

Codex'te ikonlu **Geoproje MCP** plugin kartını kurmak için (repo pushlandıktan
sonra):

```powershell
codex plugin marketplace add https://github.com/EmreErbek/geoappmain
codex plugin add geoproje-mcp --marketplace geoproje-main
```

Codex'i yeniden başlatın. Plugin aynı uzak MCP sunucusunu kullanır; API anahtarınızı
ikinci kez girmeniz gerekmez.

Ücret harcayabilen araçlar için Codex'in kullanıcı onay penceresini ayrıca
etkinleştirin. MCP `destructiveHint` alanı tek başına onay garantisi vermez; bu
ayar, Codex'in kullanıcı düzeyindeki `config.toml` dosyasına eklenmelidir. Aşağıdaki
örnek yalnız maliyet doğurabilecek dört aracı her çağrıda onaya bağlar; diğer
araçların varsayılanı otomatik kalır:

```toml
[plugins."geoproje-mcp@geoproje-main".mcp_servers.geoproje]
default_tools_approval_mode = "auto"

[plugins."geoproje-mcp@geoproje-main".mcp_servers.geoproje.tools.arac_kos]
approval_mode = "prompt"

[plugins."geoproje-mcp@geoproje-main".mcp_servers.geoproje.tools.asistana_sor]
approval_mode = "prompt"

[plugins."geoproje-mcp@geoproje-main".mcp_servers.geoproje.tools.cikarim_baslat]
approval_mode = "prompt"

[plugins."geoproje-mcp@geoproje-main".mcp_servers.geoproje.tools.etut_belge_ekle]
approval_mode = "prompt"
```

Bu, depo içindeki plugin manifestinden otomatik uygulanmaz; kullanıcının
`config.toml` dosyasına birleştirilmesi ve Codex'in yeniden başlatılması gerekir.
Araçtaki `onay` argümanı model girdisidir, insan onayı yerine geçmez. Daha fazla
bilgi: [Codex config reference — plugin MCP approvals](https://developers.openai.com/codex/config-reference/).

### Claude Code (uzak)

```bash
claude mcp add --transport http geoproje https://mcp.geoproje.com.tr/mcp   --header "Authorization: Bearer gp_live_..."
```

### Cursor (uzak)

```json
{
  "mcpServers": {
    "geoproje": {
      "url": "https://mcp.geoproje.com.tr/mcp",
      "headers": { "Authorization": "Bearer gp_live_..." }
    }
  }
}
```

`X-Geoproje-Api-Key: gp_live_...` başlığı da kabul edilir.

### claude.ai ve ChatGPT (OAuth, başlık girilmeden)

Bu iki arayüzde özel bağlayıcıya başlık yazılamaz; bağlantı OAuth 2.1 + PKCE
ile kurulur. Sunucu tarafında `GEOPROJE_MCP_OAUTH_SECRET` tanımlıysa uçlar
açıktır ve istemci kaydını (DCR) kendisi yapar.

1. claude.ai: Ayarlar > Bağlayıcılar > **Özel bağlayıcı ekle** (ChatGPT'de:
   Ayarlar > Bağlayıcılar > **Ekle**).
2. Adres olarak `https://mcp.geoproje.com.tr/mcp` yazın, kaydedin.
3. **Bağlan**'a basın: Geoproje'nin onay sayfası açılır ve OAuth callback hostu
   gösterilir. İki serviste de `GEOPROJE_MCP_HUB_BRIDGE_SECRET` ayarlıysa
   **Geoproje hesabınla bağlan** düğmesiyle hub hesabında oturum açıp izin verin.
   Bilinmeyen host için hesapla bağlan engellenir; API anahtarı formu hostu
   gösterip uyarır.
4. Köprü kapalıysa veya anahtar yolunu seçerseniz Geoproje API anahtarınızı
   (app.geoproje.com.tr > Profil > API Anahtarları) girip **İzin ver**'e basın.
5. Bağlayıcı bağlandı; araçlar sohbette görünür. OAuth erişim jetonu 7 gün, yenileme jetonu 180 gün sürer; claude.ai ve ChatGPT sessizce yeniler, yenileme yapmayan istemci (Codex) haftada bir anahtar sorar.
   Anahtar iptal edilirse hub doğrulaması erişimi keser; normal kullanımda API
   anahtarı tekrar sorulmaz.

Anahtar sunucuda **saklanmaz**: yalnız istemciye verilen şifreli belirtecin
içinde taşınır. İzni geri almak için anahtarı Profil > API Anahtarları
bölümünden iptal edin (belirteç o an işlevsiz kalır).

### Kendi kopyanı koşturmak

```bash
geoproje-mcp --transport streamable-http --host 0.0.0.0 --port 8000
```

| Değişken | Varsayılan | Ne işe yarar |
|---|---|---|
| `GEOPROJE_MCP_TRANSPORT` | `stdio` | `stdio` ya da `streamable-http` |
| `GEOPROJE_MCP_HOST` | `127.0.0.1` | dinlenecek adres |
| `PORT` | `8000` | dinlenecek kapı (Railway bunu verir) |
| `GEOPROJE_MCP_ALLOWED_ORIGINS` | boş | tarayıcı istemcileri için izinli `Origin` listesi (virgüllü). Boşken `Origin` taşıyan istek 403 alır; joker (`*`) hiçbir zaman verilmez. |
| `GEOPROJE_MCP_OAUTH_SECRET` | boş | 32+ karakter. Verilirse OAuth uçları açılır (claude.ai/ChatGPT); boşken `/.well-known/*` ve `/oauth/*` 404 döner. |
| `GEOPROJE_MCP_HUB_BRIDGE_SECRET` | boş | Hub ve MCP servislerinde aynı, ayrı 32+ karakter rastgele sır. Açarsa hesapla bağlan yolunu; OAuth anahtar formu bundan bağımsızdır. |
| `GEOPROJE_MCP_PUBLIC_URL` | `https://mcp.geoproje.com.tr` | OAuth issuer ve kaynak adresi (sondaki `/` kırpılır). |
| `GEOPROJE_MCP_OPENAI_CHALLENGE` | boş | doluysa `GET /.well-known/openai-apps-challenge` bu değeri `text/plain` 200 ile döner (OpenAI eklenti başvurusu alan adı doğrulaması); boşken 404. |
| `GEOPROJE_MCP_GOOGLE_CONNECTED_APPS_TOKEN` | boş | Google Connected Console'un verdiği belirteç(ler), virgüllü. Doluysa `GET /.well-known/google-connected-apps` `{"verification_tokens":[...]}` JSON'unu 200 ile döner (Google Connected Apps alan adı doğrulaması); boşken 404. |

Uçlar: `POST /mcp` (MCP; kimliksiz istek 401 + `WWW-Authenticate`), `GET /healthz`
(kimliksiz), `GET /probe` (anahtarsız 401), `GET /.well-known/openai-apps-challenge`
(yalnız `GEOPROJE_MCP_OPENAI_CHALLENGE` tanımlıysa 200), `GET /.well-known/google-connected-apps`
(yalnız `GEOPROJE_MCP_GOOGLE_CONNECTED_APPS_TOKEN` tanımlıysa 200) ve OAuth açıkken
`/.well-known/oauth-protected-resource`, `/.well-known/oauth-authorization-server`,
`/oauth/register`, `/oauth/authorize`, `/oauth/token` ve bridge sırrı varsa
`/oauth/hub-callback`.
Dağıtım ayrıntıları: [DEPLOY.md](DEPLOY.md).

### MCP Registry kaydı

[`server.json`](server.json) resmi MCP Registry'nin (`registry.modelcontextprotocol.io`)
kayıt dosyasıdır: yalnız uzak OAuth adresini (`/mcp`) duyurur, zorunlu başlık
ilan etmez. Sürümü `__version__` ile aynı olmalıdır
(`tests/test_registry_server_json.py` bekçidir). PyPI paketi bu dosyada yoktur:
paket eklenecekse PyPI README'si `mcp-name: tr.com.geoproje/mcp` satırını taşır (başta, yorum)
ve yayınlanan sürüm güncel olmalıdır. Yayın `geoproje.com.tr` DNS doğrulamasıyla
`python scripts/publish_registry.py` ile yapılır (`mcp-publisher` gerekmez). Gizli
anahtar depoda değil, `~/.config/geoproje/mcp-registry-ed25519.key` dosyasındadır;
alan adının DNS'inde `--kayit` ile yazdırılan TXT kaydı bulunmalıdır. Her sürüm
yükseltmesinden sonra betik yeniden çalıştırılır.

PyPI yayını `.github/workflows/mcp-pypi.yml` ile elle tetiklenir (Actions →
mcp-pypi → Run workflow). Belirteç kullanılmaz: PyPI'daki `geoproje-mcp` projesinde
"trusted publisher" kaydı (sahip `EmreErbek`, depo `geoappmain`, iş akışı
`mcp-pypi.yml`, ortam `pypi`) bulunmalıdır. Yalnız wheel yüklenir.

## Araçlar

| Araç | Ne yapar | Kredi |
|---|---|---|
| `hesap_bilgisi` | hesap, sahip olunan modüller, anahtar kapsamları, kredi bakiyesi | — |
| `araclar` | modüller, dosya uzantıları, yetkin var mı, uydu hesap uçları | — |
| `etut_listele` | etüt profillerinin özeti (en yeni önce) | — |
| `etut_getir(etut_id)` | parametre satırları: değer, birim, kaynak sayfa, güven, onay | — |
| `etut_dosyasi(etut_id, arac, kaydet_yolu?)` | modülün proje dosyası (base64 + önerilen ad); `kaydet_yolu` verilirse diske yazar | — |
| `etut_belge_ekle(etut_id, dosyalar, onay, mod?, is_referansi?)` | belgeleri yeni profil açmadan mevcut etüde birleştirir | **HARCAR** |
| `etut_yukleme_baglantisi` | uzak bağlantı için tek kullanımlık yükleme bağlantısı (tarayıcı sayfası + curl), `belge_id` döner | — |
| `cikarim_tahmin(dosyalar? \| belge_idleri?, mod?)` | belgelerin çıkarımı kaça mal olur, kredi yeter mi | — |
| `cikarim_baslat(dosyalar? \| belge_idleri?, onay, mod?, is_referansi?)` | belgelerle çıkarımı başlatır | **HARCAR** |
| `cikarim_durum(is_referansi)` | işin durumu; bitince `soil_profile_id` | — |
| `cikarim_listele` | son işler | — |
| `cizim_oku(belge_id, onay)` | yüklenmiş DWG/DXF çiziminin ham okuması: katmanlar, katman bazında sayım, uzunluk, alan, blok adetleri; `onay=false` yalnız ücreti gösterir (yalnız `/mcp/uzman` ve stdio, ücretli plan) | **HARCAR** (ilk okuma) |
| `cizim_sorgula(belge_id, bolum, katman?, blok?, icerir?, uzay?, baslangic?, limit?)` | okunmuş çizimde yazı, blok yerleşimi ve katman satırı süzme | — |
| `asistan_durum` | asistan açık mı, modlar, mesaj başına tahmini kredi | — |
| `asistana_sor(mesaj, mod?, oturum_id?, profil_id?, kaynak?)` | yönetmelik/ürün sorusu (TBDY, TS EN 1997, ürün wiki) | **HARCAR** |
| `arac_kos(arac, uc, govde?, yontem?, onay?)` | modülün hesap ucunu aynı anahtarla çağırır; POST için kullanıcı onayı ve `onay=true` gerekir | uca göre |
| `proje_listele(arac?)` | hesapta kayıtlı proje dosyaları + depolama kotası | — |
| `proje_kaydet(arac, ad, dosya_yolu\|icerik_base64, dosya_adi?, aciklama?)` | proje dosyasını hesaba kaydeder; kullanıcı panelden "Araçta aç" ile sürdürür | — |
| `proje_getir(proje_id, kaydet_yolu?)` | kayıtlı dosyanın içeriği (base64); `kaydet_yolu` verilirse diske yazar | — |
| `proje_sil(proje_id)` | proje dosyasını KALICI siler | — |
| `tehlike_spektrumu(lat, lon, dd?, zemin_sinifi?, t_maks?, yonetmelik?, donus_periyodu?)` | TBDY 2018 harita katsayıları, tasarım değerleri, spektrum ve hazır `targetH` (T = 0 ve 0.01 s'den `t_maks`'a, varsayılan 4 s, en çok 20 s; seçimden önce sorulur). `yonetmelik="ec8_2024"` (0.6.1) bunun yerine Eurocode 8 2024 için ESHM20 dayanaklarını verir: `S_alpha_RP`, `S_beta_RP` (g), `donus_periyodu` 49/101/475/975/2475/5000 yıl (varsayılan 475); spektrum ve `targetH` üretmez | — |
| `secim_indirme_listesi(job_id, klasor?, bicim?)` | SelectEQ takımının kayıt listesi: kaynak sayfa, atıf, ölçek katsayısı; `klasor` verilirse csv/md/json yazar | — |
| `secim_gmps_dosyasi(job_id, yol?, hub_kaydet?)` | takımı GMPS proje dosyası olarak verir; `yol` diske yazar, `hub_kaydet` hesaba kaydeder | — |
| `secim_spektrum_grafigi(job_id, bilesen?, dil?, olcek?, klasor?, x_olcek?, y_olcek?, x_maks?)` | seçilen ve ölçeklenen kayıtların spektrum grafiği (`x_maks` 0.1-20 s: periyot ekseninin sağ ucu, SelectEQ `xmax`): ImageContent (görüntü) + ResourceLink (`selecteq_<job8>_<H\|V>.png`, baytlar `resources/read` ile; 0.4.22); `klasor` yalnız stdio'da diske yazar | — |
| `secim_proje_dosyasi(job_id, yol?)` | SelectEQ proje dosyası (`.gseq`) EmbeddedResource (application/json) olarak; Enterprise dışı hesapta spektrumsuz (`spectraOmitted`); `yol` yalnız stdio'da diske yazar | — |
| `geoproje_ana_ekran()` | Yalnız dizin `/mcp` (0.5.0, OpenAI MCP Extensions): ChatGPT kenar çubuğu uygulaması (`ui://geoproje/ana.html`); hesap, plan ve kredi özeti, proje dosyaları, etütler, modül kartları. Paneli çizmeyen istemcide kısa metin özeti. Ayrıntı: depo kökü `docs/MCP_EXTENSIONS.md` | harcamaz |
| `geoproje_sonuc_paneli(spektrum?, job_id?, etut_id?)` | Yalnız dizin `/mcp` (0.5.0): ChatGPT sohbet yan paneli (`ui://geoproje/sohbet.html`); hedef spektrum grafiği, kayıt seçimi tablosu, etüt zemin profili tablosu. Sayı dizisi taşımaz; panel veriyi mevcut salt okur araçlarla okur | harcamaz |
| `eklenti_ayarlari_oku()` / `eklenti_ayarlari_guncelle(set)` | Yalnız dizin `/mcp` (0.5.0): ChatGPT eklenti ayarları (`openai/settings`): dil, birim sistemi, ücretli işlem öncesi onay. Süreç belleğinde tutulur (kalıcı değil) | harcamaz |
| `hesap_profili()` | Yalnız dizin `/mcp` (0.5.1, OpenAI eklenti gönderimi): bağlı hesabın profili (`_meta["openai/profile"]: true`); opak ve kalıcı `id`, gösterim için `email`. ChatGPT birden çok bağlı hesabı bununla ayırt eder. Ayrıntı: depo kökü `docs/OPENAI_PLUGIN_SUBMISSION.md` | harcamaz |
| `secim_sonuc_paneli(job_id)` | SelectEQ sonuç paneli (MCP Apps, `ui://selecteq/sonuc.html`): kayıt tablosu, H/V + log/linear grafik, dosya düğmeleri; paneli desteklemeyen istemcide kısa kayıt tablosu (metin). Dizin (`/mcp`, OAuth), uzman (`/mcp/uzman`) ve stdio | — |
| `sozda_hazirlik_kontrol(manifest)` | SOZDA kanıt manifestinin zorunlu aşamalarını ve hash bağlantılarını denetler; dosya açmaz, workflow saklamaz | — |
| `dta_kanit_kontrol(manifest)` | OpenQuake DTA kaynak/koşum/AFAD/deaggregation/direktivite kanıt üstverisini denetler; OpenQuake çalıştırmaz | — |
| `openquake_installation_check()` | PATH veya standart Windows konumundaki OpenQuake için yalnız `--version` denetimi; `execution_available=false` ve nedenini döndürür; analiz çalıştırmaz | — |
| `openquake_run_prepare(is_id, kanit_id, job_ini)` | Yerel stdio DTA işinde önceden saklanmış/doğrulanmış ZIP'i yeni, hash'li girdi anlık görüntüsüne açar; motor yürütmesi kapalıdır | — |
| `openquake_run_status(is_id, run_id)` | Hazırlanan girdiyi ve değişmez manifesti tekrar doğrular; calc_id/tehlike sonucu değildir | — |
| `geoteknik_kanit_kontrol(manifest, is_id?)`, `ykze_kanit_kontrol(manifest, is_id?)` | İş kimliği yoksa üstveri; açık yerel iş kimliğiyle yalnız o işin kayıtlı kanıt baytlarını SHA-256/boyuta karşı denetler; teknik hazır oluş veya onay değildir | — |
| `is_olustur`, `is_listele`, `is_getir`, `is_asama_kaydet` | yalnız yerel stdio kipinde DTA, SOZDA, geoteknik rapor ve YKZE işlerini yönetir | — |
| `is_devam_plani(is_id)` | son manifest/taslak/Word önizlemesi kanıtını yeniden kontrol edip tek güvenli sonraki adımı önerir; koşu veya onay başlatmaz | — |
| `kanit_ekle`, `kanit_dogrula`, `kanit_bayt_dogrula` | kanıtı yerel işe ekler; manifest üstverisini veya kaydedilmiş gerçek baytları türüne uygun araçla doğrular | — |
| `kaynak_klasorunu_tara(is_id, klasor_yolu)` | kullanıcı seçtiği klasörün sınırlı dosya ad/boyut envanterini çıkarır; içerik okumaz veya kopyalamaz | — |
| `kanit_dosyasini_ice_aktar(is_id, kanit_id, klasor_yolu, goreli_yol)` | seçilen tek dosyayı yerel kanıt deposuna kopyalar; göreli kaynak yolunu kalıcı kaydeder; dosya başına 64 MiB sınırı | — |
| `is_manifesti_kaydet`, `is_manifesti_getir` | bağlı kanıtları yeniden doğrulayarak aşama manifestinin değişmez sürümünü kaydeder/yeniden açar; eksik taslak saklanabilir | — |
| `rapor_yazim_hazirligi(is_id, manifest)` | rapor yazılmadan önce rapor dışı aşamaları, gerçek kanıt baytlarını, eksikleri ve uzman writer yolunu gösterir; metin yazmaz | — |
| `rapor_taslagini_kaydet`, `rapor_taslagini_getir` | dört rapor ailesinde kanıta bağlı iç Markdown taslağını değişmez olarak saklar ve yeniden açar | — |
| `dta_rapor_yapisal_kontrol(is_id, taslak_kanit_id)` | DTA zorunlu başlıklarının varlığını/sırasını kaynak baytları yeniden doğrulanmış taslakta salt-okunur denetler; teknik, APA ve görsel onay değildir | — |
| `rapor_ic_docx_olustur(is_id, taslak_kanit_id)` | doğrulanmış taslaktan A4 Word iç inceleme dosyası üretir; tek başına duran `[FIG:id]` görsel kanıtını ekler; teknik/stil onayı veya teslim değildir | — |
| `kanit_metni_oku(is_id, kanit_id, sayfa?, baslangic?, uzunluk?)` | yalnız yerel doğrulanmış PDF sayfası, DOCX ana metni, XLSX/XLSM hücreleri veya UTF-8 metinden sınırlı alıntı; formül/önbellek ayrımı yapar ama formül, makro veya dış bağlantı çalıştırmaz; `.xls` ve OCR yok | — |
| `kanit_yapisini_oku(is_id, kanit_id, baslangic?, blok_sayisi?)` | doğrulanmış DOCX ana gövdesinde paragraf, şekil işareti ve tablo sırasını gösterir; sayfa yerleşimi/görsel piksel içeriğini göstermez | — |
| `kanit_tablosunu_oku(is_id, kanit_id, tablo_indeksi, satir_baslangici?, satir_sayisi?)` | doğrulanmış DOCX tablosunun sınırlı tam satırlarını ve birleşik hücre işaretlerini okur; iç içe tablo elle incelenir | — |
| `skill_dosyalari_listele`, `skill_dosyasi_oku` | manifest hash'i doğrulanmış `.skill` arşivindeki SKILL.md ve referans metinlerini salt-okunur sunar; kurulum veya betik çalıştırma yapmaz | — |
| `rapor_taslagi_render` | tam kanıtlı, mevcut DOCX'i PDF ve sayfa görsellerine dönüştür; yalnız iç inceleme | — |

`arac` değerleri (dosya): `geowave` (`.gwp`), `omnipile` (`.omnp`),
`hoek_brown` (`.hbproj`), `selecteq` (`.gseq`), `gmps` (`.gmps`), `json` (ham
profil). Araç dosyası yalnız **sahip olduğun** modül için üretilir; `json` kendi
ham verin olduğu için modül sahipliği aranmaz.

`arac_kos` için slug'lar: `omnipile`, `hoek_brown` (`hb`), `geowave`,
`selecteq`, `pmm` (`pmmstudio`), `gmps`. Adresler ve uçlar paketle gelen
OpenAPI belgelerinden okunur, elle yazılmaz.

## Kaynaklar (MCP resources)

| URI | İçerik |
|---|---|
| `geoproje://referans` | Dış API referansının web adresi: https://app.geoproje.com.tr/api-referansi |
| `geoproje://openapi/omnipile` … `/gmps` | Altı modülün OpenAPI 3.1 şeması — `arac_kos` gövdesi buradan kurulur |
| `geoproje://skills/sozda/v1.0.2/manifest` ve aynı önekteki güncel writer/reviewer/style kaynakları | Canonical commit, kaynak çalışma ağacının dirty durumu ve SHA-256'ları kayıtlı, açıkça kısmi SOZDA referans paketi |
| `geoproje://capabilities/v1/catalog` | DTA, SOZDA, geoteknik rapor ve YKZE iş akışlarını, koşullu araçları ve kanıta bağlı readiness durumlarını makine-okunur biçimde listeler |
| `geoproje://skill-packages/v1/manifest` | O anki paket kataloğunun `.skill` ad, boyut, SHA-256 ve kaynak sürümü; katalog her girdinin kayıtlı kaynak baytlarını manifest'e karşı denetler |
| `geoproje://skill-packages/v1/<paket-adı>` | Manifestte listelenen arşiv baytları; her paket elle kurulup incelenmelidir, MCP kaynağını okumak kurulum değildir |

Uzak sunucuda skill araçları, skill kaynakları ve prompt'lar yalnız abonelere özel
`https://mcp.geoproje.com.tr/mcp/uzman` adresindedir. Bu adres iki yolla açılır: sohbet
uygulamasında (Claude, ChatGPT) özel bağlayıcı olarak eklenip Geoproje hesabıyla giriş
yapılarak (0.7.8) ya da Claude Code, Codex, Cursor gibi araçlarda `gp_live_` API anahtarıyla.
Dizindeki `https://mcp.geoproje.com.tr/mcp` adresi dizin araç sözleşmesini (uygulama başına iki araç; 0.8.0 ile gelen `/mcp` işaret düzeltmelerinden beri 40 araç, önce 41) sunar ve
bunları içermez. Ayrıntı: `DEPLOY.md` > "İki adres". ChatGPT için üçüncü adres `https://mcp.geoproje.com.tr/mcp/chatgpt` her işlemi ayrı araç olarak sunar (90 araç, sabit işaretler; OpenAI eklenti paketi bu adrese bağlanır). Ayrıntı: `DEPLOY.md` ve `docs/agent/CONTRACTS.md` C41.

**Dizin adresinde hesap işlemleri (0.7.0).** `/mcp` adresinde `arac_kos` yoktur; her uygulamanın
işlemleri iki araçta toplanır: `<uygulama>_islem` (hesap ve yazma, ücretli olabilir) ve
`<uygulama>_oku` (ücretsiz, salt okur). Araçlar: `omnipile_islem`, `geowave_islem`, `geowave_oku`,
`gmps_islem`, `gmps_oku`, `selecteq_islem`, `selecteq_oku`, `pmm_islem`, `hoek_brown_islem`.

| Alan | Anlam |
|---|---|
| `islem` | Çalıştırılacak işlem (ör. `capacity`, `run_selection`, `match_pair`, `jobs`). İzinli değerler ve her işlemin alan özeti aracın `islem` açıklamasındadır |
| `govde` | Seçilen işlemin girdisi (OpenAPI gövdesi, yol ve sorgu parametreleri tek nesnede). Derin nesne şemaları `geoproje://openapi/<uygulama>` kaynağındadır |
| `onay` | Yalnız `*_islem` araçlarında, üst düzey. Ücretli işlem `onay=true` olmadan başlamaz; ilk çağrı güncel kredi tutarını döndürür. Güncel fiyat okunamıyorsa işlem `onay=true` ile de başlamaz |

```
omnipile_islem(islem="capacity", govde={"state": {...}}, onay=false)     # ücreti gösterir, başlatmaz
selecteq_islem(islem="run_selection", govde={"selectedDatabases": [...], "targetH": "...", "config": {"nGM": 11}}, onay=true)
selecteq_oku(islem="jobs", govde={"job_id": "<job_id>"})                 # yoklama, ücretsiz
```

0.6.x'in işlem başına araç adları (`omnipile_kapasite`, `selecteq_kayit_secimi`,
`selecteq_is_durumu` ...) listede görünmez ama çağrılabilir kalır: aynı girdi şeması, aynı onay
kapısı ve aynı ücret; yanıta yalnız yeni adı söyleyen kısa not eklenir. Yeni işlerde yeni adları
kullanın. Yerel stdio ve `/mcp/uzman` bu değişiklikten etkilenmez; orada `araclar` ve `arac_kos`
aynen çalışır.

MCP prompt'ları DTA/SOZDA uzman akışlarını ve mühendislik iş akışı seçicisini
sunar; `muhendislik_akisi_sec` DTA, SOZDA, geoteknik rapor ve
Yapı-Kazık-Zemin Etkileşimi (YKZE) isteklerini katalog kanıtına göre yönlendirir.
Güncel araç, kaynak ve prompt kayıtlarını `geoproje-mcp --check` ile listeleyin.
Router `.skill` paketi MCP tarafından istemciye otomatik kurulmaz; gerekirse manifestte
bulunan `geoproje-engineering-assistant` arşivini doğrula ve manuel kurulum için ayrıca
incele. `geoproje://skills/sozda/v1.0.2/*` güncel, `v1.0.1` geriye uyumluluk için sunulan
önceki metin snapshot'ıdır; ikisi de kısmi referans paketidir. Ayrıca sunulan `.skill` arşivleri kendi manifest ve
`PACKAGE_REQUIREMENTS.md` sınırlarıyla değerlendirilir. Hiçbiri tek başına
onaylı kurumsal stil veya mühendislik sonucu değildir.
`skill-packages/v1` arşivleri ise ayrı kurulabilir paketlerdir; harici
OpenQuake motoru, proje kanıtları ve müşteri verileri paketlenmez. Bu yerel
paketlerin kaynak ağacı henüz commit edilmemiş değişiklikler içerdiği için
manifest `dirty` damgası taşır. `dta_rapor_akisi` prompt'u DTA sınırını,
`docs/DTA_MCP.md` kanıt sözleşmesini açıklar; gerçek hesabı MCP koşturmaz.
DTA rapor yazarı ve denetçisi de ayrı doğrulanabilir `.skill` paketleridir;
şablon, kontrol listesi ve stil kuralları içerirler. OpenQuake hesap motoru,
proje kanıtları ve dış uzman referansları bu rapor paketlerinde yoktur.

Yerel iş deposu dört iş türünde create/list/get/stage/ingest/byte-verification
sağlar. `kanit_bayt_dogrula` yalnız kayıtlı artifact baytlarını yeniden hash'ler.
`is_devam_plani` iş yeniden açıldığında kaynağı, en son manifesti ve taslağı
karşılaştırır; YKZE yöntemi seçilmediyse insan kararını ister. Önerisi analiz
koşumu, metin doğruluğu veya teslim yetkisi değildir.
Dört iş türünde ayrı üstveri-manifest denetimi ve kanıtı bağlı mevcut DOCX'i
iç incelemeye render etme yolu vardır; rapor metni üretimi ve teknik onay yoktur.
`geoteknik_kanit_kontrol` ve `ykze_kanit_kontrol` araçlarına isteğe bağlı
`is_id` (`is_olustur` çıktısındaki `workflow_id`) açıkça verilirse, mevcut yerel
deponun read/verify API'si manifestteki her `artifact_ref` için gerçek baytları
yeniden hash'ler ve beyan edilen SHA-256 ile `size_bytes` değerini karşılaştırır.
Referanslar yalnız seçilen işin kayıt anahtarlarıdır; keyfi dosya yolu/URL açılmaz,
başka işteki aynı hash veya proje kimliği kanıt yerine geçmez. İş türü ve proje
kimliği de eşleşmelidir. Eksik/yabancı referans veya hash/boyut uyuşmazlığı başarı
üretmez; yanlış iş türü reddedilir. `is_id` yoksa veya `null` ise önceki salt
üstveri yanıtı aynen korunur; boş/geçersiz bir iş kimliği üstveri kipine düşmez.
Bu seçenek uzak MCP'de kapalıdır. Yerel sonuçta `manifest_status` üstveri
durumunu, `status=local_artifact_bytes_verified` ise yalnız kayıtlı bayt
bütünlüğünü belirtir (`verification_scope=artifact_byte_integrity_only`).
YKZE'nin mevcut giriş envanteri JSON biçim/durum eşleşmesi kontrolü korunur;
`ready` beyanı teknik hazır oluşa yükseltilmez. Native içerik, hesap doğruluğu,
solver koşumu, görsel QA ve mühendislik/yayın onayı doğrulanmaz. Bu dilimin
regresyonları `tests/test_manifest_integrity.py` dosyasına yazılmıştır; bu
implementasyon turunda test çalıştırılmamıştır.
Rapor yazımı öncesi `rapor_yazim_hazirligi` rapor aşaması henüz boşken de
kaynakların aşama/gerçek bayt durumunu gösterir. Kullanıcı proje klasörü
verirse `kaynak_klasorunu_tara` yalnız dosya adlarını ve boyutlarını (en çok
1000 girdi/4 iç içe düzey) listeler; içerik okumaz ve kopyalama yapmaz.
`kanit_dosyasini_ice_aktar` seçilen tek dosyayı en çok 64 MiB olacak şekilde
kanıt deposuna alır ve göreli yolunu saklar. `kanit_metni_oku` metni yalnız
yerel stdio deposundan ve sınırlandırılmış parçalar hâlinde okur; taranmış
PDF için ayrıca OCR gerekir. DOCX tablo/şekil bağlamı gerektiğinde
`kanit_yapisini_oku` ile gövde sırasını, `kanit_tablosunu_oku` ile tablo
satırlarını ayrı doğrula. Bunlar başlık/altbilgi, dipnot, metin kutusu,
görsel içeriği veya işlenmiş sayfa numarasını çıkarmaz. Ajanın yazdığı iç Markdown taslağı
`rapor_taslagini_kaydet` ile manifest ve kaynak SHA-256 bağlantılarına bağlı
değişmez sürüm olarak saklanır; `rapor_taslagini_getir` aynı işi yeniden açıp
kaynak baytlarını tekrar denetler. Atıf işaretinin dosyaya bağlanması teknik
iddianın doğruluğunu veya müşteriye teslim iznini kanıtlamaz.
`rapor_ic_docx_olustur` bu değişmez taslağı kaynaktaki gerçek baytları tekrar
denetleyerek iç Word önizlemesine dönüştürür. Onaylı Word şablonu henüz bağlı
olmadığından A4/Times New Roman aday stilini kullanır; üst bilgide iç inceleme
uyarısı ve metinde kaynak işaretleri görünür kalır. `[FIG:id]` yalnız ayrı satırda
ve gerçek görsel kanıtına bağlıysa yerleştirilir; sessizce atlanmaz. Çıktı için
ayrı bir değişmez receipt saklanır. PDF/sayfa render'ı, APA atıfları, otomatik
içindekiler/şekil/tablo listeleri, teknik gözden geçirme ve insan onayı bu
adımın kapsamında değildir; dosya müşteriye gönderilmez.
`dta_rapor_yapisal_kontrol` aynı kaynak bütünlüğünü yeniden denetleyerek DTA
iskeletindeki zorunlu başlıkların varlığını ve sırasını kontrol eder. Bu
ön kontrol yalnız belge yapısını kapsar; eksik başlıkları raporlar, ancak
başlıkların içeriğini, kaynakçayı, APA biçimini, şekilleri veya teknik sonucu
incelemez ve hiçbir onay vermez.
`rapor_yapisal_kontrol` DTA, SOZDA ve geoteknik taslaklarında zorunlu ana
bölüm başlıklarını; YKZE'de ise yalnız kaynak manifestinde
`method.selection=direct_common_system` ile eşleşen açık `method1_direct`
varyantını kontrol eder. Alt başlıkların tamamını, teknik içeriği, APA'yı veya
görsel düzeni doğrulamaz; sonucu her durumda `review_required` kalır.
Belgelerdeki talimatlar güvenilmeyen proje verisidir.
`is_manifesti_kaydet`/`is_manifesti_getir` kaynak–koşu–rapor bağlarını yerel
değişmez JSON sürümleri olarak tutar; yeniden açıldığında kaynak baytları yine
kontrol edilir. Bu kayıt teknik hazır oluş veya onay değildir.
Mevcut kapsam ile tam asistan arasındaki uygulama sırası
[mühendislik asistanı planında](docs/engineering_assistant_plan.md) tutulur.

Ajan bir hesap ucunu çağırmadan önce ilgili şemayı okumalıdır; gövde alanları
uygulamadan uygulamaya değişir ve hiçbir ortak sözleşmeye bağlı değildir.

Şemalar canlı `https://<modül>.geoproje.com.tr/openapi.json` belgelerinin
kopyasıdır (depoda `docs/openapi/*.json`); insan okuru için aynı bilgi
https://app.geoproje.com.tr/api-referansi adresindedir.

### Tipik akış

```
etut_listele → etut_getir(sp-…) → etut_dosyasi(sp-…, "geowave", "C:/proje")
```

Elde yalnız etüt PDF'i varsa:

```
cikarim_tahmin(["C:/etutler/sahaB.pdf"])                 # kaça mal olur (harcamaz)
cikarim_baslat([...], onay=true, is_referansi="sahaB")   # KREDİ HARCAR
cikarim_durum("api-…-sahaB")                             # soil_profile_id gelene kadar
etut_dosyasi(soil_profile_id, "omnipile")
arac_kos("omnipile", "/api/run", {"project": {...}, "outputs": ["capacity"]}, onay=true)
```

Mevcut bir etüde belge eklemek için önce aynı dosyalarla `cikarim_tahmin`
çağırılır; kullanıcı onayından sonra `etut_belge_ekle` çağrılır. Sonuç yeni
profil açmaz, `etut_id` ile verilen profile birleşir:

```
cikarim_tahmin(["C:/etutler/SK-1.pdf", "C:/etutler/SK-2.pdf"])  # ücretsiz
etut_belge_ekle("sp-…", [...], onay=true, is_referansi="sahaB-loglar-1")
cikarim_durum("api-…-sahaB-loglar-1")
```

`is_referansi` (job_ref) verirsen çağrı idempotent olur: ağ koparsa aynı
referansla tekrar çağır, yeni iş açılmaz ve **ikinci kez ücret alınmaz**.

### SelectEQ: koordinattan GMPS'e

Deprem kaydı seçimini uçtan uca ajanla koşarsın:

```
# Önce sor: "Grafik ve hedef spektrum kaç saniyeye kadar çizilsin? (varsayılan 4 s, en çok 20 s)"
tehlike_spektrumu(41.0082, 28.9784, "DD2", "ZC", t_maks=4)  # TBDY spektrumu + hazır targetH (0-4 s)
arac_kos("selecteq", "/api/run-selection",              # ÜCRETLİ: önce fiyatı gösterip onay al
         {"selectedDatabases": ["nga_west2"],
          "targetH": "<tehlike_spektrumu yanıtındaki targetH>",
          "config": {"nGM": 11, "selectionMethod": "spectral"}},
         onay=true)                                         # POST varsayılan olarak onaysız reddedilir
arac_kos("selecteq", "/api/jobs/<job_id>", yontem="GET")  # status done olana kadar
secim_indirme_listesi("<job_id>", "C:/proje/kayitlar", "csv")
secim_gmps_dosyasi("<job_id>", "C:/proje", hub_kaydet=true)
secim_spektrum_grafigi("<job_id>", bilesen="H", x_maks=2) # seçilen kayıtların spektrum grafiği (PNG)
secim_proje_dosyasi("<job_id>")                           # SelectEQ proje dosyası (.gseq)
secim_sonuc_paneli("<job_id>")                            # sonuç paneli (MCP Apps); panelsiz istemcide metin tablo
```

**Yönetmelik uyum kontrolü ve darbe-benzeri kayıtlar (0.6.1).** `run-selection` gövdesindeki
`config` şu yeni alanları alır (SelectEQ şemasıyla aynı kurallarla, ücretli çağrıdan ÖNCE
doğrulanır; `arac_kos` ve dizindeki `selecteq_islem(islem=run_selection)` aynı denetimi uygular):

| Alan | Anlam |
|---|---|
| `codeCheck` | Tek ayar ya da en çok 8 ayarlık liste: `{code, T1, tLower?, tUpper?, geotechnical?, meanType?, nearFault?}`. `code`: `tbdy2018`, `ntc18_slu`, `ntc18_sle`, `ec8_2024`, `asce7_22`, `nz1170_2025`, `custom`. Ön ayarlar `T1` ister (ya da `tLower` ile `tUpper` birlikte); `custom` iki ucu da ister. `nearFault` yalnız `ec8_2024` ve `nz1170_2025` için ölçüt üretir |
| `pulseFilter` | `any` (öntanım), `pulse_only`, `exclude_pulse`; `/api/filter-count` içinde `filters.pulseFilter` olarak da çalışır |
| `minPulseShare` | 0-1; takımda en az bu oranda Pulse=1 kayıt (kota `nGM` ile çarpılıp yukarı yuvarlanır). `exclude_pulse` ile birlikte karşılanamaz ve reddedilir |

İş bitince sonuçtaki `codeChecks` (yönetmelik başına karar ve ölçüt listesi) ve `pulseSummary`
yanıtta, ayrıca `arac_kos` ve dizindeki `selecteq_oku(islem=jobs)` çıktısında `kod_kontrolu` (karar tablosu) ve
`darbe_ozeti` (özet + atıf) alanlarıyla; `secim_sonuc_paneli` panelinde karar kartı, Darbe sütunu ve
metin tablosu olarak gösterilir. Hepsi SelectEQ'nun planın izin verdiği yanıtından okunur:
Pro/Free hesapta ölçüt başına tek değer gelir (periyot ve kayıt bilgisi yoktur) ve MCP bunları
yerelde hesaplayıp doldurmaz. Darbe etiketleri Shahi ve Baker (2014), BSSA 104(5), 2456-2466
yöntemine dayanır (NGA-West2 için yayımlanmış sınıflandırma:
https://www.jackwbaker.com/pulse_classification_v2/Pulse-like-records.html); atıf, etiket gösteren her
çıktıda bulunur. Etiketi olmayan kayıt "bilinmiyor"dur. Eurocode 8 2024 kuralları standardın açık
olmayan metni yerine ikincil kaynaklara dayanır ve Ulusal Ek farklı olabilir; uyum kararı resmi
metin kontrolünün yerine geçmez.

Kayıtların ivme-zaman verisini **dağıtmıyoruz**: indirme listesi her kayıt için
kaynağın herkese açık sayfasını (`source_page`) ve atıf metnini verir, kayıtları
kullanıcı oradan kendi hesabıyla indirir. Kayıt spektrumları yalnız hedefin periyotlarında
hesaplanır: grafiğin en uzun periyodu seçimden ÖNCE `t_maks` ile belirlenir, sonradan
uzatılamaz (0.4.19). GMPS aktarım dosyasının
`files[].content` alanları da bu yüzden boştur; indirilen kayıtlar GMPS'te aynı
adlarla yüklenir. `hub_kaydet=true` dosyayı `tool: gmps` olarak hesaba kaydeder,
kullanıcı panelde **Araçta aç** ile takımı GMPS'te sürdürür.

Kayıt spektrumlarına erişim **plana bağlıdır** (hub `GET /api/v1/me` → `plans.selecteq`).
Enterprise hesapta SelectEQ yanıtı `spectraAccess: "full"` taşır ve sayısal spektrumlar
yanıtta kalır. Pro/Free hesapta (`plot_only` ya da alan yok) kayıt başına sayısal spektrum
verilmez; KiK-net/NIED gibi kaynakların koşulları yeniden dağıtımı ve değiştirmeyi yasaklar.
`arac_kos` savunma derinliği olarak `spectraAccess` `full` olmayan her SelectEQ yanıtından
`sampleSmallH/V`, aday `sampleH/V`, liste değerli `selectedMean*`/`selectedStd*`,
`periodRatios` ve aday `scaleH/scaleV` alanlarını siler; `run-selection` gövdesinden
`forceRecordSet`/`scoreOnly`/`skipRankedCandidates` alanlarını her planda çıkarır;
`/api/jobs/<id>/spectra-plot` çağrısını resim olarak döndürür. Grafikten değer okuyup
sayıya çevirmeyin; sayı gerekiyorsa kayıtları kaynağından indirip GMPS ile işleyin
(`arac_kos` gmps `/api/process-record` ya da `/api/process-records`).

**Dosyalar çalışma klasörüne nasıl gelir.** Uzak sunucu diske yazmaz. Dosya üreten
SelectEQ araçları dosyayı MCP yanıtında kaynak olarak verir: `secim_proje_dosyasi` `.gseq`
dosyasını **gömülü kaynak** (`EmbeddedResource`, `TextResourceContents`, `application/json`)
ile; `secim_spektrum_grafigi` PNG'yi bir kez `ImageContent` olarak (sohbette görünür) ve bir
**kaynak bağlantısı** (`ResourceLink`, `image/png`) ile verir; PNG baytları o adresten
`resources/read` ile alınır (0.4.22; önceden aynı baytlar bir de `EmbeddedResource` olarak
dönüyordu ve Claude Code grafiği iki kez çiziyordu). Kaynak adresi
`geoproje://selecteq/jobs/<job_id>/<dosya adı>`, son yol parçası dosya adıdır (grafikte çizim
seçenekleri sorgu dizesindedir: `?dil=..&x_olcek=..&y_olcek=..&x_maks=..`); aynı ad yapısal
çıktının `dosya_adi` alanında da durur. Gömülü kaynak MCP tool sonucunun standart içerik türüdür; istemcilerin
onu modele ya da kullanıcıya nasıl sunduğu değişir ve istemci başına canlı olarak
doğrulanmadı. Güvenli yol: `.gseq` metni kaynağın `text` alanındadır, ajan onu olduğu gibi
`dosya_adi` adıyla yazar; PNG için yerel (stdio) kurulumda `klasor` parametresi dosyayı
doğrudan yazar. Yerel kurulumda `klasor`/`yol` verildiğinde sunucu dosyayı
`GEOPROJE_OUTPUT_DIR` kuralıyla kendisi yazar.

#### Sonuç paneli (MCP Apps)

`secim_sonuc_paneli(job_id)` biten seçimi sohbetin içinde etkileşimli bir panelde açar
(MCP Apps uzantısı `io.modelcontextprotocol/ui`, spesifikasyon SEP-1865 / ext-apps
`2026-01-26`; Python SDK `mcp.server.apps`). Tasarım ve doğrulanan ayrıntılar:
[`docs/MCP_APPS_SELECTEQ.md`](docs/MCP_APPS_SELECTEQ.md).

- Araç `_meta.ui.resourceUri = "ui://selecteq/sonuc.html"` taşır; kaynak
  `text/html;profile=mcp-app` türünde, boş CSP (`connectDomains`/`resourceDomains` boş) ile
  sunulur. Panel dış ağa çıkmaz; yalnız host köprüsüyle (`postMessage` üzerinde JSON-RPC)
  `tools/call` yapar.
- **Pro/Free (`plot_only`)**: panel verisinde sayısal dizi yoktur (testle kilitli). Grafik,
  panelin H/V ve X/Y log/linear düğmeleriyle yeniden çağırdığı `secim_spektrum_grafigi`
  PNG'sidir (eksenler farklıysa `x_olcek`/`y_olcek`; SelectEQ `xscale`/`yscale`). **T maks**
  seçimi (0.4.19; Otomatik ya da verinin son periyoduna kadar 0.5-20 s) `x_maks` olarak gider;
  seçenekler panel verisindeki `period_max` ile sınırlıdır. Sunucu `x_maks`'ı reddederse panel
  `x_maks`'sız yeniden ister ve küçük bir uyarı gösterir.
- **Pro/Free etkileşimli (0.4.23)**: panel önce yalnız panele açık `secim_spektrum_sekli`
  aracıyla SelectEQ `spectra-figure` piksel şeklini ister (PNG ile aynı bilgi, tam sayı tuval
  pikseli; beyaz listeyle doğrulanır) ve SVG çizer: kayıt aç/kapa, satıra ya da çizgiye
  tıklayınca vurgu, çizginin üzerine gelince kayıt kimliği/deprem/istasyon/ölçek katsayısı
  (Sa değeri YOK). Eksen/T maks değişimi şekli yeniden ister (250 ms birikim, 429/503'te kısa
  not ve en çok iki yeniden deneme). Şekil alınamazsa (eski SelectEQ, hata) PNG'ye düşer.
- **Enterprise (`spectraAccess: "full"`)**: panel dizileri yalnız panele açık
  `secim_panel_verisi` aracından ister ve grafiği istemcide çizer (SVG, dış kütüphane yok):
  kayıt aç/kapa, üzerine gelince değer, eksen başına log/linear (doğrusal X 0'dan, ilk periyot
  0.01 s ya da küçükse T=0'da PGA), T maks ile görünür periyot aralığı (Sa aralığı ve üzerine
  gelince değer görünen aralıktan).
- **Model gören sonuçta sayı dizisi yoktur (0.4.18).** Araç çıktı şeması bildirdiği için MCP
  Apps çizmeyen istemciler (ör. Claude Code) modele metin yerine `structuredContent`'i
  verebilir; bu yüzden `secim_sonuc_paneli` sonucu her kipte yalnız tabloyu ve
  `spectra_available` bayrağını taşır.
- Dosya düğmeleri `secim_proje_dosyasi`, `secim_indirme_listesi` (CSV) ve
  `secim_spektrum_grafigi` (PNG) çağırır. Host `ui/download-file` destekliyorsa dosya
  kullanıcıya indirilir; desteklemiyorsa panel "dosya hazır, ajandan kaydetmesini isteyin"
  der ve (host izin veriyorsa) `ui/update-model-context` ile ajana iletir.
- Paneli çizmeyen istemci (istemci başına durum canlı doğrulanacak; bkz. tasarım notu §5) kısa bir kayıt tablosu ve grafik/dosya
  araçlarına not alır; diğer araçların çıktısı değişmez. Veri politikası müzakereye bağlı
  değildir (0.4.16): SDK 2.2.0 ile 2025-11-25 protokolünde uzantı müzakere edilemez, host paneli
  `_meta.ui`'den çizer; `full` hesapta diziler yalnız `secim_panel_verisi` sonucunda (0.4.18),
  plot_only'de hiç yoktur. Enterprise panelinde dizi gelmezse panel sunucu PNG'sine düşer.
- Süresi dolan iş (SelectEQ işleri 7 gün saklanır, 404 `job_not_found`) bütün SelectEQ iş
  araçlarında "İş bulunamadı ya da süresi doldu; seçimi yeniden çalıştırın" iletisini verir.
- Panel üç yerde de açılır: dizin adresi `/mcp` (claude.ai / Claude Desktop / ChatGPT
  bağlayıcısı, OAuth; 0.4.15, sahip kararı 2026-09-28), uzman adresi `/mcp/uzman` ve yerel
  stdio. Dizinde `secim_spektrum_grafigi` ve `secim_proje_dosyasi`, iki yüzeyde de
  `secim_panel_verisi` ve `secim_spektrum_sekli` yalnız panele açıktır (`_meta.ui.visibility = ["app"]`); modelin araç
  listesine yalnız `secim_sonuc_paneli` eklenir.

### SOZDA: SelectEQ → GMPS → GeoWave/DeepSoil → rapor

`sozda_rapor_akisi` prompt'u kaynakları, insan inceleme kapılarını ve araç sırasını
yönlendirir. `sozda_hazirlik_kontrol` salt verilen manifestin alanlarını ve aşamalar arası
SHA-256 bağlantılarını denetler. Manifest; kabul edilmiş hedef/receipt, gerçek SELECTEQ
`.gseq`, seçilen her kaydın H1/H2 waveform dosyası için pozitif byte boyutu, SHA-256, artifact
referansı, source page/atıf/lisans, GMPS pre/post `.gmps` ile hazırlama onayı ve QC, solver
native projesi/sonuçları, rapor taslağı/iç inceleme kanıtını bağlar. Bundle kaynağı, sürüm ve
hash'ler güncel snapshot için `geoproje://skills/sozda/v1.0.2/manifest` içindedir.

Kontrol dosyaları indirmez/açmaz ve SHA-256'yı yeniden hesaplamaz; dolayısıyla
`manifest_metadata_complete` yalnız zorunlu metadata ve bağlantıların verildiği anlamına
gelir, dosya varlığı/hash doğruluğu, teknik uyum, solver parity, review pass veya yayın izni
anlamına gelmez. SELECTEQ job `done` ve `secim_gmps_dosyasi` tek başına waveform kanıtı
değildir (`files[].content` boş kalır); kayıtlar ve provenance ayrıca kullanıcı tarafından
sağlanmalıdır. `sozda_hazirlik_kontrol` stateless kalır; ayrı yerel stdio araçları
gerçek dosya baytları ve iş durumunu saklayabilir. Hub ProjectFile tek modül dosyası
içindir (en fazla 20 MB); rapor/çok-aşamalı iş deposu değildir. MCP çözücü çalıştırmaz
ve teknik rapor metni yazmaz; mevcut DOCX'i yalnız iç inceleme PDF'ine render edebilir.
DeepSoil/GeoWave hesapları haricen çalışır. Ücretli `arac_kos` uçları prompt
ile otomatik çağrılmaz; ücret ve açık kullanıcı onayı kapısı geçerlidir.
Alan adları, beklenen artifact descriptor'ları ve durumların yorumlanması için
[SOZDA MCP rehberine](docs/SOZDA_MCP.md) bakın.

TBDY dışındaki yönetmelikler için hazır uçlar `arac_kos` ile çağrılır:
`/api/hazard/asce7-22`, `/api/hazard/ec8`, `/api/hazard/nbcc`.

## Kredi notları

- Kredi harcayan yollar: `cikarim_baslat`, `asistana_sor` ve ücretli uydu
  hesap uçları üzerinden `arac_kos`. Okuma, iş yoklama ve dosya üretimi
  ücretsizdir; canlı uç fiyatı için `hesap_bilgisi` içindeki `api_run` alanını
  ve ilgili `geoproje://openapi/<arac>` kaynağını okuyun.
- `arac_kos` POST varsayılan olarak ağa çıkmadan reddedilir. Fiyatı ve işlemi
  kullanıcıya açıklayıp açık onay aldıktan sonra `onay=true` gönderin. Bu alan
  yalnız çağıranın beyanıdır; gerçek kullanıcı kapısı için Codex'te araç başına
  `approval_mode="prompt"` ayarı da kullanılmalıdır. GET durum yoklamaları
  `onay` alanı istemez.
- `cikarim_baslat` **onay olmadan çalışmaz**: `onay=true` gelmezse çağrı
  reddedilir ve ağa tek bir istek bile çıkmaz. Ajanın önce `cikarim_tahmin`
  sonucunu kullanıcıya göstermesi beklenir.
- Çıkarımda kredi yükleme anında **rezerve** edilir, iş bitince gerçek kullanım
  üzerinden kapanır ve rezervi aşmaz. İş kabul edilmez ya da zaman aşımına
  uğrarsa rezervasyon serbest bırakılır — müşteri ödemez.
- `mod=derin` daha uzun düşünen, **daha pahalı** modeldir. Sunucuda kapalıysa
  istek `400 deep_mode_disabled` alır; sessizce hızlı moda DÜŞÜLMEZ.
- Asistan hızlı modda ≈ 0,05 kredi/mesaj (uzun bağlamda artar). Güncel tahmin
  `asistan_durum` yanıtındaki `modlar[].tahmini_kredi_mesaj` alanındadır,
  sabit varsayma.
- `arac_kos` ve SelectEQ akışındaki çağrılar aynı API anahtarını uyduya taşır.
  Okuma/iş yoklama uçları ücretsiz olabilir; hesap koşusu gibi ücretli uçlarda
  güncel `api_run` fiyatı uygulanır. İstemci hiçbir fiyatı sabit varsaymamalıdır.

## Uyarıları görmezden gelme

`etut_dosyasi` yanıtındaki `missing`, `warnings` ve `unconfirmed_count` doluysa
`uyari` alanı da dolar. Bu alanlar "dosyada boş kalan yerler" ve "yapılmış
varsayımlar" demektir; ajan bunları kullanıcıya söylemeden dosyayı hesaba
sokmamalıdır. Onaylanmamış satır, kullanıcının henüz gözden geçirmediği bir
çıkarım sonucudur.

`asistana_sor` yanıtındaki `eylemler` yalnız **öneridir**; sunucu hiçbirini
uygulamaz, uygulayan senin arayüzündür.

## Güvenlik

- **Anahtar hiçbir yere yazılmaz.** Loglanmaz, hata mesajlarına girmez,
  `repr(Settings)` bile `***` gösterir. Tek yerde durur: verdiğiniz ortam değişkeni
  (uzak kipte: yalnız o isteğin başlığı). Dışa çıkan tek iz `key_hint`, yani
  anahtarın ilk 8 karakteri olan `gp_live_` önekidir.
- **Uzak kipte anahtarlar karışmaz.** Her anahtarın kendi HTTP istemcisi vardır;
  anahtarsız gelen çağrı hub'a hiç çıkmadan açık bir hatayla döner. Tarayıcıdan
  gelen istekler `Origin` izin listesiyle denetlenir (varsayılan: liste boş).
- **Diske yazma yalnız istenirse.** `etut_dosyasi`, `secim_indirme_listesi` ve
  `secim_gmps_dosyasi` varsayılan olarak base64
  döndürür; dosya ancak `kaydet_yolu` verilirse yazılır. Sunucudan gelen dosya
  adı güvenilmez veri sayılır: yalnız taban adı kullanılır ve hedef yol
  çözüldükten sonra hedef dizinin içinde olduğu ayrıca doğrulanır (`../../` ya
  da `C:\Windows\...` denemesi dizinin dışına çıkamaz).
- **Yükleme yerel dosyaları okur**, yazmaz; kabul edilen türler `.pdf .dwg .dxf
  .xlsx .xls .docx .doc .txt .csv`, en fazla 10 dosya, dosya başına 10 MB. Bu
  sınırlar yerelde de bakılır: reddedilecek bir yüklemeyi ağa çıkarmayız.
- **`arac_kos` yalnız yol alır.** Tam URL verilemez ve yalnız `/api/...` uçları
  çağrılabilir; başka bir sunucuya anahtarla istek atılamaz.
- **Hız sınırı** anahtar başınadır: okuma dakikada 120; çıkarım başlatma ve
  asistan mesajı dakikada 20 (asistanda ayrıca saatte 200 mesaj tavanı). 429
  gelirse sunucunun `Retry-After` süresi kadar beklenip **en fazla 2 kez**
  yeniden denenir, sonra hata ajana bırakılır.
- **Kredi harcayan yollar tekrar denenmez.** Yalnız 429 yeniden denenir; başka
  hiçbir hata kör tekrarla ikinci kez ücret çıkaramaz.

## Hata mesajları

Ajan HTTP kodu değil, ne yapacağını söyleyen metin görür:

| Kod | Ajanın gördüğü |
|---|---|
| 401 | anahtar geçersiz/iptal — yeniden üretin |
| 403 | kapsam yok **ya da** modül aboneliğinizde yok |
| 402 | kredi yetersiz (gereken / kullanılabilir), **ücret alınmadı** |
| 429 | hız sınırı; beklendi, tekrar denendi, yine olmadı |
| 502/503 | hizmet geçici olarak kullanılamıyor, kredi alınmadı |

Uydu (`arac_kos`) hatalarında uygulamanın **kendi mesajı** aynen iletilir; kod
adları uygulamadan uygulamaya değişir (OmniPile `scope_required`, diğerleri
`missing_scope`) ve tek doğru kaynak sunucudur.

## Geliştirme

```bash
pip install -e "mcp/geoproje-mcp[dev]"
pytest mcp/geoproje-mcp
geoproje-mcp --check
```

Testler ağa çıkmaz: HTTP `httpx.MockTransport` ile taklit edilir.

Resmî MCP Python SDK'sı 2.x kullanılır; orada `FastMCP` sınıfı `MCPServer`
olarak yeniden adlandırıldı (`mcp.server.mcpserver.MCPServer`). Paket bu yüzden
`mcp>=2.1` ister.

Uydu OpenAPI belgeleri `docs/openapi/*.json` dosyalarının kopyasıdır ve paket
verisi olarak `src/geoproje_mcp/openapi/` altında durur. Bir uydunun adresi ya
da ucu değişirse önce depodaki belge güncellenir, sonra buraya kopyalanır.
