Metadata-Version: 2.5
Name: geoproje-mcp
Version: 0.1.0
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: httpx>=0.27
Requires-Dist: mcp>=2.1.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# 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 (PyPI'ye çıkmadan önce):

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

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

```bash
geoproje-mcp --check    # ayarlar okunuyor mu, 12 araç ve 7 kaynak kurulu mu
geoproje-mcp --help
```

## Anahtar

Anahtar `app.geoproje.com.tr` > **Profil** > **API Anahtarları** bölümünden
üretilir (aktif **enterprise** aboneliği 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` | harcamaz |
| `extractions:write` | `cikarim_baslat` | **HARCAR** |
| `assistant:ask` | `asistan_durum`, `asistana_sor` | **HARCAR** |
| `tools:run` | `arac_kos` (uydu hesap uçları) | harcamaz (kullanım kaydedilir) |

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` göreli bir `kaydet_yolu` 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

`~/.codex/config.toml`:

```toml
[mcp_servers.geoproje]
command = "uvx"
args = ["geoproje-mcp"]
env = { GEOPROJE_API_KEY = "gp_live_..." }
```

`uvx` yoksa `command = "geoproje-mcp"` (pipx kurulumu) ya da
`command = "python"`, `args = ["-m", "geoproje_mcp"]` de çalışır.

### 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_..." }
    }
  }
}
```

## 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 | — |
| `cikarim_tahmin(dosyalar, mod?)` | yerel belgelerin çıkarımı kaça mal olur | — |
| `cikarim_baslat(dosyalar, onay, mod?, is_referansi?)` | belgeleri yükler, çıkarımı başlatır | **HARCAR** |
| `cikarim_durum(is_referansi)` | işin durumu; bitince `soil_profile_id` | — |
| `cikarim_listele` | son işler | — |
| `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?)` | modülün hesap ucunu aynı anahtarla çağırır | — |

`arac` değerleri (dosya): `geowave` (`.gwp`), `omnipile` (`.json`),
`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 |

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.

### 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"]})
```

`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**.

## Kredi notları

- Kredi harcayan **iki** araç var: `cikarim_baslat` ve `asistana_sor`. Diğer
  hepsi okuma; dosya üretimi deterministiktir ve ücretsizdir.
- `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` kredi harcamaz ama koşu hesabın kullanım kaydına (`usage_events`)
  yazılı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.
- **Diske yazma yalnız istenirse.** `etut_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.
