trustgraph/trustgraph-cli/scripts/tg-set-tool
cybermaggedon 9c7a070681
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
2025-07-08 16:19:19 +01:00

195 lines
4.7 KiB
Python
Executable file

#!/usr/bin/env python3
"""
Configures and registers tools in the TrustGraph system.
Allows defining tool metadata including ID, name, description, type,
and argument specifications. Tools are stored in the agent configuration
and indexed for discovery and execution.
"""
from typing import List
import argparse
import os
from trustgraph.api import Api, ConfigKey, ConfigValue
import json
import tabulate
import textwrap
import dataclasses
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
@dataclasses.dataclass
class Argument:
name : str
type : str
description : str
@staticmethod
def parse(s):
parts = s.split(":")
if len(parts) != 3:
raise RuntimeError(
"Arguments should be form name:type:description"
)
valid_types = [
"string", "number",
]
if parts[1] not in valid_types:
raise RuntimeError(
f"Type {parts[1]} invalid, use: " +
", ".join(valid_types)
)
return Argument(name=parts[0], type=parts[1], description=parts[2])
def set_tool(
url : str,
id : str,
name : str,
description : str,
type : str,
arguments : List[Argument],
):
api = Api(url).config()
values = api.get([
ConfigKey(type="agent", key="tool-index")
])
ix = json.loads(values[0].value)
object = {
"id": id,
"name": name,
"description": description,
"type": type,
"arguments": [
{
"name": a.name,
"type": a.type,
"description": a.description,
}
for a in arguments
]
}
if id not in ix:
ix.append(id)
values = api.put([
ConfigValue(
type="agent", key="tool-index", value=json.dumps(ix)
),
ConfigValue(
type="agent", key=f"tool.{id}", value=json.dumps(object)
)
])
print("Tool set.")
def main():
parser = argparse.ArgumentParser(
prog='tg-set-tool',
description=__doc__,
epilog=textwrap.dedent('''
Valid tool types:
knowledge-query - Query knowledge bases
text-completion - Text completion/generation
mcp-tool - Model Control Protocol tool
Valid argument types:
string - String/text parameter
number - Numeric parameter
Examples:
%(prog)s --id weather --name "Weather lookup" \\
--type knowledge-query \\
--description "Get weather information" \\
--argument location:string:"Location to query" \\
--argument units:string:"Temperature units (C/F)"
%(prog)s --id calculator --name "Calculator" --type mcp-tool \\
--description "Perform calculations" \\
--argument expression:string:"Mathematical expression"
''').strip(),
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
'-u', '--api-url',
default=default_url,
help=f'API URL (default: {default_url})',
)
parser.add_argument(
'--id',
help=f'Tool ID',
)
parser.add_argument(
'--name',
help=f'Tool name',
)
parser.add_argument(
'--description',
help=f'Tool description',
)
parser.add_argument(
'--type',
help=f'Tool type, one of: knowledge-query, text-completion, mcp-tool',
)
parser.add_argument(
'--argument',
nargs="*",
help=f'Arguments, form: name:type:description',
)
args = parser.parse_args()
try:
valid_types = [
"knowledge-query", "text-completion", "mcp-tool"
]
if args.id is None:
raise RuntimeError("Must specify --id for prompt")
if args.name is None:
raise RuntimeError("Must specify --name for prompt")
if args.type:
if args.type not in valid_types:
raise RuntimeError(
"Type must be one of: " + ", ".join(valid_types)
)
if args.argument:
arguments = [
Argument.parse(a)
for a in args.argument
]
else:
arguments = []
set_tool(
url=args.api_url, id=args.id, name=args.name,
description=args.description,
type=args.type,
arguments=arguments
)
except Exception as e:
print("Exception:", e, flush=True)
main()