Skip to content

Commit fb956dc

Browse files
committed
fix: add resources to capabilities in fallback
1 parent 53fa98b commit fb956dc

2 files changed

Lines changed: 94 additions & 9 deletions

File tree

src/metorial/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Metorial SDK version."""
22

3-
__version__ = "2.0.0"
3+
__version__ = "2.0.1"

src/metorial/mcp/mcp_session.py

Lines changed: 93 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from metorial.exceptions import AuthenticationError, NotFoundError, OAuthRequiredError
1010

1111
from .mcp_client import MetorialMcpClient
12-
from .mcp_tool import Capability
12+
from .mcp_tool import Capability, ResourceTemplate, Tool
1313

1414
if TYPE_CHECKING:
1515
from .mcp_tool_manager import MetorialMcpToolManager
@@ -645,14 +645,60 @@ def _raise_critical_error(self, error: Exception) -> None:
645645
raise error
646646

647647
async def _get_tools_via_direct_mcp(self) -> list[Capability]:
648-
"""Get tools by connecting directly to MCP server, bypassing capabilities API."""
648+
"""Get capabilities via direct MCP when the capabilities API is unavailable."""
649649
_log_info("Starting direct MCP tool discovery...")
650650

651+
def _normalize_tool(raw_tool: object) -> Tool | None:
652+
if isinstance(raw_tool, dict):
653+
name_value = raw_tool.get("name")
654+
description_value = raw_tool.get("description")
655+
input_schema_value = raw_tool.get("inputSchema")
656+
else:
657+
name_value = getattr(raw_tool, "name", None)
658+
description_value = getattr(raw_tool, "description", None)
659+
input_schema_value = getattr(raw_tool, "inputSchema", None)
660+
661+
if not isinstance(name_value, str) or not name_value:
662+
return None
663+
664+
normalized_tool: Tool = {"name": name_value}
665+
if isinstance(description_value, str):
666+
normalized_tool["description"] = description_value
667+
if isinstance(input_schema_value, dict):
668+
normalized_tool["inputSchema"] = input_schema_value
669+
return normalized_tool
670+
671+
def _normalize_resource_template(
672+
raw_template: object,
673+
) -> ResourceTemplate | None:
674+
if isinstance(raw_template, dict):
675+
name_value = raw_template.get("name")
676+
description_value = raw_template.get("description")
677+
uri_template_value = raw_template.get("uriTemplate")
678+
else:
679+
name_value = getattr(raw_template, "name", None)
680+
description_value = getattr(raw_template, "description", None)
681+
uri_template_value = getattr(raw_template, "uriTemplate", None)
682+
683+
if not isinstance(name_value, str) or not name_value:
684+
return None
685+
if not isinstance(uri_template_value, str) or not uri_template_value:
686+
return None
687+
688+
normalized_template: ResourceTemplate = {
689+
"name": name_value,
690+
"uriTemplate": uri_template_value,
691+
}
692+
if isinstance(description_value, str):
693+
normalized_template["description"] = description_value
694+
return normalized_template
695+
651696
capabilities: list[Capability] = []
652697

653698
for deployment_id in self.server_deployment_ids:
654699
client = None
655-
tools = []
700+
tools: list[Tool] = []
701+
resource_templates: list[ResourceTemplate] = []
656702

657703
# Step 1: Get client
658704
try:
@@ -666,12 +712,19 @@ async def _get_tools_via_direct_mcp(self) -> list[Capability]:
666712
try:
667713
tools_response = await client.list_tools()
668714

715+
raw_tools: object
669716
if hasattr(tools_response, "tools"):
670-
tools = tools_response.tools
717+
raw_tools = tools_response.tools
671718
elif isinstance(tools_response, dict):
672-
tools = tools_response.get("tools", [])
719+
raw_tools = tools_response.get("tools", [])
673720
else:
674-
tools = []
721+
raw_tools = []
722+
723+
if isinstance(raw_tools, list):
724+
for raw_tool in raw_tools:
725+
normalized_tool = _normalize_tool(raw_tool)
726+
if normalized_tool is not None:
727+
tools.append(normalized_tool)
675728

676729
_log_info(f"Direct MCP found {len(tools)} tools for {deployment_id}")
677730

@@ -683,10 +736,27 @@ async def _get_tools_via_direct_mcp(self) -> list[Capability]:
683736
try:
684737
templates_response = await client.list_resource_templates()
685738

739+
raw_templates: object
686740
if hasattr(templates_response, "resourceTemplates"):
687-
pass # templates = templates_response.resourceTemplates (unused)
741+
raw_templates = templates_response.resourceTemplates or []
742+
elif hasattr(templates_response, "resource_templates"):
743+
raw_templates = templates_response.resource_templates or []
688744
elif isinstance(templates_response, dict):
689-
pass # templates = templates_response.get("resourceTemplates", []) (unused)
745+
raw_templates = templates_response.get(
746+
"resourceTemplates"
747+
) or templates_response.get("resource_templates", [])
748+
else:
749+
raw_templates = []
750+
751+
if isinstance(raw_templates, list):
752+
for raw_template in raw_templates:
753+
normalized_template = _normalize_resource_template(raw_template)
754+
if normalized_template is not None:
755+
resource_templates.append(normalized_template)
756+
757+
_log_info(
758+
f"Direct MCP found {len(resource_templates)} resource templates for {deployment_id}"
759+
)
690760
except Exception as e:
691761
logger.debug(
692762
f"Warning: Failed to get resource templates for {deployment_id}: {e}"
@@ -706,6 +776,21 @@ async def _get_tools_via_direct_mcp(self) -> list[Capability]:
706776
logger.warning(f"Warning: Failed to process tool {tool}: {e}")
707777
continue
708778

779+
# Step 5: Process resource templates into capabilities
780+
for template in resource_templates:
781+
try:
782+
template_capability: Capability = {
783+
"type": "resource-template",
784+
"resourceTemplate": template,
785+
"serverDeployment": {"id": deployment_id},
786+
}
787+
capabilities.append(template_capability)
788+
except Exception as e:
789+
logger.warning(
790+
f"Warning: Failed to process resource template {template}: {e}"
791+
)
792+
continue
793+
709794
_log_info(f"Direct MCP discovery completed: {len(capabilities)} total capabilities")
710795
return capabilities
711796

0 commit comments

Comments
 (0)