misc: display name + error handling

This commit is contained in:
lda
2026-04-30 00:44:20 +07:00 Verified
parent 449e61b0d5
commit 0afd61cf27
9 changed files with 70 additions and 6 deletions
+2 -2
View File
@@ -8,6 +8,7 @@ from typing import Any, Literal
from mcp.server.fastmcp import FastMCP
from .error_info import error_payload
from .mcp_sdk_adapter import McpSdkAdapter
from .models import BrokerConfig, ConnectionConfig
from .service import WfMcpService
@@ -63,8 +64,7 @@ def create_broker_server(service: WfMcpService) -> FastMCP:
return {
"connection_id": connection_id,
"refreshed": False,
"error_type": type(exc).__name__,
"error": str(exc),
**error_payload(exc),
}
snapshot = service.get_connection_snapshot(connection_id)
if snapshot is None:
+6
View File
@@ -7,6 +7,7 @@ from typing import Any
@dataclass(slots=True)
class DiscoveredTool:
name: str
display_name: str | None
description: str | None
input_schema: dict[str, Any]
output_schema: dict[str, Any]
@@ -18,6 +19,7 @@ class DiscoveredTool:
class DiscoveredResource:
uri: str
name: str
display_name: str | None
description: str | None
mime_type: str | None = None
metadata: dict[str, Any] = field(default_factory=dict)
@@ -26,6 +28,7 @@ class DiscoveredResource:
@dataclass(slots=True)
class DiscoveredPrompt:
name: str
display_name: str | None
description: str | None
arguments: list[dict[str, Any]] = field(default_factory=list)
metadata: dict[str, Any] = field(default_factory=dict)
@@ -36,6 +39,7 @@ class CatalogNodeEntry:
qualified_name: str
connection_id: str
local_name: str
display_name: str | None
description: str | None
outcomes: tuple[str, ...]
input_schema: dict[str, Any]
@@ -47,6 +51,7 @@ class CatalogResourceEntry:
qualified_name: str
connection_id: str
local_name: str
display_name: str | None
uri: str
description: str | None
mime_type: str | None = None
@@ -58,6 +63,7 @@ class CatalogPromptEntry:
qualified_name: str
connection_id: str
local_name: str
display_name: str | None
description: str | None
arguments: list[dict[str, Any]] = field(default_factory=list)
metadata: dict[str, Any] = field(default_factory=dict)
+10
View File
@@ -20,6 +20,7 @@ def snapshot_from_specs(
connection_id: str,
*,
specs: dict[str, NodeSpec[Any, Any]],
tool_display_names: dict[str, str | None] | None = None,
resources: list[DiscoveredResource] | None = None,
prompts: list[DiscoveredPrompt] | None = None,
metadata: dict[str, Any] | None = None,
@@ -34,6 +35,10 @@ def snapshot_from_specs(
else qualify_node_name(connection_id, entry.name),
connection_id=connection_id,
local_name=entry.name.removeprefix(f"{connection_id}."),
display_name=(tool_display_names or {}).get(
entry.name.removeprefix(f"{connection_id}."),
entry.display_name,
),
description=entry.description,
outcomes=entry.outcomes,
input_schema=entry.input_schema,
@@ -46,6 +51,7 @@ def snapshot_from_specs(
qualified_name=qualify_node_name(connection_id, resource.name),
connection_id=connection_id,
local_name=resource.name,
display_name=resource.display_name,
uri=resource.uri,
description=resource.description,
mime_type=resource.mime_type,
@@ -58,6 +64,7 @@ def snapshot_from_specs(
qualified_name=qualify_node_name(connection_id, prompt.name),
connection_id=connection_id,
local_name=prompt.name,
display_name=prompt.display_name,
description=prompt.description,
arguments=prompt.arguments,
metadata=prompt.metadata,
@@ -116,6 +123,7 @@ class CombinedCatalog:
"qualified_name": entry.qualified_name,
"connection_id": entry.connection_id,
"local_name": entry.local_name,
"display_name": entry.display_name,
"description": entry.description,
"outcomes": list(entry.outcomes),
"input_schema": entry.input_schema,
@@ -128,6 +136,7 @@ class CombinedCatalog:
"qualified_name": entry.qualified_name,
"connection_id": entry.connection_id,
"local_name": entry.local_name,
"display_name": entry.display_name,
"uri": entry.uri,
"description": entry.description,
"mime_type": entry.mime_type,
@@ -140,6 +149,7 @@ class CombinedCatalog:
"qualified_name": entry.qualified_name,
"connection_id": entry.connection_id,
"local_name": entry.local_name,
"display_name": entry.display_name,
"description": entry.description,
"arguments": entry.arguments,
"metadata": entry.metadata,
+21
View File
@@ -0,0 +1,21 @@
from __future__ import annotations
def root_exception(exc: BaseException) -> BaseException:
current: BaseException = exc
while isinstance(current, ExceptionGroup) and current.exceptions:
nested = current.exceptions[0]
if isinstance(nested, BaseException):
current = nested
continue
break
return current
def error_payload(exc: BaseException) -> dict[str, str]:
root = root_exception(exc)
return {
"error_type": type(root).__name__,
"error": str(root),
}
+8
View File
@@ -41,8 +41,14 @@ def _tool_to_discovered(tool: McpTool) -> DiscoveredTool:
"type": "object",
"properties": {"content": {"type": "array"}},
}
display_name = (
tool.annotations.title
if tool.annotations is not None and tool.annotations.title
else tool.title
)
return DiscoveredTool(
name=tool.name,
display_name=display_name,
description=tool.description,
input_schema=tool.inputSchema,
output_schema=output_schema,
@@ -56,6 +62,7 @@ def _resource_to_discovered(resource: McpResource) -> DiscoveredResource:
return DiscoveredResource(
uri=str(resource.uri),
name=local_name,
display_name=resource.title,
description=resource.description,
mime_type=resource.mimeType,
metadata=resource.model_dump(by_alias=True, mode="json"),
@@ -69,6 +76,7 @@ def _prompt_to_discovered(prompt: McpPrompt) -> DiscoveredPrompt:
]
return DiscoveredPrompt(
name=prompt.name,
display_name=prompt.title,
description=prompt.description,
arguments=arguments,
metadata=prompt.model_dump(by_alias=True, mode="json"),
+5 -4
View File
@@ -11,6 +11,7 @@ from .adapters import BackendAdapter
from .catalog import CombinedCatalog, snapshot_from_specs
from .connections import ConnectionRegistry, parse_connection_id, qualify_node_name
from .discovery import discover_connection_capabilities, specs_from_discovered_tools
from .error_info import error_payload
from .events import McpEvent, make_event
from .models import (
AuthRecord,
@@ -313,6 +314,9 @@ class WfMcpService:
snapshot = snapshot_from_specs(
connection_id,
specs=self.specs_by_connection.get(connection_id, {}),
tool_display_names={
tool.name: tool.display_name for tool in capabilities.tools
},
resources=capabilities.resources,
prompts=capabilities.prompts,
metadata=capabilities.metadata,
@@ -336,10 +340,7 @@ class WfMcpService:
make_event(
"catalog_refresh_failed",
connection_id=connection_id,
payload={
"error_type": type(exc).__name__,
"error": str(exc),
},
payload=error_payload(exc),
)
)
raise