Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions README.v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ def get_user(user_id: str) -> UserProfile:

# Classes WITHOUT type hints cannot be used for structured output
class UntypedConfig:
def __init__(self, setting1, setting2): # type: ignore[reportMissingParameterType]
def __init__(self, setting1, setting2): # type: ignore[reportMissingParameterType] # noqa: ANN001
self.setting1 = setting1
self.setting2 = setting2

Expand Down Expand Up @@ -744,7 +744,7 @@ server_params = StdioServerParameters(
)


async def run():
async def run() -> None:
"""Run the completion client example."""
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
Expand Down Expand Up @@ -795,7 +795,7 @@ async def run():
print(f"Completions for 'style' argument: {result.completion.values}")


def main():
def main() -> None:
"""Entry point for the completion client."""
asyncio.run(run())

Expand Down Expand Up @@ -1210,7 +1210,7 @@ def hello(name: str = "World") -> str:
return f"Hello, {name}!"


def main():
def main() -> None:
"""Entry point for the direct execution server."""
mcp.run()

Expand Down Expand Up @@ -1280,6 +1280,7 @@ uvicorn examples.snippets.servers.streamable_starlette_mount:app --reload
"""

import contextlib
from collections.abc import AsyncIterator

from starlette.applications import Starlette
from starlette.routing import Mount
Expand Down Expand Up @@ -1308,7 +1309,7 @@ def add_two(n: int) -> int:

# Create a combined lifespan to manage both session managers
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
async def lifespan(app: Starlette) -> AsyncIterator[None]:
async with contextlib.AsyncExitStack() as stack:
await stack.enter_async_context(echo_mcp.session_manager.run())
await stack.enter_async_context(math_mcp.session_manager.run())
Expand Down Expand Up @@ -1392,6 +1393,7 @@ Run from the repository root:
"""

import contextlib
from collections.abc import AsyncIterator

from starlette.applications import Starlette
from starlette.routing import Mount
Expand All @@ -1410,7 +1412,7 @@ def hello() -> str:

# Create a lifespan context manager to run the session manager
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
async def lifespan(app: Starlette) -> AsyncIterator[None]:
async with mcp.session_manager.run():
yield

Expand Down Expand Up @@ -1439,6 +1441,7 @@ Run from the repository root:
"""

import contextlib
from collections.abc import AsyncIterator

from starlette.applications import Starlette
from starlette.routing import Host
Expand All @@ -1457,7 +1460,7 @@ def domain_info() -> str:

# Create a lifespan context manager to run the session manager
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
async def lifespan(app: Starlette) -> AsyncIterator[None]:
async with mcp.session_manager.run():
yield

Expand Down Expand Up @@ -1486,6 +1489,7 @@ Run from the repository root:
"""

import contextlib
from collections.abc import AsyncIterator

from starlette.applications import Starlette
from starlette.routing import Mount
Expand All @@ -1511,7 +1515,7 @@ def send_message(message: str) -> str:

# Create a combined lifespan to manage both session managers
@contextlib.asynccontextmanager
async def lifespan(app: Starlette):
async def lifespan(app: Starlette) -> AsyncIterator[None]:
async with contextlib.AsyncExitStack() as stack:
await stack.enter_async_context(api_mcp.session_manager.run())
await stack.enter_async_context(chat_mcp.session_manager.run())
Expand Down Expand Up @@ -1718,7 +1722,7 @@ server = Server(
)


async def run():
async def run() -> None:
"""Run the server with lifespan management."""
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
Expand Down Expand Up @@ -1796,7 +1800,7 @@ server = Server(
)


async def run():
async def run() -> None:
"""Run the basic low-level server."""
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
Expand Down Expand Up @@ -1889,7 +1893,7 @@ server = Server(
)


async def run():
async def run() -> None:
"""Run the structured output server."""
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
Expand Down Expand Up @@ -1964,7 +1968,7 @@ server = Server(
)


async def run():
async def run() -> None:
"""Run the server."""
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
Expand Down Expand Up @@ -2127,7 +2131,7 @@ async def handle_sampling_message(
)


async def run():
async def run() -> None:
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write, sampling_callback=handle_sampling_message) as session:
# Initialize the connection
Expand Down Expand Up @@ -2165,7 +2169,7 @@ async def run():
print(f"Structured tool result: {result_structured}")


def main():
def main() -> None:
"""Entry point for the client script."""
asyncio.run(run())

Expand All @@ -2191,7 +2195,7 @@ from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client


