Skip to content

Commit 47ac425

Browse files
committed
basic poc
1 parent ce1cfdf commit 47ac425

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from abc import ABC, abstractmethod
2+
from typing import Dict
3+
import httpx
4+
5+
class ITransport(ABC):
6+
@abstractmethod
7+
async def tools_list(self) -> Dict:
8+
pass
9+
10+
@abstractmethod
11+
async def tool_invoke(self, tool_name: str, arguments: Dict) -> Dict:
12+
pass
13+
14+
@abstractmethod
15+
async def close(self):
16+
pass
17+
18+
class McpHttpTransport(ITransport):
19+
def __init__(self, base_url: str):
20+
self._base_url = base_url.rstrip('/')
21+
self._client = httpx.AsyncClient()
22+
self._request_id = 0
23+
24+
def _build_json_rpc_payload(self, method: str, params: Dict) -> Dict:
25+
self._request_id += 1
26+
return {"jsonrpc": "2.0", "method": method, "params": params, "id": self._request_id}
27+
28+
async def tools_list(self) -> Dict:
29+
payload = self._build_json_rpc_payload("tools/list", {})
30+
response = await self._client.post(f"{self._base_url}/mcp", json=payload)
31+
response.raise_for_status()
32+
return response.json()
33+
34+
async def tool_invoke(self, tool_name: str, arguments: Dict) -> Dict:
35+
params = {"name": tool_name, "arguments": arguments}
36+
payload = self._build_json_rpc_payload("tools/call", params)
37+
response = await self._client.post(f"{self._base_url}/mcp", json=payload)
38+
response.raise_for_status()
39+
return response.json()
40+
41+
async def close(self):
42+
await self._client.aclose()
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import asyncio
2+
import json
3+
from mcp_transport import McpHttpTransport
4+
5+
class MCPClient:
6+
"""A simple client to interact with an MCP server."""
7+
def __init__(self, base_url: str):
8+
self._transport = McpHttpTransport(base_url=base_url)
9+
10+
async def list_all_tools(self):
11+
print("--> Attempting to list tools...")
12+
response = await self._transport.tools_list()
13+
return response.get("result", {}).get("tools", [])
14+
15+
async def invoke_a_tool(self, tool_name: str, args: dict):
16+
print(f"\n--> Attempting to invoke tool: '{tool_name}'...")
17+
response = await self._transport.tool_invoke(tool_name, args)
18+
return response.get("result", {})
19+
20+
async def close(self):
21+
await self._transport.close()
22+
23+
24+
async def main():
25+
server_url = "http://127.0.0.1:5000"
26+
client = MCPClient(base_url=server_url)
27+
28+
try:
29+
# 1. List all available tools
30+
tools = await client.list_all_tools()
31+
print("\n✅ Tools listed successfully:")
32+
print(json.dumps(tools, indent=2))
33+
34+
# 2. Invoke a specific tool
35+
tool_to_invoke = "get-n-rows"
36+
arguments = {"num_rows": "2"}
37+
invocation_result = await client.invoke_a_tool(tool_to_invoke, arguments)
38+
39+
print("\n✅ Tool invoked successfully:")
40+
print(json.dumps(invocation_result, indent=2))
41+
42+
except Exception as e:
43+
print(f"\n❌ An error occurred: {e}")
44+
finally:
45+
await client.close()
46+
47+
48+
if __name__ == "__main__":
49+
asyncio.run(main())

0 commit comments

Comments
 (0)