# Model Context Protocol (MCP)

> Tecof uzak MCP sunucusu (api.tecof.com/mcp): kimlik, kapsamlar, onay ve kredi semantiği, istemci kurulumu ve @tecof/mcp stdio paketi.
>
> Kaynak: https://tecof-app-dev.vercel.app/mcp · Bölüm: AI ve MCP · Son güncelleme: 2018-10-20

Tecof, yapay zekâ ajanlarına (Claude Code, Codex CLI, Gemini CLI, Cursor, Claude Desktop) üç MCP yüzeyi sunar:

| Yüzey | Adres / paket | Ne zaman |
| :--- | :--- | :--- |
| **Uzak MCP sunucusu** | `https://api.tecof.com/mcp` (Streamable HTTP) | Paket kurmadan, tema reposu olmadan; Claude Desktop / claude.ai / Cursor için tek yol |
| **`@tecof/mcp` stdio paketi** | `npx -y @tecof/mcp@latest` — `local` (varsayılan) ya da `remote` mod | Tema reposunun içinde çalışırken (bileşen kataloğu diskten okunur) |
| **Doküman MCP sunucusu** | Bu sitenin `/api/mcp` ucu (stdio: `npm run mcp`) | Bu dokümantasyonu ajana okutmak için ([ayrıntı](/ai-docs#dokuman-mcp-sunucusu)) |

Üç yüzeyin ortak sözleşmesi: **sayfa ve CMS yazmaları taslaktır, yayını kullanıcı panelden yapar**; ürün ve DNS yazmaları ise anında canlıdır ve onay ister.

---

## Uzak MCP sunucusu: api.tecof.com/mcp

Backend'in araç kayıt defterini doğrudan sunan Streamable HTTP MCP sunucusu. Araç adları, JSON Schema'lar, hata kodları ve sonuç biçimi stdio paketiyle birebir aynıdır; her çağrı aynı koşucudan (kapsam → paket → onay → kredi → handler) geçer.

### Kimlik ve başlıklar

İki yol vardır; ikisi de sonunda bir mağaza + bir kullanıcıya bağlı, kapsamlı bir erişim anahtarı (`tcf_…`) üretir ve `apiAccess` paket özelliği ister:

| Yol | Ne zaman | Nasıl |
| :--- | :--- | :--- |
| **OAuth 2.1** | Claude Desktop / claude.ai bağlayıcısı, Claude Code, Cursor ve OAuth destekleyen diğer istemciler | Adresi ekleyin → istemci `401` sınamasını izleyip Tecof onay sayfasını açar → panelde mağaza, yetkiler ve bağlantı süresi seçilir. Anahtar 8 saatte bir sessizce yenilenir; bağlantı panelin API Anahtarları listesinde “Bağlayıcı” rozetiyle görünür ve oradan iptal edilir |
| **Statik başlık** | CI, betikler, başlık verebilen istemciler | Panelde **Ayarlar → Geliştirici / API Anahtarları** ile anahtar üretip `Authorization: Bearer tcf_…` olarak gönderin |

`code:write`, `sandbox:run` ve `deploy:write` kapsamları OAuth onayında varsayılan kapalıdır ve ayrıca açık onay ister. Ekipten çıkarılan kullanıcının bağlantısı kısa süre içinde geçersiz olur.

```http
POST /mcp
Authorization: Bearer tcf_...
Accept: application/json, text/event-stream
Content-Type: application/json
X-Tecof-Toolsets: pages,cms          # isteğe bağlı
```

| Başlık / parametre | Açıklama |
| :--- | :--- |
| `Authorization: Bearer tcf_…` | Zorunlu: OAuth ile basılan ya da panelde üretilen anahtar. Kimliksiz istek `401` + `WWW-Authenticate: Bearer resource_metadata=…` döner; OAuth istemcileri bu sınamayla onay akışını başlatır. |
| `X-Tecof-Toolsets` ya da `?toolsets=` | Virgülle modül adları (`pages,cms,media,products,domains,code,general`). Yalnız bu modüllerin araçları listelenir; bilinmeyen ad yok sayılır, boş = hepsi. |
| `GET /mcp/health` | Kimliksiz sağlık ucu: `{ ok, name, version, protocolVersions, toolCount }`. |

Sınırlar: IP başına 60 istek/dk (kimlik öncesi), anahtar başına 240 JSON-RPC/dk; araç başına okuma 120/dk, yazma 30/dk (`429 rate-limited`, `Retry-After: 60`). Oturum yoktur (`Mcp-Session-Id` üretilmez); uzun işler tutamaç + durum aracıyla yürür (aşağıda).

### Kapsamlar ve canlıya etkisi

Anahtarı yalnız gereken kapsamlarla üretin. Kapsamı yetmeyen araçlar da listelenir; hata çağrı anında `403 insufficient-scope { required, missing }` olarak döner.

| Kapsam | Araçlar | Canlıya etkisi |
| :--- | :--- | :--- |
| `pages:read` | `list_pages`, `get_page`, `get_preview_url`, `list_components`, `validate_document` | Yok (okuma) |
| `pages:write` | `create_page`, `update_page`, `delete_page` | **Taslak** — yayın panelden. `delete_page` soft delete, onay ister |
| `cms:read` | `list_cms_collections`, `get_cms_collection`, `list_cms_items`, `get_cms_item` | Yok |
| `cms:write` | `create_cms_collection`, `update_cms_collection`, `create_cms_item`, `update_cms_item`, `delete_cms_item` | Yeni içerik **taslak**; yayındaki içeriği değiştirmek/silmek `allowPublishedEdit:true` ile **anında canlı**; şema değişikliği veri kaybettirebilir (`allowFieldLoss`) |
| `media:read` / `media:write` | `list_media` / `import_image` | Kütüphaneye dosya ekler; sayfaya bağlanmadıkça vitrini değiştirmez |
| `ai:generate` | `generate_image` | **Kredi düşer** (`ai-image-generate`, 3 kredi); dosya kütüphaneye gider |
| `products:read` | `list_products`, `get_product`, `get_product_import_template` | Yok |
| `products:write` | `upsert_products`, `delete_product` | **ANINDA CANLI** — `status:"active"` ürünü vitrine çıkarır; önce `dryRun:true`. Silme onay ister |
| `domains:read` | `domain_list`, `domain_check`, `domain_dns_list`, `domain_nameservers_get` | Yok |
| `domains:write` | `domain_dns_upsert`, `domain_dns_delete`, `domain_nameservers_set`, `domain_sync` | **ANINDA CANLI** — DNS/NS değişikliği yayılır; `_upsert/_delete/_set` onay ister |
| `analytics:read` | `analytics_summary`, `store_health_check`, `search_knowledge` | Yok |
| `memory:write` | `remember` | Mağaza için ajan notu kaydeder; vitrine etkisi yok |
| `code:read` | `ide_session_status`, `ide_list_dir`, `ide_read_file`, `ide_list_snapshots`, `theme_repo_tree`, `theme_get_file`, `theme_deploy_status` | Yok (okuma). `.env*`, `.npmrc`, `.git/`, `node_modules/` hiçbir araçtan dönmez |
| `code:write` | `ide_write_files`, `ide_save_draft`, `ide_commit_push`, `theme_commit_files` | Sandbox yazması ve taslak (`tecof-ide-draft`) canlıyı değiştirmez; **`ide_commit_push` / `theme_commit_files` varsayılan dala push eder → Vercel ÜRETİM yayını** (onay ister) |
| `sandbox:run` | `ide_start_session`, `ide_ping`, `ide_exec`, `ide_extend`, `ide_stop`, `ide_snapshot` | Sandbox içinde kod çalıştırma yetkisi (`build/lint/test` paket script'lerini koşar). `ide_start_session` ve `ide_extend` **kredi düşer** (`ide-session`) |
| `deploy:write` | `theme_deploy` | **ANINDA CANLI** — üretim yeniden dağıtımı (onay ister) |

Ayrıca `get_site_context` kapsam istemez — her oturuma onunla başlayın (diller, tema, anahtarın kapsamı ve bitişi).

### Sonuç biçimi

Her araç `content[0].text` (JSON) ve `structuredContent` (aynı veri) döner; başarılı yazmalarda `credit` ve `warnings` alanları eklenebilir.

```json
{
  "content": [{ "type": "text", "text": "{ \"pageId\": \"…\", \"status\": \"draft\", … }" }],
  "structuredContent": { "pageId": "…", "status": "draft", "warnings": [] }
}
```

Hata `isError: true` ile döner; metin `"<messageCode>: <mesaj>" + ipucu`, `structuredContent = { error: messageCode, message, status, …data }`:

| Kod | Anlamı | Ajanın adımı |
| :--- | :--- | :--- |
| `validation-error` | Girdi şemaya/kurala uymuyor (`data.issues[{path,message}]`) | Alanı düzelt, tekrar dene |
| `insufficient-scope` | Anahtarın kapsamı yetersiz (`data.missing`) | Kullanıcıya yeni anahtar üretmesini söyle |
| `confirmation-required` | Onay isteyen araç `confirm:true` olmadan çağrıldı | Aşağıdaki onay akışı |
| `insufficient-credits` | Kredi yetersiz (`data.required`, `data.balance`) | Kullanıcıya bildir; tekrar deneme |
| `plan-feature-unavailable` | Paket bu özelliği kapsamıyor | Kullanıcıya bildir |
| `page-modified` / iyimser kilit `409` | Kayıt siz okuduktan sonra değişti | `get_page` / `get_cms_item` ile yeniden oku, değişikliği tekrar uygula |
| `rate-limited` | Sınır aşıldı | 60 sn bekle; toplu işleri tek çağrıda birleştir |
| `tool-aborted` | İstemci bağlantıyı kesti / zaman aşımı | Durumu `get_*` ile doğrula; düşen kredi iade edilmez |

### Onay semantiği (`confirm:true` + `confirmId`)

Silme ve canlı değişiklik araçları (`delete_page`, `delete_cms_item`, `delete_product`, `domain_dns_upsert`, `domain_dns_delete`, `domain_nameservers_set`, `ide_commit_push`, `ide_extend`, `ide_snapshot`, `theme_commit_files`, `theme_deploy`) `confirm: true` olmadan çalışmaz. İki araçta onay girdiye bağlıdır ve satır içi döner (`data.needsConfirmation:true` + `summary`, `confirmId` yok; aynı girdiyle `confirm:true`): `ide_write_files` içinde `vercel.json`, `ide_exec` ile `npm-install-scripts`. Kural yüzeye göre dürüsttür:

| Yüzey | Kim onaylar | Akış |
| :--- | :--- | :--- |
| MCP / Developer API (PAT) | İstemci — Claude Code'un `anthropic/requiresUserInteraction` prompt'u, Codex `approval_mode = "prompt"` | 1) Araç `confirm` olmadan çağrılır → `409 confirmation-required { needsConfirmation:true, confirmId, summary, expiresAt }` (15 dk). 2) Kullanıcı özeti onaylar. 3) **Aynı girdiyle** `confirm:true` + `confirmId` gönderilir; tek geçişte çalışır (girdi hash'i yeniden kontrol edilir: onaylanan girdi = çalıştırılan girdi). `confirmId` eşleşmezse `409 confirmation-expired` → `confirmId` olmadan tekrar dene, yeni özet üretilir. |
| Panel asistanı | Kullanıcı (sohbette) | Onay yalnız GÜNCEL kullanıcı mesajı `Onaylıyorum, uygula (onay: <confirmId>)` taşıyorsa tüketilir; ardışık iki model çağrısı onay sayılmaz. |

Onay isteyen araçlar `tools/list`'te `_meta["anthropic/requiresUserInteraction"] = true` ve `annotations.destructiveHint` ile işaretlidir — Claude Code otomatik modda bile sorar.

### Kredi

Kredi düşen araçlar katalogda `credit: { operation, cost, managedByHandler }` ile görünür (bugün `generate_image` → `ai-image-generate`, 3 kredi; `ide_start_session` ve `ide_extend` → `ide-session` 5, aktif her 10 dk 1 — `managedByHandler:true`, servis düşer/iade eder; `ide_extend` onaysız ilk çağrıda ücretsizdir). Kural:

- Kapsam, paket ve onay kapılarından geçmeyen çağrı krediye **hiç** ulaşmaz.
- Handler yan etkiden önce hata verirse (doğrulama, servis hatası) kredi iade edilir; istemci bağlantıyı keserse (`tool-aborted`) iade **edilmez** — kredi düşen araçlarda bağlantıyı açık tutun.
- Başarılı yanıtta `credit: { charged, balance }` döner; yetersizse `402 insufficient-credits { required, balance }`.

### Uzun işler ve `booting` oturum akışı

Uzak sunucu oturumsuzdur; dakikalar süren işler tutamaç + durum aracıyla yürür. Örnek, Geliştirme modu (Cloud IDE, `code` toolset'i):

1. `ide_start_session { themeId?, restoreDraft?, fromSnapshotId? }` saniyeler içinde döner: `{ sessionId, status: "booting", reused, pollAfterMs: 5000, hint }`. Kredi (`ide-session`) bu anda düşer; `booting` satırı tema başına boot kilididir — aynı kullanıcının canlı oturumu varsa `reused:true` (kredi yok), başka kullanıcının oturumu varsa `409 session-busy { userId, channel, expiresAt }`. IDE arayüz bağlantısı (vscode) MCP'den asla dönmez.
2. `pollAfterMs` kadar bekleyip `ide_session_status { sessionId }` çağırın; `status` `active` olunca `previewUrl`, `sandboxId`, `expiresAt` gelir. Boot bütçesini (15 dk) aşan oturum `failed` olur (kilit çözülür, `bootError` döner, kredi iade edilir).
3. `ide_list_dir` / `ide_read_file` / `ide_write_files` / `ide_exec` yalnız `active` oturumda çalışır (`booting` dahil aksi hâlde `409 session-not-active { status }`). Yazma/exec/commit oturumu açan kullanıcıya aittir; başka kullanıcının oturumu `409 session-busy` — devralma yalnız onaylı `ide_commit_push` / `ide_snapshot` içinde `takeOver:true` ile (özet kullanıcıyı adlandırır).
4. Yayın: `ide_commit_push { sessionId, message, confirm:true }` varsayılan dala push eder → Vercel **üretim** yayını; `theme_deploy_status` ile izleyin. Süre `ide_extend` (onay + kredi) ile uzar; bitirirken `ide_stop` (taslağı `tecof-ide-draft` dalına kaydeder) ya da `ide_snapshot` (30 gün saklanan görüntü; oturumu bitirir, `fromSnapshotId` ile devam).
5. Sandbox'sız depo işleri: `theme_repo_tree` / `theme_get_file` (HEAD okuma), `theme_commit_files` (onaylı push → üretim), `theme_deploy` (onaylı yeniden dağıtım). Yalnız özel (`isCustom`) temalarda; mağaza temalarında `403 not-custom-theme`.

SSE ilerleme bildirimi (`notifications/progress`) yalnız istemci istekte `_meta.progressToken` gönderdiyse üretilir; ilerleme yük taşımaz, sonuç her zaman araç yanıtındadır.

### İstemci kurulumu

**Claude Code**

```bash
claude mcp add --transport http tecof https://api.tecof.com/mcp --header "Authorization: Bearer ${TECOF_API_TOKEN}"
```

ya da proje kökünde `.mcp.json` (git'e girer, sır içermez — token ortam değişkeninden gelir):

```json
{
  "mcpServers": {
    "tecof": {
      "type": "http",
      "url": "https://api.tecof.com/mcp",
      "headers": { "Authorization": "Bearer ${TECOF_API_TOKEN}" },
      "timeout": 600000
    }
  }
}
```

**Codex CLI** — `~/.codex/config.toml`:

```toml
[mcp_servers.tecof]
url = "https://api.tecof.com/mcp"
bearer_token_env_var = "TECOF_API_TOKEN"
startup_timeout_sec = 20
tool_timeout_sec = 300

[mcp_servers.tecof.tools.delete_page]
approval_mode = "prompt"   # delete_cms_item, delete_product, domain_dns_upsert/delete, domain_nameservers_set için tekrarlayın
```

**Gemini CLI** — `.gemini/settings.json`:

```json
{
  "mcpServers": {
    "tecof": {
      "httpUrl": "https://api.tecof.com/mcp",
      "headers": { "Authorization": "Bearer $TECOF_API_TOKEN" },
      "timeout": 600000
    }
  }
}
```

**Cursor** — `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "tecof": {
      "url": "https://api.tecof.com/mcp",
      "headers": { "Authorization": "Bearer ${env:TECOF_API_TOKEN}" }
    }
  }
}
```

**Claude Desktop / claude.ai** — Settings → Connectors → *Add custom connector* → URL `https://api.tecof.com/mcp` → **Connect**. Tarayıcıda Tecof onay sayfası açılır; mağazayı ve yetkileri seçip onaylayın. Anahtar kopyalamak ya da dosya düzenlemek gerekmez.

**Proje kökünde tek komut** — `tecof setup agent` projenin `.mcp.json` (Claude Code) ya da `.cursor/mcp.json` (Cursor) dosyasına `tecof` sunucusunu sır yazmadan ekler; istemci ilk bağlantıda OAuth onayını açar ([Güvenlik ve CI](/dev-security#tecof-setup-agent)).

İlk komut her istemcide aynı: *"get_site_context çağır, hangi mağaza ve temaya bağlıyız?"*

---

## `@tecof/mcp` stdio Paketi

Tema reposunun içinden çalışan stdio sunucusu (`npx -y @tecof/mcp@latest`; `.env` içinde `TECOF_API_TOKEN`, `TECOF_API_URL`/`NEXT_PUBLIC_BASE_URL`, isteğe bağlı `TECOF_THEME_ID`). Bileşen kataloğunu diskten (AST) okuduğu için ajan, çalışma ağacındaki bileşen şemasıyla yazar. Ayrıntılı kurulum ve yazarlık biçimi paket README'sindedir.

| Mod | `TECOF_MCP_MODE` | Araçlar nereden | Ne zaman |
| :--- | :--- | :--- | :--- |
| `local` (varsayılan) | — | Paketin kendi 26 aracı; Developer API v1 uçları doğrudan | Tema geliştirme; yayında olmayan bileşenle taslak yazma |
| `remote` | `remote` | Backend kataloğu (`GET /api/v1/tools?surface=mcp`, 38+ araç); çağrılar `POST /api/v1/tools/:name?stream=1` | Backend'e eklenen yeni araçları paket güncellemeden kullanmak; uzak sunucuyla birebir davranış (onay, kredi, hata kodları) |

`remote` modun kuralları:

- **Başlangıç ağa bloklanmaz.** Katalog 3 sn bütçeyle arka planda alınır; yetişmezse paketle gelen snapshot (38 araç) kullanılır ve stderr'e `Katalog: snapshot` yazılır. `tools/list` çevrimdışı da deterministiktir; canlı katalog sonradan gelirse eksik araçlar eklenir (`tools/list_changed`).
- **`TECOF_TOOLSETS=pages,cms`** hem katalog sorgusunu hem snapshot'ı daraltır.
- **Yerel tema kataloğu varsa** (`components/` dizini) `list_components` ve `validate_document` diskten çalışır; `create_page` / `update_page` hibrittir: bölümler yerel katalogla inşa edilip doğrulanır, hazır `document` sunucuya gider ve sunucu kendi (yayındaki tema) kataloğuyla bir kez daha doğrular — yayında olmayan bileşen `unknown-type` ile reddedilir. `components/` yoksa dört araç da sunucudan gelir.
- Her istek `X-Tecof-Surface: mcp` taşır: onay kuralı uzak sunucuyla aynıdır (`confirm:true` + `confirmId`, tek geçiş).
- Sonuç ve hata biçimi yukarıdaki uzak sunucuyla aynıdır; ilerleme yalnız `progressToken` verildiyse iletilir.

---

## Doküman MCP sunucusu

Bu dokümantasyonun kendisi de salt-okunur bir MCP sunucusu olarak sunulur (arama, sayfa okuma, güncel paket sürümleri ve `@tecof/theme-editor` tip tanımları). Mağaza verisine erişmez, kimlik istemez. Kurulum ve araç listesi: [Dokümanı AI ile kullanın](/ai-docs#dokuman-mcp-sunucusu).
