docs: publish translated docs in twelve languages and the tool that maintains them (#3280)

This commit is contained in:
Max 2026-08-14 17:07:34 +01:00 • committed by GitHub
commit 52ad0a8876
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 89737 additions and 54 deletions

View file

@ -0,0 +1,144 @@
---
translation:
sections: [0d6c05bcbf836bf3, 59a7b14eeefc68c1, 7114d8d6daba203f, e8bbb56a98ba7bc9, 5138010f6159901c, f78da7c7c363d4c6, 220a939cab348686]
tool: 1
---
# İlk adımlar {#first-steps}
**[Giriş sayfası](../index.md)** hızlı ilerler: bir sunucu yazın, çalıştırın, bir araç çağırın.
Bu sayfa ise ağırdan alır: bir sunucunun sunabileceği üç şeyin hepsini ele alır ve yol boyunca her şeye bir ad verir.
## Host, istemci ve sunucu {#host-client-and-server}
Bundan sonraki her sayfada göreceğiniz üç sözcük:
* **Host**, LLM uygulamasıdır: Claude, bir IDE, bir ajan çalışma zamanı. Kullanıcının konuştuğu şey odur.
* **İstemci**, host'un içinde yaşar ve MCP konuşur. Host, bağlandığı her sunucu için bir istemci çalıştırır.
* **Sunucu**, bu SDK ile sizin oluşturduğunuz şeydir. İstemcilere bir şeyler sunar. Modelle hiçbir zaman doğrudan konuşmaz.
Sunucuyu siz yazarsınız. Host'lar başkasının ürünüdür. SDK size bir de `Client` verir. Onu sunucularınızı test etmek için kullanırsınız; bu sayfanın ilerisinde karşınıza çıkar.
## Üç temel öğe {#the-three-primitives}
Bir sunucu tam olarak üç tür şey sunar. Onları birbirinden ayıran, **kullanılmalarına kimin karar verdiğidir**:
| Temel öğe | Kontrol eden | Nedir | Örnek |
|----------------|-----------------|---------------------------------------------------------------|-----------------------------------------------|
| **Araçlar** | Model | Modelin bir eylemde bulunmak için çağırdığı fonksiyon | Bir API çağrısı, bir veritabanı yazma işlemi |
| **Kaynaklar** | Uygulama | Host'un modelin bağlamına yüklediği veri | Bir dosyanın içeriği, bir API yanıtı |
| **Prompt'lar** | Kullanıcı | Kullanıcının adıyla çağırdığı, yeniden kullanılabilir mesaj şablonu | Bir slash komutu, bir menü girdisi |
"Kontrol eden", bu ayrımın özüdür. Bir araç, **model** onu çağırmaya karar verdiği için çalışır. Bir kaynak, **uygulama** modelin ona ihtiyacı olduğuna karar verdiği için eklenir. Bir prompt, **kullanıcı** onu seçtiği için çalışır.
!!! info
Daha önce bir web API'si geliştirdiyseniz sezginin çoğu zaten sizde var: **kaynak** bir `GET`'tir
(veri yükler, hiçbir şeyi değiştirmez), **araç** ise bir `POST`'tur (iş yapar ve yan etkileri
olabilir). **Prompt**'un HTTP'de karşılığı yoktur; kullanıcının adıyla çalıştırdığı kayıtlı bir
sorguya daha yakındır.
## Tek sunucu, üçü birden {#one-server-all-three}
```python title="server.py" hl_lines="6 12 18"
--8<-- "docs_src/first_steps/tutorial001.py"
```
Üç sade fonksiyon, üç dekoratör. Her dekoratör kaydın tamamıdır:
* `@mcp.tool()`, `add`'i bir **araç** yapar.
* `@mcp.resource("greeting://{name}")`, `greeting`'i bir **kaynak şablonu** yapar: URI içindeki `{name}`, fonksiyonun parametresidir.
* `@mcp.prompt()`, `summarize`'ı bir **prompt** yapar. Döndürdüğü dize bir kullanıcı mesajına dönüşür.
Geri kalan her şeyi (adı, açıklamayı, argüman şemasını) SDK fonksiyonun kendisinden okur: adından, docstring'inden, tür ipuçlarından. Hiçbirini ayrıca bildirmediniz.
!!! tip
SDK'nın iki yarısının iki ayrı import yolu vardır: `from mcp import Client` ve
`from mcp.server import MCPServer`. `from mcp import MCPServer` diye bir şey yoktur.
### Deneyin {#try-it}
MCP Inspector ile çalıştırın:
```console
uv run mcp dev server.py
```
Yazdırdığı URL'yi açın. Inspector'da her temel öğe için bir sekme var; sırayla üzerinden geçin.
**Tools.** Tek bir girdi: `add`, açıklaması *Add two numbers.* Formda `a` için zorunlu bir tamsayı alanı, `b` için de bir tane daha var. Doldurun, çağırın; sonuç `3`. Inspector bu formu `a: int, b: int` ifadesinden oluşturdu. Diğer tüm istemciler de öyle yapar.
**Resources.** *Resources* listesi boş. `greeting`, **Resource Templates** altında; çünkü `greeting://{name}` bir parametre içerir: biri bir `name` verene kadar listelenecek tek bir kaynak yoktur. Ona `World` verin ve okuyun:
```text
Hello, World!
```
**Prompts.** Tek bir girdi: tek bir zorunlu `text` argümanı olan `summarize`. Biraz metinle getirin; `role: user` taşıyan ve içeriği işlenmiş dizeniz olan tek bir mesaj alırsınız. Bir prompt'un hepsi budur: mesaj oluşturan bir fonksiyon.
Inspector sunucunuzu **stdio** üzerinden çalıştırdı; bu, bir MCP sunucusunun konuşabileceği aktarımlardan biridir. Henüz bir tane seçmiyorsunuz; bunun sayfası **[Sunucunuzu çalıştırma](../run/index.md)**.
## Yetenekler {#capabilities}
Inspector'da üç sekme gördünüz. Üç tane olduğunu nereden bildi?
Bir istemci bağlandığında sunucu **yeteneklerini** beyan eder: hangi istek ailelerini yanıtlayacağını. İstemci, neyi isteyeceğine karar vermek için bu beyanı kullanır. Bunu siz hiç yazmadınız; `MCPServer` sizin yerinize beyan eder.
Kendiniz bakın. SDK'nın `Client`'ı sunucu nesnesini doğrudan kabul eder ve ona **bellek içinde** bağlanır (alt süreç yok, port yok):
```python
import asyncio
from mcp import Client
from server import mcp
async def main() -> None:
async with Client(mcp) as client:
print(client.server_capabilities.model_dump(exclude_none=True))
asyncio.run(main())
```
```text
{'prompts': {'list_changed': True}, 'resources': {'subscribe': True, 'list_changed': True}, 'tools': {'list_changed': True}}
```
Bu sözlük, sunucunuzun beyan ettiği **yeteneklerdir**. Bağlanan her istemcinin öğrendiği ilk şey budur:
| Yetenek | İstemci artık şunları çağırabilir |
|-------------|----------------------------------------------------------------|
| `tools` | `tools/list`, `tools/call` |
| `resources` | `resources/list`, `resources/templates/list`, `resources/read` |
| `prompts` | `prompts/list`, `prompts/get` |
`MCPServer` üç temel öğenin hepsini sunar; bu yüzden üçü de her zaman beyan edilir.
Orada ne olmadığına dikkat edin. `completions` (kaynak şablonları ve prompt'lar için argüman otomatik tamamlama) sizin yazacağınız bir işleyici gerektirir; bu sunucuda yok, dolayısıyla yetenek de yok ve uslu bir istemci sormaz. İsteğe bağlı her şey için kural budur: şeyi kaydedin, yetenek belirir; **[Tamamlamalar](../servers/completions.md)** bunu kanıtlar.
!!! info
`Client(mcp)`, bu belgelerdeki her örneğin test edildiği aynı bellek içi istemcidir;
sizinkileri de böyle test edeceksiniz. Kendine ait koca bir sayfası var: **[Test etme](testing.md)**.
## Yazmadıklarınız {#what-you-did-not-write}
Bu sayfaya dönüp bir bakın. Üç küçük Python fonksiyonu yazdınız. Şunları **yazmadınız**:
* Bir JSON Schema. `a: int, b: int`, `add` şemasının *ta kendisidir*.
* Bir istek işleyici. `tools/list`, `resources/read`, `prompts/get`: hepsi sizin yerinize sunulur.
* Bir yetenek beyanı. `MCPServer` onu sizin yerinize yaptı.
* Tek satır protokol. Sürüm anlaşması, JSON-RPC çerçevelemesi, yetenek değiş tokuşu: hepsi `mcp dev` ve `Client(mcp)` içinde oldu ve siz hiçbirini görmediniz.
SDK'nın bütün meselesi bu oran.
## Özet {#recap}
* **Host** LLM uygulamasıdır, **istemci** onun MCP konuşan yarısıdır, **sunucu** ise sizin oluşturduğunuz şeydir.
* Araçları **model**, kaynakları **uygulama**, prompt'ları **kullanıcı** kontrol eder.
* Her temel öğe için bir dekoratör: `@mcp.tool()`, `@mcp.resource(uri)`, `@mcp.prompt()`. Ad, açıklama ve şema fonksiyondan gelir.
* İçinde `{param}` olan bir URI, somut kaynaklardan ayrı listelenen bir kaynak **şablonu** oluşturur.
* Sunucunun **yetenekleri** sizin yerinize beyan edilir ve bir istemci yalnızca sunucunun beyan ettiklerini ister.
* `Client(mcp)` sunucu nesnesine bellek içinde bağlanır: ilk günden test düzeneğiniz.
Sırada **[Gerçek bir host'a bağlanma](real-host.md)** var: bu sunucu, gerçekten, Claude Desktop'ın ya da bir IDE'nin içinde. Ardından **[Test etme](testing.md)**: bir sayfa, bir bellek içi istemci ve çalışıp çalışmadığını bir daha asla tahmin etmek zorunda kalmazsınız. Ondan sonra her temel öğenin kendi sayfası var; modelin yönettiğiyle başlıyoruz: **[Araçlar](../servers/tools.md)**.

View file

@ -0,0 +1,57 @@
---
translation:
sections: [ed4a756b4c53c585, 97e2fb315b7fe398, 4d04f1c6f4bf6c1d, 577d73078fc62baf]
tool: 1
---
# Başlarken {#get-started}
MCP'de ya da bu SDK'da yeni misiniz? Buradan başlayın. Bu sayfalar sizi sıfırdan
çalışan, test edilmiş bir sunucuya götürür: [SDK'yı kurun](installation.md),
[ilk sunucunuzu](first-steps.md) yazın, [onu gerçek bir host'a bağlayın](real-host.md) ve
bellek içi bir istemciyle [test edin](testing.md).
## Kodu çalıştırma {#run-the-code}
Kod bloklarının tamamı doğrudan kopyalanıp kullanılabilir: hepsi eksiksiz, çalışan dosyalardır.
Takip etmek için bir bloğu `server.py` dosyasına yapıştırın ve MCP Inspector'da açın:
```console
uv run mcp dev server.py
```
Kodu yazmanız (ya da kopyalamanız), düzenlemeniz ve yerelde çalıştırmanız **ŞİDDETLE önerilir**. Asıl meseleyi kendi editörünüzde kullanırken görürsünüz: ne kadar az kod yazdığınızı, otomatik tamamlamayı, daha hiçbir şeyi çalıştırmadan hataları yakalayan tür denetimlerini.
## Tahmin yürütmeyeceksiniz {#you-will-not-be-guessing}
Bu belgelerdeki her örnek, SDK'nın kendi deposunda [`docs_src/`](https://github.com/modelcontextprotocol/python-sdk/tree/main/docs_src) altında duran eksiksiz bir dosyadır ve her biri SDK'nın test paketi tarafından **bellek içi bir istemci** aracılığıyla çalıştırılır:
```python
import pytest
from mcp import Client
from server import mcp
@pytest.mark.anyio
async def test_add() -> None:
async with Client(mcp) as client:
result = await client.call_tool("add", {"a": 1, "b": 2})
assert result.structured_content == {"result": 3}
```
Alt süreç yok, port yok, aktarım yok. `Client(mcp)` sunucu nesnesine doğrudan bağlanır.
SDK'daki bir değişiklik bu sayfalardan birindeki örneği bozarsa, sayfadan önce CI kırmızıya döner. Burada okuduğunuz kod, çalışan kodun ta kendisidir.
Bunu [Test etme](testing.md) sayfasında kendiniz de kullanacaksınız; kendi sunucularınızı da böyle test edersiniz.
## Bundan sonra nereye {#where-to-go-next}
Bir sunucuyu çalıştırdıktan sonra bu belgelerin geri kalanı bir kurs değil, bir başvuru kaynağıdır.
Her sayfa kendi başına ayakta durur; bu yüzden doğrudan ihtiyacınız olana atlayın:
* Bir sunucunun ne sunduğu (araçlar, kaynaklar, prompt'lar) **[Sunucular](../servers/index.md)** bölümünde.
* Kaydettiğiniz fonksiyonların içinde nelerin kullanılabildiği **[İşleyicinin içinde](../handlers/index.md)** bölümünde.
* Sunucuyu istemcilerin önüne çıkarma (stdio, HTTP, mevcut FastAPI uygulamanız) **[Sunucunuzu çalıştırma](../run/index.md)** bölümünde.
* Diğer tarafı, yani MCP sunucularını *kullanan* bir uygulamayı oluşturma **[İstemciler](../client/index.md)** bölümünde.

View file

@ -0,0 +1,47 @@
---
translation:
sections: [6e2f9bab94d5ed36, 8cf653388f69e28b, 6fd9ea2f65de0df6]
tool: 1
---
# Kurulum {#installation}
Python SDK, PyPI'da [`mcp`](https://pypi.org/project/mcp/) adıyla yayımlanır. **Python 3.10+** gerektirir.
Bu belgeler, güncel kararlı sürüm hattı olan **v2**'yi anlatır:
=== "uv"
```bash
uv add "mcp[cli]"
```
=== "pip"
```bash
pip install "mcp[cli]"
```
!!! note "v1'den mi geliyorsunuz?"
v2, geriye dönük uyumsuz değişiklikler içeren bir ana sürümdür; **[Geçiş kılavuzu](../migration.md)**
bunların her birini ele alır. *Paketiniz* `mcp`'ye bağımlıysa ve henüz geçişe hazır değilse,
sabitlenmemiş bir çözümlemenin 1.x hattında kalması için `<2` üst sınırını koruyun (örneğin `mcp>=1.28,<2`).
## Neler kurulur {#what-gets-installed}
SDK'yı kullanmak için bunların hiçbirini bilmeniz gerekmez. Yine de her bağımlılığın ne işe yaradığını merak ediyorsanız:
* `mcp-types`: tüm protokol türleri (istekler, sonuçlar, içerik blokları), SDK ile birebir aynı sürüm numarasıyla yayımlanan ayrı bir paket olarak gelir. `mcp`'ye bağımlı kod bunu `mcp.types` takma adı üzerinden içe aktarır (bu belgelerdeki her `from mcp.types import ...` satırı böyledir); `mcp_types`'ı doğrudan yalnızca `mcp-types`'ı SDK olmadan kuran bir projede içe aktarın.
* [`anyio`](https://anyio.readthedocs.io/): asenkron çalışma zamanı. SDK'nın tamamı anyio üzerine yazıldığı için hem `asyncio` hem de `trio` üzerinde çalışır.
* [`pydantic`](https://docs.pydantic.dev/): her `mcp.types` modelinin temeli; ayrıca tüm şema üretimi ve doğrulaması.
* [`httpx2`](https://pypi.org/project/httpx2/): Streamable HTTP ve SSE *istemci* aktarımlarının arkasındaki HTTP istemcisi; server-sent events desteği yerleşik olarak gelir.
* [`starlette`](https://www.starlette.io/), [`uvicorn`](https://www.uvicorn.org/), [`sse-starlette`](https://pypi.org/project/sse-starlette/) ve [`python-multipart`](https://pypi.org/project/python-multipart/): HTTP *sunucu* aktarımları.
* [`jsonschema`](https://pypi.org/project/jsonschema/): bir aracın yapılandırılmış çıktısını, bildirdiği çıktı şemasına göre doğrular.
* [`pyjwt[crypto]`](https://pyjwt.readthedocs.io/): yetkilendirme için OAuth token işleme.
* [`opentelemetry-api`](https://opentelemetry-python.readthedocs.io/): yalnızca hafif API; bu sayede siz bir OpenTelemetry SDK'sı ve dışa aktarıcı kurmadıkça SDK'nın izleme middleware'inin hiçbir maliyeti olmaz.
* [`typing-extensions`](https://typing-extensions.readthedocs.io/) ve [`typing-inspection`](https://pypi.org/project/typing-inspection/): Python 3.10'da modern tür özellikleri.
* [`pywin32`](https://pypi.org/project/pywin32/): yalnızca Windows'ta, `stdio` alt süreç yönetimi için kullanılır.
## İsteğe bağlı ekler {#optional-extras}
* `mcp[cli]`, `mcp` komut satırı aracı (`mcp dev`, `mcp run`, `mcp install`) için [`typer`](https://typer.tiangolo.com/) ve [`python-dotenv`](https://pypi.org/project/python-dotenv/) paketlerini ekler. Geliştirme sırasında bunu istersiniz; dağıtılmış bir sunucuda gerekmeyebilir.
* `mcp[rich]`, daha okunaklı sunucu log'ları için [`rich`](https://rich.readthedocs.io/) paketini ekler.

View file

@ -0,0 +1,183 @@
---
translation:
sections: [3c4f2f06b4e978b6, 22520eecae3d1961, f4e1709db18d635a, 2eb57992049671d9, 1ba83e9af37cc1b4, 4822586344b08d9e, 1c93afef72478992, b6b448f9eddd51dc, fe55370fd931815b]
tool: 1
---
# Gerçek bir host'a bağlanma {#connect-to-a-real-host}
**Host**, sunucunuzun sonunda içine girdiği uygulamadır: Claude Desktop, Claude Code, bir IDE. Kullanıcının konuştuğu şey host'tur. Onun içinde bir MCP **istemcisi** sunucunuzu bir alt süreç olarak başlatır ve onunla o sürecin stdin'i ve stdout'u üzerinden konuşur.
Yani bir host'a bağlanmak tek bir eylemdir: ona **sunucunuzu başlatan komutu** söylersiniz. Bu sayfadaki her şey (iki CLI komutu, üç JSON dosyası) aynı komutu koyacağınız farklı bir yerdir.
## Tek sunucu, her host {#one-server-every-host}
```python title="server.py" hl_lines="3 33-34"
--8<-- "docs_src/real_host/tutorial001.py"
```
İki araç ve bir kaynak, tek dosya. Bu dosyayla ilgili üç şey aşağıdaki her host için önemlidir:
* Argümansız `mcp.run()` bir **stdio** sunucusu başlatır: bloklar, protokol mesajlarını stdin'den okur ve stdout'a yazar. Bu sayfadaki her host'un konuştuğu aktarım budur. Host dosyanızı bir alt süreç olarak başlatır ve bu iki kanalın sahibidir; bağlanmanın her zaman yalnızca "işte komut" olmasının nedeni de budur. Hiçbir zaman port seçmezsiniz ve hiçbir şey bir portu dinlemez.
* `run()`, `if __name__ == "__main__":` altındadır. Aşağıdaki her şey bu dosyayı çalıştırmak yerine **import eder**; bu yüzden korumasız bir `run()`, modülü herhangi bir şey yüklediği anda bir sunucu başlatırdı.
* Sunucu nesnesi, `mcp` adında modül düzeyinde bir globaldir. `mcp run`'ın aradığı ad budur (`server` ve `app` de olur). Başka bir ad verirseniz açıkça belirtirsiniz: `mcp run server.py:bookshop`.
Bu, bu sayfadaki son Python satırı. Buradan aşağısı tamamen host yapılandırması.
## Başlatma komutu {#the-launch-command}
Aşağıdaki her host aynı komutu alır:
```bash
uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
```
Hepsi için tek komut, çünkü `uv run --with` SDK'yı anında yeni bir ortama çözümler: herhangi bir dizinden çalışır, ne bir projeye ne de etkinleştirilecek bir sanal ortama ihtiyaç duyar. Bu, burada başka her yerden daha önemlidir; çünkü host sunucunuzu sizin kabuğunuzdan değil, *kendi* çalışma dizininden ve neredeyse boş bir ortamla başlatır.
Bu aynı zamanda `mcp install`'un sizin için Claude Desktop'ın yapılandırmasına yazdığı komuttur (aşağıda). Böylece elle yazdığınız ile aracın ürettiği, aracın eklediği tam sürüm sabitlemesi dışında örtüşür.
!!! tip "Host `uv`'yi bulamazsa"
Host sunucunuzu asgari bir `PATH` ile başlatır ve `uv` bunun üzerinde olmayabilir. Yalın
`uv`'yi `which uv` (macOS/Linux) veya `where uv` (Windows) çıktısındaki mutlak yolla değiştirin.
`mcp install`'un yazdığı da tam olarak budur.
!!! note "Bu sayfa yerel senaryoyu anlatır"
Buradaki her şey sunucunuzu host'un bulunduğu makinede çalıştırır: host dosyanızı stdio
üzerinden başlatır. Kişisel ya da tek makinelik bir araç için bu tam olarak doğru olandır.
Dosyanıza sahip *olmayan* insanlara bir sunucu vermek için komut değil **URL** dağıtırsınız:
aynı `mcp` nesnesi, Streamable HTTP üzerinden sunulur. **[Sunucunuzu çalıştırma](../run/index.md)**
bu kararı tek bir tabloda verir, **[Dağıtım ve ölçekleme](../run/deploy.md)** ise oradan
gerçek bir ana bilgisayar adına giden yoldur.
Ve host, içinde bir MCP istemcisi olan bir uygulamadan başka bir şey değildir; bu yüzden kendi
Python kodunuz host rolünü oynayabilir: **[İstemci aktarımları](../client/transports.md)**
bu aynı dosyayı `stdio_client(...)` ile bir alt süreç olarak başlatır, **[Test etme](testing.md)**
ise ona hiç süreç olmadan bellek içinde bağlanır.
## Claude Desktop {#claude-desktop}
SDK'nın sizin için yapılandırabildiği tek host:
```bash
uv run mcp install server.py
```
Hepsi bu. `mcp install` sunucunun adını okumak için dosyayı import eder, Claude Desktop'ın yapılandırma dosyasını bulur ve başlatma komutunu içine yazar. Bu arada yolunuzu mutlak bir yola çevirir, sizin yapmanıza gerek kalmaz.
Kafa karıştıracak bir şey yok. Yazdığı kayıt şu:
```json
{
"mcpServers": {
"Bookshop": {
"command": "/absolute/path/to/uv",
"args": [
"run",
"--frozen",
"--with",
"mcp[cli]==2.0.0",
"mcp",
"run",
"/absolute/path/to/server.py"
]
}
}
}
```
Bu, yukarıdaki bölümdeki başlatma komutunun üç eklemeli hâli: `uv`'nin mutlak yolu, `uv` yakınında bulunduğu bir kilit dosyasını asla yeniden yazmasın diye `--frozen` ve kurulu `mcp` sürümüne tam bir sabitleme. Şurada bulunan `claude_desktop_config.json` dosyasına yazılır:
* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
Bu dosyayı elle yazabilirsiniz. `mcp install`, bunu yaparken klasik hatayı (göreli yol) yapmayın diye vardır.
Claude Desktop'tan tamamen çıkın (yalnızca penceresini kapatmayın) ve yeniden açın.
!!! warning
Claude Desktop'ın yapılandırma *dizini* henüz yoksa `mcp install`, `Claude app not found`
hatasıyla başarısız olur. Claude Desktop'ı kurun ve bir kez çalıştırın: dizini oluşturan budur.
!!! tip
Claude Desktop sunucunuzu kendi sürecinde başlatır; bu yüzden kabuğunuzun ortam değişkenleri
orada yoktur. `uv run mcp install server.py -v API_KEY=abc123` (veya `-f .env`) bunları kaydın
`env` alanına işler. `--name` kayıt adını geçersiz kılar; varsayılan olarak sunucunun `name`
değeridir.
## Claude Code {#claude-code}
Düzenlenecek dosya yok. Sunucuyu `claude` CLI ile kaydedin; `--` sonrasındaki her şey başlatma komutudur.
```bash
claude mcp add bookshop -- uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
```
`bookshop`'un bağlı olduğunu ve araçlarının listelendiğini doğrulamak için bir Claude Code oturumunda `/mcp` çalıştırın.
## Cursor {#cursor}
Proje kök dizininizde `.cursor/mcp.json` dosyasını oluşturun.
```json
{
"mcpServers": {
"bookshop": {
"command": "uv",
"args": ["run", "--with", "mcp[cli]", "mcp", "run", "/absolute/path/to/server.py"]
}
}
}
```
Aynı `command` artı `args`, Claude Desktop'ın kullandığı aynı `mcpServers` anahtarı altında. Sunucu, Cursor'ın MCP ayarlarında iki araç da listelenmiş olarak görünür.
## VS Code {#vs-code}
Proje kök dizininizde `.vscode/mcp.json` dosyasını oluşturun.
```json
{
"servers": {
"bookshop": {
"type": "stdio",
"command": "uv",
"args": ["run", "--with", "mcp[cli]", "mcp", "run", "/absolute/path/to/server.py"]
}
}
}
```
Cursor'ın dosyasından iki fark var ve yalnızca bu ikisi: sarmalayıcı anahtar `mcpServers` değil `servers`'tır ve her kayıt `type`'ını bildirir. Güven iletişim kutusunu onaylayın; ardından Command Palette'teki **MCP: List Servers**, `bookshop`'u çalışır durumda gösterir.
!!! note
**GitHub Copilot** eklentisiyle oturum açılmış VS Code 1.99 veya üzeri gerekir (Copilot Free
yeterli) ve Copilot Chat **Agent** modunda olmalıdır; çünkü başka hiçbir mod araç çağırmaz.
## Görünmüyor {#it-doesnt-show-up}
Herhangi bir host yapılandırmasına dokunmadan önce başlatma komutunu kendiniz çalıştırın:
```bash
uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
```
Hiçbir şey yazdırmaz ve geri dönmez. Bu sessizlik doğrudur: stdio sunucusu, bir host'un stdin'de ilk konuşan taraf olmasını bekler (durdurmak için `Ctrl-C`). Asıl hata bir traceback ya da anında çıkıştır; artık onu bir host üzerinden tahmin etmeye çalışmak yerine okuyabilirsiniz.
Bu komut oturup beklediğinde, geriye kalan neredeyse her zaman üç şeyden biridir:
* **Göreli yol.** Host sunucunuzu kaydı yaptığınız dizinden değil, *kendi* çalışma dizininden başlatır. `/absolute/path/to/server.py` gereken yerde `server.py` yazmak, açık ara en yaygın hatadır. Host `uv`'yi de bulamıyorsa o yol da mutlak olmalıdır.
* **Host hâlâ eski yapılandırmasını çalıştırıyor.** Host'lar yapılandırmalarını başlarken okur. Özellikle Claude Desktop'tan, `claude_desktop_config.json` üzerindeki bir düzenleme etkili olmadan önce *tamamen çıkılması* (yalnızca penceresinin kapatılması değil) ve yeniden açılması gerekir.
* **Yönlendirilen pencerenin dışında stdout'a bir şey ulaştı.** stdio'da stdout protokolün *ta kendisidir*. SDK, hizmet verirken flush edilmiş başıboş çıktıyı stderr'e yönlendirir; ancak o andan önce stdout'a flush edilen çıktı (bir sarmalayıcı betiğin echo'su, tamponsuz bir süreçte import anında bir `print()`) ya da yorumlayıcı çıkışında boşaltılan tamponlanmış bir `print()`, host'a bozuk bir mesaj verir ve host bağlantıyı keser. stderr işleyicisi her kaydı flush eden varsayılan `logging` yapılandırmasıyla log tutun; özel işleyiciler de stdout'tan uzak durmalıdır. Ayrıntıların tamamı **[Logging](../handlers/logging.md)** sayfasında.
Claude Desktop her sunucu için bir log tutar: `mcp-server-<NAME>.log` sunucunuzun stderr'idir, bağlantılar için `mcp.log`'un yanında; macOS'te `~/Library/Logs/Claude`, Windows'ta `%APPDATA%\Claude\logs` altında.
Bu üçünün ötesindeki her şey için doğru sayfa **[Sorun giderme](../troubleshooting.md)**.
## Özet {#recap}
* **Host** (Claude Desktop, bir IDE), sunucunuzu stdio üzerinden bir alt süreç olarak başlatan bir MCP istemcisi çalıştırır. Bağlanmak, ona tek bir başlatma komutu vermek demektir.
* O komut `uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py`: etkinleştirilecek venv yok, her dizinden çalışır.
* **Claude Desktop**, `mcp install`'un sizin için yapılandırdığı tek host'tur. Aynı komutu (artı `uv`'nin mutlak yolu, `--frozen` ve kurulu sürüme tam bir sabitleme) `claude_desktop_config.json` dosyasına yazar; böylece sizin yapmanıza hiç gerek kalmaz.
* **Claude Code** için `claude mcp add bookshop -- <launch command>`. **Cursor** için `mcpServers` altında `.cursor/mcp.json`. **VS Code** için `servers` altında `.vscode/mcp.json`, her kayıtta bir `type` ile.
* Her yerde mutlak yollar, yapılandırmasını düzenledikten sonra host'u yeniden başlatın ve SDK dışında hiçbir şeyin stdout'a yazmasına izin vermeyin.
Bu sayfadaki her host aynı dosyaya, aynı komutla bağlandı. O dosyanın neler *sunabileceği* ise bu belgelerin geri kalanı: **[Araçlar](../servers/tools.md)**, **[Kaynaklar](../servers/resources.md)** ve stdio dışındaki tüm aktarımlar için **[Sunucunuzu çalıştırma](../run/index.md)**.

View file

@ -0,0 +1,116 @@
---
translation:
sections: ['4926721070127497', c52a1de2b6b32f40, 2e410b412c25f314, 627195f7159e24ef]
tool: 1
---
# Test etme {#testing}
Python SDK, **bellek içi aktarıma** sahip bir `Client` sınıfıyla gelir: ona sunucu nesnenizi geçirirsiniz, o da doğrudan bağlanır.
Alt süreç yok. Port yok. Hiç aktarım yok. FastAPI'nin `TestClient`'ıyla aynı fikir.
## Temel kullanım {#basic-usage}
Tek bir aracı olan basit bir sunucunuz olduğunu varsayalım:
```python title="server.py"
--8<-- "docs_src/testing/tutorial001.py"
```
Aşağıdaki testi çalıştırmak için iki ek (geliştirme) bağımlılığına ihtiyacınız var:
=== "uv"
```bash
uv add --dev pytest inline-snapshot
```
=== "pip"
```bash
pip install pytest inline-snapshot
```
!!! info
Bu belgeler [`pytest`](https://docs.pytest.org/en/stable/)'i zaten bildiğinizi varsayar.
Aşağıdaki test, sonuç nesnesinin tamamını tek satırda doğrulamak için
[`inline-snapshot`](https://15r10nk.github.io/inline-snapshot/latest/) kullanır. Bir testin
çıktısını, gördüğünüz `snapshot(...)` değişmezi olarak kaydeder. Kullanmak istemezseniz
import satırını silin ve herhangi bir testte olduğu gibi ilgilendiğiniz alanları doğrulayın
(`result.content[0].text == "3"`).
Şimdi test:
```python title="test_server.py"
import pytest
from inline_snapshot import snapshot
from mcp import Client
from mcp.types import CallToolResult, TextContent
from server import mcp
@pytest.fixture
def anyio_backend(): # (1)!
return "asyncio"
@pytest.fixture
async def client(): # (2)!
async with Client(mcp, raise_exceptions=True) as c:
yield c
@pytest.mark.anyio
async def test_call_add_tool(client: Client):
result = await client.call_tool("add", {"a": 1, "b": 2})
# Drop the server identity stamp in `_meta`; it is not what this test is about.
result.meta = None
assert result == snapshot(
CallToolResult(
content=[TextContent(type="text", text="3")],
structured_content={"result": 3},
)
)
```
1. `trio` kullanıyorsanız bunun yerine `"trio"` döndürün. Ayrıntılar için [anyio belgelerine](https://anyio.readthedocs.io/en/stable/testing.html#specifying-the-backends-to-run-on) bakın.
2. Fixture, bağlı bir istemci üretir. `client` alan her test, aynı sunucuya yeni bir bellek içi bağlantı alır.
İşte bu kadar! Artık testlerinizi daha fazla senaryoyu kapsayacak şekilde genişletebilirsiniz.
## Neden `raise_exceptions=True`? {#why-raise_exceptionstrue}
İki farklı şey ters gidebilir ve bu bayrak yalnızca birine dokunur.
**Araçlarınızdan** birinin içindeki bir istisna, protokol hatası değildir. `is_error=True` taşıyan
normal bir sonuca dönüşür ve model mesajı okur. `raise_exceptions` bunu değiştirmez: onunla da
onsuz da `call_tool` aynı `is_error=True` sonucunu döndürür. Bu konuda ayrı bir sayfa var:
**[Hataları ele alma](../servers/handling-errors.md)**.
Araç gövdesinin **dışındaki** bir hata ise farklıdır. `Client(mcp)`'nin size verdiği bağlantıda
sunucu, istemci görmeden önce onu genel bir `"Internal server error"` mesajına dönüştürerek
temizler. Beklenmedik bir çökmenin ayrıntılarını uzak bir çağırana asla sızdırmamalısınız. Bir
testte ise tam olarak *istemediğiniz* şey budur ve `raise_exceptions=True`'nun değiştirdiği de
budur: testiniz temizlenmiş mesaj yerine gerçek mesajı görür.
Testlerde açık bırakın. Üretim kodunda bir anlamı yoktur.
## Varsayılan olarak süreç içi {#in-process-by-default}
!!! note
`Client(mcp)` süreç içinde bağlanır ve varsayılan olarak **nesilden bağımsızdır**: sunucuyu
yoklar ve uygun protokol yolunu seçer. Testiniz eski nesle özgü anlamları (örnekleme (sampling)
veya elicitation (kullanıcıdan bilgi isteme) itmesi, `message_handler`) sınıyorsa `mode="legacy"`
olarak sabitleyin ve orada `raise_exceptions=True`'yu kaldırın: eski nesil bir bağlantı zaten
hiçbir zaman temizleme yapmaz ve bayrak, hatayı testinizde değil sunucu görevinin içinde
yeniden fırlatır.
Bu belgelerin, örneklerinin çalıştığı sözünü verebilmesinin nedeni de o tek satırdır: her örnek
dosya SDK'nın kendi test paketinde çalıştırılır, neredeyse hepsi tam olarak bu istemci
üzerinden. SDK'nın kendi üzerinde kullandığı aracın aynısını kullanıyorsunuz.
Çalışan, test edilmiş bir sunucunuz var. Onu gerçek bir uygulamanın (Claude Desktop, bir IDE)
içine koymak **[Gerçek bir host'a bağlanma](real-host.md)** sayfasında; sunmanın diğer tüm
yolları ise **[Sunucunuzu çalıştırma](../run/index.md)** sayfasında.