refactor: replace lowlevel Server decorators with on_* constructor kwargs (#1985)
This commit is contained in:
parent
d6d3ad9a7c
commit
0a22a9dc33
1 changed files with 3563 additions and 5481 deletions
|
|
@ -2,68 +2,70 @@
|
|||
|
||||
from collections.abc import AsyncIterator
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Any
|
||||
|
||||
import anyio
|
||||
import click
|
||||
import uvicorn
|
||||
from mcp import types
|
||||
from mcp.server import Server, ServerRequestContext
|
||||
from mcp.server.experimental.task_context import ServerTaskContext
|
||||
from mcp.server.lowlevel import Server
|
||||
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
|
||||
from starlette.applications import Starlette
|
||||
from starlette.routing import Mount
|
||||
|
||||
server = Server("simple-task-server")
|
||||
|
||||
async def handle_list_tools(
|
||||
ctx: ServerRequestContext, params: types.PaginatedRequestParams | None
|
||||
) -> types.ListToolsResult:
|
||||
return types.ListToolsResult(
|
||||
tools=[
|
||||
types.Tool(
|
||||
name="long_running_task",
|
||||
description="A task that takes a few seconds to complete with status updates",
|
||||
input_schema={"type": "object", "properties": {}},
|
||||
execution=types.ToolExecution(task_support=types.TASK_REQUIRED),
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
async def handle_call_tool(
|
||||
ctx: ServerRequestContext, params: types.CallToolRequestParams
|
||||
) -> types.CallToolResult | types.CreateTaskResult:
|
||||
"""Dispatch tool calls to their handlers."""
|
||||
if params.name == "long_running_task":
|
||||
ctx.experimental.validate_task_mode(types.TASK_REQUIRED)
|
||||
|
||||
async def work(task: ServerTaskContext) -> types.CallToolResult:
|
||||
await task.update_status("Starting work...")
|
||||
await anyio.sleep(1)
|
||||
|
||||
await task.update_status("Processing step 1...")
|
||||
await anyio.sleep(1)
|
||||
|
||||
await task.update_status("Processing step 2...")
|
||||
await anyio.sleep(1)
|
||||
|
||||
return types.CallToolResult(content=[types.TextContent(type="text", text="Task completed!")])
|
||||
|
||||
return await ctx.experimental.run_task(work)
|
||||
|
||||
return types.CallToolResult(
|
||||
content=[types.TextContent(type="text", text=f"Unknown tool: {params.name}")],
|
||||
is_error=True,
|
||||
)
|
||||
|
||||
|
||||
server = Server(
|
||||
"simple-task-server",
|
||||
on_list_tools=handle_list_tools,
|
||||
on_call_tool=handle_call_tool,
|
||||
)
|
||||
|
||||
# One-line setup: auto-registers get_task, get_task_result, list_tasks, cancel_task
|
||||
server.experimental.enable_tasks()
|
||||
|
||||
|
||||
@server.list_tools()
|
||||
async def list_tools() -> list[types.Tool]:
|
||||
return [
|
||||
types.Tool(
|
||||
name="long_running_task",
|
||||
description="A task that takes a few seconds to complete with status updates",
|
||||
input_schema={"type": "object", "properties": {}},
|
||||
execution=types.ToolExecution(task_support=types.TASK_REQUIRED),
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
async def handle_long_running_task(arguments: dict[str, Any]) -> types.CreateTaskResult:
|
||||
"""Handle the long_running_task tool - demonstrates status updates."""
|
||||
ctx = server.request_context
|
||||
ctx.experimental.validate_task_mode(types.TASK_REQUIRED)
|
||||
|
||||
async def work(task: ServerTaskContext) -> types.CallToolResult:
|
||||
await task.update_status("Starting work...")
|
||||
await anyio.sleep(1)
|
||||
|
||||
await task.update_status("Processing step 1...")
|
||||
await anyio.sleep(1)
|
||||
|
||||
await task.update_status("Processing step 2...")
|
||||
await anyio.sleep(1)
|
||||
|
||||
return types.CallToolResult(content=[types.TextContent(type="text", text="Task completed!")])
|
||||
|
||||
return await ctx.experimental.run_task(work)
|
||||
|
||||
|
||||
@server.call_tool()
|
||||
async def handle_call_tool(name: str, arguments: dict[str, Any]) -> types.CallToolResult | types.CreateTaskResult:
|
||||
"""Dispatch tool calls to their handlers."""
|
||||
if name == "long_running_task":
|
||||
return await handle_long_running_task(arguments)
|
||||
else:
|
||||
return types.CallToolResult(
|
||||
content=[types.TextContent(type="text", text=f"Unknown tool: {name}")],
|
||||
is_error=True,
|
||||
)
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option("--port", default=8000, help="Port to listen on")
|
||||
def main(port: int) -> int:
|
||||
|
|
|
|||
Loading…
Reference in a new issue