Service Management Guide¶
This guide documents how to manage MCP servers, users, and access groups in the MCP Gateway Registry using the Registry Management API.
Table of Contents¶
- Overview
- What's New
- Prerequisites
- Quick Start
- Service Management
- Add Server
- Delete Server
- List Servers
- Enable/Disable Server
- Group Management
- Create Group
- Delete Group
- List Groups
- Add Server to Group
- Remove Server from Group
- User Management
- Create M2M User
- Create Human User
- Delete User
- List Users
- Complete Workflow Example
- Configuration Format
- Troubleshooting
Overview¶
The MCP Gateway Registry provides a comprehensive Registry Management API for programmatic access to all registry operations. This API replaces the previous shell script approach with a modern, type-safe Python interface.
Management Options:
- Registry Management API (
api/registry_management.py): Core API for server, group, and user management - Registry Client (
api/registry_client.py): High-level Python client with authentication handling - REST API Endpoints: Direct HTTP API access at
/api/management/*
These tools work together to provide: - Server Registration: Validates config and registers new servers - Access Control: Fine-grained permissions via groups - User Management: M2M service accounts and human users - Health Verification: Confirms servers are working and discoverable - FAISS Integration: Automatic indexing for intelligent tool discovery
What's New¶
Registry Management API (New in v1.0.7): - Modern Python API for all registry operations - Type-safe interfaces using Pydantic models - Automatic FAISS indexing on server registration - Integrated health checking and validation - RESTful HTTP endpoints for external integrations - Comprehensive error handling and logging
The new API provides the same functionality as the previous shell scripts but with better error handling, type safety, and integration capabilities.
Prerequisites¶
Before using the Registry Management API, ensure:
-
MCP Gateway is running: All containers should be up
-
Authentication is configured: You need OAuth2/JWT access
-
Python environment: Use
uvfor package management
Quick Start¶
Using the Registry Client (Python)¶
from api.registry_client import RegistryClient
# Initialize client
client = RegistryClient(
base_url="http://localhost"
)
# Add a server
client.add_server(
server_name="My MCP Server",
path="/my-server",
proxy_pass_url="http://my-server:8000",
description="My custom MCP server",
tags=["productivity", "automation"]
)
# List all servers
servers = client.list_servers()
for server in servers:
print(f"{server['name']}: {server['path']}")
# Delete a server
client.delete_server("my-server")
Using the REST API (HTTP)¶
# Get access token via OAuth2 client credentials flow
TOKEN=$(curl -X POST http://localhost/api/auth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'grant_type=client_credentials&client_id=your_client_id&client_secret=your_client_secret' | jq -r '.access_token')
# Add a server
curl -X POST http://localhost/api/management/servers \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"server_name": "My MCP Server",
"path": "/my-server",
"proxy_pass_url": "http://my-server:8000",
"description": "My custom MCP server",
"tags": ["productivity", "automation"]
}'
# List servers
curl -X GET http://localhost/api/management/servers \
-H "Authorization: Bearer $TOKEN"
# Delete a server
curl -X DELETE http://localhost/api/management/servers/my-server \
-H "Authorization: Bearer $TOKEN"
Service Management¶
Add Server¶
Using Python Client¶
from api.registry_client import RegistryClient
client = RegistryClient(
base_url="http://localhost"
)
# Add server with all options
response = client.add_server(
server_name="Advanced MCP Server",
path="/advanced-server",
proxy_pass_url="http://advanced-server:8001/",
description="A server with all optional fields",
tags=["productivity", "automation", "enterprise"],
num_tools=5,
num_stars=4,
is_python=True,
license="MIT",
metadata={
"team": "data-platform",
"owner": "alice@example.com",
"compliance_level": "PCI-DSS",
"cost_center": "engineering",
"deployment_region": "us-east-1"
}
)
print(f"Server added: {response['name']}")
Custom Metadata¶
Servers support optional custom metadata for organization, compliance, and integration tracking. All metadata is fully searchable via semantic search.
Example with Metadata:
# Add server with custom metadata
response = client.add_server(
server_name="Payment Processor",
path="/payment-processor",
proxy_pass_url="http://payment:8080/",
description="Payment processing service",
tags=["finance", "payments"],
metadata={
"team": "finance-platform",
"owner": "bob@example.com",
"compliance_level": "PCI-DSS",
"data_classification": "confidential",
"cost_center": "finance-ops",
"deployment_region": "us-east-1",
"environment": "production",
"jira_ticket": "FIN-789"
}
)
Search by Metadata:
# Servers with metadata are searchable via semantic search API
# Example queries:
# - "team:finance-platform servers"
# - "PCI-DSS compliant services"
# - "bob@example.com owned servers"
# - "us-east-1 deployed services"
Metadata Use Cases: - Organization: team, owner, department - Compliance: compliance_level, data_classification, audit_logging - Cost Tracking: cost_center, project_code, budget_allocation - Deployment: deployment_region, environment, version - Integration: jira_ticket, service_now_id, monitoring_url
What Happens During Registration¶
- Config validation (required fields, constraints)
- Server registration with the gateway
- Nginx configuration update
- FAISS index update (automatic)
- Health check verification
Delete Server¶
List Servers¶
# Get all servers
servers = client.list_servers()
for server in servers:
print(f"Name: {server['name']}")
print(f"Path: {server['path']}")
print(f"Status: {server['enabled']}")
print(f"Tags: {', '.join(server.get('tags', []))}")
print("---")
Enable/Disable Server¶
# Disable a server (removes from FAISS, keeps in registry)
client.disable_server("my-server")
# Enable a server (adds back to FAISS)
client.enable_server("my-server")
Group Management¶
Create Group¶
# Create a new access control group
client.create_group(
group_name="mcp-servers-finance/read",
description="Finance services with read access"
)
What this does: - Creates the group in Keycloak - Adds the group to scopes.yml - Reloads the auth server to apply changes immediately
List Groups¶
# Get all groups
groups = client.list_groups()
for group in groups:
print(f"Group: {group['name']}")
print(f"Synced: {group['synced']}")
Delete Group¶
Add Server to Group¶
# Add server to one or more groups
client.add_server_to_groups(
server_name="mcpgw",
groups=["mcp-servers-finance/read"]
)
# Add to multiple groups
client.add_server_to_groups(
server_name="fininfo",
groups=["mcp-servers-finance/read", "mcp-servers-finance/execute"]
)
Remove Server from Group¶
# Remove server from groups
client.remove_server_from_groups(
server_name="fininfo",
groups=["mcp-servers-finance/read"]
)
User Management¶
Create M2M User¶
# Create machine-to-machine service account
credentials = client.create_m2m_user(
name="finance-analyst-bot",
groups=["mcp-servers-finance/read", "mcp-servers-finance/execute"],
description="Finance analyst bot with full access"
)
print(f"Client ID: {credentials['client_id']}")
print(f"Client Secret: {credentials['client_secret']}")
What this does: - Creates a new Keycloak M2M client with service account - Assigns the service account to specified groups - Generates client credentials - Returns client_id and client_secret
Create Human User¶
# Create human user account
client.create_human_user(
username="jdoe",
email="jdoe@example.com",
firstname="John",
lastname="Doe",
password="secure_password",
groups=["mcp-servers-restricted/read"]
)
List Users¶
# Get all users
users = client.list_users()
for user in users:
print(f"Username: {user['username']}")
print(f"Email: {user.get('email', 'N/A')}")
print(f"Enabled: {user['enabled']}")
Delete User¶
Complete Workflow Example¶
This example demonstrates the complete workflow using the Registry Management API:
from api.registry_client import RegistryClient
# Initialize client
client = RegistryClient(
base_url="http://localhost"
)
# Step 1: Create a new access group
print("Creating group...")
client.create_group(
group_name="mcp-servers-time/read",
description="Time-related services with read access"
)
# Step 2: Add servers to the group
print("Adding servers to group...")
# Add mcpgw (provides intelligent_tool_finder)
client.add_server_to_groups(
server_name="mcpgw",
groups=["mcp-servers-time/read"]
)
# Add currenttime server
client.add_server_to_groups(
server_name="currenttime",
groups=["mcp-servers-time/read"]
)
# Step 3: Create M2M service account
print("Creating M2M user...")
credentials = client.create_m2m_user(
name="time-service-bot",
groups=["mcp-servers-time/read"],
description="Bot for accessing time-related services"
)
print(f"M2M Account Created:")
print(f" Client ID: {credentials['client_id']}")
print(f" Client Secret: {credentials['client_secret']}")
# Step 4: Create human user
print("Creating human user...")
client.create_human_user(
username="time-user",
email="time-user@example.com",
firstname="Time",
lastname="User",
password="secure_password",
groups=["mcp-servers-time/read"]
)
# Step 5: Verify setup
print("\nVerifying setup...")
print(f"Groups: {client.list_groups()}")
print(f"Servers: {[s['name'] for s in client.list_servers()]}")
print(f"Users: {[u['username'] for u in client.list_users()]}")
print("\nWorkflow complete!")
Configuration Format¶
Required Fields¶
{
"server_name": "Display name for the server",
"path": "/unique-url-path",
"proxy_pass_url": "http://server-host:port"
}
Complete Example¶
{
"server_name": "Advanced MCP Server",
"path": "/advanced-server",
"proxy_pass_url": "http://advanced-server:8001/",
"description": "A server with all optional fields",
"tags": ["productivity", "automation", "enterprise"],
"num_tools": 5,
"num_stars": 4,
"is_python": True,
"license": "MIT"
}
Field Constraints¶
Required Fields: - server_name: Non-empty string - path: Must start with / and be more than just / - proxy_pass_url: Must start with http:// or https://
Optional Fields: - description: String description - tags: Array of strings - num_tools: Non-negative integer - num_stars: Non-negative integer - is_python: Boolean - license: String
Troubleshooting¶
Common Issues¶
Authentication Errors¶
Solution: Verify your OAuth2 credentials or JWT token are valid and not expiredServer Already Exists¶
Solution: Delete the existing server first or use a different pathGroup Not Found¶
Solution: Create the group first usingcreate_group() Connection Refused¶
Solution: Ensure MCP Gateway is running (docker compose ps) Debug Tips¶
# Enable debug logging
import logging
logging.basicConfig(level=logging.DEBUG)
# Test connectivity
from api.registry_client import RegistryClient
client = RegistryClient(base_url="http://localhost")
# This will show detailed request/response logs
servers = client.list_servers()
API Documentation¶
For complete API reference, see: - Registry Management API: api/registry_management.py - Registry Client: api/registry_client.py - REST API endpoints: http://localhost/api/management/docs (OpenAPI/Swagger)
Best Practices¶
- Use the Python Client: The
RegistryClienthandles authentication and error handling automatically - Version Control Configurations: Store server configurations in JSON files
- Test After Adding: Verify servers are accessible after registration
- Use Descriptive Names: Make server names and groups clear and searchable
- Always Include mcpgw: Add
mcpgwto custom groups forintelligent_tool_finderfunctionality - Handle Errors: Wrap API calls in try/except blocks for production use
Integration with CI/CD¶
#!/usr/bin/env python3
from api.registry_client import RegistryClient
import sys
def deploy_server(config_file):
"""Deploy server from configuration file"""
client = RegistryClient(
base_url="http://localhost"
)
try:
# Load configuration
with open(config_file) as f:
config = json.load(f)
# Add server
response = client.add_server(**config)
print(f"Server deployed successfully: {response['name']}")
return 0
except Exception as e:
print(f"Deployment failed: {e}", file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(deploy_server("production-server.json"))
For advanced operations and direct API usage, see the API documentation.