Compare commits
No commits in common. "333bef1289787b4d9a0dbc080d0e478b8a3af0f1" and "dee850407d04ca77433c0312b86f5da9d8b21880" have entirely different histories.
333bef1289
...
dee850407d
@ -144,13 +144,16 @@ async def enhanced_generate_stream_response(
|
|||||||
elif isinstance(msg, ToolMessage) and msg.content:
|
elif isinstance(msg, ToolMessage) and msg.content:
|
||||||
message_tag = "TOOL_RESPONSE"
|
message_tag = "TOOL_RESPONSE"
|
||||||
waiting_for_answer_first_char = False
|
waiting_for_answer_first_char = False
|
||||||
# Always output UIResource responses even when tool_response is disabled
|
# Always output UIResource, ask_user and render_ui responses even when tool_response is disabled
|
||||||
is_ui_resource = (
|
is_ui_resource = (
|
||||||
msg.text
|
msg.text
|
||||||
and msg.text.lstrip().startswith('{"')
|
and msg.text.lstrip().startswith('{"')
|
||||||
and '"ui://' in msg.text
|
and '"ui://' in msg.text
|
||||||
|
and ('"text/html' in msg.text or '"text/uri-list' in msg.text)
|
||||||
)
|
)
|
||||||
if config.tool_response or is_ui_resource:
|
is_ask_user = msg.name == 'ask_user'
|
||||||
|
is_render_ui = msg.name == 'render_ui'
|
||||||
|
if config.tool_response or is_ui_resource or is_ask_user or is_render_ui:
|
||||||
new_content = f"[{message_tag}] {msg.name}\n{msg.text}\n"
|
new_content = f"[{message_tag}] {msg.name}\n{msg.text}\n"
|
||||||
|
|
||||||
# Collect full content
|
# Collect full content
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import json
|
|||||||
import sys
|
import sys
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from mcp_ui_server import create_ui_resource, UIMetadataKey
|
|
||||||
|
|
||||||
from mcp_common import (
|
from mcp_common import (
|
||||||
create_error_response,
|
create_error_response,
|
||||||
create_initialize_response,
|
create_initialize_response,
|
||||||
@ -20,65 +18,40 @@ from mcp_common import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _serialize_ui_resource(ui_resource) -> str:
|
ASK_USER_RESPONSE = "Questions sent to user."
|
||||||
"""Serialize a UIResource to JSON string."""
|
|
||||||
return json.dumps(ui_resource.model_dump(mode="json"), ensure_ascii=False)
|
|
||||||
|
|
||||||
|
|
||||||
def ask_user() -> Dict[str, Any]:
|
def ask_user() -> Dict[str, Any]:
|
||||||
"""Return a UIResource response for ask_user tool.
|
"""Return a minimal fixed response for ask_user tool.
|
||||||
|
|
||||||
The actual questions are in the TOOL_CALL arguments. The frontend
|
The actual questions/options are already in the TOOL_CALL arguments,
|
||||||
detects ui_type from the UIResource metadata and extracts content
|
so the frontend parses them directly from there. This response only
|
||||||
from the corresponding TOOL_CALL args.
|
serves to acknowledge the tool call and minimize token usage in the
|
||||||
|
subsequent LLM inference round.
|
||||||
"""
|
"""
|
||||||
resource = create_ui_resource({
|
return {
|
||||||
"uri": "ui://mcp-ui/ask-user",
|
"content": [
|
||||||
"content": {"type": "rawHtml", "htmlString": "Questions sent to user."},
|
{"type": "text", "text": ASK_USER_RESPONSE}
|
||||||
"encoding": "text",
|
]
|
||||||
"uiMetadata": {
|
}
|
||||||
"type": "ask_user",
|
|
||||||
"interactive": True,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return {"content": [{"type": "text", "text": _serialize_ui_resource(resource)}]}
|
|
||||||
|
|
||||||
|
|
||||||
def render_ui(arguments: Dict[str, Any]) -> Dict[str, Any]:
|
RENDER_UI_RESPONSE = "UI rendered."
|
||||||
"""Return a UIResource response for render_ui tool.
|
|
||||||
|
|
||||||
The actual html_content/url is in the TOOL_CALL arguments. The frontend
|
|
||||||
detects ui_type from the UIResource metadata and extracts content
|
def render_ui() -> Dict[str, Any]:
|
||||||
from the corresponding TOOL_CALL args.
|
"""Return a minimal fixed response for render_ui tool.
|
||||||
|
|
||||||
|
The actual html_content/url is already in the TOOL_CALL arguments,
|
||||||
|
so the frontend parses them directly from there. This response only
|
||||||
|
serves to acknowledge the tool call and minimize token usage in the
|
||||||
|
subsequent LLM inference round.
|
||||||
"""
|
"""
|
||||||
html_content = arguments.get("html_content", "")
|
return {
|
||||||
url = arguments.get("url", "")
|
"content": [
|
||||||
width = arguments.get("width", "100%")
|
{"type": "text", "text": RENDER_UI_RESPONSE}
|
||||||
height = arguments.get("height", "auto")
|
]
|
||||||
|
}
|
||||||
if html_content:
|
|
||||||
resource = create_ui_resource({
|
|
||||||
"uri": "ui://mcp-ui/render-ui",
|
|
||||||
"content": {"type": "rawHtml", "htmlString": "UI rendered."},
|
|
||||||
"encoding": "text",
|
|
||||||
"uiMetadata": {
|
|
||||||
UIMetadataKey.PREFERRED_FRAME_SIZE: [width, height],
|
|
||||||
"type": "render_ui_html",
|
|
||||||
"interactive": False,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
resource = create_ui_resource({
|
|
||||||
"uri": "ui://mcp-ui/render-ui",
|
|
||||||
"content": {"type": "externalUrl", "iframeUrl": url},
|
|
||||||
"encoding": "text",
|
|
||||||
"uiMetadata": {
|
|
||||||
UIMetadataKey.PREFERRED_FRAME_SIZE: [width, height],
|
|
||||||
"type": "render_ui_url",
|
|
||||||
"interactive": False,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return {"content": [{"type": "text", "text": _serialize_ui_resource(resource)}]}
|
|
||||||
|
|
||||||
|
|
||||||
async def handle_request(request: Dict[str, Any]) -> Dict[str, Any]:
|
async def handle_request(request: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
@ -136,7 +109,7 @@ async def handle_request(request: Dict[str, Any]) -> Dict[str, Any]:
|
|||||||
request_id, -32602, "Missing required parameter: html_content or url"
|
request_id, -32602, "Missing required parameter: html_content or url"
|
||||||
)
|
)
|
||||||
|
|
||||||
result = render_ui(arguments)
|
result = render_ui()
|
||||||
return {"jsonrpc": "2.0", "id": request_id, "result": result}
|
return {"jsonrpc": "2.0", "id": request_id, "result": result}
|
||||||
|
|
||||||
elif tool_name == "ask_user":
|
elif tool_name == "ask_user":
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user