docs: refresh translations, and translate pages in parallel (#3458)
This commit is contained in:
parent
08a3bc8eaf
commit
fd66270926
23 changed files with 4821 additions and 2277 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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)**.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)**.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)**.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue