docs: refresh translations, and translate pages in parallel (#3458)

This commit is contained in:
Max 2026-09-07 13:35:53 +01:00 • committed by GitHub
commit fd66270926
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 4821 additions and 2277 deletions

View file

@ -1,6 +1,6 @@
---
translation:
sections: [0355618e5f4d5fe4, 1821eaf50f2d0b64, 82e0b28ebd3abf5a, 8ac39614c094f2d0, dab6ff945501ab2a, bd5565c3b2d4f959, 96819ce3d63a0487]
sections: [0355618e5f4d5fe4, 0fefa31fb7c7b585, 5c53e7487c9c70cc, 8ac39614c094f2d0, dab6ff945501ab2a, bd5565c3b2d4f959, 96819ce3d63a0487]
tool: 1
---
# MCP Apps {#mcp-apps}
@ -18,7 +18,7 @@ SDK bunu yerleşik `Apps` uzantısı (`io.modelcontextprotocol/ui`) olarak sunar
## Yüzü olan bir saat {#a-clock-with-a-face}
```python title="server.py" hl_lines="19 22 30 32"
```python title="server.py" hl_lines="17 20 28 30"
--8<-- "docs_src/apps/tutorial001.py"
```
@ -39,11 +39,31 @@ Her istemci uygulamaları çizmez. Şartname bunun sizin için ne anlama geldiğ
Model `content`'i okur; iframe insanlar içindir. UI destekli bir host yine de metin sonucunu modele iletir, yalnızca metin destekleyen bir istemci ise *sadece* onu alır. Yani kanonik desen tek araç, iki yanıttır. `get_time`'a bir daha bakın:
```python title="server.py" hl_lines="23-27"
```python title="server.py" hl_lines="21-25"
--8<-- "docs_src/apps/tutorial001.py"
```
`client_supports_apps(ctx)` yalnızca istemci `io.modelcontextprotocol/ui` uzantısını beyan ettiğinde **ve** `mimeTypes` ayarlarında `text/html;profile=mcp-app`'i listelediğinde `True` olur. Alan zorunludur, bu yüzden onu atlayan bir istemci sayılmaz. Aynı dosyadaki `main()` tam olarak bunu beyan eder: anlaşmanın istemci tarafı, ve zengin yanıt geri gelir.
`client_supports_apps(ctx)` yalnızca istemci `io.modelcontextprotocol/ui` uzantısını beyan ettiğinde **ve** `mimeTypes` ayarlarında `text/html;profile=mcp-app`'i listelediğinde `True` olur. Alan zorunludur, bu yüzden onu atlayan bir istemci sayılmaz. Anlaşmanın istemci tarafı şöyle:
```python title="client.py" hl_lines="8 12"
--8<-- "docs_src/apps/tutorial001_client.py"
```
`server.py` dosyasını HTTP üzerinden sunun, ardından istemciyi ikinci bir terminalden çalıştırın:
```console
uv run mcp run server.py --transport streamable-http
```
```console
python client.py
```
```text
2026-06-26T12:00:00Z
```
Zengin yanıt geri geldi. `Client` çağrısından `extensions=[APPS_SUPPORT]` argümanını çıkarın; aynı program bunun yerine `The time is 2026-06-26T12:00:00Z.` yazdırır. Yalnızca metin destekleyen bir istemcinin görüp göreceği de budur.
!!! warning
Tek içerik olarak asla `"[Rendered UI]"` gibi bir yer tutucu döndürmeyin. Yedek metin işe yaramazsa araç, yalnızca metin destekleyen her istemci için ve modelin kendisi için işe yaramaz. O cümleyi yazın.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [05891e7cc1938a13, b3c01a6af28c51ee, 7ffc91f5e38bdfe0, 717d3f235a8333a7, f471a13b2fe5d737, ed6af2df4b656dff]
sections: [05891e7cc1938a13, b3c01a6af28c51ee, 6eba6ce094f4417e, 125f28588c85dd7b, ddd8969b698ca11c, ed6af2df4b656dff]
tool: 1
---
# Uzantılar {#extensions}
@ -49,7 +49,7 @@ TypeError: Stamps.identifier must be a `vendor-prefix/name` string
İşe yarar en küçük uzantı, bir araç ve bir ayarlar eşlemesidir:
```python title="server.py" hl_lines="17 19-20 22-23 26"
```python title="server.py" hl_lines="16 18-19 21-22 25"
--8<-- "docs_src/extensions/tutorial003.py"
```
@ -57,17 +57,23 @@ TypeError: Stamps.identifier must be a `vendor-prefix/name` string
* `settings()`, `capabilities.extensions["com.example/stamps"]` konumunda duyurulan değerdir. Uzantıyı ayarsız duyurmak için `{}` (varsayılan) döndürün.
* Uzantı sunucuyu hiçbir zaman almaz. Katkıları veri olarak beyan eder; bunları `MCPServer` tüketir. Değiştirilecek bir `self.server` yoktur.
Kanıtı da `main()`: doğrudan `mcp`'ye bağlanan bellek içi bir istemci:
HTTP üzerinden sunun; kanıt da bir istemcidir:
```python title="server.py" hl_lines="29-34"
--8<-- "docs_src/extensions/tutorial003.py"
```console
uv run mcp run server.py --transport streamable-http
```
```python title="client.py" hl_lines="7-11"
--8<-- "docs_src/extensions/tutorial003_client.py"
```
Bu sayfadaki her `server.py` bu komutla sunulur; her `client.py` de ikinci bir terminalden `python client.py` ile onun yanında çalışır.
### Kendi metotlarınızı sunma {#serving-your-own-methods}
Bir uzantı **yeni istek metotları** kaydedebilir: spesifikasyonunkilerin yanında sunulan kendi fiilleri:
```python title="server.py" hl_lines="16-22 31 40-48"
```python title="server.py" hl_lines="14-20 24 33-41"
--8<-- "docs_src/extensions/tutorial004.py"
```
@ -83,14 +89,15 @@ Metotlar **yalnızca ekleme niteliğindedir**. SDK bunu çalışma zamanında de
### İstemci tarafı {#the-client-side}
Aynı dosyadaki `main()`, istemci tarafının tamamıdır; iki yarısıyla birlikte:
İstemci başlı başına bir programdır ve istemci tarafının iki yarısını da taşır:
```python title="server.py" hl_lines="54-58"
--8<-- "docs_src/extensions/tutorial004.py"
```python title="client.py" hl_lines="21-23 27-30"
--8<-- "docs_src/extensions/tutorial004_client.py"
```
* `Client(..., extensions=[advertise(EXTENSION_ID)])` uzantıyı beyan eder. Beyanlar `ClientCapabilities.extensions` hâline gelir: 2026-07-28 bağlantısında eşleme istek başına `_meta` zarfında taşınır, böylece sunucu onu **her** istekte görür; eski nesil bir bağlantıda `initialize` el sıkışmasıyla taşınır. Sunucu kodu hangisi olduğuyla ilgilenmez: `require_client_extension(ctx, ...)` ve `ctx.session.check_client_capability(...)` her iki yolda da doğru kaynağı okur.
* Satıcıya özgü metotlar bir katman aşağıya, `client.session.send_request(...)` düzeyine iner; `Client` yalnızca spesifikasyon fiilleri için birinci sınıf metotlar kazanır. `send_request` herhangi bir `Request` alt sınıfını kabul eder, bu yüzden satıcıya özgü istek olduğu gibi geçer.
* `SearchRequest` ve taşıdığı iki model uzantının iletim sözleşmesidir; bu yüzden istemci onları kendisi için beyan eder. Yayımlanmış bir uzantı bunları her iki tarafın da içe aktardığı bir pakette sunardı.
### `tools/call` isteğini yakalama {#intercepting-toolscall}
@ -109,12 +116,18 @@ Kanca `tools/call` isteğini sarmalar, başka hiçbir şeyi değil. Her iletiyi
## Bir istemci uzantısı kullanma {#using-a-client-extension}
**İstemci uzantısı**, aynı sözleşmenin tüketen taraftan görünüşüdür: tek bir tanımlayıcının arkasında toplanmış bir istemci tarafı davranış paketi. Örnekleri `Client(extensions=[...])` ile geçirin ve araçları normal şekilde çağırın:
**İstemci uzantısı**, aynı sözleşmenin tüketen taraftan görünüşüdür: tek bir tanımlayıcının arkasında toplanmış bir istemci tarafı davranış paketi. Buradaki sunucu `buy` çağrısını malın kendisi yerine kullanılacak bir makbuzla yanıtlar; bunu da yalnızca uzantıyı beyan etmiş bir istemci için yapar:
```python title="client.py" hl_lines="66-68"
```python title="server.py" hl_lines="22-25"
--8<-- "docs_src/extensions/tutorial006.py"
```
İstemcide örnekleri `Client(extensions=[...])` ile geçirin ve araçları normal şekilde çağırın:
```python title="client.py" hl_lines="33-35"
--8<-- "docs_src/extensions/tutorial006_client.py"
```
`call_tool("buy", ...)`, diğer her çağrı gibi düz bir `CallToolResult` döndürür. Uzantının değiştirdiği şu: sunucu artık `buy` çağrısını nihai bir sonuç yerine `receipt` adlı bir **sonuç biçimiyle** yanıtlayabilir ve `Receipts`, `call_tool` dönmeden önce onu tamamlar (burada makbuzu bir takip çağrısıyla kullanarak). Çağrı yerinde hiçbir şey değişmez.
Uzantıyı çıkarırsanız bunların hiçbiri olmaz: sunucunun kontrol noktası onu beyan etmemiş bir istemciyi reddeder (hata -32021) ve kontrolü atlayan bir sunucudan gelen sahiplenilmiş bir biçim, spesifikasyonun tanınmayan bir `resultType` için gerektirdiği gibi doğrulamadan geçemez. Bağlantının her iki ucunda da varsayılan olarak kapalı.
@ -124,15 +137,15 @@ Uzantıyı çıkarırsanız bunların hiçbiri olmaz: sunucunun kontrol noktası
```python
from mcp.client import advertise
client = Client(mcp, extensions=[advertise("com.example/search")])
client = Client("http://localhost:8000/mcp", extensions=[advertise("com.example/search")])
```
## İstemci uzantısı yazma {#writing-a-client-extension}
`ClientExtension`'dan alt sınıf türetin ve yalnızca ihtiyaç duyduklarınızı geçersiz kılın. Her birinin varsayılanı olan üç katkı türü var: `settings()`, `claims()` ve `notifications()`.
```python title="client.py" hl_lines="17-18 43-44 46-47"
--8<-- "docs_src/extensions/tutorial006.py"
```python title="client.py" hl_lines="16-17 25-26 28-29"
--8<-- "docs_src/extensions/tutorial006_client.py"
```
* Tanımlayıcı, sunucununkiyle aynı dilbilgisini izler ve sınıf tanımlandığında doğrulanır.
@ -153,12 +166,18 @@ def notifications(self) -> Sequence[NotificationBinding[Any]]:
### Uzantı fiilleri {#extension-verbs}
Bir uzantının kendi istek metotları istemci tarafında kayıt gerektirmez. Satıcıya özgü bir istek türü `mcp.types.Request`'ten türer ve [Kendi metotlarınızı sunma](#serving-your-own-methods) bölümündeki gibi `client.session.send_request` üzerinden gider. Tek bir ekleme var: bir params anahtarının `Mcp-Name` başlığında taşınması gerektiğinde (tasks gibi uzantı spesifikasyonları kendi fiilleri için bunu şart koşar) istek türü `name_param` beyan eder:
Bir uzantının kendi istek metotları istemci tarafında kayıt gerektirmez. Satıcıya özgü bir istek türü `mcp.types.Request`'ten türer ve [Kendi metotlarınızı sunma](#serving-your-own-methods) bölümündeki gibi `client.session.send_request` üzerinden gider. Uzantısı, adlandırılmış bir iş hakkında tek bir fiil sunan bir sunucu düşünün:
```python title="client.py" hl_lines="22-25 46-47"
```python title="server.py" hl_lines="12-13 30"
--8<-- "docs_src/extensions/tutorial007.py"
```
İstemcide tek bir ekleme var: bir params anahtarının `Mcp-Name` başlığında taşınması gerektiğinde (tasks gibi uzantı spesifikasyonları kendi fiilleri için bunu şart koşar) istek türü `name_param` beyan eder:
```python title="client.py" hl_lines="20-23 28-29"
--8<-- "docs_src/extensions/tutorial007_client.py"
```
Oturum, `params["jobId"]` değerini her gönderim yolunda `Mcp-Name` başlığına yansıtır; eksik bir değer ise gerekli bir başlığı sessizce atlamak yerine açıkça hata verir.
## Bir uzantının yapamayacakları {#what-an-extension-cannot-do}

View file

@ -1,6 +1,6 @@
---
translation:
sections: [2c79b6338e09b7ac, 7edc43b3fae11314, 1086e77ce561cd7f, a3f71823df5efc31, 9fc7109f72201cae, d50fe7faead8cf68, 7bf25983df655b66, 6330e1f4c6029683, 2f1749c8c133fa1c, 8db7116fc8ddd0ee, ebc33704fbd74262, cd0e9c933350390e]
sections: [2c79b6338e09b7ac, 9d5d10a5f0405d0a, 1086e77ce561cd7f, a3f71823df5efc31, 9fc7109f72201cae, d50fe7faead8cf68, 7bf25983df655b66, 6330e1f4c6029683, 2f1749c8c133fa1c, 8db7116fc8ddd0ee, ebc33704fbd74262, 0fde3bcea081ba3a]
tool: 1
---
# Düşük seviyeli Server {#the-low-level-server}
@ -36,18 +36,22 @@ Bu, **[Araçlar](../servers/tools.md)** sayfasında dokuz satır `@mcp.tool()` i
### Deneyin {#try-it}
Bunun için Inspector yok: `mcp dev` ve `mcp run` yalnızca `MCPServer` kabul eder. Bellek içi `Client` bunu umursamaz; düşük seviyeli bir `Server`'ı tıpkı bir `MCPServer`'ı aldığı gibi alır:
`mcp dev` ve `mcp run` yalnızca `MCPServer` kabul eder, bu yüzden bunu kendiniz sunarsınız. `server.py` dosyasının son satırı ondan sıradan bir ASGI uygulaması oluşturur, uvicorn da onu çalıştırır:
```python title="main.py"
```console
uvicorn server:app --port 8000
```
Inspector'ı ya da herhangi bir istemciyi `http://localhost:8000/mcp` adresine yönlendirin:
```python title="client.py"
import asyncio
from mcp import Client
from server import server
async def main() -> None:
async with Client(server) as client:
async with Client("http://localhost:8000/mcp") as client:
result = await client.call_tool("search_books", {"query": "dune", "limit": 5})
print(result.content)
@ -64,6 +68,8 @@ asyncio.run(main())
* `result.structured_content` değeri `None`. Yüksek seviyeli sunucu `-> str` dönüş türünü sizin yerinize `{"result": ...}` içine sarmalar; burada sizin oluşturmadığınızı kimse oluşturmaz.
* `list_tools`, **sizin** yazdığınız şemayı karakteri karakterine döndürür. Yüksek seviyeli sürümde her özellikte `"title": "Query"`, kökte de `"title": "search_booksArguments"` vardı: Pydantic'in bıraktığı izler. Burada ise ağa giden bir şey varsa onu oraya siz koymuşsunuzdur.
Testte uvicorn'u ve portu atlarsınız: `Client(server)`, düşük seviyeli bir `Server`'ı süreç içinde tıpkı bir `MCPServer`'ı aldığı gibi alır; **[Test etme](../get-started/testing.md)** sayfasının anlattığı kalıp da budur.
## Sizin yerinize hiçbir şey denetlenmez {#nothing-is-checked-for-you}
`MCPServer`, çağrıyı kendi ürettiği şemaya göre doğrulayarak hatalı bir argümanı fonksiyonunuz daha çalışmadan reddeder (**[Araçlar](../servers/tools.md)**).
@ -215,4 +221,4 @@ Bunların her biri, artık kavramlarını bildiğiniz birer fikir; her birinin k
* `add_request_handler(method, params_type, handler)` her metodu sunar. `initialize` ayrılmıştır.
* Bir `Server`'ın duyurduğu yetenekler, hangi işleyicileri kaydettiğinizden türetilir.
`Client(server)` iki sunucuya da aynı davrandı, çünkü ikisi aynı protokolün *ta kendisi*; bütün mesele de bu. Bir alt katman ise bir sınıf bile değil: **[Middleware](middleware.md)**.
İstemci iki sunucuya da aynı davrandı, çünkü ikisi aynı protokolün *ta kendisi*; bütün mesele de bu. Bir alt katman ise bir sınıf bile değil: **[Middleware](middleware.md)**.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [a9aba7a026c7bd85, ed32bda7ba9ae33a, 7e64cc5646abb91f, 22a0129ee78b3c63, d875373c06d8d2f9]
sections: [a9aba7a026c7bd85, 83e2a08b9d46a398, 9fd8a0aa384b3257, 22a0129ee78b3c63, d875373c06d8d2f9]
tool: 1
---
# Sayfalama {#pagination}
@ -31,9 +31,13 @@ Sayfalama, kaynak listesi aslında bir veritabanı olan sunucu içindir: tek yan
### Deneyin {#try-it}
`Client(server)`, düşük seviyeli bir `Server`'a bellek içinde, bir `MCPServer`'a bağlandığı gibi bağlanır.
`mcp run` yalnızca bir `MCPServer` kabul eder; bu yüzden bunu kendiniz sunarsınız. `server.py` dosyasının son satırı `Server`'dan sıradan bir ASGI uygulaması oluşturur, uvicorn da onu çalıştırır:
`list_resources()`'ı argümansız çağırın. `book-1`'den `book-10`'a kadar on kaynak alırsınız ve `next_cursor`, `"10"` dizgesidir.
```console
uvicorn server:app --port 8000
```
Herhangi bir istemciyi (**[İstemci](../client/index.md)** ya da Inspector) `http://localhost:8000/mcp` adresine yönlendirin ve `list_resources()`'ı argümansız çağırın. `book-1`'den `book-10`'a kadar on kaynak alırsınız ve `next_cursor`, `"10"` dizgesidir.
Bunu `list_resources(cursor="10")` ile geri verin; ilk kaynak `book-11`, yeni `next_cursor` ise `"20"` olur.
@ -43,7 +47,7 @@ Onuncu sayfa, `next_cursor` değeri `None` olarak döner. Bitti.
`Client` üzerindeki her `list_*` metodu (`list_tools`, `list_resources`, `list_resource_templates`, `list_prompts`) bir `cursor=` anahtar kelimesi alır. Sayfalanmış bir listeyi sonuna kadar okumak tek bir `while True`'dur:
```python title="client.py" hl_lines="26-32"
```python title="client.py" hl_lines="9-15"
--8<-- "docs_src/pagination/tutorial002.py"
```
@ -51,7 +55,7 @@ Onuncu sayfa, `next_cursor` değeri `None` olarak döner. Bitti.
* `next_cursor`'a bakmadan **önce** listeyi genişletin: son sayfada da kaynaklar vardır.
* Çıkış koşulu `next_cursor is None`'dır. Bunun dışındaki her şey, dokunulmadan doğrudan `cursor=`'a geri gider.
`main()`'ini çalıştırın; `100 resources` yazdırır: on tane onluk sayfa, on sayfa olduğundan hiç haberi olmayan bir döngü tarafından birleştirilmiş.
uvicorn hâlâ `server.py` dosyasını sunarken ikinci bir terminalde `python client.py` komutunu çalıştırın. `100 resources` yazdırır: on tane onluk sayfa; bunları, on sayfa olduğundan hiç haberi olmayan bir döngü birleştirir.
Bu, **[İstemci](../client/index.md)** sayfasının her `list_*` fiili için gösterdiği döngünün aynısıdır ve sayfalamayan bir sunucuya karşı hiçbir maliyeti yoktur: ilk yanıtta `next_cursor`, `None` olur ve döngü bir kez çalışır.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [9e7b9a1710e5aeba, b74ca4c1d2ddddee, fa8714e61bf90c5a, 04db67a886b7271c, 857690fb8f876800]
sections: [9e7b9a1710e5aeba, 66a2e9acc9101d54, d3d25aa802f5145a, 04db67a886b7271c, 857690fb8f876800]
tool: 1
---
# Önbellekleme ipuçları {#caching-hints}
@ -30,7 +30,7 @@ Varsayılan olarak her sonuç `ttlMs: 0, cacheScope: "private"` der: anında bay
Alt düzey `Server`'da işleyiciler sonuçlarını elle oluşturur ve `ttl_ms` / `cache_scope` sonuç modellerindeki sıradan alanlardır. Bunları açıkça ayarlayan bir işleyici, alan alan, her zaman oluşturucu eşlemesine üstün gelir:
```python title="server.py" hl_lines="10 16"
```python title="server.py" hl_lines="11 17"
--8<-- "docs_src/caching/tutorial002.py"
```
@ -44,10 +44,24 @@ Sayfalandırılmış listelerle ilgili bir uyarı: protokol bir listenin **her s
2026-07-28 oturumunda `Client` ipuçlarına sizin yerinize uyar: varsayılan olarak açık, yerleşik bir yanıt önbelleği vardır. `ttlMs` taşıyarak gelen bir sonuç saklanır ve o TTL içinde yapılan özdeş bir çağrı hiç tur atılmadan önbellekten sunulur. *Hiç* ipucu taşımayan bir sonuç önbelleğe alınmaz: ipucu taşımayan sonuçlar `CacheConfig.default_ttl_ms` değerini alır, bu da varsayılan olarak `0`'dır (anında bayat); dolayısıyla hiçbir şey beyan etmeyen bir sunucu, her zaman gördüğü çağrı başına bir istek trafiğinin aynısını görür.
```python title="client.py" hl_lines="33 35 38"
Bunu izlemek için önceki bölümdeki `server.py` dosyasını uvicorn ile sunun (son satırı ASGI uygulamasını oluşturur). İşleyici, gerçekten her çalıştığında bir satır yazdırır:
```console
uvicorn server:app --port 8000
```
```python title="client.py" hl_lines="20 23 28"
--8<-- "docs_src/caching/tutorial003.py"
```
İkinci bir terminalden `python client.py` komutunu çalıştırın. İlk sonucun taşıdığı ipuçlarını yazdırır: işleyicinin `ttlMs` değeri, eşlemenin `cacheScope`'unun yanında:
```text
1000 public
```
Hikâyenin geri kalanını sunucunun terminali anlatır: uvicorn'un istek log'ları arasında `tools/list served` üç kez görünür.
Dört çağrı, üç getirme. İkinci çağrı taze bir girdi buldu ve sunucuya hiç ulaşmadı; (enjekte edilen) saati TTL'nin ötesine ilerletmek üçüncünün yeniden getirmesine yol açtı; dördüncü `cache_mode="refresh"` dedi. Bu anahtar sözcük argümanı önbellekleme yapan beş fiilde bulunur (`list_tools`, `list_prompts`, `list_resources`, `list_resource_templates`, `read_resource`):
* `"use"` (varsayılan) varsa taze bir girdiyi sunar, yoksa getirilen sonucu saklar.
@ -56,7 +70,7 @@ Dört çağrı, üç getirme. İkinci çağrı taze bir girdi buldu ve sunucuya
`"use"`'un üzerinde bir kural vardır: **`meta` taşıyan çağrılar her zaman sunucuya ulaşır.** `meta` ayarlanmış bir istek (bir ilerleme token'ı, izleme alanları) ağ üzerinde gerçek bir istek bekler; bu yüzden `cache_mode="use"` altında `"refresh"` gibi ele alınır: önbellek okuması atlanır ve getirilen sonuç yine de önbellekteki girdinin yerine geçer. `"bypass"` ve açık bir `"refresh"` her zamanki gibi davranır.
Önbelleklemeyi tamamen kapatmak için `Client(server, cache=None)` ile oluşturun: her çağrı yeniden bir tur olur ve `cache_mode` hâlâ kabul edilse de hiçbir şey yapmaz.
Önbelleklemeyi tamamen kapatmak için `Client`'ı oluştururken `cache=None` geçirin: her çağrı yeniden bir tur olur ve `cache_mode` hâlâ kabul edilse de hiçbir şey yapmaz.
Kapsama da otomatik olarak uyulur: `"private"` girdiler önbelleğin *bölümüne* (partition, aşağıda) göre anahtarlanır, `"public"` olanlar ise daha geniş paylaşıma katılmayı seçebilir. Ayrıca **bildirimler TTL'yi yener**, ama yalnızca tam olarak adlandırdıkları girdiler için: bir `list_changed` bildirimi eşleşen önbellekteki listeyi çıkarır, `resources/updated` ise tam olarak kendi URI'si altında saklanan önbellekteki okumayı çıkarır; ne kadar taze olurlarsa olsunlar. 2026-07-28 bağlantısında bu bildirimler `client.listen(...)` ile açtığınız bir `subscriptions/listen` akışı üzerinden gelir ve çıkarma, izleyiciniz olayı görmeden önce tamamlanır; bunun sayfası **[Abonelikler](subscriptions.md)**.
@ -82,7 +96,7 @@ client = Client("https://api.example.com/mcp", cache=CacheConfig(default_ttl_ms=
Bölüm ayrıca `Client`'ın ömrü boyunca sabittir. Bağlantının yetkilendirme bağlamı oturum ortasında değişirse (örneğin farklı bir principal olarak yeniden kimlik doğrulama), önbellek bunu takip etmez; yeni principal için yeni bir `Client` oluşturun.
Önbellek anahtarları ayrıca **sunucunun kimliğini** de taşır: bağlandığınız URL dizesi, varsa `user:pass@` kullanıcı bilgisi çıkarılmış ve bunun dışında bayt bayt aynı hâliyle. Büyük/küçük harf katlama yok, sorgu yeniden sıralama yok, sondaki eğik çizgi temizliği yok. Az normalleştirmek yalnızca paylaşımdan ödün verir, aşırı normalleştirmek ise iki kiracıyı birleştirebilir (`?tenant=a` ve `?tenant=b`); bu yüzden yüzeysel olarak farklı URL'ler girdi paylaşmaz, o kadar. URL olmadığında (süreç içi bir sunucu ya da bir `Transport` örneği) istemci bunun yerine örnek başına rastgele bir kimlik alır; sunucuya ad vermek için `CacheConfig.target_id`'yi ayarlayın (özel bir depoyla bu zorunludur ve oluşturma bunu söyler). Kimlik, anahtar malzemesine girmeden önce sha256 ile özetlenir; dolayısıyla sorgu dizesinde sır taşıyan bir URL depo anahtarlarında asla görünmez. Özet öncesi hâlini siz de loglamayın.
Önbellek anahtarları ayrıca **sunucunun kimliğini** de taşır: bağlandığınız URL dizesi, varsa `user:pass@` kullanıcı bilgisi çıkarılmış ve bunun dışında bayt bayt aynı hâliyle. Büyük/küçük harf katlama yok, sorgu yeniden sıralama yok, sondaki eğik çizgi temizliği yok. Az normalleştirmek yalnızca paylaşımdan ödün verir, aşırı normalleştirmek ise iki kiracıyı birleştirebilir (`?tenant=a` ve `?tenant=b`); bu yüzden yüzeysel olarak farklı URL'ler girdi paylaşmaz, o kadar. URL olmadığında (süreç içi bir sunucu ya da bir `Transport` örneği) istemci bunun yerine örnek başına rastgele bir kimlik alır; sunucuya ad vermek için `CacheConfig.target_id`'yi ayarlayın (özel bir depoyla bu zorunludur ve oluşturma bunu söyler). Kimlik, anahtar malzemesine girmeden önce sha256 ile özetlenir; dolayısıyla sorgu dizesinde sır taşıyan bir URL depo anahtarlarında asla görünmez. Özet öncesi hâlini siz de log'a yazmayın.
!!! warning "`share_public` sunucuya tüm filo genelinde güvenir"
Varsayılan olarak `"public"` girdiler bile kendi bölümlerinde kalır. `share_public=True`, sunucunun `cacheScope: "public"` olarak işaretlediği girdileri depoyu kullanan **her** bölüme sunar; sunucunun sınıflandırmasına hepsi adına güvenir. Kiracıya özgü veriye (hata ya da kötü niyet sonucu) `"public"` damgası vuran bir sunucu, o zaman bir kiracının yanıtını diğerlerine sızdırır. Bayrak bilerek yalnızca oluşturucu düzeyindedir: çağrı başına `cache_mode` önbelleklemeyi daraltabilir, ama çağrı başına hiçbir şey paylaşımı genişletemez.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [adf3c545b5be46b6, 916cd3ab1c03f461, e9be7a8d0eb0a456, 565890a636288ecf, 6af7e49db9129ec3, 06b0238c174186af, 90c6043be435fcb0]
sections: [adf3c545b5be46b6, 916cd3ab1c03f461, 32ef568335dd95a7, 565890a636288ecf, 6af7e49db9129ec3, 06b0238c174186af, 0abc5ea5cb7ff6b3]
tool: 1
---
# İstemci callback'leri {#client-callbacks}
@ -63,7 +63,7 @@ Sizden tek bir `tools/call`, sunucudan geriye tek bir `elicitation/create`, onu
`Client(...)` çağrısındaki `mode="legacy"` gerçekten iş yapıyor. Varsayılan olarak `Client(...)` modern
protokol yolunu müzakere eder ve o yolda sunucudan istemciye gelen istekler için bir geri kanal (back-channel)
yoktur: `ctx.elicit`, callback'iniz daha çalışmadan başarısız olur. Buna aktarım karar vermez; müzakere edilen
protokol karar verir, bellek içinde de bir URL üzerinden de aynı şekilde. İstemcinizin böyle bir isteği
protokol karar verir. İstemcinizin böyle bir isteği
yanıtlaması gerektiğinde `mode="legacy"`'yi sabitleyin; bu sayfanın arkasındaki her test bunu yapar.
Ayrıntıların tamamı **[Protokol sürümleri](../protocol-versions.md)** sayfasında.
@ -152,4 +152,4 @@ Bunları `Client(...)`'a tıpkı `elicitation_callback` gibi geçirin.
* `sampling_callback` ve `list_roots_callback` aynı şekilde çalışır ama kullanım dışı özelliklere hizmet eder; modern sunucular bunun yerine çok turlu istekler (multi-round-trip) kullanır.
* `logging_callback` ve `message_handler` bildirimleri alır. Hiçbir şey bildirmezler.
`Client(...)`'ın ilk argümanı bir aktarım nesnesidir. **[İstemci aktarımları](transports.md)** her türünü ele alır.
`Client(...)`'ın ilk argümanı aktarımı seçer. **[İstemci aktarımları](transports.md)** her türünü ele alır.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [ebef1e7a0df854f4, 8355cfaf1f76c9d5, 8e79141fc2985342, 46bdb07c7537e8a5, 80ce41579825a6fa, 5f0fa90494de8f65, 83d10514eaa62fa5, 9190555aa39a5d28, 84a4c9d8bf14dddb, 927d71cf40b58c30]
sections: [ebef1e7a0df854f4, 7e16449f66e7dfd6, eeb0682f7d2a1079, 5713f0196a34e6e7, 0e844597859e4248, 3a97d9195ddcc92e, 1da08c483e59c141, 84702cc6e0a1fd42, 8dee7a31c86ffc5c, 83a5bce168ef23d7]
tool: 1
---
# İstemci {#the-client}
@ -11,13 +11,23 @@ Tek bir yaşam döngüsü olan tek bir nesnedir: oluşturun, `async with` bloğu
## İlk istemciniz {#your-first-client}
```python title="client.py" hl_lines="14-18"
Bir istemcinin konuşacağı bir sunucuya ihtiyacı vardır. Bu sayfadaki her örneğin bağlandığı sunucu aşağıdaki Bookshop. Onu `server.py` olarak kaydedin ve HTTP üzerinden çalışır durumda bırakın:
```python title="server.py"
--8<-- "docs_src/client/tutorial001.py"
```
Üstteki sunucu yalnızca bağlanacak bir şeyiniz olsun diye orada. İstemci, vurgulanan beş satırdan ibaret.
```console
uv run mcp run server.py --transport streamable-http
```
* `Client(mcp)` çağrısına **sunucu nesnesinin kendisi** verilir. Bu, bellek içi aktarımdır: alt süreç yok, port yok, HTTP yok. Bu sayfadaki her örnek ve yazdığınız her test böyle bağlanır.
Bu, sunucuyu `http://localhost:8000/mcp` adresinde sunar. İstemci ayrı bir programdır. Onu `client.py` olarak kaydedin ve ikinci bir terminalde `python client.py` komutunu çalıştırın:
```python title="client.py" hl_lines="7-11"
--8<-- "docs_src/client/tutorial001_client.py"
```
* `Client("http://localhost:8000/mcp")` çağrısına bir **URL** verilir; bu yüzden az önce başlattığınız sunucuya Streamable HTTP üzerinden bağlanır.
* `async with` **yaşam döngüsüdür**. Bloğa girdiğinizde bağlantı kurulur ve anlaşma yapılır; çıktığınızda bağlantı kesilir. `connect()` / `close()` çifti yoktur ve blok bittikten sonra bir `Client` yeniden kullanılamaz.
* Bloğun içinde bağlantı bilgileri düz özellikler olarak zaten hazırdır.
@ -25,10 +35,10 @@ Tek bir yaşam döngüsü olan tek bir nesnedir: oluşturun, `async with` bloğu
`Client` tek bir konumsal argüman alır ve aktarımı onun türünden çözümler:
* Bir `MCPServer` (veya düşük seviyeli `Server`) örneği: **süreç içinde** bağlanır.
* Bir URL dizesi (`Client("http://localhost:8000/mcp")`): Streamable HTTP, yani üretim yolu.
* Bir `StdioServerParameters`: **alt süreç** olarak başlatılacak komut; onunla stdin ve stdout'u üzerinden konuşulur.
* Bir URL dizesi (`Client("http://localhost:8000/mcp")`): Streamable HTTP, dağıtımda kullandığınız aktarım.
* Bir `StdioServerParameters`: yerel bir **alt süreç** olarak başlatılacak komut; onunla stdin ve stdout'u üzerinden konuşulur.
* Bir **aktarım**: `async with ... as (read, write)` ile kullanabileceğiniz herhangi bir şey; örneğin kendi HTTP istemcinizi saran `streamable_http_client(url, http_client=...)`.
* Bir `MCPServer` (veya düşük seviyeli `Server`) örneği: **süreç içinde** bağlanır; alt süreç yok, port yok. Bu seçenek testler içindir ve **[Test etme](../get-started/testing.md)** sayfası onun üzerine kurulur.
Bu sayfadaki geri kalan her şey dördünde de aynıdır. Başlıklar, alt süreçler, zaman aşımları ve `Transport` protokolünün kendi sayfası var: **[İstemci aktarımları](transports.md)**.
@ -49,11 +59,11 @@ Hiç protokol sürümü seçmediniz. Varsayılan olarak `Client` sunucuyu yoklar
## Araçları listeleme {#listing-tools}
```python title="client.py" hl_lines="15-20"
```python title="client.py" hl_lines="8-13"
--8<-- "docs_src/client/tutorial002.py"
```
`list_tools()` bir `ListToolsResult` döndürür; araçlar `.tools` içindedir. Her biri, bir host'un modele vereceği eksiksiz tanımdır:
`list_tools()` bir `ListToolsResult` döndürür; araçlar `.tools` içindedir. Her biri, bir host'un modele vereceği eksiksiz tanımdır. İşte ilki:
```python
tool.name # 'search_books'
@ -77,6 +87,8 @@ tool.description # 'Search the catalog by title or author.'
Bu şema, bir arayüzün argüman formu oluşturması için gereken her şeydir; bir modelin geçerli argümanlar üretmesi için gereken her şey de odur.
İkinci araç olan `lookup_book`, `title=` olmadan kaydedildi; bu yüzden `tool.title` değeri `None`.
!!! tip
`title` isteğe bağlıdır; bu yüzden araçları bir insana gösteren arayüzün seçim yapması gerekir: varsa `title`,
yoksa `name`. `from mcp.shared.metadata_utils import get_display_name` tam olarak bunu yapar;
@ -86,7 +98,7 @@ Bu şema, bir arayüzün argüman formu oluşturması için gereken her şeydir;
`call_tool(name, arguments)` aracı çalıştırır ve size bir `CallToolResult` geri verir.
```python title="client.py" hl_lines="27-34"
```python title="client.py" hl_lines="9-16"
--8<-- "docs_src/client/tutorial003.py"
```
@ -142,7 +154,7 @@ Tek dönüş değeri, okunacak üç şey. Her birinin tüketicisi farklı.
Kaynak fiilleri çift gelir: listelemenin iki yolu, okumanın tek yolu.
```python title="client.py" hl_lines="22-31"
```python title="client.py" hl_lines="9-18"
--8<-- "docs_src/client/tutorial004.py"
```
@ -156,7 +168,7 @@ Bir istemciye bir kaynağın ne zaman değiştiği de bildirilebilir. 2025 nesli
## Prompt'lar {#prompts}
```python title="client.py" hl_lines="15-20"
```python title="client.py" hl_lines="8-13"
--8<-- "docs_src/client/tutorial005.py"
```
@ -181,7 +193,7 @@ Host bu mesajları doğrudan modele verir. Özelliğin tamamı bu.
Tamamlama işleyicisi olan bir sunucu, kullanıcı yazdıkça prompt ve kaynak şablonu argümanlarını otomatik tamamlayabilir.
```python title="client.py" hl_lines="27-31"
```python title="client.py" hl_lines="9-13"
--8<-- "docs_src/client/tutorial006.py"
```
@ -194,21 +206,21 @@ Yanıt `result.completion.values` içindedir. `"p"` yazın, sunucu `['poetry']`
Her `list_*` yöntemi bir `cursor=` anahtar sözcüğü alır ve her sonuç bir `next_cursor` taşır. `next_cursor` `None` olduğunda her şeyi almışsınız demektir.
```python title="client.py" hl_lines="22-30"
```python title="client.py" hl_lines="7-15"
--8<-- "docs_src/client/tutorial007.py"
```
Bu döngü her sunucuya karşı doğrudur. `MCPServer` her şeyi tek sayfada döndürür; bu yüzden `next_cursor` `None` olur ve döngü bir kez çalışır. Çoğu kodun bunu hiç yazmamasının nedeni budur. Gerçekten sayfalayan sunucular ve imleçlerin uyduğu kurallar **[Sayfalama](../advanced/pagination.md)** sayfasında.
`list_all_tools` her sunucuya karşı doğrudur. `MCPServer` her şeyi tek sayfada döndürür; bu yüzden `next_cursor` `None` olur ve döngü bir kez çalışır. Çoğu kodun bunu hiç yazmamasının nedeni budur. Gerçekten sayfalayan sunucular ve imleçlerin uyduğu kurallar **[Sayfalama](../advanced/pagination.md)** sayfasında.
## Testlerde {#in-tests}
Süreç ve port olmadan `Client(mcp)`, sunucunuz için zaten bir test düzeneğidir.
Bu sayfadaki her `client.py`, `server.py` dosyasına HTTP üzerinden ulaştı. Bir testte ağı atlar ve `Client`'a sunucu nesnesinin kendisini verirsiniz: `from server import mcp`, ardından `Client(mcp)`. Süreç yok, port yok; yukarıdaki her yöntem aynı şekilde çalışır.
Bunun için yapılmış tek bir kurucu bayrağı var: `Client(mcp, raise_exceptions=True)`. Yalnızca bellek içi bağlantılarda etkisi olur; onu açıklayan ve bütün kalıbı onun etrafında kuran sayfa ise **[Test etme](../get-started/testing.md)**.
Bunun için yapılmış tek bir kurucu bayrağı var: `Client(mcp, raise_exceptions=True)`. Yalnızca süreç içi bağlantılarda etkisi olur; onu açıklayan ve bütün kalıbı onun etrafında kuran sayfa ise **[Test etme](../get-started/testing.md)**.
## Özet {#recap}
* `Client(x)` bir sunucu nesnesine bellek içinden, bir URL dizesine Streamable HTTP üzerinden, geri kalan her şeye de bir aktarım aracılığıyla bağlanır.
* `Client(x)` bir URL dizesine Streamable HTTP üzerinden bağlanır, bir `StdioServerParameters` için alt süreç başlatır, bir aktarıma doğrudan girer ve testlerde sunucu nesnesinin kendisini alır.
* `async with` yaşam döngüsünün tamamıdır. İçinde `server_capabilities` ve `protocol_version` zaten doludur; sunucu sağladığında `server_info` ve `instructions` da öyle.
* `list_tools()` size her aracın `name`, `title`, `description` ve `input_schema` değerlerini verir.
* `call_tool()` model için `content`, kodunuz için `structured_content` ve `is_error` döndürür. İstisna fırlatan bir araç istisna değil, sonuçtur.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [c6899d3892bd9fa0, 79372cff3cc48a88, 63878d29e87c3e73, 13175843d3588af4, e7e2b9fd516f77de, 758f06399b513c1f, a05d7278487d610b]
sections: [c6899d3892bd9fa0, 79372cff3cc48a88, c2dae1ebe2ebd543, 13175843d3588af4, df06056fb16b3846, 758f06399b513c1f, a05d7278487d610b]
tool: 1
---
# OAuth istemcileri {#oauth-clients}
@ -82,20 +82,22 @@ Gerçek bir istemci `input()` çağırmak yerine yönlendirme URI'si üzerinde k
`Client` ilk kez bir istek gönderdiğinde sunucu `401` yanıtını verir. Sağlayıcı devralır:
1. **Keşif.** `WWW-Authenticate` başlığını okur, sunucunun Protected Resource Metadata belgesini `/.well-known/oauth-protected-resource` adresinden alır, bu kaynağı hangi yetkilendirme sunucusunun koruduğunu öğrenir ve *o* sunucunun metadatasını alır.
1. **Keşif.** `WWW-Authenticate` başlığını okur, sunucunun Protected Resource Metadata belgesini `/.well-known/oauth-protected-resource` adresinden alır, bu kaynağı hangi yetkilendirme sunucusunun koruduğunu öğrenir ve *o* sunucunun metadatasını alır. (Kaynak metadatası yayımlamayan daha eski bir sunucudan bunun yerine kendi kökeninde yetkilendirme sunucusu metadatası istenir.) Her iki durumda da metadata, `issuer` alanında hangi sunucu için alındıysa o sunucuyu belirtmelidir; başka her şey reddedilir.
2. **Kayıt.** Depoda bir şey yok mu? `OAuthClientMetadata`'nızla sizi dinamik olarak kaydeder ve sonucu saklar.
3. **Yetkilendirme.** PKCE çiftini ve bir `state` üretir, yetkilendirme URL'sini oluşturur, `redirect_handler`'ınızı await eder, ardından kod için `callback_handler`'ınızı await eder.
4. **Değişim.** Kodu bir `OAuthToken` ile takas eder, onu saklar ve özgün isteğinizi `Authorization: Bearer ...` ile yeniden gönderir.
Bundan sonra sessizdir. Token'lar depodan gelir, süresi dolmuş bir erişim token'ı yenileme token'ıyla yenilenir ve ancak bunların hiçbiri işe yaramadığında akışı yeniden çalıştırır.
Bu isteklerin hepsi için tek bir aktarım kuralı geçerlidir: içinde çalıştıkları MCP isteği gibi, bir yönlendirmeyi yalnızca aynı kökende kalıyor ve metodu koruyorsa izlerler (örneğin sondaki eğik çizgi için bir 307/308); başka her yönlendirmeyi o URL yanıt vermiyormuş gibi ele alırlar.
Bunların hiçbirini siz yazmadınız. Geriye iki anahtar sözcük argümanı kalır (`client_metadata_url` ve `validate_resource_url`) ve bu dosyanın ikisine de ihtiyacı yoktur. Bilmeye değer olanı `client_metadata_url`'dir; aşağıda kendi bölümü var.
### Deneyin {#try-it}
Bu belgelerdeki örneklerin çoğunu bellek içi bir `Client(server)` ile sınayabilirsiniz. Bunu değil: akışın bütün amacı bir HTTP `401`'idir ve bellek içi bir istemci ile sunucusu arasında HTTP yoktur.
Testlerinizin kullandığı bellek içi `Client(server)` burada işe yaramaz: akışın bütün amacı bir HTTP `401`'idir ve bellek içi bir istemci ile sunucusu arasında HTTP yoktur.
Depo canlı sürümü içerir. `examples/servers/simple-auth/` bağımsız bir yetkilendirme sunucusu ile korumalı bir MCP sunucusu çalıştırır; `examples/clients/simple-auth-client/` ise bu sayfadaki istemcinin küçük bir CLI'a dönüşmüş hâlidir. README'sinde iki komut var: sunucuları başlatın, istemciyi onlara karşı çalıştırın ve dört adımın geçişini izleyin.
Depo canlı sürümü içerir. `examples/servers/simple-auth/` bağımsız bir yetkilendirme sunucusu ile korumalı bir MCP sunucusu çalıştırır; `examples/clients/simple-auth-client/` ise bu sayfadaki istemcinin küçük bir CLI aracına dönüşmüş hâlidir. README'sinde iki komut var: sunucuları başlatın, istemciyi onlara karşı çalıştırın ve dört adımın geçişini izleyin.
## Client ID Metadata Documents {#client-id-metadata-documents}
@ -111,13 +113,14 @@ Bir gece görevi, bir CI adımı, başka bir servis. Tarayıcı yok, "allow" dü
`ClientCredentialsOAuthProvider` aynı `httpx2.Auth`'tur, insan hariç:
```python title="client.py" hl_lines="4 27-33"
```python title="client.py" hl_lines="4 27-34"
--8<-- "docs_src/oauth_clients/tutorial002.py"
```
Neler değişti:
* `OAuthClientMetadata` yok, işleyiciler yok. `client_id` ve `client_secret` geçirirsiniz; sağlayıcı bunların etrafında asgari bir `client_credentials` kaydı oluşturur ve dinamik kaydı tamamen atlar.
* `issuer`, bu kimlik bilgilerini veren yetkilendirme sunucusunu belirtir; onun `/.well-known/oauth-authorization-server` belgesinin döndürdüğü `issuer` değerini kullanın. Keşif yine yukarıdaki gibi çalışır, ancak token istekleri yalnızca *o* yayıncıya ait metadatadan oluşturulur; MCP sunucusu başka bir yeri gösteriyorsa akış bunun yerine bir `OAuthFlowError` ile durur. Bu parametreyi atlamak kullanım dışı bırakıldı ve 3.0 sürümünde zorunlu hâle gelir (bkz. **[Kullanım dışı özellikler](../deprecated.md#deprecated-sdk-helpers)**); o zamana kadar sağlayıcı uyarı verir ve keşif hangi yetkilendirme sunucusunu bulursa onu kullanır.
* `scope`, boşlukla ayrılmış bir dizedir; OAuth'un iletilen verideki biçimi budur.
* Bundan sonraki her şey aynıdır: aynı `TokenStorage`, aynı `httpx2.AsyncClient(auth=...)`, aynı `streamable_http_client`.
@ -130,7 +133,7 @@ Varsayılan olarak sır, token isteğinde HTTP Basic kimlik doğrulaması olarak
`mcp.client.auth.extensions.client_credentials` içinde bir sağlayıcı daha var:
paylaşılan bir sır yerine JWT ile kimlik doğrulayan istemciler için **`PrivateKeyJWTOAuthProvider`**
(`private_key_jwt`; anahtar çifti ve iş yükü kimliği türü). Aynı kalıbı izler:
bir tane oluşturun, `auth=`'a koyun. Aynı modül, onun assertion'ını oluşturan iki yardımcıyı da
bir tane oluşturun (aynı isteğe bağlı `issuer` parametresini alır), `auth=`'a koyun. Aynı modül, onun assertion'ını oluşturan iki yardımcıyı da
sunar: `SignedJWTParameters` ve `static_assertion_provider`.
İnsansız bir durum daha var: istemci, hangi MCP sunucularına erişebileceğine kullanıcının değil kimlik sağlayıcısının karar verdiği bir kuruluşa aittir. Bu, kendi güven modeli ve kendi sayfası olan farklı bir yetkilendirme türüdür: **[Kimlik beyanı](identity-assertion.md)**.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [09c857a25a9dc37a, 43bc6a76a243a50e, 0a716022a88768df, 4b7f78042bfcfff7, c112662e61b03315, 58974ba1f489a8b4, d18adbdbb835ea73]
sections: [09c857a25a9dc37a, 43bc6a76a243a50e, 0a716022a88768df, 4b7f78042bfcfff7, c112662e61b03315, 58974ba1f489a8b4, ed4d17e894864056]
tool: 1
---
# Oturum grupları {#session-groups}
@ -78,7 +78,7 @@ Elinizde zaten bağlı bir `ClientSession` varsa (`Client.session` bunlardan bir
## Özet {#recap}
* `ClientSessionGroup` birçok sunucu bağlantısını tutar ve bunların araçlarını, kaynaklarını ve prompt'larını birer `dict`'te birleştirir.
* Her sunucu için `connect_to_server(params)`. Aktarım parametreleri alır; bir `Client`'ın aldığı sunucu nesnesini ya da URL'yi asla almaz.
* Her sunucu için `connect_to_server(params)`. Aktarım parametreleri alır; bir `Client`'ın aldığı URL'yi ya da `Transport`'u asla almaz.
* `group.call_tool(name, arguments)` çağrıyı sizin yerinize sahibi olan sunucuya yönlendirir.
* Adlar grubun tamamında benzersiz olmalıdır; `search` aracı olan iki sunucu kendi hâllerine bırakılırsa bir arada bulunamaz.
* `component_name_hook=` kaydedilen her adı yeniden yazar. Sözlük anahtarı değişir, ağ üzerindeki ad değişmez.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [9cac816674181eb0, 0700f337babcd4dd, 2bde0dd58cdf00f5, 40b4916d82eaf1d4, 3d0832f39b0d7059, dfa4446556badef0, 5bd93be2ab2ecb9c]
sections: [9cac816674181eb0, 7c157764133fea1f, 40b4916d82eaf1d4, 10d151f2cc75317f, 3d0832f39b0d7059, 92742ba36533633d, 0aeca6145e7bd302]
tool: 1
---
# İstemci aktarımları {#client-transports}
@ -11,30 +11,15 @@ Aktarımı hiçbir zaman ayrıca yapılandırmazsınız. `Client` tek bir konums
Her birinin *sunucu* tarafı (`mcp.run()`'ın ne yaptığı ve neyi dağıttığınız) **[Sunucunuzu çalıştırma](../run/index.md)** sayfasında.
## Bellek içinde {#in-memory}
Sunucu nesnesinin kendisini geçirin:
```python title="client.py" hl_lines="14"
--8<-- "docs_src/client_transports/tutorial001.py"
```
Alt süreç yok, port yok, ağ üzerinde tek bir bayt yok. İstemci ve sunucu aynı süreçteki iki nesnedir; yine de çağrı gerçek protokol katmanından geçer: `search_books`, HTTP üzerinden nasıl olacaksa tam olarak öyle listelenir, doğrulanır ve çağrılır.
Bu, onu aynı anda iki şey yapar:
* **Bir test düzeneği.** Bu belgelerdeki her örnek bu şekilde çalıştırılır ve **[Test etme](../get-started/testing.md)** sayfası tüm deseni bunun üzerine kurar.
* **Bir gömme API'si.** Sunucuyu oluşturan bir uygulamanın, araçlarını çağırmak için ağ üzerinden bir sıçrama yapmasına gerek yoktur.
## Streamable HTTP {#streamable-http}
Bir URL dizesi geçirin; arkasına dağıtım yaptığınız aktarım olan **Streamable HTTP**'yi elde edersiniz:
Bir URL dizesi geçirin; arkasına dağıtım yaptığınız ve ilk başvurmanız gereken aktarım olan **Streamable HTTP**'yi elde edersiniz:
```python title="client.py" hl_lines="5"
--8<-- "docs_src/client_transports/tutorial002.py"
```
Üretim istemcisinin tamamı bu. `Client`, URL'yi sizin için `streamable_http_client(...)` ile sarar; bunu da MCP'nin gerektirdiği şekilde yapılandırılmış bir `httpx2.AsyncClient` üzerine kurar: `follow_redirects=True`, connect/write/pool için 30 saniyelik zaman aşımı ve sunucu bir yanıt akışını açık tutabileceği için 300 saniyelik okuma zaman aşımı.
Üretim istemcisinin tamamı bu. `Client`, URL'yi sizin için `streamable_http_client(...)` ile sarar; bunu da MCP'nin gerektirdiği şekilde yapılandırılmış bir `httpx2.AsyncClient` üzerine kurar: connect/write/pool için 30 saniyelik zaman aşımı ve sunucu bir yanıt akışını açık tutabileceği için 300 saniyelik okuma zaman aşımı.
!!! check
Oluşturduğunuz bir `Client` bağlı **değildir**. Oluşturma yalnızca aktarımı seçer;
@ -50,7 +35,7 @@ Bir URL dizesi geçirin; arkasına dağıtım yaptığınız aktarım olan **Str
Bir `Authorization` başlığına, bir çereze, bir vekil sunucuya, mTLS'e ya da farklı bir zaman aşımına ihtiyaç duyduğunuz anda `httpx2.AsyncClient`'ı kendiniz oluşturun ve `streamable_http_client`'a verin:
```python title="client.py" hl_lines="8-14"
```python title="client.py" hl_lines="8-13"
--8<-- "docs_src/client_transports/tutorial003.py"
```
@ -79,9 +64,30 @@ ortam değişkenlerini ayarlayın ya da `httpx2.AsyncClient`'ınıza açıkça b
!!! info
`httpx2`, tanıdık `httpx` API'sini korur; yani `httpx`'i biliyorsanız kimlik doğrulama,
vekil sunucular, olay kancaları, yeniden denemeler ve bağlantı sınırlarının burada nasıl yapılacağını zaten biliyorsunuz. SDK üzerine hiçbir şey eklemez,
hiçbir şeyi de eksiltmez. OAuth'un takıldığı yer de burası:
[yönlendirme işleme](#redirects) dışında hiçbir şeyi de eksiltmez. OAuth'un takıldığı yer de burası:
`httpx2.AsyncClient(auth=OAuthClientProvider(...))`. Bu akışın tamamı **[OAuth istemcileri](oauth-clients.md)** sayfasında.
### Yönlendirmeler {#redirects}
Aktarım, verdiğiniz URL'ye ve yalnızca o kökene (origin) bağlanır.
* Aynı şema, ana bilgisayar ve portta kalan bir `307`/`308` yönlendirmesi izlenir; aynı ana bilgisayar üzerindeki `http://` → `https://` yönlendirmesi de öyle. Bu, alışıldık `/mcp` → `/mcp/` sondaki eğik çizgi yönlendirmesini kapsar.
* Başka herhangi bir yere yapılan yönlendirme **izlenmez**. Çağrı şu hatayla başarısız olur:
```text
MCPError: Redirect to https://other.example.com/mcp not followed; use that URL as the endpoint if it is the intended server
```
O URL kastettiğiniz sunucuysa yapılandırmanıza yazın. Değilse sunucu ya da önündeki bir vekil sunucu yanlış yapılandırılmıştır.
Bu, geçirdiğiniz her `httpx2.AsyncClient` için geçerlidir: MCP isteklerinde `follow_redirects` ayarına hiçbir yönde bakılmaz. SDK'nın OAuth sağlayıcıları da aynı kuralı kendi isteklerine uygular.
!!! tip
`Redirect to http://… not followed: it would downgrade this HTTPS endpoint to plain HTTP` iletisi,
sunucunun haberdar olmadığı, TLS sonlandıran bir vekil sunucunun arkasında durduğu ve `http://` yönlendirmeleri
verdiği anlamına gelir. Bu, sunucu tarafında düzeltilir (**[Dağıtım ve ölçekleme](../run/deploy.md#behind-a-tls-terminating-proxy)**)
ya da iletinin önerdiği tam `https://…/` URL'si kullanılarak.
## stdio {#stdio}
Bir **stdio** sunucusu bir alt süreçtir. İstemci onu başlatır, stdin'ine JSON-RPC yazar ve stdout'undan JSON-RPC okur. Bir masaüstü host'un makinenizde bir sunucuyu çalıştırma biçimi budur: bir host, bu kod artı bir kullanıcı arayüzü*dür* ve **[Gerçek bir host'a bağlanma](../get-started/real-host.md)**, aynı ilişkinin host'un tarafından, bir yapılandırma dosyası olarak görülen halidir.
@ -104,6 +110,18 @@ Alt sürecin stderr'i sizinkine gider. Başka bir yere göndermek için aktarım
Bir API anahtarına ihtiyaç duyan bir sunucu onu orada bulamaz. `env=` ile açıkça geçirin; bu
değişkenler izin listesinin üstüne birleştirilir. Yukarıda `BOOKSHOP_API_KEY`'in yaptığı budur.
## Bellek içinde {#in-memory}
Bir testte dağıtılacak da başlatılacak da bir şey yoktur. Sunucu nesnesinin kendisini geçirin:
```python hl_lines="14"
--8<-- "docs_src/client_transports/tutorial001.py"
```
Alt süreç yok, port yok, ağ üzerinde tek bir bayt yok. İstemci ve sunucu aynı süreçteki iki nesnedir; yine de çağrı gerçek protokol katmanından geçer: `search_books`, HTTP üzerinden nasıl olacaksa tam olarak öyle listelenir, doğrulanır ve çağrılır. **[Test etme](../get-started/testing.md)** sayfası tüm deseni bunun üzerine kurar.
Aynı biçim bir gömme API'si olarak da iş görür: sunucuyu kendisi oluşturan bir uygulama, araçlarını ağ üzerinden bir sıçrama olmadan çağırabilir.
## SSE {#sse}
`mcp.client.sse` içindeki `sse_client(url)`, Streamable HTTP'nin yerini aldığı HTTP aktarımıdır. Hâlâ onu konuşan bir sunucuyla konuşmak için aynı şekilde sarın, `Client(sse_client("http://localhost:8000/sse"))`, ve üzerine yeni hiçbir şey kurmayın.
@ -112,15 +130,16 @@ Alt sürecin stderr'i sizinkine gider. Başka bir yere göndermek için aktarım
`Client` için yukarıdakilerin hepsi aynı şeydir.
Bir **aktarım**, `(read, write)` mesaj akışı çifti veren herhangi bir asenkron bağlam yöneticisidir: resmi olarak `mcp.client` içindeki `Transport` protokolü. `Client`, argümanını türüne göre çözümler: bir sunucu nesnesi süreç içinde bağlanır, bir `str` `streamable_http_client(url)` olur, bir `StdioServerParameters` `stdio_client(params)` olur ve geri kalan her şeye doğrudan bir aktarım olarak girilir. `stdio_client(...)`, `streamable_http_client(...)` ve `sse_client(...)`'in hepsinin aynı yuvaya oturmasının ve kendinizinkini yazabilmenizin nedeni bu son kuraldır.
Bir **aktarım**, `(read, write)` mesaj akışı çifti veren herhangi bir asenkron bağlam yöneticisidir: resmi olarak `mcp.client` içindeki `Transport` protokolü. `Client`, argümanını türüne göre çözümler: bir `str` `streamable_http_client(url)` olur, bir `StdioServerParameters` `stdio_client(params)` olur, bir sunucu nesnesi süreç içinde bağlanır ve geri kalan her şeye doğrudan bir aktarım olarak girilir. `stdio_client(...)`, `streamable_http_client(...)` ve `sse_client(...)`'in hepsinin aynı yuvaya oturmasının ve kendinizinkini yazabilmenizin nedeni bu son kuraldır.
## Özet {#recap}
* `Client(mcp)` (sunucu nesnesi) bellek içinde bağlanır. Testler ve gömme için kullanın.
* `Client("http://.../mcp")` (bir URL), üretim aktarımı olan Streamable HTTP üzerinden bağlanır.
* Başlıklar, kimlik doğrulama, vekil sunucular ve zaman aşımları, `streamable_http_client(url, http_client=...)`'a geçirdiğiniz bir `httpx2.AsyncClient` üzerinde yer alır. `headers=` anahtar sözcüğü yoktur.
* Yönlendirmeler yalnızca URL'nin kendi kökeni içinde (sondaki eğik çizgi için `307`/`308`) ve aynı ana bilgisayarda `http`→`https` için izlenir. Geri kalan her şey `Redirect to … not followed` hatasıyla başarısız olur; nihai URL'yi yapılandırın.
* stdio, `Client(StdioServerParameters(...))` demektir. Onu `stdio_client(...)` ile yalnızca alt sürecin stderr'ini başka yere yönlendirmek için kendiniz sarın.
* Alt süreç sizinkini değil, izin listesine göre oluşturulmuş bir ortam alır; `env=` buna ekleme yapar.
* `Client(mcp)` (sunucu nesnesi) bellek içinde bağlanır. Testlerde ya da bir sunucuyu onu oluşturan uygulamaya gömmek için kullanın.
* Bir aktarım, `async with x as (read, write)` yapabildiğiniz herhangi bir şeydir. `Client`, sunucu nesnesi, URL ya da `StdioServerParameters` olmayan her şeyi doğrudan bu protokole verir.
* Bir `Client` oluşturmak aktarımı seçer. Onu `async with` açar.

View file

@ -1,11 +1,11 @@
---
translation:
sections: [490237e61c3a7a44, 01262a123ad9501d, 429db5b574a2ac08, e2d0d273fbd2d74b, 64ab0331e868f3d4, 6c8878ce2d1f6d56, 4068f23e371bf0b3, eaef75b8725bc931]
sections: [4c1dea378b2b1bf7, 01262a123ad9501d, 429db5b574a2ac08, e2d0d273fbd2d74b, 64ab0331e868f3d4, 6c8878ce2d1f6d56, c3d1099701156881, e185a1b8e53669f6]
tool: 1
---
# Kullanım dışı özellikler {#deprecated-features}
2026-07-28 spesifikasyonu beş şeyi emekliye ayırıyor. SDK hâlâ hepsini uygular ve artık her biri bir **kullanım dışı bırakma uyarısı** taşır. Bir SDK yardımcısı ise kendi gerekçesiyle kullanım dışı bırakıldı ve [sayfanın sonunda](#deprecated-sdk-helpers) listeleniyor.
2026-07-28 spesifikasyonu beş şeyi emekliye ayırıyor. SDK hâlâ hepsini uygular ve artık her biri bir **kullanım dışı bırakma uyarısı** taşır. SDK düzeyindeki birkaç kullanım dışı bırakma ise kendi gerekçesine dayanır ve [sayfanın sonunda](#deprecated-sdk-helpers) listeleniyor.
Aşağıdaki tablo kullanım dışı bırakılan her özelliği, neden gittiğini ve yerine neyin üzerine inşa etmeniz gerektiğini gösterir.
@ -136,11 +136,13 @@ API'nin tamamı bu. Yöntem başına bir anahtar yok, zaten istemezsiniz de: tek
## Kullanım dışı SDK yardımcıları {#deprecated-sdk-helpers}
Bunlar spesifikasyon değişikliği değil, yalnızca daha iyi bir alternatifi olan SDK iç ayrıntılarıdır. Aynı `MCPDeprecationWarning` ile uyarırlar ve 3.0'da kaldırılacaklar.
Bunlar spesifikasyon değişikliği değil, yalnızca daha iyi bir alternatifi olan SDK kullanım biçimleridir. Aynı `MCPDeprecationWarning` ile uyarırlar ve 3.0 eski biçimi kaldırır.
| Kullanım dışı | Bunun yerine ne yaparsınız |
|---|---|
| `FuncMetadata.call_fn_with_arg_validation()` | `FuncMetadata.validate_arguments()`, ardından `FuncMetadata.call_fn()`. Bunu yalnızca `FuncMetadata`'yı doğrudan kullanan kod (örneğin özel bir `Tool` alt sınıfı) çağırırdı. |
| `validate_token_resource=` olmadan `AuthSettings(resource_server_url=...)` | Onu ayarlayın: `True`, doğrulayıcınızın `resource_server_url` için düzenlendiğini bildirmediği bearer token'ları sunucunun reddetmesini sağlar; `False`, token'ın audience değerini doğrulayıcınızın kendisinin denetlediğini söyler (bkz. **[Yetkilendirme](run/authorization.md#a-token-verifier)**). Ayarlanmadığında `False` gibi davranır; 3.0, `resource_server_url` ayarlı olduğunda `True`'yu varsayılan yapar. |
| `issuer=` olmadan `ClientCredentialsOAuthProvider(...)` veya `PrivateKeyJWTOAuthProvider(...)` | Kimlik bilgilerini düzenleyen yetkilendirme sunucusunu belirten `issuer=` geçirin (bkz. **[OAuth istemcileri yazma](client/oauth-clients.md#machine-to-machine)**). Onsuz, kimlik bilgilerini hangi yetkilendirme sunucusunun alacağına MCP sunucusu karar verir; 3.0 bu anahtar kelimeyi zorunlu yapar. |
## Özet {#recap}
@ -149,7 +151,7 @@ Bunlar spesifikasyon değişikliği değil, yalnızca daha iyi bir alternatifi o
* Kullanım dışı bırakma tavsiye niteliğindedir: iletilen veride değişiklik yok, her şey 2026 öncesi oturumlarda çalışmaya devam eder ve görünür bir `MCPDeprecationWarning` alırsınız (bir `UserWarning`, dolayısıyla varsayılan olarak açık).
* Örnekleme ve kök dizinler ayrıca, 2026-07-28 oturumunda bulunmayan bir geri kanala ihtiyaç duyar. Modern bir bağlantıda önce uyarır, sonra istisna fırlatırlar.
* `warnings.filterwarnings("ignore", category=MCPDeprecationWarning)` tüm kategoriyi susturur; pytest'te `"error::mcp.MCPDeprecationWarning"` bunu bir test hatasına dönüştürür.
* Bir SDK yardımcısı, `FuncMetadata.call_fn_with_arg_validation()`, 3.0'da kaldırılmak üzere ayrıca kullanım dışı bırakıldı.
* [SDK düzeyindeki kullanım dışı bırakmalar](#deprecated-sdk-helpers) da aynı kurala uyar: şimdi uyarırlar, 3.0 ise eski biçimi kaldırır.
* Yeni kod bunların hiçbiri üzerine kurulmamalıdır.
Bu belgelerdeki diğer tüm sayfalar güncel API'yi anlatır.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [0d6c05bcbf836bf3, 59a7b14eeefc68c1, 7114d8d6daba203f, e8bbb56a98ba7bc9, 5138010f6159901c, f78da7c7c363d4c6, 220a939cab348686]
sections: [0d6c05bcbf836bf3, 9a78b5f6b44b18ab, 7114d8d6daba203f, e8bbb56a98ba7bc9, bfd2fd1153e71dac, 1615a994ef071fdd, 65c599fae991f245]
tool: 1
---
# İlk adımlar {#first-steps}
@ -17,7 +17,7 @@ Bundan sonraki her sayfada göreceğiniz üç sözcük:
* **İ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.
Sunucuyu siz yazarsınız. Host'lar başkasının ürünüdür. SDK size bir de `Client` verir: bir host'un bir sunucuya URL ile ulaşmak ya da onu alt süreç olarak başlatmak için kullanacağı sınıfın ta kendisi. Bu sayfanın ilerisinde karşınıza çıkar; sunucularınızı da onunla test edeceksiniz.
## Üç temel öğe {#the-three-primitives}
@ -83,22 +83,20 @@ 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):
Kendiniz bakın. Bir terminalde `server.py` dosyasını HTTP üzerinden çalışır halde bırakın:
```python
import asyncio
```console
uv run mcp run server.py --transport streamable-http
```
from mcp import Client
ve başka bir terminalden bir istemciyi ona yöneltin:
from server import mcp
```python title="client.py" hl_lines="7-8"
--8<-- "docs_src/first_steps/tutorial001_client.py"
```
async def main() -> None:
async with Client(mcp) as client:
print(client.server_capabilities.model_dump(exclude_none=True))
asyncio.run(main())
```console
python client.py
```
```text
@ -115,11 +113,12 @@ Bu sözlük, sunucunuzun beyan ettiği **yeteneklerdir**. Bağlanan her istemcin
`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.
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 kurallara uyan 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)**.
Bu `client.py` eksiksiz bir MCP istemcisidir; sayfası da **[İstemci](../client/index.md)**.
Bir testte terminali ve portu atlar, `Client`'a doğrudan sunucu nesnesinin kendisini verirsiniz:
`Client(mcp)`. Onun da kendine ait koca bir sayfası var: **[Test etme](testing.md)**.
## Yazmadıklarınız {#what-you-did-not-write}
@ -128,7 +127,7 @@ Bu sayfaya dönüp bir bakın. Üç küçük Python fonksiyonu yazdınız. Şunl
* 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.
* Tek satır protokol. Sürüm anlaşması, JSON-RPC çerçevelemesi, yetenek değiş tokuşu: hepsi `mcp dev` ve `client.py` içinde oldu ve siz hiçbirini görmediniz.
SDK'nın bütün meselesi bu oran.
@ -139,6 +138,6 @@ SDK'nın bütün meselesi bu oran.
* 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.
* `Client("http://localhost:8000/mcp")` çalışan sunucunuzla konuşur. Ona bunun yerine sunucu nesnesini verin, `Client(mcp)`, ve ilk günden test düzeneğiniz olur.
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

@ -1,13 +1,13 @@
---
translation:
sections: ['4926721070127497', c52a1de2b6b32f40, 8e792bf8c7489ec6, 627195f7159e24ef]
sections: [5d13c2f0ba42c0d2, c52a1de2b6b32f40, 8e792bf8c7489ec6, 38552ea228b0a04f]
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.
SDK'nın `Client` sınıfı, yani bir URL'ye bağlanan ya da bir alt süreç başlatan sınıfın ta kendisi, **bellek içinde** de bağlanır: ona sunucu nesnenizi geçirin, o da sunucuyla doğrudan konuşur.
Alt süreç yok. Port yok. Hiç aktarım yok. FastAPI'nin `TestClient`'ıyla aynı fikir.
Alt süreç yok. Port yok. Ağ üzerinden giden hiçbir şey yok. FastAPI'nin `TestClient`'ıyla aynı fikir.
## Temel kullanım {#basic-usage}
@ -97,7 +97,7 @@ 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}
## Varsayılan olarak nesilden bağımsız {#era-neutral-by-default}
!!! note
`Client(mcp)` süreç içinde bağlanır ve varsayılan olarak **nesilden bağımsızdır**: sunucuyu

View file

@ -1,6 +1,6 @@
---
translation:
sections: [74011e683045eea9, 9b64cc175c18b6a9, 4b41be4824030397, e3b1502da786ec33, 71e41161f143c6a9, 9ec2c1eeb8c36378, 8dd027377d46448b, f81491125dcbfe8b]
sections: [74011e683045eea9, 9b64cc175c18b6a9, 4b41be4824030397, e3b1502da786ec33, 71e41161f143c6a9, 9ec2c1eeb8c36378, b47667184ca5b516, f81491125dcbfe8b]
tool: 1
---
# Çok turlu istekler {#multi-round-trip-requests}
@ -164,7 +164,7 @@ Düşük seviyeli `Server` hiçbir şeyin hazır gelmediği katmandır: `MCPServ
## 2026-07-28 sürümüne özgü bir sonuç {#a-2026-07-28-result}
`InputRequiredResult` yalnızca **2026-07-28** protokol sürümünde vardır. Bellek içi `Client(server)` onu sizin yerinize anlaşarak belirler; ağ üzerinde `mode="auto"` keşfeder. Bağlandıktan sonra `client.protocol_version` size ne elde ettiğinizi söyler.
`InputRequiredResult` yalnızca **2026-07-28** protokol sürümünde vardır. `Client`'ın varsayılan `mode="auto"` ayarı onu her bağlantıda keşfeder. Bağlandıktan sonra `client.protocol_version` size ne elde ettiğinizi söyler.
!!! warning
2026 öncesi bir oturumda `InputRequiredResult` koyacak bir yer yoktur. `mode="legacy"` bir

View file

@ -1,6 +1,6 @@
---
translation:
sections: [5315262fe26b33e1, 9d8e98840f1b78f0, 0284b215e85366c4, 8534d8dbb4053a70, 2966fac6fe697007]
sections: [5315262fe26b33e1, 9d8e98840f1b78f0, 52d6009a07e770ea, 8534d8dbb4053a70, 2966fac6fe697007]
tool: 1
---
# İlerleme {#progress}
@ -29,19 +29,17 @@ Bir **`Context`** parametresi alın ve `report_progress`'i çağırın:
İstemci, `call_tool`'a `progress_callback=` geçirerek **çağrı başına** dahil olur:
```python title="client.py" hl_lines="7 16"
```python title="client.py" hl_lines="5 14"
import anyio
from mcp import Client
from server import mcp
async def show(progress: float, total: float | None, message: str | None) -> None:
print(f"{message} ({progress}/{total})")
async def main() -> None:
async with Client(mcp) as client:
async with Client("http://localhost:8000/mcp") as client:
result = await client.call_tool(
"import_catalog",
{"urls": ["https://example.com/a.json", "https://example.com/b.json"]},
@ -56,28 +54,31 @@ anyio.run(main)
Callback, sunucunun bildirdiklerini olduğu gibi alan `async` bir fonksiyondur: `progress`, `total`, `message`.
!!! info
`Client(mcp)` doğrudan sunucu nesnesine, bellek içinde bağlanır; **[Test etme](../get-started/testing.md)**
sayfasının üzerine kurulduğu istemcinin aynısıdır. `Client` hangi aktarımı kullanırsa kullansın
`progress_callback` aynı parametredir; birazdan göreceğiniz *zamanlama* ise bellek içi bağlantıya
özgüdür. Bu bağlantı callback'inizi satır içinde çalıştırır, bu yüzden her bildirim `call_tool`
dönmeden önce ulaşır. Gerçek bir aktarım üzerinde bildirimler sonuçla yarışır ve yavaş bir callback,
`call_tool` döndükten sonra hâlâ çalışıyor olabilir.
`Client`'a ne verirseniz verin `progress_callback` aynı parametredir: buradaki gibi bir URL, bir
`StdioServerParameters` ya da testteki sunucu nesnesi. Yine de gerçek bir aktarım üzerinde
zamanlamaya dikkat edin. Her bildirim yanıtın yanında, kendi başına iletilir; bu yüzden yavaş bir
callback, `call_tool` döndükten sonra hâlâ çalışıyor olabilir. Yalnızca süreç içi test bağlantısı
callback'i satır içinde çalıştırır ve her bildirimin önce ulaşmasını garanti eder.
### Deneyin {#try-it}
`client.py` dosyasını `server.py` dosyasının yanına koyun ve çalıştırın:
`server.py` dosyasını HTTP üzerinden sunun, ardından istemciyi ikinci bir terminalden çalıştırın:
```console
uv run mcp run server.py --transport streamable-http
```
```console
python client.py
```
```text
Imported https://example.com/a.json (1/2)
Imported https://example.com/b.json (2/2)
Imported https://example.com/a.json (1.0/2.0)
Imported https://example.com/b.json (2.0/2.0)
{'result': 'Imported 2 records.'}
```
Sunucudaki her `await ctx.report_progress(...)`, istemcide sırasıyla bir `show` çağrısına dönüştü ve her iki satır da `call_tool` dönmeden **önce** yazdırıldı. İlerleme sonucun içine paketlenmez; araç hâlâ çalışırken akar.
Sunucudaki her `await ctx.report_progress(...)`, istemcide sırasıyla bir `show` çağrısına dönüştü. İlerleme sonucun içine paketlenmez. Araç hâlâ çalışırken akar.
!!! warning
`progress_callback` `Client`'a değil, **çağrıya** aittir. Bunun için bir kurucu argümanı yoktur,

View file

@ -1,6 +1,6 @@
---
translation:
sections: [478fd619e5f90ef8, aef094a00e44e248, bab8cbf3449fa7e9, df1809b15a58335b, 5f9d8c2336ed0239, f54974398e43ddef, b24443dd78584870]
sections: [d98e337bf28845e0, dd642acbba36f615, f547b3e76da19c94, 149513378588da5c, 4e149ed992046709, f54974398e43ddef, b24443dd78584870]
tool: 1
---
# Protokol sürümleri {#protocol-versions}
@ -11,9 +11,17 @@ MCP'nin iki nesli var.
Bununla neredeyse hiç ilgilenmeniz gerekmez, çünkü anlaşmayı sizin yerinize `Client` yapar. Bu sayfa, bunu denetleyen tek yapıcı argümanı, yani `mode=` parametresini ve onu değiştireceğiniz üç durumu anlatır.
Bu sayfadaki her kod parçası, **[İstemci](client/index.md)** sayfasındaki Bookshop `server.py` sunucusuyla konuşan bir `client.py` dosyasıdır. O sunucuyu bir terminalde başlatın:
```console
uv run mcp run server.py --transport streamable-http
```
Ardından her kod parçasını ikinci bir terminalde `python client.py` ile çalıştırın.
## `mode="auto"` {#modeauto}
```python title="client.py" hl_lines="14-15"
```python title="client.py" hl_lines="7-8"
--8<-- "docs_src/protocol_versions/tutorial001.py"
```
@ -31,13 +39,14 @@ Her iki durumda da bağlanmış olarak çıkarsınız ve hangisinin gerçekleşt
Özelliğin tamamı bu. Tek bir `Client`, her nesilden sunucu, kodunuzda dallanma yok.
!!! info
`MCPServer`, `server/discover` isteğini her aktarımda yanıtlar (bellek içi, stdio, Streamable
HTTP); bu yüzden kendi sunucunuza karşı `auto` her zaman `2026-07-28`'e ulaşır. Geri dönüş
yalnızca gerçek bir 2026 öncesi sunucuya karşı devreye girer, ki tam da o zaman bunu istersiniz.
`MCPServer`, `server/discover` isteğini her aktarımda yanıtlar (Streamable HTTP, stdio ve
testlerinizin kullandığı süreç içi bağlantı); bu yüzden kendi sunucunuza karşı `auto` her zaman
`2026-07-28`'e ulaşır. Geri dönüş yalnızca gerçek bir 2026 öncesi sunucuya karşı devreye girer,
ki tam da o zaman bunu istersiniz.
## `mode="legacy"` {#modelegacy}
```python title="client.py" hl_lines="14"
```python title="client.py" hl_lines="7"
--8<-- "docs_src/protocol_versions/tutorial002.py"
```
@ -61,7 +70,7 @@ Sunucunun başlattığı bir istek, sunucunun *sizi* çağırmasıdır: `ctx.eli
`mode`, modern bir protokol sürümü dizgesini de kabul eder. Bugün bu küme tam olarak `["2026-07-28"]`.
```python title="client.py" hl_lines="14"
```python title="client.py" hl_lines="7"
--8<-- "docs_src/protocol_versions/tutorial003.py"
```
@ -94,7 +103,7 @@ Sorgu ucuzdur, ancak yine de her yeniden bağlanmada ödediğiniz bir turdur ve
Öyleyse saklayın. Bir `auto` bağlantısından sonra `client.session.discover_result`, sunucunun gönderdiği `DiscoverResult`'ı olduğu gibi tutar: `supported_versions`, `capabilities`, `instructions` ve sunucunun sonucun `_meta` alanına işlediği kimlik. Bir sonraki sefer bunu `prior_discover=` olarak geri verin:
```python title="client.py" hl_lines="15 17"
```python title="client.py" hl_lines="8 10"
--8<-- "docs_src/protocol_versions/tutorial004.py"
```

View file

@ -1,6 +1,6 @@
---
translation:
sections: [1062ef792791488a, 4be2b831547184a9, 374b049e770385f2, b72f6947089e6de0, b172c9db7831bb31, 70b9ece244ca1b0c, cba78e052898c3f6, f06bdb541cb0b469, fb82d526320b7cc3]
sections: [1062ef792791488a, 4be2b831547184a9, 374b049e770385f2, b72f6947089e6de0, b172c9db7831bb31, 10394c6f16601638, cba78e052898c3f6, f06bdb541cb0b469, 6dc898ccc5a903f9]
tool: 1
---
# Mevcut bir uygulamaya ekleme {#add-to-an-existing-app}
@ -100,7 +100,7 @@ Sondaki o `/mcp`, `streamable_http_path` değeridir. Bunu `"/"` yapın, mount ö
--8<-- "docs_src/asgi/tutorial004.py"
```
Artık istemciler `/notes/mcp` yoluna değil `/notes` yoluna bağlanır.
Artık istemciler `/notes/mcp` yoluna değil `/notes/` yoluna bağlanır.
## Tarayıcı istemcileri için CORS {#cors-for-browser-clients}
@ -143,4 +143,4 @@ Tarayıcı tabanlı bir istemcinin sizden iki izne ihtiyacı vardır: MCP istek
* Tarayıcı istemcilerinin CORS'a ihtiyacı vardır: `Mcp-*` istek başlıkları için `allow_headers`, yanıt için `expose_headers=["Mcp-Session-Id"]`.
* `@mcp.custom_route()`, `/mcp`'nin yanına düz, kimlik doğrulaması olmayan HTTP endpoint'leri ekler.
Sunucu gerçek bir URL'den erişilebilir olduğunda **[İstemci](../client/index.md)** ona bir sunucu nesnesi yerine o URL ile bağlanır.
Sunucu gerçek bir URL'den erişilebilir olduğunda **[İstemci](../client/index.md)** ona o URL ile bağlanır.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [d62c13457fc4a534, 80e73abaca6e0652, d1dc4c54cd00ec9c, 14ad3bc7904036bb, 5225f127bc1b9c77, fe1626fdd5aad1da, 4556cb7ea1a04a31]
sections: [d62c13457fc4a534, 80e73abaca6e0652, 128a492d18295f64, 14ad3bc7904036bb, 54a6697833fcc1d9, fe1626fdd5aad1da, 811d083c1da8bcf6]
tool: 1
---
# Yetkilendirme {#authorization}
@ -23,12 +23,12 @@ Bu sayfa sunucu tarafını anlatır. Yetkilendirme sunucunuzu keşfeden ve token
SDK'nın geçerli bir token'ın neye benzediği konusunda bir fikri yoktur. Bunu **`TokenVerifier`**'ı uygulayarak siz söylersiniz:
```python title="server.py" hl_lines="12-14 19-24"
```python title="server.py" hl_lines="14-16 21-27"
--8<-- "docs_src/authorization/tutorial001.py"
```
* `TokenVerifier` tek bir asenkron metodu olan bir protokoldür. `verify_token`, `Authorization` başlığındaki ham token'ı alır; geçerliyse bir **`AccessToken`**, değilse `None` döndürür. Uygulanacak başka bir şey yok.
* Buradaki, token'ı bir tabloda arar. Gerçek bir doğrulayıcı JWT imzasını doğrular ya da yetkilendirme sunucusunun token-introspection endpoint'ini çağırır. O kod sizindir; SDK onu yalnızca çağırır.
* Buradaki, token'ı bir tabloda arar; her girdi, token'ın hangi kaynak için verildiğini kaydeder. Gerçek bir doğrulayıcı JWT imzasını doğrular ya da yetkilendirme sunucusunun token-introspection endpoint'ini çağırır ve token'ın kimin için verildiğini (`aud` değerini) `AccessToken.resource` içinde bildirir. O kod sizindir; SDK onu yalnızca çağırır.
* `token_verifier=` ve `auth=` her zaman birlikte kullanılır. Birini diğeri olmadan geçirirseniz `MCPServer(...)` daha tek bir istek sunmadan `ValueError` fırlatır.
`AuthSettings`, kaynak sunucunuzun dışa dönük yüzüdür:
@ -36,6 +36,10 @@ SDK'nın geçerli bir token'ın neye benzediği konusunda bir fikri yoktur. Bunu
* `issuer_url`: token'larınızı veren yetkilendirme sunucusu.
* `resource_server_url`: bu MCP endpoint'inin herkese açık URL'si. Bir token'ın *hangi* kaynak için olduğunu belirtir ve keşif belgesi burada bulunur.
* `required_scopes`: her token bunların hepsini taşımalıdır.
* `validate_token_resource`: `AccessToken.resource` değeri `resource_server_url` olmayan her token'ı reddeder. `resource_server_url` ayarlıyken bunu ayarlamadan bırakmak uyarı verir (`MCPDeprecationWarning`) ve `False` gibi davranır; 3.0 sürümü kaynak sunucuları için varsayılanı `True` yapar.
* Yetkilendirme sunucunuz token'ları istemcinin istediği `resource` değerine bağlıyorsa açın; MCP istemcileri bu değeri her zaman gönderir. `resource_server_url` değerini istemcilerin bağlandığı URL'nin birebir aynısı olarak tutun.
* Yetkilendirme sunucunuz kendi audience tanımlayıcılarını kullanıyorsa (bir Auth0 API tanımlayıcısı, bir Entra uygulama kimliği) kapalı bırakın ve bunun yerine `aud` değerini doğrulayıcınızda denetleyin; bu sunucu için olmayan bir token'da `None` döndürün.
* `aud` bir listeyse, `resource_server_url` ile eşit olan girdiyi `resource` alanına koyun.
!!! tip
SDK deposundaki `examples/servers/simple-auth/` dizininde, gerçek bir yetkilendirme sunucusunun
@ -91,7 +95,7 @@ Sunucunuzu hiç duymamış bir istemci içeri giden yolu bu belgeyle bulur: `aut
Herhangi bir işleyicinin içinde **`get_access_token()`**, doğrulayıcınızın geçerli istek için döndürdüğü `AccessToken`'dır:
```python title="server.py" hl_lines="4 32-35"
```python title="server.py" hl_lines="4 35-38"
--8<-- "docs_src/authorization/tutorial002.py"
```
@ -125,6 +129,6 @@ Bir yetkilendirme sunucusu, kullanıcının onay ekranından tıklayarak geçmes
* `token_verifier=` ve `auth=AuthSettings(issuer_url=..., resource_server_url=..., required_scopes=[...])` her zaman birlikte kullanılır.
* SDK, [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) Protected Resource Metadata belgesini `/.well-known/oauth-protected-resource/...` altında yayımlar ve kimliği doğrulanmamış istekleri, `WWW-Authenticate` başlığı ona işaret eden bir 401 ile yanıtlar. Keşif hikâyesinin tamamı bu.
* Herhangi bir işleyicide `get_access_token()`, kimin çağırdığını söyler.
* Yetkilendirme bir HTTP meselesidir. `stdio` ve bellek içi istemci onu hiç görmez.
* Yetkilendirme bir HTTP meselesidir. `stdio` ve bellek içi test istemcisi onu hiç görmez.
İstemci yarısı (yetkilendirme sunucunuzu keşfetme ve token'ı sizin yerinize alma) **[OAuth istemcileri](../client/oauth-clients.md)** sayfasında. Kullanıcıdan kimlik istemek yerine bir kimliği *beyan eden* istemci ise **[Kimlik beyanı](../client/identity-assertion.md)** sayfasında.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [28221886b198784f, f88ea1f1614f3a1d, ce926d686730b6d0, 3be24f8ad8bb5ab9, 3fad24032b2224ff, f25a7f860e579ecb, e758745df6fb7b0a]
sections: [28221886b198784f, f88ea1f1614f3a1d, 2e76f5cb9df15042, ce926d686730b6d0, 3be24f8ad8bb5ab9, 3fad24032b2224ff, f25a7f860e579ecb, 697b01d95080880d]
tool: 1
---
# Dağıtım ve ölçekleme {#deploy-scale}
@ -47,6 +47,22 @@ Gerçek bir ana bilgisayar adının arkasına dağıtıldığında, aynı varsay
her bağlantıyı reddeden bir sunucu, aksi kanıtlanana kadar bir Host izin listesi sorunudur.
**[Sorun giderme](../troubleshooting.md)** de buradan başlar.
## TLS sonlandıran bir vekil sunucunun arkasında {#behind-a-tls-terminating-proxy}
TLS bir vekil sunucuda (bir ingress, bir yük dengeleyici, Caddy, nginx) sona eriyor ve uvicorn onun arkasında düz HTTP sunuyorsa, uvicorn'a vekil sunucunun `X-Forwarded-*` başlıklarına güvenmesini söyleyin:
```console
uvicorn server:app --proxy-headers --forwarded-allow-ips='<proxy address>'
```
Bu olmadan uygulama `http://` üzerinden sunulduğunu sanır ve verdiği her yönlendirme (en yaygını `/mcp` → `/mcp/`) `http://…` adresini gösterir. Python istemcisi bir HTTPS endpoint'inden düz HTTP'ye giden bir yönlendirmeyi izlemeyi reddeder ve bunu açıkça söyler:
```text
MCPError: Redirect to http://mcp.example.com/mcp/ not followed: it would downgrade this HTTPS endpoint to plain HTTP.
```
İstemci tarafındaki geçici çözüm, sunucunun sunduğu tam URL'yi (`https://mcp.example.com/mcp/`, sondaki eğik çizgi dahil) yapılandırmaktır; böylece hiç yönlendirme olmaz. Asıl çözüm yukarıdaki bayraktır. `FORWARDED_ALLOW_IPS` aynı ayarın ortam değişkeni yazımıdır; `*` her atlama noktasına güvenir, bu da yalnızca uvicorn'a vekil sunucudan başka hiçbir şey ulaşamıyorsa doğrudur.
## Worker'lar ve kimin yapışkan olması gerektiği {#workers-and-who-has-to-be-sticky}
Ana bilgisayar adı yanıt vermeye başladıktan sonra, arkasına birden fazla worker koyun. Bunun için SDK'da bir ayar yoktur; bir Starlette uygulamasını, herhangi bir ASGI uygulamasını ölçeklediğiniz gibi ölçeklersiniz: nesneyi, fork etmeyi bilen bir şeye verirsiniz:
@ -171,6 +187,7 @@ Bir `MCPServer` bir uygulama sunucusu değil, bir protokol gerçeklemesidir. Bun
## Özet {#recap}
* Varsayılan olarak uygulama yalnızca localhost'a gönderilen istekleri yanıtlar. `transport_security=TransportSecuritySettings(allowed_hosts=[...], allowed_origins=[...])` yayına çıkış kapısıdır: onu geçirene kadar gerçek bir ana bilgisayar adının arkasındaki her istek bir `421`'dir ve nedeni yalnızca sunucunun log'undadır.
* TLS sonlandıran bir vekil sunucunun arkasında uvicorn'u `--proxy-headers --forwarded-allow-ips=...` ile çalıştırın; yoksa yönlendirmeleri `http://` adresini gösterir ve istemci onları reddeder.
* 2026-07-28'de oturum yoktur ve bir yük dengeleyicinin yapışacağı hiçbir şey yoktur. `stateless_http=True` yalnızca eski nesle ait bir ayardır, çünkü modern bir istek o bayrak hiç okunmadan yönlendirilir ve yanıtlanır.
* Varsayılan `requestState` anahtarı, süreç başına basılan `os.urandom(32)`'dir. Farklı bir worker'a ulaşan çok turlu bir yeniden deneme `-32602` *"Invalid or expired requestState"* ile başarısız olur.
* Çözüm `RequestStateSecurity(keys=[...])` **ve** her örnekte aynı sunucu adıdır. Ad, token'ın varsayılan audience claim'idir. Aynı anahtarlar, aynı ad.

View file

@ -1,6 +1,6 @@
---
translation:
sections: [fea8d769ff9edeba, ce8e2ad42f29ef71, 0d705efb19cf99c2, 2fd7cf825e6d2b2c, 9adc400e8c88e854, 318893ad8e2e9924, 6b63ab96b34476c0]
sections: [fea8d769ff9edeba, ce8e2ad42f29ef71, 0d705efb19cf99c2, 9fd2357154a5b7e7, 9adc400e8c88e854, 318893ad8e2e9924, 6b63ab96b34476c0]
tool: 1
---
# Sunucunuzu çalıştırma {#running-your-server}
@ -75,6 +75,11 @@ Her aktarımın kendi anahtar sözcük argümanları vardır ve hepsi `run()` ü
* `max_request_body_size`: bayt cinsinden kabul edilen en büyük istek gövdesi. Varsayılan olarak 4 MiB;
daha büyük istekler, ayrıştırma veya oturum oluşturma öncesinde HTTP 413 alır. Bunu yalnızca meşru
MCP mesajları bu boyutu aştığında yükseltin.
* `session_idle_timeout`: eski nesil bir oturumun, sunucu onu kapatmadan önce sürmekte olan hiçbir şey
olmadan bekleyebileceği saniye sayısı. Varsayılan 1800. `None` bunu devre dışı bırakır. Bkz.
[Oturum ömrü ve sınırlar](legacy-clients.md#session-lifetime-and-limits).
* `max_sessions`: bir sürecin aynı anda kaç eski nesil oturum tuttuğu. Varsayılan 10 000. `None`
sınırı kaldırır. Aynı bölümde ele alınır.
* `event_store`, `retry_interval`, `transport_security`: kaldığı yerden devam edebilme ve DNS rebinding koruması. localhost dışında bir yere dağıtım yapana kadar bekleyebilirler; `transport_security` konusunu **[Dağıtım ve ölçekleme](deploy.md)** ele alır.
!!! warning

Some files were not shown because too many files have changed in this diff Show more