Imported from ChangooLee/opas (
skills/project/mcp-gateway/SKILL.md). Install upstream withnpx skills add ChangooLee/opas --skill mcp-gateway. Copyright stays with the author.
MCP Gateway Development Rules
Rules for Model Context Protocol (MCP) server management.
Overview
MCP Gateway enables:
- MCP server registration and discovery
- Streamable HTTP and SSE transport
- Kong Gateway integration for security
- Tool discovery and invocation
Architecture
MCP Client (Agent Builder)
|
Kong Gateway (port 8002)
| (key-auth, rate-limit)
Backend BFF (MCP Registry)
|
MCP Server (Streamable HTTP/SSE)
File Locations
backend/app/services/mcp_registry.py # MCP server registry
backend/app/routes/mcp.py # API endpoints
webui/src/routes/(app)/build/mcp/+page.svelte # Admin UI
config/kong.yml # Kong configuration
Database Schema (MariaDB)
CREATE TABLE mcp_servers (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
url VARCHAR(512) NOT NULL,
transport ENUM('streamable-http', 'sse') DEFAULT 'streamable-http',
enabled BOOLEAN DEFAULT TRUE,
health_status VARCHAR(50),
created_at TIMESTAMP,
updated_at TIMESTAMP
);
CREATE TABLE mcp_tools (
id INT AUTO_INCREMENT PRIMARY KEY,
server_id VARCHAR(36),
name VARCHAR(255),
description TEXT,
input_schema JSON,
discovered_at TIMESTAMP,
FOREIGN KEY (server_id) REFERENCES mcp_servers(id)
);
API Endpoints
GET /mcp/servers
POST /mcp/servers
GET /mcp/servers/{id}
PUT /mcp/servers/{id}
DELETE /mcp/servers/{id}
GET /mcp/servers/{id}/tools
POST /mcp/servers/{id}/discover
POST /mcp/servers/{id}/tools/{tool_name}/invoke
MCP Protocol
Tool List
POST /mcp/v1/tools/list
Content-Type: application/json
{}
Response:
{
"tools": [{
"name": "search",
"description": "Search the web",
"inputSchema": {
"type": "object",
"properties": { "query": { "type": "string" } },
"required": ["query"]
}
}]
}
Tool Call
POST /mcp/v1/tools/call
Content-Type: application/json
{
"name": "search",
"arguments": { "query": "AI news" }
}
Kong Integration
services:
- name: mcp-proxy
url: http://backend:8000/mcp
routes:
- name: mcp-route
paths: [/mcp]
strip_path: false
plugins:
- name: key-auth
config:
key_names: ["X-API-Key"]
- name: rate-limiting
config:
minute: 100
policy: local
SSE Transport
async def stream_tool_call(server_url: str, tool_name: str, args: Dict):
async with httpx.AsyncClient() as client:
async with client.stream(
'POST',
f"{server_url}/mcp/v1/tools/call",
json={"name": tool_name, "arguments": args},
headers={"Accept": "text/event-stream"}
) as response:
async for line in response.aiter_lines():
if line.startswith("data: "):
yield json.loads(line[6:])
Frontend API Calls
const MCP_URL = '/api/mcp';
const response = await fetch(`${MCP_URL}/servers`);
const tools = await fetch(`${MCP_URL}/servers/${id}/discover`, { method: 'POST' });
const result = await fetch(`${MCP_URL}/servers/${id}/tools/${toolName}/invoke`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ arguments: args })
});
MCP Server Code Update (Docker Volume)
MCP servers run inside the Docker volume (mcp_storage → /data/mcp/), NOT on the host filesystem. Host-side git pull alone does NOT update the running MCP server.
Update Script (Recommended)
# Update ALL MCP servers (git pull → docker cp → pip install → restart)
./scripts/update-mcp-servers.sh
# Update specific server only
./scripts/update-mcp-servers.sh legislation
./scripts/update-mcp-servers.sh news
Registered MCP Servers
| Name | Host Repo | Container Path |
|---|---|---|
| mcp-kr-legislation | ~/Workspace/mcp-kr-legislation | /data/mcp/mcp-kr-legislation |
| mcp-kr-health | ~/Workspace/mcp-kr-health | /data/mcp/mcp-kr-health |
| mcp-kr-realestate | ~/Workspace/mcp-kr-realestate | /data/mcp/mcp-kr-realestate |
| mcp-naver-news | ~/Workspace/mcp-naver-news | /data/mcp/mcp-naver-news |
| mcp-opendart | ~/Workspace/mcp-opendart | /data/mcp/mcp-opendart |
Manual Update (single server)
cd ~/Workspace/mcp-kr-legislation && git pull origin main
docker cp ~/Workspace/mcp-kr-legislation/src opas-backend-1:/data/mcp/mcp-kr-legislation/src
docker cp ~/Workspace/mcp-kr-legislation/pyproject.toml opas-backend-1:/data/mcp/mcp-kr-legislation/pyproject.toml
docker compose exec backend bash -c "cd /data/mcp/mcp-kr-legislation && .venv/bin/pip install -e . --quiet"
curl -X POST http://localhost:3010/mcp/servers/<SERVER_ID>/restart
Key Rules
- Use Streamable HTTP as default transport
- Set 60s timeout for tool invocations (may be slow)
- Store discovered tools for quick reference
- Integrate with Kong for API security
- Use
/api/mcp/proxy from frontend - MCP code lives in Docker volume — always use
docker cp+ reinstall to update
Last Updated: 2026-02-05