Revert "Remove token parameters from MCP tools"

This reverts commit e585100625.
This commit is contained in:
tim
2025-10-28 01:55:41 +08:00
parent 03eb027ea4
commit 541ad4d149

View File

@@ -57,9 +57,7 @@ class SessionTokenManager:
def __init__(self) -> None: def __init__(self) -> None:
self._tokens: WeakKeyDictionary[Any, str] = WeakKeyDictionary() self._tokens: WeakKeyDictionary[Any, str] = WeakKeyDictionary()
def resolve( def resolve(self, ctx: Context | None, token: str | None) -> str | None:
self, ctx: Context | None, token: str | None = None
) -> str | None:
"""Resolve and optionally persist the token for the current session.""" """Resolve and optionally persist the token for the current session."""
session = self._get_session(ctx) session = self._get_session(ctx)
@@ -129,8 +127,8 @@ async def lifespan(_: FastMCP):
app = FastMCP( app = FastMCP(
name="openisle-mcp", name="openisle-mcp",
instructions=( instructions=(
"Use this server to search OpenIsle content, reply to posts and comments with " "Use this server to search OpenIsle content, reply to posts and comments with an "
"session-managed authentication, retrieve details for a specific post, list posts created " "authentication token, retrieve details for a specific post, list posts created "
"within a recent time window, and review unread notification messages." "within a recent time window, and review unread notification messages."
), ),
host=settings.host, host=settings.host,
@@ -192,7 +190,7 @@ async def search(
@app.tool( @app.tool(
name="reply_to_post", name="reply_to_post",
description="Create a comment on a post using session authentication.", description="Create a comment on a post using an authentication token.",
structured_output=True, structured_output=True,
) )
async def reply_to_post( async def reply_to_post(
@@ -211,6 +209,15 @@ async def reply_to_post(
description="Optional captcha solution if the backend requires it.", description="Optional captcha solution if the backend requires it.",
), ),
] = None, ] = None,
token: Annotated[
str | None,
PydanticField(
default=None,
description=(
"Optional JWT bearer token. When omitted the configured access token is used."
),
),
] = None,
ctx: Context | None = None, ctx: Context | None = None,
) -> CommentCreateResult: ) -> CommentCreateResult:
"""Create a comment on a post and return the backend payload.""" """Create a comment on a post and return the backend payload."""
@@ -221,7 +228,7 @@ async def reply_to_post(
sanitized_captcha = captcha.strip() if isinstance(captcha, str) else None sanitized_captcha = captcha.strip() if isinstance(captcha, str) else None
resolved_token = session_token_manager.resolve(ctx) resolved_token = session_token_manager.resolve(ctx, token)
try: try:
logger.info( logger.info(
@@ -290,7 +297,7 @@ async def reply_to_post(
@app.tool( @app.tool(
name="reply_to_comment", name="reply_to_comment",
description="Reply to an existing comment using session authentication.", description="Reply to an existing comment using an authentication token.",
structured_output=True, structured_output=True,
) )
async def reply_to_comment( async def reply_to_comment(
@@ -309,6 +316,15 @@ async def reply_to_comment(
description="Optional captcha solution if the backend requires it.", description="Optional captcha solution if the backend requires it.",
), ),
] = None, ] = None,
token: Annotated[
str | None,
PydanticField(
default=None,
description=(
"Optional JWT bearer token. When omitted the configured access token is used."
),
),
] = None,
ctx: Context | None = None, ctx: Context | None = None,
) -> CommentReplyResult: ) -> CommentReplyResult:
"""Create a reply for a comment and return the backend payload.""" """Create a reply for a comment and return the backend payload."""
@@ -319,7 +335,7 @@ async def reply_to_comment(
sanitized_captcha = captcha.strip() if isinstance(captcha, str) else None sanitized_captcha = captcha.strip() if isinstance(captcha, str) else None
resolved_token = session_token_manager.resolve(ctx) resolved_token = session_token_manager.resolve(ctx, token)
try: try:
logger.info( logger.info(
@@ -446,11 +462,18 @@ async def get_post(
int, int,
PydanticField(ge=1, description="Identifier of the post to retrieve."), PydanticField(ge=1, description="Identifier of the post to retrieve."),
], ],
token: Annotated[
str | None,
PydanticField(
default=None,
description="Optional JWT bearer token to view the post as an authenticated user.",
),
] = None,
ctx: Context | None = None, ctx: Context | None = None,
) -> PostDetail: ) -> PostDetail:
"""Fetch post details from the backend and validate the response.""" """Fetch post details from the backend and validate the response."""
resolved_token = session_token_manager.resolve(ctx) resolved_token = session_token_manager.resolve(ctx, token)
try: try:
logger.info("Fetching post details for post_id=%s", post_id) logger.info("Fetching post details for post_id=%s", post_id)
@@ -519,11 +542,20 @@ async def list_unread_messages(
description="Number of unread notifications to include per page.", description="Number of unread notifications to include per page.",
), ),
] = 30, ] = 30,
token: Annotated[
str | None,
PydanticField(
default=None,
description=(
"Optional JWT bearer token. When omitted the configured access token is used."
),
),
] = None,
ctx: Context | None = None, ctx: Context | None = None,
) -> UnreadNotificationsResponse: ) -> UnreadNotificationsResponse:
"""Retrieve unread notifications and return structured data.""" """Retrieve unread notifications and return structured data."""
resolved_token = session_token_manager.resolve(ctx) resolved_token = session_token_manager.resolve(ctx, token)
try: try:
logger.info( logger.info(