The Tool Management Service is the central tool catalog for AI agents. It ingests Swagger/OpenAPI specs from App Connect and other sources, parses them into structured tool definitions, manages agent-tool assignments (Atlas, Herald), maintains the MCP server registry, and seeds built-in local tools.
Overview
| Property |
Value |
| Service |
tool-management-service |
| Image |
intento/tool-management-service |
| Namespace |
nexivo |
| Replicas |
2 |
| Port |
8009 |
| Root path |
/tools |
| Language |
Python 3.13 |
| Framework |
FastAPI |
Tech Stack
| Component |
Library |
| Framework |
FastAPI |
| Language |
Python 3.13 |
| ORM / migrations |
SQLAlchemy + Alembic |
| Database |
PostgreSQL |
| HTTP client |
httpx (async) |
| LLM (optional) |
OpenAI AsyncOpenAI — GPT-4o-mini |
| Credential encryption |
Fernet |
| Logging |
Loguru |
Swagger Sync Flow
flowchart TD
AC([App Connect\nOn spec create / update]) -->|POST /tools/sync-swagger| TM[Tool Management Service]
TM --> H[Compute SHA-256\ncontent hash]
H --> CH{Hash changed?}
CH -->|No change| SKIP([Skip — no DB update])
CH -->|Changed| ASSIGN{Endpoints assigned\nto agents?}
ASSIGN -->|Yes| CONF([409 Conflict])
ASSIGN -->|No| PARSE[Parse OpenAPI spec\nResolve $ref · detect circular refs]
PARSE --> UPSERT[Upsert apis + endpoints\n+ parameters tables]
UPSERT --> AGENT[Agent queries\nGET /tools/agents/agent_id/tools]
AGENT --> ATLAS([Atlas — builds MCP tool list])
AGENT --> HERALD([Herald — builds tool list])
Database Schema
apis
| Column |
Type |
Description |
id |
UUID PK |
|
tenant_id |
String |
|
app_id |
String |
|
name |
String |
Human-readable API name |
base_url |
String |
|
swagger_url |
String |
|
headers |
JSONB |
Auth headers stored encrypted |
content_hash |
String |
SHA-256 of last synced spec |
endpoints
| Column |
Type |
Description |
id |
UUID PK |
|
api_id |
UUID FK → apis |
|
name |
String |
Tool name (from operationId or path+method) |
method |
String |
HTTP method |
path |
String |
|
description |
String |
|
expose_as |
JSONB |
|
enabled |
Boolean |
|
parameters
| Column |
Type |
Description |
endpoint_id |
UUID FK → endpoints |
|
name |
String |
|
type |
String |
|
required |
Boolean |
|
in_path |
Boolean |
|
in_query |
Boolean |
|
in_body |
Boolean |
|
default_value |
String |
|
| Column |
Description |
tenant_id |
|
app_id |
|
agent_id |
|
endpoint_id |
FK → endpoints |
enabled |
|
| UNIQUE |
(agent_id, endpoint_id) per tenant |
mcp_servers
| Column |
Description |
id |
UUID PK |
app_id |
|
server_url |
|
access_token |
Encrypted |
refresh_token |
Encrypted |
client_id |
|
client_secret |
Encrypted |
token_url |
|
scope |
|
timeout |
|
tenant_id |
|
is_active |
|
| Column |
Description |
tenant_id |
|
app_id |
|
agent_id |
|
tools |
JSONB — assigned MCP tool names |
| UNIQUE |
(agent_id) per tenant |
| Column |
Description |
id |
UUID PK |
name |
Programmatic name |
display_name |
|
description |
|
category |
|
agent_types |
TEXT[] — voice / text / background |
input_schema |
JSONB |
is_active |
|
REST API
All endpoints are served under the /tools root path.
Health & Status
| Method |
Path |
Description |
GET |
/health |
Health check |
GET |
/agents/local-tools |
List built-in tools; filter by agent_type (voice / text / background) |
GET |
/agents/{agent_id}/tool-count |
Assigned tool count for a single agent |
GET |
/agents/tool-count |
Tool count for all agents (header: x-tenantId) |
Preview & Validate
| Method |
Path |
Description |
POST |
/preview-swagger |
Preview endpoints from URL without saving — returns valid, tools_preview[], warnings, compatibility_score (0–100) |
Add / Sync
| Method |
Path |
Description |
POST |
/sync-swagger |
Add or sync API from URL or JSON body (headers: x-tenantId, x-appId); returns endpoints_added, endpoints_updated, content_hash |
POST |
/sync-swagger/file |
Upload Swagger JSON or YAML file |
Browse Inventory
| Method |
Path |
Description |
GET |
/apis |
List APIs (headers: x-tenantId, x-appId) |
GET |
/api/details |
API detail (header: x-apiId) |
GET |
/api/endpoints |
Endpoints for an API, optionally filtered by agent |
Endpoint Operations
| Method |
Path |
Description |
POST |
/api/endpoints/{id}/test |
Execute endpoint with provided parameters |
GET |
/api/endpoints/{id} |
Endpoint details including parameters |
PATCH |
/api/endpoints/{id} |
Update endpoint name or description |
POST |
/api/endpoints/{id}/describe |
LLM-enhanced description via GPT-4o-mini |
Agent Assignment
| Method |
Path |
Description |
POST |
/agents/{agent_id}/tools |
Assign endpoint IDs to agent |
POST |
/agents/{agent_id}/mcp-tools |
Assign MCP tool names to agent |
GET |
/agents/{agent_id}/tools |
Retrieve assigned tools for agent |
MCP Servers
| Method |
Path |
Description |
POST |
/mcp-servers |
Register a new MCP server |
GET |
/mcp-servers |
List MCP servers |
PATCH |
/mcp-servers/{id}/tokens |
Update OAuth tokens |
DELETE |
/mcp-servers/{id} |
Remove MCP server |
Swagger Sync Logic
- Content hash deduplication — SHA-256 of the raw spec body. If the hash is unchanged, the database update is skipped entirely.
- Assignment guard — if any endpoints from the API are currently assigned to agents, the sync returns
409 Conflict to prevent breaking live agent configurations.
$ref resolution — OpenAPI 3.0 $ref pointers are resolved recursively with circular-reference detection.
- Tool naming — tool name is derived from
operationId when present, otherwise from a cleaned {method}_{path} slug.
- Trigger — App Connect calls
POST /tools/sync-swagger automatically on every spec create or update.
11 tools are seeded at startup and are always available regardless of API sync state.
| Tool Name |
Display Name |
Category |
Agent Types |
search_knowledge |
Search Knowledge |
knowledge |
voice, text, background |
send_email |
Send Email |
communication |
voice, text, background |
transfer_to_human_agent |
Transfer to Human Agent |
call_control |
voice, text |
end_call |
End Call |
call_control |
voice |
switch_language |
Switch Language |
language |
voice, text |
set_stt_mode |
Set STT Mode |
language |
voice |
report_user_language |
Report User Language |
language |
voice, text |
report_clarification_failure |
Report Clarification Failure |
operations |
voice, text |
refund_processor |
Refund Processor |
operations |
background |
request_human_approval |
Request Human Approval |
governance |
voice, text, background |
lookup_kb |
Lookup KB |
knowledge |
voice, text, background |
Configuration
| Variable |
Default |
Required |
Description |
DATABASE_URL |
postgresql://postgres:postgres@localhost:5437/mcp_central |
Yes |
PostgreSQL connection string |
OPENAI_API_KEY |
— |
No |
Enables LLM description enhancement (GPT-4o-mini) |
CREDENTIAL_SECRET |
— |
Yes |
Fernet key for encrypting stored credentials |
DEFAULT_TENANT |
— |
No |
Fallback tenant ID |
LOG_LEVEL |
INFO |
No |
Loguru log level |
LLM description enhancement is optional
POST /api/endpoints/{id}/describe requires OPENAI_API_KEY. If the key is absent, the endpoint returns an error for that specific operation; the rest of the service operates normally.