SimpleSallap:SimpleMCP:tools/list
Fix a oversight wrt ToolManager.meta, where I had created a dict of name-keyed toolcall metas, instead of a simple list of toolcall metas. Rather I blindly duplicated structure I used for storing the tool calls in the tc_switch in the anveshika sallap client side code. Add dataclasses to mimic the MCP tools/list response. However wrt the 2 odd differences between the MCP structure and OpenAi tools handshake structure, for now I have retained the OpenAi tools hs structure. Add a common helper send_mcp to ProxyHandler given that both mcp_toolscall and mcp_toolslist and even others like mcp_initialise in future require a common response mechanism. With above and bit more implement initial go at tools/list response.
This commit is contained in:
parent
69be7f2029
commit
fac947f9cd
|
|
@ -86,13 +86,21 @@ class ProxyHandler(http.server.BaseHTTPRequestHandler):
|
|||
return mTC.TCOutResponse(False, 400, "WARN:Invalid auth")
|
||||
return mTC.TCOutResponse(True, 200, "Auth Ok")
|
||||
|
||||
def send_mcp(self, statusCode: int, statusMessage: str, body: Any):
|
||||
self.send_response(statusCode, statusMessage)
|
||||
self.send_header('Content-Type', "application/json")
|
||||
# Add CORS for browser fetch, just in case
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps(body).encode('utf-8'))
|
||||
|
||||
def mcp_toolscall(self, oRPC: Any):
|
||||
"""
|
||||
If authorisation is ok for the request, run the specified handler.
|
||||
"""
|
||||
try:
|
||||
if not gMe.op.toolManager:
|
||||
raise RuntimeError("DBUG:PH:TCRun:ToolManager uninitialised")
|
||||
raise RuntimeError("DBUG:PH:MCPToolsCall:ToolManager uninitialised")
|
||||
resp = gMe.op.toolManager.tc_handle(oRPC["id"], oRPC["params"]["name"], oRPC["params"]["arguments"], self.headers)
|
||||
if not resp.response.callOk:
|
||||
self.send_error(resp.response.statusCode, resp.response.statusMsg)
|
||||
|
|
@ -104,24 +112,21 @@ class ProxyHandler(http.server.BaseHTTPRequestHandler):
|
|||
mTC.MCPTCRContentText(resp.response.contentData.decode('utf-8'))
|
||||
])
|
||||
)
|
||||
self.send_response(resp.response.statusCode, resp.response.statusMsg)
|
||||
self.send_header('Content-Type', "application/json")
|
||||
# Add CORS for browser fetch, just in case
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps(tcresp).encode('utf-8'))
|
||||
self.send_mcp(resp.response.statusCode, resp.response.statusMsg, tcresp)
|
||||
except Exception as e:
|
||||
self.send_error(400, f"ERRR:PH:{e}")
|
||||
|
||||
def mcp_toolslist(self):
|
||||
|
||||
pass
|
||||
def mcp_toolslist(self, oRPC: Any):
|
||||
if not gMe.op.toolManager:
|
||||
raise RuntimeError("DBUG:PH:MCPToolsList:ToolManager uninitialised")
|
||||
tcl = mTC.MCPToolsList(oRPC["id"], mTC.MCPTLResult(gMe.op.toolManager.meta()))
|
||||
self.send_mcp(200, "tools/list follows", tcl)
|
||||
|
||||
def mcp_run(self, oRPC: Any):
|
||||
if oRPC["method"] == "tools/call":
|
||||
self.mcp_toolscall(oRPC)
|
||||
elif oRPC["method"] == "tools/list":
|
||||
self.mcp_toolslist()
|
||||
self.mcp_toolslist(oRPC)
|
||||
else:
|
||||
self.send_error(400, f"ERRR:PH:MCP:Unknown")
|
||||
|
||||
|
|
|
|||
|
|
@ -54,10 +54,10 @@ class TCInParameters():
|
|||
class TCFunction():
|
||||
name: str
|
||||
description: str
|
||||
parameters: TCInParameters
|
||||
parameters: TCInParameters ### Delta wrt naming btw OpenAi Tools HS (parameters) and MCP(inputSchema)
|
||||
|
||||
@dataclass
|
||||
class ToolCallMeta():
|
||||
class ToolCallMeta(): ### Delta wrt tree btw OpenAi Tools HS (Needs this wrapper) and MCP (directly use TCFunction)
|
||||
type: str = "function"
|
||||
function: TCFunction|None = None
|
||||
|
||||
|
|
@ -112,6 +112,17 @@ class ToolCall():
|
|||
return ToolCallMeta("function", tcf)
|
||||
|
||||
|
||||
@dataclass
|
||||
class MCPTLResult:
|
||||
tools: list[ToolCallMeta]
|
||||
|
||||
@dataclass
|
||||
class MCPToolsList:
|
||||
id: str
|
||||
result: MCPTLResult
|
||||
jsonrpc: str = "2.0"
|
||||
|
||||
|
||||
class ToolManager():
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
|
@ -121,9 +132,10 @@ class ToolManager():
|
|||
self.toolcalls[fName] = tc
|
||||
|
||||
def meta(self):
|
||||
oMeta = {}
|
||||
lMeta: list[ToolCallMeta]= []
|
||||
for tcName in self.toolcalls.keys():
|
||||
oMeta[tcName] = self.toolcalls[tcName].meta()
|
||||
lMeta.append(self.toolcalls[tcName].meta())
|
||||
return lMeta
|
||||
|
||||
def tc_handle(self, callId: str, tcName: str, tcArgs: TCInArgs, inHeaders: HttpHeaders) -> ToolCallResponseEx:
|
||||
try:
|
||||
|
|
|
|||
Loading…
Reference in New Issue