Skip to content

Commit 0520af7

Browse files
style: apply ruff 0.16 formatting to Markdown code blocks
ruff 0.16.0 started formatting Python code blocks inside Markdown files, so CI (which installs the latest ruff satisfying >=0.8) rejects the previously formatted docs. Blank-line normalization only, no content changes.
1 parent 02eb15c commit 0520af7

5 files changed

Lines changed: 52 additions & 29 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ from authplane_fastmcp import authplane_auth
2020
from fastmcp import FastMCP
2121
from fastmcp.server.auth import require_scopes
2222

23+
2324
async def main() -> None:
2425
result = await authplane_auth(
2526
issuer="https://auth.company.com",
@@ -37,6 +38,7 @@ async def main() -> None:
3738
finally:
3839
await result.aclose()
3940

41+
4042
asyncio.run(main())
4143
```
4244

authplane-fastmcp/README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ async def main():
3232
)
3333

3434
@mcp.tool(auth=require_scopes("tools/query"))
35-
async def query_database(
36-
query: str, token: AccessToken = CurrentAccessToken()
37-
) -> str:
35+
async def query_database(query: str, token: AccessToken = CurrentAccessToken()) -> str:
3836
user_id = token.claims.get("sub")
3937
return f"Query: {query}, User: {user_id}"
4038

authplane-fastmcp/docs/user-guide.md

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import asyncio
3737
from fastmcp import FastMCP
3838
from authplane_fastmcp import authplane_auth
3939

40+
4041
async def main() -> None:
4142
result = await authplane_auth(
4243
issuer="https://auth.company.com",
@@ -55,6 +56,7 @@ async def main() -> None:
5556
finally:
5657
await result.aclose()
5758

59+
5860
asyncio.run(main())
5961
```
6062

@@ -99,11 +101,13 @@ Use FastMCP's built-in `require_scopes` decorator to enforce per-tool scope requ
99101
```python
100102
from fastmcp.server.auth import require_scopes
101103

104+
102105
@mcp.tool(auth=require_scopes("tools/query"))
103106
def query(sql: str) -> str:
104107
"""Requires the tools/query scope."""
105108
return f"Ran: {sql}" # replace with your real handler
106109

110+
107111
@mcp.tool(auth=require_scopes("tools/admin", "tools/delete"))
108112
def delete_all() -> str:
109113
"""Requires BOTH tools/admin AND tools/delete scopes."""
@@ -120,21 +124,22 @@ FastMCP enforces scopes **before** the handler runs by **filtering tools the cal
120124
from fastmcp.dependencies import CurrentAccessToken
121125
from fastmcp.server.auth import AccessToken
122126

127+
123128
@mcp.tool()
124129
async def my_tool(data: str, token: AccessToken = CurrentAccessToken()) -> str:
125130
# Standard JWT claims
126-
sub = token.claims.get("sub") # Subject (user ID)
127-
jti = token.claims.get("jti") # JWT ID
128-
iss = token.claims.get("iss") # Issuer
129-
aud = token.claims.get("aud") # Audience
130-
exp = token.claims.get("exp") # Expiration (Unix timestamp)
131-
nbf = token.claims.get("nbf") # Not before
132-
iat = token.claims.get("iat") # Issued at
131+
sub = token.claims.get("sub") # Subject (user ID)
132+
jti = token.claims.get("jti") # JWT ID
133+
iss = token.claims.get("iss") # Issuer
134+
aud = token.claims.get("aud") # Audience
135+
exp = token.claims.get("exp") # Expiration (Unix timestamp)
136+
nbf = token.claims.get("nbf") # Not before
137+
iat = token.claims.get("iat") # Issued at
133138

134139
# OAuth claims
135-
client_id = token.client_id # Client ID
136-
scopes = token.scopes # List of granted scopes
137-
expires_at = token.expires_at # Expiration (Unix timestamp)
140+
client_id = token.client_id # Client ID
141+
scopes = token.scopes # List of granted scopes
142+
expires_at = token.expires_at # Expiration (Unix timestamp)
138143

139144
# Custom claims
140145
tenant = token.claims.get("tenant_id")
@@ -150,6 +155,7 @@ The `claims` dict contains the **full JWT payload** including all standard and c
150155
```python
151156
from fastmcp.server.dependencies import get_access_token
152157

158+
153159
@mcp.tool()
154160
async def my_tool(data: str) -> str:
155161
token = get_access_token() # Returns None if unauthenticated
@@ -247,10 +253,12 @@ Implement your own revocation logic with an async callable:
247253
```python
248254
from authplane import VerifiedClaims
249255

256+
250257
async def check_blocklist(claims: VerifiedClaims, raw_token: str) -> bool:
251258
"""Return True to reject the token (it is revoked)."""
252259
return await redis_client.sismember("revoked_tokens", claims.jti)
253260

261+
254262
await authplane_auth(
255263
issuer="https://auth.company.com",
256264
base_url="https://mcp.company.com",
@@ -280,8 +288,8 @@ result = await authplane_auth(
280288
downstream = await result.client.exchange(
281289
TokenExchangeOptions(
282290
subject_token=inbound_token,
283-
scope="tools/add", # narrow to the minimum
284-
resources=("https://downstream.example",), # RFC 8707 audience binding
291+
scope="tools/add", # narrow to the minimum
292+
resources=("https://downstream.example",), # RFC 8707 audience binding
285293
)
286294
)
287295

@@ -314,6 +322,7 @@ from authplane import ConsentRequiredError
314322
from authplane.oauth import TokenExchangeOptions
315323
from mcp.shared.exceptions import UrlElicitationRequiredError
316324

325+
317326
@mcp.tool(auth=require_scopes("tools/call_downstream"))
318327
async def call_downstream(payload: str) -> str:
319328
try:
@@ -406,6 +415,7 @@ When `fetch_settings` is provided, `dev_mode` is ignored for both metadata and J
406415
```python
407416
import asyncio
408417

418+
409419
async def main() -> None:
410420
result = await authplane_auth(...)
411421
try:
@@ -414,6 +424,7 @@ async def main() -> None:
414424
finally:
415425
await result.aclose()
416426

427+
417428
asyncio.run(main())
418429
```
419430

authplane-mcp/docs/user-guide.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,14 @@ Use the `require_scope()` helper at the top of tool handlers to enforce per-tool
102102
```python
103103
from authplane_mcp import require_scope
104104

105+
105106
@mcp.tool()
106107
async def query(sql: str) -> str:
107108
"""Requires the tools/query scope."""
108109
require_scope("tools/query")
109110
return f"Ran: {sql}" # replace with your real handler
110111

112+
111113
@mcp.tool()
112114
async def delete_all() -> str:
113115
"""Requires the tools/admin scope."""
@@ -128,14 +130,15 @@ Use the MCP SDK's `get_access_token()` to access the validated token in tool han
128130
```python
129131
from mcp.server.auth.middleware.auth_context import get_access_token
130132

133+
131134
@mcp.tool()
132135
async def my_tool(data: str) -> str:
133136
token = get_access_token()
134137
if token:
135-
client_id = token.client_id # Client ID
136-
scopes = token.scopes # List of granted scopes
137-
expires_at = token.expires_at # Expiration (Unix timestamp)
138-
resource = token.resource # Resource (audience) URL
138+
client_id = token.client_id # Client ID
139+
scopes = token.scopes # List of granted scopes
140+
expires_at = token.expires_at # Expiration (Unix timestamp)
141+
resource = token.resource # Resource (audience) URL
139142
return f"Processing {data}"
140143
```
141144

@@ -238,10 +241,12 @@ Implement your own revocation logic with an async callable:
238241
```python
239242
from authplane import VerifiedClaims
240243

244+
241245
async def check_blocklist(claims: VerifiedClaims, raw_token: str) -> bool:
242246
"""Return True to reject the token (it is revoked)."""
243247
return await redis_client.sismember("revoked_tokens", claims.jti)
244248

249+
245250
await authplane_mcp_auth(
246251
issuer="https://auth.company.com",
247252
resource="https://mcp.company.com",
@@ -271,8 +276,8 @@ result = await authplane_mcp_auth(
271276
downstream = await result.client.exchange(
272277
TokenExchangeOptions(
273278
subject_token=inbound_token,
274-
scope="tools/add", # narrow to the minimum
275-
resources=("https://downstream.example",), # RFC 8707 audience binding
279+
scope="tools/add", # narrow to the minimum
280+
resources=("https://downstream.example",), # RFC 8707 audience binding
276281
)
277282
)
278283

@@ -305,6 +310,7 @@ The adapter handles this for you. The `client` returned by `authplane_mcp_auth(.
305310
```python
306311
from authplane.oauth import TokenExchangeOptions
307312

313+
308314
@mcp.tool()
309315
async def call_downstream(user_token: str, payload: str) -> str:
310316
downstream = await result.client.exchange(
@@ -406,6 +412,7 @@ When `fetch_settings` is provided, `dev_mode` is ignored for both metadata and J
406412
```python
407413
import asyncio
408414

415+
409416
async def main() -> None:
410417
auth_result = await authplane_mcp_auth(...)
411418
try:
@@ -414,6 +421,7 @@ async def main() -> None:
414421
finally:
415422
await auth_result.aclose()
416423

424+
417425
asyncio.run(main())
418426
```
419427

authplane/docs/user-guide.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,11 @@ res = client.resource(
137137
resource="https://api.example.com",
138138
scopes=["read"],
139139
inbound_dpop=InboundDPoPOptions(
140-
replay_store=InMemoryDPoPReplayStore(), # process-scoped by default
140+
replay_store=InMemoryDPoPReplayStore(), # process-scoped by default
141141
max_proof_age_seconds=300,
142142
clock_skew_seconds=30,
143143
allowed_proof_algorithms=("RS256", "ES256"),
144-
required=True, # reject bearer-only tokens
144+
required=True, # reject bearer-only tokens
145145
),
146146
)
147147
```
@@ -159,13 +159,16 @@ For each incoming request that may carry a DPoP-bound token, build a
159159
```python
160160
from dataclasses import dataclass
161161

162+
162163
@dataclass
163164
class IncomingRequest:
164165
"""Implements DPoPRequestContext."""
166+
165167
method: str
166168
url: str
167169
proof: str | None
168170

171+
169172
claims = await res.verify(
170173
token,
171174
dpop_request=IncomingRequest(
@@ -261,6 +264,7 @@ res = client.resource(
261264
```python
262265
from authplane import VerifiedClaims
263266

267+
264268
async def my_revocation_checker(claims: VerifiedClaims, raw_token: str) -> bool:
265269
return claims.jti in revoked_jtis
266270
```
@@ -415,12 +419,12 @@ For multi-instance or shared-state deployments, provide your own `DPoPNonceStore
415419
```python
416420
from authplane import DPoPKeyMaterial, DPoPNonceStore, DPoPProvider
417421

422+
418423
class MyNonceStore:
419-
def get(self, key: str) -> str:
420-
...
424+
def get(self, key: str) -> str: ...
425+
426+
def put(self, key: str, nonce: str) -> None: ...
421427

422-
def put(self, key: str, nonce: str) -> None:
423-
...
424428

425429
provider = DPoPProvider(
426430
DPoPKeyMaterial.from_pem(private_key_pem),
@@ -597,8 +601,8 @@ except AuthplaneError as e:
597601
Generate an RFC 9728 protected resource metadata document with:
598602

599603
```python
600-
prm = res.prm_response() # the document body (a dict)
601-
url = res.prm_url() # the well-known URL where clients can fetch it
604+
prm = res.prm_response() # the document body (a dict)
605+
url = res.prm_url() # the well-known URL where clients can fetch it
602606
```
603607

604608
Example output:

0 commit comments

Comments
 (0)