Skip to content

Commit eb3d0d0

Browse files
committed
chore: enforce type annotations on all functions via ruff ANN rules
Enable the `ANN` (flake8-annotations) rule set to require return type and argument annotations on all function definitions. Pyright strict already enforces argument types but infers return types silently; this closes the gap so every function has an explicit return annotation. Configuration choices: - `ANN401` (any-type) is ignored: `Any` is sometimes the right answer and pyright strict already catches genuine misuse. - `allow-star-arg-any = true`: `*args: Any, **kwargs: Any` is a common valid pattern for pass-through wrappers. - Per-file ignores for `test_func_metadata.py` and `test_server.py` where untyped parameters are intentional (testing schema inference on unannotated signatures). - README code snippets (via pytest-examples) exempt — short doc examples shouldn't need full annotations. Auto-fix added `-> None` or inferred return types to ~910 functions. The remaining ~100 were annotated manually — mostly `@asynccontextmanager` generators, pytest fixtures, and ASGI handlers that Ruff couldn't infer.
1 parent 92c693b commit eb3d0d0

File tree

149 files changed

+1151
-1036
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

149 files changed

+1151
-1036
lines changed

examples/mcpserver/memory.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,17 @@ def cosine_similarity(a: list[float], b: list[float]) -> float:
5050
return np.dot(a_array, b_array) / (np.linalg.norm(a_array) * np.linalg.norm(b_array))
5151

5252

