mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-30 19:06:21 +02:00
Feature/react call mcp (#428)
Key Features - MCP Tool Integration: Added core MCP tool support with ToolClientSpec and ToolClient classes - API Enhancement: New mcp_tool method for flow-specific tool invocation - CLI Tooling: New tg-invoke-mcp-tool command for testing MCP integration - React Agent Enhancement: Fixed and improved multi-tool invocation capabilities - Tool Management: Enhanced CLI for tool configuration and management Changes - Added MCP tool invocation to API with flow-specific integration - Implemented ToolClientSpec and ToolClient for tool call handling - Updated agent-manager-react to invoke MCP tools with configurable types - Enhanced CLI with new commands and improved help text - Added comprehensive documentation for new CLI commands - Improved tool configuration management Testing - Added tg-invoke-mcp-tool CLI command for isolated MCP integration testing - Enhanced agent capability to invoke multiple tools simultaneously
This commit is contained in:
parent
e56186054a
commit
9c7a070681
22 changed files with 2718 additions and 9 deletions
|
|
@ -14,12 +14,19 @@ class AgentManager:
|
|||
|
||||
async def reason(self, question, history, context):
|
||||
|
||||
print(f"calling reason: {question}", flush=True)
|
||||
|
||||
tools = self.tools
|
||||
|
||||
print(f"in reason", flush=True)
|
||||
print(tools, flush=True)
|
||||
|
||||
tool_names = ",".join([
|
||||
t for t in self.tools.keys()
|
||||
])
|
||||
|
||||
print("Tool names:", tool_names, flush=True)
|
||||
|
||||
variables = {
|
||||
"question": question,
|
||||
"tools": [
|
||||
|
|
@ -83,6 +90,9 @@ class AgentManager:
|
|||
|
||||
async def react(self, question, history, think, observe, context):
|
||||
|
||||
logger.info(f"question: {question}")
|
||||
print(f"question: {question}", flush=True)
|
||||
|
||||
act = await self.reason(
|
||||
question = question,
|
||||
history = history,
|
||||
|
|
@ -104,13 +114,12 @@ class AgentManager:
|
|||
else:
|
||||
raise RuntimeError(f"No action for {act.name}!")
|
||||
|
||||
print("TOOL>>>", act)
|
||||
print("TOOL>>>", act, flush=True)
|
||||
|
||||
resp = await action.implementation(context).invoke(
|
||||
**act.arguments
|
||||
)
|
||||
|
||||
print("RSETUL", resp)
|
||||
|
||||
resp = resp.strip()
|
||||
|
||||
logger.info(f"resp: {resp}")
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@ Simple agent infrastructure broadly implements the ReAct flow.
|
|||
import json
|
||||
import re
|
||||
import sys
|
||||
import functools
|
||||
|
||||
from ... base import AgentService, TextCompletionClientSpec, PromptClientSpec
|
||||
from ... base import GraphRagClientSpec
|
||||
from ... base import GraphRagClientSpec, ToolClientSpec
|
||||
|
||||
from ... schema import AgentRequest, AgentResponse, AgentStep, Error
|
||||
|
||||
from . tools import KnowledgeQueryImpl, TextCompletionImpl
|
||||
from . tools import KnowledgeQueryImpl, TextCompletionImpl, McpToolImpl
|
||||
from . agent_manager import AgentManager
|
||||
|
||||
from . types import Final, Action, Tool, Argument
|
||||
|
|
@ -67,6 +68,13 @@ class Processor(AgentService):
|
|||
)
|
||||
)
|
||||
|
||||
self.register_specification(
|
||||
ToolClientSpec(
|
||||
request_name = "mcp-tool-request",
|
||||
response_name = "mcp-tool-response",
|
||||
)
|
||||
)
|
||||
|
||||
async def on_tools_config(self, config, version):
|
||||
|
||||
print("Loading configuration version", version)
|
||||
|
|
@ -102,17 +110,21 @@ class Processor(AgentService):
|
|||
|
||||
impl_id = data.get("type")
|
||||
|
||||
name = data.get("name")
|
||||
|
||||
if impl_id == "knowledge-query":
|
||||
impl = KnowledgeQueryImpl
|
||||
elif impl_id == "text-completion":
|
||||
impl = TextCompletionImpl
|
||||
elif impl_id == "mcp-tool":
|
||||
impl = functools.partial(McpToolImpl, name=k)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
f"Tool-kind {impl_id} not known"
|
||||
)
|
||||
|
||||
tools[data.get("name")] = Tool(
|
||||
name = data.get("name"),
|
||||
name = name,
|
||||
description = data.get("description"),
|
||||
implementation = impl,
|
||||
config=data.get("config", {}),
|
||||
|
|
@ -181,6 +193,8 @@ class Processor(AgentService):
|
|||
|
||||
await respond(r)
|
||||
|
||||
print("Call React", flush=True)
|
||||
|
||||
act = await self.agent.react(
|
||||
question = request.question,
|
||||
history = history,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
import json
|
||||
|
||||
# This tool implementation knows how to put a question to the graph RAG
|
||||
# service
|
||||
class KnowledgeQueryImpl:
|
||||
|
|
@ -23,3 +25,29 @@ class TextCompletionImpl:
|
|||
arguments.get("question")
|
||||
)
|
||||
|
||||
# This tool implementation knows how to do MCP tool invocation. This uses
|
||||
# the mcp-tool service.
|
||||
class McpToolImpl:
|
||||
|
||||
def __init__(self, context, name):
|
||||
self.context = context
|
||||
self.name = name
|
||||
|
||||
async def invoke(self, **arguments):
|
||||
|
||||
client = self.context("mcp-tool-request")
|
||||
|
||||
print(f"MCP tool invocation: {self.name}...", flush=True)
|
||||
output = await client.invoke(
|
||||
name = self.name,
|
||||
parameters = {},
|
||||
)
|
||||
|
||||
print(output)
|
||||
|
||||
if isinstance(output, str):
|
||||
return output
|
||||
else:
|
||||
return json.dumps(output)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue