Skip to content

Commit e31e1a1

Browse files
committed
docs: refresh translations for recent English changes
Re-run scripts/docs/translations.py translate for all twelve languages: two new pages (handlers/cancellation.md, advanced/header-parameters.md) and the changed sections of fourteen others.
1 parent d5cebd1 commit e31e1a1

192 files changed

Lines changed: 2996 additions & 510 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
translation:
3+
sections: [81862a209b483d27, b76e8073487afa03, bc214b2fc2bcdae4, d5835477c0b60163, a5d9786f902ad8e1]
4+
tool: 1
5+
---
6+
# Header-Parameter {#header-parameters}
7+
8+
Die meisten Server brauchen das nie.
9+
10+
Ein Gateway oder Load Balancer vor deinem Server kann nur anhand dessen routen, was er lesen kann, ohne den Body zu parsen. Markiere ein Tool-Argument mit `x-mcp-header`, und Clients mit der **[Protokollversion](../protocol-versions.md)** `2026-07-28` senden seinen Wert zusätzlich als HTTP-Header.
11+
12+
## Ein Argument markieren {#mark-an-argument}
13+
14+
Die Markierung ist ein zusätzlicher Schlüssel im JSON Schema des Arguments. Bei `MCPServer` setzt `Field` ihn dort:
15+
16+
```python title="server.py" hl_lines="13"
17+
--8<-- "docs_src/header_parameters/tutorial001.py"
18+
```
19+
20+
* Über Streamable HTTP mit `2026-07-28` sendet ein Client `Mcp-Param-Region` zusätzlich zum Body, und der Server lehnt einen Aufruf ab, bei dem beide nicht übereinstimmen.
21+
* Ein Client, der das Tool nicht aufgelistet hat, hat die Markierung nie gesehen: Er sendet keinen Header, und der Aufruf wird abgelehnt. Der `Client` dieses SDK listet dann die Tools auf und sendet den Aufruf einmal erneut. Vorher aufzulisten spart also nur einen Roundtrip.
22+
* Jede andere Verbindung ignoriert die Annotation.
23+
24+
Deine Funktion ändert sich nicht: `region` kommt weiterhin als Argument an.
25+
26+
## Was sich markieren lässt {#what-can-be-marked}
27+
28+
Argumente vom Typ `str`, `int` und `bool`. Alles andere wird beim Registrieren des Tools mit `InvalidSignature` abgewiesen.
29+
30+
Das gilt auch für `str | None`, das keinen einzelnen Typ hat. Ein optionales Argument braucht ein ausgeschriebenes Schema, mit `WithJsonSchema` von Pydantic:
31+
32+
```python
33+
region: Annotated[str | None, WithJsonSchema({"type": "string", "x-mcp-header": "Region"})] = None
34+
```
35+
36+
## Beim Low-Level-`Server` {#on-the-low-level-server}
37+
38+
Dort schreibst du `input_schema` von Hand, der Schlüssel kommt also direkt hinein:
39+
40+
```python title="server.py" hl_lines="18"
41+
--8<-- "docs_src/header_parameters/tutorial002.py"
42+
```
43+
44+
* Nichts prüft die Annotation für dich: Eine ungültige wird ausgeliefert, und `2026-07-28`-Clients lassen das Tool aus ihrer Auflistung weg.
45+
46+
### Schemas nach Namen {#schemas-by-name}
47+
48+
Um den Header zu prüfen, braucht das SDK das Eingabeschema des Tools, bevor es den Aufruf weiterleitet. Ohne `get_tool_input_schema` holt es sich das Schema, indem es bei jedem Aufruf mit Argumenten deinen `on_list_tools`-Handler ausführt – egal, ob überhaupt ein Tool markiert ist.
49+
50+
```python title="server.py" hl_lines="26 39-41 48"
51+
--8<-- "docs_src/header_parameters/tutorial003.py"
52+
```
53+
54+
* Übergib die Funktion, um aus dem zu antworten, was du schon hast.
55+
* Gib `None` für ein Tool zurück, bei dem es nichts zu prüfen gibt.
56+
57+
## Zusammenfassung {#recap}
58+
59+
* `x-mcp-header` an einem Tool-Argument sorgt dafür, dass `2026-07-28`-Clients es als HTTP-Header `Mcp-Param-*` wiederholen.
60+
* Der Server lehnt einen Aufruf ab, bei dem Header und Body nicht übereinstimmen.
61+
* Nur Argumente vom Typ `str`, `int` und `bool` lassen sich markieren. Bei allem anderen löst `MCPServer` `InvalidSignature` aus.
62+
* Der Low-Level-`Server` prüft nichts, und Clients verwerfen ein Tool mit ungültiger Annotation.
63+
* `get_tool_input_schema` verhindert, dass der Low-Level-`Server` bei jedem Aufruf `on_list_tools` ausführt.
64+
65+
Der Rest der handgeschriebenen `Server`-API steht in **[Der Low-Level-Server](low-level-server.md)**.

‎i18n/de/pages/advanced/index.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [ca6988b7503cd2d3]
3+
sections: [348f8697c6b12cd0]
44
tool: 1
55
---
66
# Für Fortgeschrittene {#advanced}
@@ -14,6 +14,8 @@ von `MCPServer` im Weg ist:
1414
eigene JSON-RPC-Methoden.
1515
* **[Paginierung](pagination.md)** und **[Middleware](middleware.md)**: zwei Dinge, die
1616
*nur* auf dem Low-Level-`Server` gehen.
17+
* **[Header-Parameter](header-parameters.md)**: lassen ein Gateway einen Tool-Aufruf anhand
18+
eines seiner Argumente routen.
1719
* **[Erweiterungen](extensions.md)** und **[MCP Apps](apps.md)**: die
1820
Erweiterungsfläche des Protokolls. Kombiniere Erweiterungspakete zu einem Server oder schreibe deine eigenen.
1921

‎i18n/de/pages/advanced/low-level-server.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [2c79b6338e09b7ac, 9d5d10a5f0405d0a, 1086e77ce561cd7f, a3f71823df5efc31, 9fc7109f72201cae, d50fe7faead8cf68, 7bf25983df655b66, 6330e1f4c6029683, 2f1749c8c133fa1c, 8db7116fc8ddd0ee, ebc33704fbd74262, 0fde3bcea081ba3a]
3+
sections: [2c79b6338e09b7ac, 9d5d10a5f0405d0a, 1086e77ce561cd7f, a3f71823df5efc31, 9fc7109f72201cae, d50fe7faead8cf68, 7bf25983df655b66, 6330e1f4c6029683, 2f1749c8c133fa1c, 8db7116fc8ddd0ee, 2090d99b355bc2c7, 0fde3bcea081ba3a]
44
tool: 1
55
---
66
# Der Low-Level-Server {#the-low-level-server}
@@ -209,6 +209,7 @@ Jeder davon ist eine Idee, für die du jetzt das Vokabular hast; jeder hat seine
209209
* `on_call_tool`, `on_get_prompt` und `on_read_resource` dürfen statt ihres normalen Ergebnisses ein `InputRequiredResult` zurückgeben, um den Aufruf anzuhalten und den Client um Eingaben zu bitten; siehe **[Multi-Roundtrip-Requests](../handlers/multi-round-trip.md)** (multi-round-trip requests). Getreu dieser Ebene wird nichts für dich installiert: Wo `MCPServer` `requestState` standardmäßig versiegelt, geht hier der `request_state`, den du setzt, genau so über die Leitung, wie du ihn geschrieben hast, bis du dich mit `server.middleware.append(RequestStateBoundary(RequestStateSecurity(keys=[...]), default_audience=server.name))` dafür entscheidest: eine Zeile (beide Namen lassen sich aus `mcp.server.request_state` importieren) für genau die Versiegelung und Verifizierung, die `MCPServer` vornimmt (**[`requestState` schützen](../handlers/multi-round-trip.md#protecting-requeststate)**).
210210
* `on_list_resources`, `on_read_resource`, `on_list_prompts`, `on_get_prompt`, `on_completion` haben dieselbe Form `(ctx, params) -> result` für die anderen Primitive.
211211
* `on_subscriptions_listen` bedient den Stream `subscriptions/listen` aus 2026-07-28. Übergib einen `ListenHandler`, der auf einem `SubscriptionBus` aufgebaut ist, und veröffentliche Ereignisse aus deinen anderen Handlern auf dem Bus; die vollständige Zusammensetzung steht in **[Abonnements](../handlers/subscriptions.md)**.
212+
* `get_tool_input_schema` hält `on_list_tools` aus dem Aufrufpfad heraus; siehe **[Header-Parameter](header-parameters.md#schemas-by-name)**.
212213
* `server.streamable_http_app()` gibt dieselbe Starlette-App zurück wie die von `MCPServer`; stelle sie bereit, wie **[Den Server betreiben](../run/index.md)** jede andere ASGI-App bereitstellt. Hier unten gibt es kein `server.run(transport=...)`: `server.run(read_stream, write_stream, server.create_initialization_options())` treibt eine Verbindung über ein Paar Streams, und diese eine Zeile ist alles.
213214

214215
## Zusammenfassung {#recap}

‎i18n/de/pages/advanced/middleware.md‎

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [6048b4f308edbb8c, 46056f318ef205e4, c3e565b61acd75c5, c62422b159c6ed09, 420968f514138f43]
3+
sections: [58e1103d9a323ccf, 46056f318ef205e4, 812b414557fb0c35, 4df162eea2518d38, c62422b159c6ed09, 420968f514138f43]
44
tool: 1
55
---
66
# Middleware {#middleware}
@@ -16,7 +16,7 @@ Du schreibst sie als `async (ctx, call_next)` und hängst sie an `server.middlew
1616

1717
`MCPServer` nimmt die Liste bei der Konstruktion entgegen (`MCPServer(name, middleware=[...])`) und stellt
1818
sie als `mcp.middleware` bereit; der Low-Level-`Server` stellt dieselbe Liste als `server.middleware`
19-
bereit. Das Beispiel unten verwendet den Low-Level-`Server`; wenn `Server(name, on_call_tool=...)` neu
19+
bereit. Die Beispiele unten verwenden den Low-Level-`Server`; wenn `Server(name, on_call_tool=...)` neu
2020
für dich ist, lies zuerst **[Der Low-Level-Server](low-level-server.md)**.
2121

2222
## Eine Timing-Middleware {#a-timing-middleware}
@@ -61,14 +61,38 @@ Genau darum geht es. Middleware umschließt **jede** eingehende Nachricht:
6161
* Sogar eine Methode, für die der Server keinen Handler hat: `call_next` wirft den
6262
`MCPError(-32601, "Method not found")` *durch* deine Middleware hindurch auf dem Weg zum Client.
6363

64+
## Eine Obergrenze für gleichzeitige Aufrufe {#a-concurrency-cap}
65+
66+
Eine Middleware muss `call_next(ctx)` nicht aufrufen. Wirf stattdessen einen `MCPError`, und diese eine
67+
Nachricht wird **abgelehnt**: Die Verbindung bleibt bestehen, und die nächste Nachricht geht durch.
68+
69+
Angenommen, jede Suche belegt eine Verbindung aus einem Pool von vier. Diese Middleware lässt vier
70+
Tool-Aufrufe gleichzeitig laufen und lehnt den fünften ab:
71+
72+
```python title="server.py" hl_lines="15-16 40-55 59"
73+
--8<-- "docs_src/middleware/tutorial002.py"
74+
```
75+
76+
* Gezählt wird nur `tools/call`. Der Server beantwortet `server/discover` und `tools/list` also
77+
weiter, während er Tool-Aufrufe ablehnt.
78+
* MCP definiert keinen Fehlercode für „Server ausgelastet“, also ist `SERVER_BUSY` ein eigener Code
79+
dieses Servers.
80+
* Das Ablehnen sagt dem Client sofort, dass der Server überlastet ist. Wenn du Aufrufer lieber warten
81+
lässt, umschließe stattdessen `call_next(ctx)` mit einem `anyio.CapacityLimiter`.
82+
83+
Ein geworfener `MCPError` geht an die Client-Anwendung, nicht an das Modell. Soll das Modell die
84+
Meldung lesen, gib stattdessen ein Tool-Ergebnis mit `is_error=True` zurück: Das ist **Antworten**,
85+
weiter unten.
86+
6487
## Was du in einer Middleware tun kannst {#what-you-can-do-inside-one}
6588

6689
In aufsteigender Reihenfolge danach, wie sehr du zögern solltest:
6790

68-
* **Beobachten.** Miss es, zähle es, logge es. Das Beispiel oben.
91+
* **Beobachten.** Miss es, zähle es, logge es. Die Timing-Middleware oben.
6992
* **Ablehnen.** Wirf einen `MCPError` *statt* `call_next(ctx)` aufzurufen, und diese eine Nachricht
7093
wird mit einem JSON-RPC-Fehler beantwortet. Die Verbindung bleibt bestehen; die nächste Nachricht
71-
geht durch. So beschränkt ein Server `subscriptions/listen` pro Aufrufer:
94+
geht durch. Die Obergrenze für gleichzeitige Aufrufe oben. So beschränkt ein Server auch
95+
`subscriptions/listen` pro Aufrufer:
7296
**[Entscheiden, wer zusehen darf](../handlers/subscriptions.md#deciding-who-may-watch)** auf der
7397
Seite Abonnements führt es Schritt für Schritt vor.
7498
* **Umschreiben.** `ctx` ist eine Dataclass: `await call_next(dataclasses.replace(ctx, params=...))`

‎i18n/de/pages/client/identity-assertion.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [a91322c46111d16d, 8e6fd6d6f59bb568, e7828fd2729b2c9d, a03ec26bfc678b65, 1034c653c0bcf1b0]
3+
sections: [a91322c46111d16d, 8e6fd6d6f59bb568, 7cf38181f6c99fd5, 37804d4fb36d6302, 1034c653c0bcf1b0]
44
tool: 1
55
---
66
# Identity Assertion {#identity-assertion}
@@ -66,7 +66,7 @@ Die Erweiterung verlangt das nicht; es ist eine bewusst strengere Entscheidung.
6666

6767
### Ein vertraulicher Client {#a-confidential-client}
6868

69-
`client_secret` ist erforderlich; ohne löst der Konstruktor einen `ValueError` aus. Das IETF-Profil unter [SEP-990](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/990) reserviert diesen Grant für vertrauliche Clients, SEP-990 verlangt, dass sich der Client authentifiziert, und dieses SDK setzt beides durch, indem es auf einem geteilten Secret besteht. `token_endpoint_auth_method` legt fest, wo es mitreist: `client_secret_post` (der Standardwert, im Formular-Body) oder `client_secret_basic` (ein HTTP-Basic-Header). Das Profil erlaubt außerdem `private_key_jwt`; dieser Provider unterstützt es nicht.
69+
`client_secret` ist erforderlich; ohne löst der Konstruktor einen `ValueError` aus. Das IETF-Profil unter [SEP-990](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/990) empfiehlt diesen Grant nur für vertrauliche Clients, und [RFC 7521](https://datatracker.ietf.org/doc/html/rfc7521) überlässt diese Richtlinie dem Autorisierungsserver. Dieses SDK wählt auf beiden Seiten die vorsichtige Lesart: Der eingebaute Autorisierungsserver weist einen Client ab, der kein geteiltes Secret hat, und dieser Provider besteht auf einem. `token_endpoint_auth_method` legt fest, wo es mitreist: `client_secret_post` (der Standardwert, im Formular-Body) oder `client_secret_basic` (ein HTTP-Basic-Header). Das Profil erlaubt außerdem `private_key_jwt`; dieser Provider unterstützt es nicht.
7070

7171
!!! tip
7272
Lies `client_secret` aus der Umgebung oder einem Secret-Manager, nie aus der Versionsverwaltung.
@@ -93,6 +93,7 @@ Das SDK kann aber auch selbst der Autorisierungsserver *sein*: `create_auth_rout
9393

9494
* `identity_assertion_enabled=True` schaltet alles frei. Ausgeschaltet – das ist der Standardwert – beantwortet `/token` diesen Grant mit `unsupported_grant_type`, selbst wenn du den Hook implementiert hast, und die Metadaten erwähnen ihn nicht. Eingeschaltet erhalten die Metadaten den Grant-Typ `jwt-bearer` und listen `urn:ietf:params:oauth:grant-profile:id-jag` in `authorization_grant_profiles_supported`, dem Feld, mit dem die Erweiterung Unterstützung bekannt gibt. (Der Client dieses SDK liest es nie: Er ist für genau einen Issuer eingerichtet und fragt einfach.)
9595
* **`exchange_identity_assertion`** ist der Hook. Bevor er läuft, hat das SDK den Client authentifiziert, öffentliche Clients abgewiesen und Clients abgewiesen, deren Registrierung den Grant nicht aufführt. Du bekommst ein `IdentityAssertionParams` (die rohe `assertion`, die angeforderten `scopes` und `resource`) und gibst ein schlichtes `OAuthToken` zurück.
96+
* Öffentliche Clients abzuweisen ist eine Richtlinie des SDK, keine Vorgabe der Spezifikation. Der eingebaute Server authentifiziert Clients nur per geteiltem Secret: Er unterstützt kein `private_key_jwt` und löst Client ID Metadata Documents noch nicht auf ([#1801](https://github.com/modelcontextprotocol/python-sdk/issues/1801)), deshalb kann ein Client, der sich über ein solches Dokument ausweist, diesen Grant hier nicht nutzen. Ein Deployment, das eine andere Richtlinie will, kann die `/token`-Route, die `create_auth_routes` zurückgibt, durch eine eigene ersetzen.
9697
* Die dynamische Client-Registrierung lehnt diesen Grant ausnahmslos ab, deshalb bedient `get_client` hier einen von Hand eingerichteten Client. Ein ID-JAG-Client kann sich nicht selbst ins Leben registrieren.
9798
* Die halbe Klasse besteht aus Ablehnungen. `OAuthAuthorizationServerProvider` ist der *ganze* Autorisierungsserver, also verlangt er auch den Authorization-Code-Flow; ein Server, der Personen zusätzlich anmeldet, implementiert diese Methoden wirklich, und dieser hier hat genau eine Tür.
9899

‎i18n/de/pages/client/transports.md‎

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
translation:
3-
sections: [9cac816674181eb0, 7c157764133fea1f, 40b4916d82eaf1d4, 10d151f2cc75317f, 3d0832f39b0d7059, 92742ba36533633d, 0aeca6145e7bd302]
3+
sections: [9cac816674181eb0, 5619e950d206e6c8, 40b4916d82eaf1d4, 10d151f2cc75317f, 3d0832f39b0d7059, 92742ba36533633d, 991c10e47fda2636]
44
tool: 1
55
---
66
# Client-Transporte {#client-transports}
@@ -44,23 +44,41 @@ Zwei Dinge fallen auf:
4444
* Der `httpx2.AsyncClient` gehört dir, also betrittst und verlässt **du** ihn. Das SDK schließt nie einen Client, den es nicht selbst erzeugt hat.
4545
* `streamable_http_client(url, http_client=...)` gibt einen Transport zurück, und `Client(transport)` nimmt ihn an wie alles andere auch.
4646

47+
Behalte das `timeout=` bei. Es ist dasselbe, das der SDK-eigene Client verwendet (30 Sekunden, 300 für Lesevorgänge); ein `httpx2.AsyncClient`, der ohne gebaut wird, bekommt den 5-Sekunden-Standardwert von `httpx2`, und ein Tool-Aufruf, der länger läuft, schlägt mit einem Read-Timeout fehl.
48+
4749
Eine Anmerkung zu TLS: `httpx2` prüft Zertifikate gegen den Trust Store des Betriebssystems (über
4850
[`truststore`](https://pypi.org/project/truststore/)), nicht gegen eine mitgelieferte CA-Liste. In einer Umgebung ohne
4951
nutzbaren System-CA-Store (manche minimalen Container) setzt du die Standard-Umgebungsvariablen `SSL_CERT_FILE`/`SSL_CERT_DIR`
5052
oder übergibst deinem `httpx2.AsyncClient` ein explizites `verify=ssl_context`
5153
(Hintergrund in
5254
[`httpx` und `httpx-sse` durch `httpx2` ersetzt](../migration.md#httpx-and-httpx-sse-replaced-by-httpx2)).
5355

56+
### Größere SSE-Events {#larger-sse-events}
57+
58+
Übergib `max_sse_event_size`, wenn ein Server ein großes Tool-Ergebnis oder eine große Benachrichtigung in einem einzigen SSE-Event sendet:
59+
60+
```python title="client.py" hl_lines="6-9"
61+
--8<-- "docs_src/client_transports/tutorial005.py"
62+
```
63+
64+
Der Standardwert ist 1 MiB pro Event, gemessen in Bytes, bevor das Event geparst wird. Das Limit gilt für
65+
POST-Responses, den GET-Stream und wiederaufgenommene Streams. Ein zu großes Event in einer POST-Response oder einem
66+
wiederaufgenommenen Stream lässt diesen Request mit einem SSE-Fehler fehlschlagen. Beim GET-Stream im Hintergrund loggt
67+
der Client den Fehler und startet den Stream neu. Setze `max_sse_event_size=None`, um die Obergrenze abzuschalten, wenn du dem
68+
Server vertraust und größere Events brauchst. JSON-Responses sind nicht betroffen. Wenn du `ClientSessionGroup` verwendest, setze
69+
dieselbe Option an `StreamableHttpParameters`.
70+
5471
!!! warning
5572
`streamable_http_client` nahm früher `headers=` und `timeout=` direkt entgegen. Das tut er nicht mehr:
56-
seine einzigen Parameter sind `url`, `http_client` und `terminate_on_close`. Greifst du aus
73+
Seine Parameter sind `url`, `http_client`, `terminate_on_close` und `max_sse_event_size`. Greifst du aus
5774
Gewohnheit zu `headers=`, bekommst du:
5875

5976
```text
6077
TypeError: streamable_http_client() got an unexpected keyword argument 'headers'
6178
```
6279

63-
Alles, was mit HTTP zu tun hat, lebt jetzt auf dem einen `httpx2.AsyncClient`, den du übergibst.
80+
Header, Authentifizierung, Proxys und Timeouts leben auf dem einen `httpx2.AsyncClient`, den du übergibst.
81+
`max_sse_event_size` gilt dagegen für die SSE-Reader des MCP-Transports.
6482

6583
!!! info
6684
`httpx2` behält die vertraute `httpx`-API bei. Wenn du `httpx` kennst, weißt du hier also bereits, wie Auth,
@@ -137,6 +155,7 @@ Ein **Transport** ist ein beliebiger asynchroner Kontextmanager, der ein `(read,
137155

138156
* `Client("http://.../mcp")` (eine URL) verbindet über Streamable HTTP, den Produktions-Transport.
139157
* Header, Auth, Proxys und Timeouts gehören auf einen `httpx2.AsyncClient`, den du an `streamable_http_client(url, http_client=...)` übergibst. Es gibt kein Keyword `headers=`.
158+
* Verwende `streamable_http_client(url, max_sse_event_size=...)`, um das Byte-Limit für jedes SSE-Event zu ändern.
140159
* Redirects wird nur innerhalb des eigenen Origins der URL gefolgt (ein Trailing-Slash-`307`/`308`), plus `http`→`https` auf demselben Host. Alles andere schlägt mit `Redirect to … not followed` fehl; konfiguriere die endgültige URL.
141160
* stdio ist `Client(StdioServerParameters(...))`. Pack es nur dann selbst in `stdio_client(...)` ein, wenn du die stderr des Kindprozesses umleiten willst.
142161
* Der Subprozess bekommt eine Umgebung per Allow-List, nicht deine; `env=` ergänzt sie.

0 commit comments

Comments
 (0)