Spaces:
Sleeping
Sleeping
Use session lifespan context instead of global state
Browse files
app.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
|
|
|
|
|
| 1 |
from dataclasses import dataclass, field
|
| 2 |
from typing import Any, Union
|
| 3 |
|
| 4 |
-
from mcp.server.fastmcp import FastMCP
|
|
|
|
| 5 |
|
| 6 |
|
| 7 |
Observation = Union[str, dict[str, Any]]
|
|
@@ -60,14 +63,28 @@ class WordleEnv:
|
|
| 60 |
return self._obs
|
| 61 |
|
| 62 |
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
|
| 66 |
# Stateful server (maintains session state)
|
| 67 |
-
mcp = FastMCP("StatefulServer")
|
|
|
|
| 68 |
|
| 69 |
@mcp.tool()
|
| 70 |
-
def step_fn(guess: str) -> tuple[str, float, bool, dict]:
|
| 71 |
"""
|
| 72 |
Perform a step in the Wordle environment.
|
| 73 |
|
|
@@ -81,6 +98,7 @@ def step_fn(guess: str) -> tuple[str, float, bool, dict]:
|
|
| 81 |
- done: Whether the game is done.
|
| 82 |
- info: Additional info.
|
| 83 |
"""
|
|
|
|
| 84 |
result = wordle.step(guess)
|
| 85 |
return result.observation, result.reward, result.done, result.info
|
| 86 |
|
|
|
|
| 1 |
+
from collections.abc import AsyncIterator
|
| 2 |
+
from contextlib import asynccontextmanager
|
| 3 |
from dataclasses import dataclass, field
|
| 4 |
from typing import Any, Union
|
| 5 |
|
| 6 |
+
from mcp.server.fastmcp import Context, FastMCP
|
| 7 |
+
from mcp.server.session import ServerSession
|
| 8 |
|
| 9 |
|
| 10 |
Observation = Union[str, dict[str, Any]]
|
|
|
|
| 63 |
return self._obs
|
| 64 |
|
| 65 |
|
| 66 |
+
@dataclass
|
| 67 |
+
class SessionContext:
|
| 68 |
+
"""Session context with typed dependencies."""
|
| 69 |
+
|
| 70 |
+
wordle: WordleEnv
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
@asynccontextmanager
|
| 74 |
+
async def session_lifespan(server: FastMCP) -> AsyncIterator[SessionContext]:
|
| 75 |
+
"""Manage session lifecycle with type-safe context."""
|
| 76 |
+
# Initialize on session initialization
|
| 77 |
+
wordle = WordleEnv(secret="word")
|
| 78 |
+
# try-finally if you need cleanup on session termination
|
| 79 |
+
yield SessionContext(wordle=wordle)
|
| 80 |
|
| 81 |
|
| 82 |
# Stateful server (maintains session state)
|
| 83 |
+
mcp = FastMCP("StatefulServer", lifespan=session_lifespan)
|
| 84 |
+
|
| 85 |
|
| 86 |
@mcp.tool()
|
| 87 |
+
def step_fn(guess: str, ctx: Context[ServerSession, SessionContext]) -> tuple[str, float, bool, dict]:
|
| 88 |
"""
|
| 89 |
Perform a step in the Wordle environment.
|
| 90 |
|
|
|
|
| 98 |
- done: Whether the game is done.
|
| 99 |
- info: Additional info.
|
| 100 |
"""
|
| 101 |
+
wordle = ctx.request_context.lifespan_context.wordle
|
| 102 |
result = wordle.step(guess)
|
| 103 |
return result.observation, result.reward, result.done, result.info
|
| 104 |
|