53+
@dataclass
54+
class Deps:
55+
openai: AsyncOpenAI
56+
pool: asyncpg.Pool
57+
58+
5359
async def do_ai(
5460
user_prompt: str,
5561
system_prompt: str,
5662
result_type: type[T] | Annotated,
57-
deps=None,
63+
deps: Deps | None = None,
5864
) -> T:
5965
agent = Agent(
6066
DEFAULT_LLM_MODEL,
@@ -65,14 +71,8 @@ async def do_ai(
6571
return result.data
6672

6773

68-
@dataclass
69-
class Deps:
70-
openai: AsyncOpenAI
71-
pool: asyncpg.Pool
72-
73-
7474
async def get_db_pool() -> asyncpg.Pool:
75-
async def init(conn):
75+
async def init(conn: asyncpg.Connection) -> None:
7676
await conn.execute("CREATE EXTENSION IF NOT EXISTS vector;")
7777
await register_vector(conn)
7878

@@ -90,11 +90,11 @@ class MemoryNode(BaseModel):
9090
embedding: list[float]
9191

9292
@classmethod
93-
async def from_content(cls, content: str, deps: Deps):
93+
async def from_content(cls, content: str, deps: Deps) -> Self:
9494
embedding = await get_embedding(content, deps)
9595
return cls(content=content, embedding=embedding)
9696

97-
async def save(self, deps: Deps):
97+
async def save(self, deps: Deps) -> None:
9898
async with deps.pool.acquire() as conn:
9999
if self.id is None:
100100
result = await conn.fetchrow(
@@ -129,7 +129,7 @@ async def save(self, deps: Deps):
129129
self.id,
130130
)
131131

132-
async def merge_with(self, other: Self, deps: Deps):
132+
async def merge_with(self, other: Self, deps: Deps) -> None:
133133
self.content = await do_ai(
134134
f"{self.content}\n\n{other.content}",
135135
"Combine the following two texts into a single, coherent text.",
@@ -145,7 +145,7 @@ async def merge_with(self, other: Self, deps: Deps):
145145
if other.id is not None:
146146
await delete_memory(other.id, deps)
147147

148-
def get_effective_importance(self):
148+
def get_effective_importance(self) -> float:
149149
return self.importance * (1 + math.log(self.access_count + 1))
150150

151151

@@ -157,12 +157,12 @@ async def get_embedding(text: str, deps: Deps) -> list[float]:
157157
return embedding_response.data[0].embedding
158158

159159

160-
async def delete_memory(memory_id: int, deps: Deps):
160+
async def delete_memory(memory_id: int, deps: Deps) -> None:
161161
async with deps.pool.acquire() as conn:
162162
await conn.execute("DELETE FROM memories WHERE id = $1", memory_id)
163163

164164

165-
async def add_memory(content: str, deps: Deps):
165+
async def add_memory(content: str, deps: Deps) -> str:
166166
new_memory = await MemoryNode.from_content(content, deps)
167167
await new_memory.save(deps)
168168

@@ -204,7 +204,7 @@ async def find_similar_memories(embedding: list[float], deps: Deps) -> list[Memo
204204
return memories
205205

206206

207-
async def update_importance(user_embedding: list[float], deps: Deps):
207+
async def update_importance(user_embedding: list[float], deps: Deps) -> None:
208208
async with deps.pool.acquire() as conn:
209209
rows = await conn.fetch("SELECT id, importance, access_count, embedding FROM memories")
210210
for row in rows:
@@ -228,7 +228,7 @@ async def update_importance(user_embedding: list[float], deps: Deps):
228228
)
229229

230230

231-
async def prune_memories(deps: Deps):
231+
async def prune_memories(deps: Deps) -> None:
232232
async with deps.pool.acquire() as conn:
233233
rows = await conn.fetch(
234234
"""
@@ -265,7 +265,7 @@ async def display_memory_tree(deps: Deps) -> str:
265265
@mcp.tool()
266266
async def remember(
267267
contents: list[str] = Field(description="List of observations or memories to store"),
268-
):
268+
) -> str:
269269
deps = Deps(openai=AsyncOpenAI(), pool=await get_db_pool())
270270
try:
271271
return "\n".join(await asyncio.gather(*[add_memory(content, deps) for content in contents]))
@@ -281,7 +281,7 @@ async def read_profile() -> str:
281281
return profile
282282

283283

284-
async def initialize_database():
284+
async def initialize_database() -> None:
285285
pool = await asyncpg.create_pool("postgresql://postgres:postgres@localhost:54320/postgres")
286286
try:
287287
async with pool.acquire() as conn:

examples/servers/simple-auth/mcp_simple_auth/auth_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class SimpleAuthProvider(SimpleOAuthProvider):
4747
2. Stores token state for introspection by Resource Servers
4848
"""
4949

50-
def __init__(self, auth_settings: SimpleAuthSettings, auth_callback_path: str, server_url: str):
50+
def __init__(self, auth_settings: SimpleAuthSettings, auth_callback_path: str, server_url: str) -> None:
5151
super().__init__(auth_settings, auth_callback_path, server_url)
5252

5353

@@ -134,7 +134,7 @@ async def introspect_handler(request: Request) -> Response:
134134
return Starlette(routes=routes)
135135

136136

137-
async def run_server(server_settings: AuthServerSettings, auth_settings: SimpleAuthSettings):
137+
async def run_server(server_settings: AuthServerSettings, auth_settings: SimpleAuthSettings) -> None:
138138
"""Run the Authorization Server."""
139139
auth_server = create_authorization_server(server_settings, auth_settings)
140140

examples/servers/simple-auth/mcp_simple_auth/legacy_as_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class ServerSettings(BaseModel):
3939
class LegacySimpleOAuthProvider(SimpleOAuthProvider):
4040
"""Simple OAuth provider for legacy MCP server."""
4141

42-
def __init__(self, auth_settings: SimpleAuthSettings, auth_callback_path: str, server_url: str):
42+
def __init__(self, auth_settings: SimpleAuthSettings, auth_callback_path: str, server_url: str) -> None:
4343
super().__init__(auth_settings, auth_callback_path, server_url)
4444

4545

examples/servers/simple-auth/mcp_simple_auth/simple_auth_provider.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class SimpleOAuthProvider(OAuthAuthorizationServerProvider[AuthorizationCode, Re
5151
3. Maintaining token state for introspection
5252
"""
5353

54-
def __init__(self, settings: SimpleAuthSettings, auth_callback_url: str, server_url: str):
54+
def __init__(self, settings: SimpleAuthSettings, auth_callback_url: str, server_url: str) -> None:
5555
self.settings = settings
5656
self.auth_callback_url = auth_callback_url
5757
self.server_url = server_url
@@ -66,7 +66,7 @@ async def get_client(self, client_id: str) -> OAuthClientInformationFull | None:
6666
"""Get OAuth client information."""
6767
return self.clients.get(client_id)
6868

69-
async def register_client(self, client_info: OAuthClientInformationFull):
69+
async def register_client(self, client_info: OAuthClientInformationFull) -> None:
7070
"""Register a new OAuth client."""
7171
if not client_info.client_id:
7272
raise ValueError("No client_id provided")

examples/servers/simple-auth/mcp_simple_auth/token_verifier.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def __init__(
2525
introspection_endpoint: str,
2626
server_url: str,
2727
validate_resource: bool = False,
28-
):
28+
) -> None:
2929
self.introspection_endpoint = introspection_endpoint
3030
self.server_url = server_url
3131
self.validate_resource = validate_resource

examples/servers/structured-output-lowlevel/mcp_structured_output_lowlevel/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ async def handle_call_tool(ctx: ServerRequestContext, params: types.CallToolRequ
7575
)
7676

7777

78-
async def run():
78+
async def run() -> None:
7979
"""Run the low-level server using stdio transport."""
8080
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
8181
await server.run(

examples/snippets/clients/completion_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
)
1818

1919

20-
async def run():
20+
async def run() -> None:
2121
"""Run the completion client example."""
2222
async with stdio_client(server_params) as (read, write):
2323
async with ClientSession(read, write) as session:
@@ -68,7 +68,7 @@ async def run():
6868
print(f"Completions for 'style' argument: {result.completion.values}")
6969

7070

71-
def main():
71+
def main() -> None:
7272
"""Entry point for the completion client."""
7373
asyncio.run(run())
7474

examples/snippets/clients/display_utilities.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
)
1818

1919

20-
async def display_tools(session: ClientSession):
20+
async def display_tools(session: ClientSession) -> None:
2121
"""Display available tools with human-readable names"""
2222
tools_response = await session.list_tools()
2323

@@ -29,7 +29,7 @@ async def display_tools(session: ClientSession):
2929
print(f" {tool.description}")
3030

3131

32-
async def display_resources(session: ClientSession):
32+
async def display_resources(session: ClientSession) -> None:
3333
"""Display available resources with human-readable names"""
3434
resources_response = await session.list_resources()
3535

@@ -43,7 +43,7 @@ async def display_resources(session: ClientSession):
4343
print(f"Resource Template: {display_name}")
4444

4545

46-
async def run():
46+
async def run() -> None:
4747
"""Run the display utilities example."""
4848
async with stdio_client(server_params) as (read, write):
4949
async with ClientSession(read, write) as session:
@@ -57,7 +57,7 @@ async def run():
5757
await display_resources(session)
5858

5959

60-
def main():
60+
def main() -> None:
6161
"""Entry point for the display utilities client."""
6262
asyncio.run(run())
6363

examples/snippets/clients/oauth_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
class InMemoryTokenStorage(TokenStorage):
2222
"""Demo In-memory token storage implementation."""
2323

24-
def __init__(self):
24+
def __init__(self) -> None:
2525
self.tokens: OAuthToken | None = None
2626
self.client_info: OAuthClientInformationFull | None = None
2727

@@ -52,7 +52,7 @@ async def handle_callback() -> tuple[str, str | None]:
5252
return params["code"][0], params.get("state", [None])[0]
5353

5454

55-
async def main():
55+
async def main() -> None:
5656
"""Run the OAuth client example."""
5757
oauth_auth = OAuthClientProvider(
5858
server_url="http://localhost:8001",
@@ -80,7 +80,7 @@ async def main():
8080
print(f"Available resources: {[r.uri for r in resources.resources]}")
8181

8282

83-
def run():
83+
def run() -> None:
8484
asyncio.run(main())
8585

8686

examples/snippets/clients/parsing_tool_results.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from mcp.client.stdio import stdio_client
77

88

9-
async def parse_tool_results():
9+
async def parse_tool_results() -> None:
1010
"""Demonstrates how to parse different types of content in CallToolResult."""
1111
server_params = StdioServerParameters(command="python", args=["path/to/mcp_server.py"])
1212

@@ -52,7 +52,7 @@ async def parse_tool_results():
5252
print(f"Error: {content.text}")
5353

5454

55-
async def main():
55+
async def main() -> None:
5656
await parse_tool_results()
5757

5858

0 commit comments

Comments
 (0)