docs: refresh translations, and translate pages in parallel (#3458)
This commit is contained in:
parent
08a3bc8eaf
commit
fd66270926
5 changed files with 4821 additions and 2277 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
translation:
|
||||
sections: [3d1663c18edc824c, d4fd37009a13f03d, af9f398a5a8b679a, 470c2dd144294d69, 8e45827e6d24e8c8, 91dfd0ce98ebb03c]
|
||||
sections: [3d1663c18edc824c, 90956965ae6a1ca1, af9f398a5a8b679a, 5ce83b1f9d88da62, 0d9b5d13fffc94e5, 8e45827e6d24e8c8, 91dfd0ce98ebb03c]
|
||||
tool: 1
|
||||
---
|
||||
# Eski nesil istemcilere hizmet verme {#serving-legacy-clients}
|
||||
|
|
@ -22,15 +22,25 @@ Yani eski nesil istemci, *ona göre* bir şey inşa ettiğiniz bir hedef değil.
|
|||
|
||||
## Tek işleyici, iki nesil {#one-handler-both-eras}
|
||||
|
||||
İşte kullanıcıya bir şey sorması gereken bir araç ve onu çağıran her iki nesilden istemci:
|
||||
İşte kullanıcıya bir şey sorması gereken bir araç:
|
||||
|
||||
```python title="server.py" hl_lines="24 37-38"
|
||||
```python title="server.py" hl_lines="21"
|
||||
--8<-- "docs_src/legacy_clients/tutorial001.py"
|
||||
```
|
||||
|
||||
`reserve`, modelin sağlamadığı tek bir şeye ihtiyaç duyar: kaç kopya. Bir araç bunu `Annotated[..., Resolve(ask_quantity)]` ile bildirir (ayrıntıların tamamı **[Bağımlılıklar](../handlers/dependencies.md)** sayfasında). `reserve` içinde hiçbir şey bir sürüm adı vermez, bir yetenek kontrol etmez ya da dallanmaz.
|
||||
|
||||
İki istemci **aynı anda**, aynı `mcp` nesnesi üzerinde açıktır. `mode="legacy"`, `initialize` el sıkışmasını çalıştırır: 2026 öncesi bir istemcinin açtığı bağlantının ta kendisi. Diğeri varsayılanı alır ve `2026-07-28` sürümünde karar kılar.
|
||||
Onu HTTP üzerinden sunun. İşte onu çağıran her iki nesilden istemci:
|
||||
|
||||
```console
|
||||
uv run mcp run server.py --transport streamable-http
|
||||
```
|
||||
|
||||
```python title="client.py" hl_lines="14-15"
|
||||
--8<-- "docs_src/legacy_clients/tutorial001_client.py"
|
||||
```
|
||||
|
||||
İki istemci **aynı anda**, çalışan aynı sunucuya karşı açıktır. `mode="legacy"`, `initialize` el sıkışmasını çalıştırır: 2026 öncesi bir istemcinin açtığı bağlantının ta kendisi. Diğeri varsayılanı alır ve `2026-07-28` sürümünde karar kılar. İkinci bir terminalden `python client.py` komutunu çalıştırın:
|
||||
|
||||
```text
|
||||
2025-11-25 {'result': "Reserved 2 of 'Dune'."}
|
||||
|
|
@ -64,6 +74,31 @@ Tek worker'da bu görünmez. İki worker'da ise sorunun tamamı budur: `Mcp-Sess
|
|||
**devam ettirilebilirliktir** (kaçırılan SSE olaylarını *aynı* oturuma yeniden bağlanan bir
|
||||
istemciye yeniden oynatmak). Bir oturumu asla başka bir süreçten erişilebilir kılmaz.
|
||||
|
||||
## Oturum ömrü ve sınırlar {#session-lifetime-and-limits}
|
||||
|
||||
Eski nesil bir oturum sonsuza dek yaşamaz ve tek bir süreç bunlardan sınırsız sayıda tutmaz. Bunu iki ayar denetler. İkisi de `run()`, `streamable_http_app()` ve `Server.streamable_http_app()` üzerinde birer anahtar sözcük argümanıdır. Modern (`2026-07-28`) bağlantılarda ve `stateless_http=True` durumunda oturum yoktur; bu yüzden iki ayar da onlar için geçerli değildir.
|
||||
|
||||
| Ayar | Varsayılan | Ne yapar | İstemci ne görür | Kapatmak için |
|
||||
|---|---|---|---|---|
|
||||
| `session_idle_timeout` | `1800` (30 dk) | Bu süre boyunca devam eden hiçbir işlemi olmayan bir oturumu kapatır. | `404 Session not found`. Yeniden `initialize` göndermesi gerekir. | `None` |
|
||||
| `max_sessions` | `10_000` | Bu sayının ötesinde oturum açmayı reddeder. Mevcut oturumlara dokunulmaz ve hiçbir şey tahliye edilmez. | JSON-RPC kodu `-32603` ile `503 Too many open sessions`. | `None` |
|
||||
|
||||
Neler "devam eden işlem" sayılır:
|
||||
|
||||
* Açık bir `GET` akışı. SDK istemcileri bir tane açık tutar; bu yüzden bağlı bir istemcinin oturumu asla sona ermez.
|
||||
* Hâlâ yanıtlanmakta olan bir istek. Zaman aşımından uzun süren bir araç çağrısı kesilmez; geri sayım ancak o bittiğinde başlar.
|
||||
* Başka hiçbir şey. İstekler arasında saat işler. Oturumdaki herhangi bir istek onu yeniden başlatır, `ping` dahil. Bir oturum sona erdikten sonra onu hiçbir şey diriltmez.
|
||||
|
||||
Oturumunu `DELETE` ile bitiren bir istemci onu hemen serbest bırakır. Açılış isteği reddedilen bir istemci de öyle.
|
||||
|
||||
```python
|
||||
mcp.run(transport="streamable-http", session_idle_timeout=None, max_sessions=50_000)
|
||||
```
|
||||
|
||||
İki olay da sunucu log'unda görünür. Sona erme, `INFO` düzeyinde `Session <id> idle timeout` olarak görünür. Reddedilen bir açılış ise `WARNING` düzeyinde `Refusing to open a new session: <n> sessions are already open` olarak.
|
||||
|
||||
Sınırlar süreç başınadır. Dört worker'la tavan, `max_sessions` değerinin dört katıdır ve her worker kendi oturumlarını kendisi sonlandırır.
|
||||
|
||||
## Tek ayar düğmesi: `stateless_http` {#the-one-knob-stateless_http}
|
||||
|
||||
Yapışkanlık ödemeyi reddettiğiniz bir bedelse, değiştirebileceğiniz tam olarak tek bir şey var.
|
||||
|
|
@ -89,8 +124,7 @@ Onunla ilgili iki şey, ne yaptığından daha önemli.
|
|||
|
||||
!!! check
|
||||
Yanlış olanı yapın. `reserve`, az önce iki istemciye de hizmet veren aracın ta kendisi. Onu
|
||||
`stateless_http=True` ile dağıtın, aynı iki istemciyi HTTP üzerinden bağlayın ve her birinden
|
||||
çağırın.
|
||||
`stateless_http=True` ile dağıtın, aynı iki istemciyi bağlayın ve her birinden çağırın.
|
||||
|
||||
Modern istemci hâlâ `Reserved 2 of 'Dune'.` alır. Modern kol değişmedi.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue