squash some bugs
This commit is contained in:
@@ -1,17 +1,22 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from mcp import McpError
|
||||
from mcp.types import METHOD_NOT_FOUND
|
||||
|
||||
from wf_authoring import NodeSpec
|
||||
|
||||
from ..capabilities import DiscoveredPrompt, DiscoveredResource, DiscoveredTool
|
||||
from ..models import AuthRecord, ConnectionConfig
|
||||
from ..sdk import BackendAdapter
|
||||
from ..shared import root_exception
|
||||
from ..workflow import wrap_discovered_tool
|
||||
from .events import McpEvent
|
||||
|
||||
_CapabilityT = TypeVar("_CapabilityT")
|
||||
|
||||
@dataclass(slots=True)
|
||||
class DiscoveredConnectionCapabilities:
|
||||
@@ -28,8 +33,12 @@ async def discover_connection_capabilities(
|
||||
adapter: BackendAdapter,
|
||||
) -> DiscoveredConnectionCapabilities:
|
||||
tools = await adapter.list_tools(connection, auth)
|
||||
resources = await adapter.list_resources(connection, auth)
|
||||
prompts = await adapter.list_prompts(connection, auth)
|
||||
resources = await _list_optional_capabilities(
|
||||
lambda: adapter.list_resources(connection, auth)
|
||||
)
|
||||
prompts = await _list_optional_capabilities(
|
||||
lambda: adapter.list_prompts(connection, auth)
|
||||
)
|
||||
metadata = await adapter.get_connection_metadata(connection, auth)
|
||||
return DiscoveredConnectionCapabilities(
|
||||
tools=tools,
|
||||
@@ -39,6 +48,25 @@ async def discover_connection_capabilities(
|
||||
)
|
||||
|
||||
|
||||
async def _list_optional_capabilities(
|
||||
load: Callable[[], Awaitable[list[_CapabilityT]]],
|
||||
) -> list[_CapabilityT]:
|
||||
"""Treat unsupported optional MCP capability families as empty lists.
|
||||
|
||||
Some SDK transports raise ``METHOD_NOT_FOUND`` from inside an
|
||||
``ExceptionGroup`` because the request ran through a task group. Resources
|
||||
and prompts are optional families, so only that exact root error means "not
|
||||
supported"; every other failure still needs to surface.
|
||||
"""
|
||||
try:
|
||||
return await load()
|
||||
except Exception as exc:
|
||||
root = root_exception(exc)
|
||||
if isinstance(root, McpError) and root.error.code == METHOD_NOT_FOUND:
|
||||
return []
|
||||
raise
|
||||
|
||||
|
||||
def specs_from_discovered_tools(
|
||||
*,
|
||||
connection: ConnectionConfig,
|
||||
|
||||
@@ -644,18 +644,20 @@ class WfMcpService:
|
||||
self,
|
||||
connection: ConnectionConfig,
|
||||
) -> None:
|
||||
"""Restore planner-visible connection specs from a stored catalog snapshot."""
|
||||
"""Register one connection source, hydrating specs from snapshot if present."""
|
||||
if connection.id in self.capability_sources:
|
||||
return
|
||||
|
||||
snapshot = self.store.load_catalog(connection.id)
|
||||
if snapshot is None or not snapshot.nodes:
|
||||
return
|
||||
|
||||
specs = {
|
||||
entry.qualified_name: self._spec_from_snapshot_entry(entry)
|
||||
for entry in snapshot.nodes
|
||||
for entry in (() if snapshot is None else snapshot.nodes)
|
||||
}
|
||||
description = (
|
||||
f"Specs restored from catalog for {connection.id}."
|
||||
if specs
|
||||
else f"No catalog loaded for {connection.id}."
|
||||
)
|
||||
self.register_capability_source(
|
||||
CapabilitySource(
|
||||
id=connection.id,
|
||||
@@ -668,7 +670,7 @@ class WfMcpService:
|
||||
admin_dashboard=True,
|
||||
),
|
||||
permissions=SourcePermissions(calls_upstream=True),
|
||||
description=f"Specs restored from catalog for {connection.id}.",
|
||||
description=description,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user