forked from themanojdesai/python-a2a
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.py
More file actions
137 lines (115 loc) · 5.07 KB
/
Copy pathproxy.py
File metadata and controls
137 lines (115 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"""
Proxy functionality for FastMCP.
This module provides functions to create a FastMCP server that acts as a proxy
to another MCP server.
"""
import asyncio
import logging
from typing import Any, Dict, List, Optional, Union
from .client import MCPClient
from .fastmcp import FastMCP, MCPResponse, text_response, error_response
# Configure logging
logger = logging.getLogger("python_a2a.mcp.proxy")
async def create_proxy_server(
mcp_client: MCPClient,
name: Optional[str] = None
) -> FastMCP:
"""
Create a FastMCP server that acts as a proxy to another MCP server.
Args:
mcp_client: MCP client to proxy to
name: Optional server name
Returns:
FastMCP server instance
"""
# Get server metadata
try:
# Try to get metadata from the server
metadata = await mcp_client.get_metadata()
server_name = metadata.get("name", "MCP Proxy")
server_version = metadata.get("version", "1.0.0")
server_description = metadata.get("description", "MCP Proxy Server")
except Exception as e:
logger.warning(f"Failed to get metadata from MCP server: {e}")
server_name = "MCP Proxy"
server_version = "1.0.0"
server_description = "MCP Proxy Server"
# Use provided name if available
if name:
server_name = name
# Create the server
server = FastMCP(
name=server_name,
version=server_version,
description=server_description
)
# Get available tools
try:
tools = await mcp_client.get_tools()
logger.info(f"Found {len(tools)} tools on target MCP server")
# Register each tool as a proxy
for tool_info in tools:
tool_name = tool_info["name"]
tool_description = tool_info.get("description", "")
tool_parameters = tool_info.get("parameters", {})
# Create a proxy function for this tool
@server.tool(name=tool_name, description=tool_description)
async def proxy_tool(**params):
try:
return await mcp_client.call_tool(tool_name, **params)
except Exception as e:
logger.error(f"Error proxying tool {tool_name}: {e}")
return error_response(f"Error proxying tool {tool_name}: {str(e)}")
except Exception as e:
logger.warning(f"Failed to get tools from MCP server: {e}")
# Get available resources
try:
resources = await mcp_client.get_resources()
logger.info(f"Found {len(resources)} resources on target MCP server")
# Register each resource as a proxy
for resource_info in resources:
if "uri" in resource_info:
# Static resource
resource_uri = resource_info["uri"]
resource_name = resource_info.get("name", "")
resource_description = resource_info.get("description", "")
@server.resource(uri=resource_uri, name=resource_name, description=resource_description)
async def proxy_resource():
try:
return await mcp_client.get_resource(resource_uri)
except Exception as e:
logger.error(f"Error proxying resource {resource_uri}: {e}")
return error_response(f"Error proxying resource {resource_uri}: {str(e)}")
elif "uriTemplate" in resource_info:
# Template resource
template_uri = resource_info["uriTemplate"]
template_name = resource_info.get("name", "")
template_description = resource_info.get("description", "")
@server.resource(uri=template_uri, name=template_name, description=template_description)
async def proxy_template_resource(**params):
try:
# Construct the actual URI by substituting parameters
actual_uri = template_uri
for param_name, param_value in params.items():
actual_uri = actual_uri.replace(f"{{{param_name}}}", str(param_value))
return await mcp_client.get_resource(actual_uri)
except Exception as e:
logger.error(f"Error proxying template resource {template_uri}: {e}")
return error_response(f"Error proxying template resource {template_uri}: {str(e)}")
except Exception as e:
logger.warning(f"Failed to get resources from MCP server: {e}")
return server
async def create_proxy_server_sync(
mcp_client: MCPClient,
name: Optional[str] = None
) -> FastMCP:
"""
Synchronous wrapper for create_proxy_server.
Args:
mcp_client: MCP client to proxy to
name: Optional server name
Returns:
FastMCP server instance
"""
loop = asyncio.get_event_loop()
return await create_proxy_server(mcp_client, name)