async def main():
async def main() -> None:
# Connect to a streamable HTTP server
async with streamable_http_client("http://localhost:8000/mcp") as (read_stream, write_stream):
# Create a session using the client streams
Expand Down Expand Up @@ -2235,7 +2239,7 @@ server_params = StdioServerParameters(
)


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

Expand All @@ -2247,7 +2251,7 @@ async def display_tools(session: ClientSession):
print(f" {tool.description}")


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

Expand All @@ -2261,7 +2265,7 @@ async def display_resources(session: ClientSession):
print(f"Resource Template: {display_name}")


async def run():
async def run() -> None:
"""Run the display utilities example."""
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
Expand All @@ -2275,7 +2279,7 @@ async def run():
await display_resources(session)


def main():
def main() -> None:
"""Entry point for the display utilities client."""
asyncio.run(run())

Expand Down Expand Up @@ -2354,7 +2358,7 @@ async def handle_callback() -> tuple[str, str | None]:
return params["code"][0], params.get("state", [None])[0]


async def main():
async def main() -> None:
"""Run the OAuth client example."""
oauth_auth = OAuthClientProvider(
server_url="http://localhost:8001",
Expand Down Expand Up @@ -2382,7 +2386,7 @@ async def main():
print(f"Available resources: {[r.uri for r in resources.resources]}")


def run():
def run() -> None:
asyncio.run(main())


Expand Down
36 changes: 18 additions & 18 deletions examples/mcpserver/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,17 @@ def cosine_similarity(a: list[float], b: list[float]) -> float:
return np.dot(a_array, b_array) / (np.linalg.norm(a_array) * np.linalg.norm(b_array))


@dataclass
class Deps:
openai: AsyncOpenAI
pool: asyncpg.Pool


async def do_ai(
user_prompt: str,
system_prompt: str,
result_type: type[T] | Annotated,
deps=None,
deps: Deps | None = None,
) -> T:
agent = Agent(
DEFAULT_LLM_MODEL,
Expand All @@ -65,14 +71,8 @@ async def do_ai(
return result.data


@dataclass
class Deps:
openai: AsyncOpenAI
pool: asyncpg.Pool


async def get_db_pool() -> asyncpg.Pool:
async def init(conn):
async def init(conn: asyncpg.Connection) -> None:
await conn.execute("CREATE EXTENSION IF NOT EXISTS vector;")
await register_vector(conn)

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

@classmethod
async def from_content(cls, content: str, deps: Deps):
async def from_content(cls, content: str, deps: Deps) -> Self:
embedding = await get_embedding(content, deps)
return cls(content=content, embedding=embedding)

async def save(self, deps: Deps):
async def save(self, deps: Deps) -> None:
async with deps.pool.acquire() as conn:
if self.id is None:
result = await conn.fetchrow(
Expand Down Expand Up @@ -129,7 +129,7 @@ async def save(self, deps: Deps):
self.id,
)

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

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


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


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


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

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


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


async def prune_memories(deps: Deps):
async def prune_memories(deps: Deps) -> None:
async with deps.pool.acquire() as conn:
rows = await conn.fetch(
"""
Expand Down Expand Up @@ -265,7 +265,7 @@ async def display_memory_tree(deps: Deps) -> str:
@mcp.tool()
async def remember(
contents: list[str] = Field(description="List of observations or memories to store"),
):
) -> str:
deps = Deps(openai=AsyncOpenAI(), pool=await get_db_pool())
try:
return "\n".join(await asyncio.gather(*[add_memory(content, deps) for content in contents]))
Expand All @@ -281,7 +281,7 @@ async def read_profile() -> str:
return profile


async def initialize_database():
async def initialize_database() -> None:
pool = await asyncpg.create_pool("postgresql://postgres:postgres@localhost:54320/postgres")
try:
async with pool.acquire() as conn:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ async def introspect_handler(request: Request) -> Response:
return Starlette(routes=routes)


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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ async def get_client(self, client_id: str) -> OAuthClientInformationFull | None:
"""Get OAuth client information."""
return self.clients.get(client_id)

async def register_client(self, client_info: OAuthClientInformationFull):
async def register_client(self, client_info: OAuthClientInformationFull) -> None:
"""Register a new OAuth client."""
if not client_info.client_id:
raise ValueError("No client_id provided")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ async def handle_call_tool(ctx: ServerRequestContext, params: types.CallToolRequ
)


async def run():
async def run() -> None:
"""Run the low-level server using stdio transport."""
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
await server.run(
Expand Down
4 changes: 2 additions & 2 deletions examples/snippets/clients/completion_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
)


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


def main():
def main() -> None:
"""Entry point for the completion client."""
asyncio.run(run())

Expand Down
Loading
Loading