Built-in MCP Servers
The AI Security Gateway includes two built-in MCP servers that AI assistants and MCP clients can connect to directly. These servers use the Streamable HTTP transport and follow MCP protocol version 2024-11-05.
| MCP Server | Endpoint | Purpose |
|---|---|---|
| MCP Discovery Server | /api/v1/mcp | Discover and connect to MCP proxies managed by the Gateway |
| Skill Security Hub | /api/v1/mcp/skill-security | Analyze skills for security risks, manage approvals, and report suspicious behavior |
Both servers are available without authentication for MCP protocol access, making them easy to add to any MCP client. The Discovery Server offers additional authenticated endpoints that provide richer configuration data.
MCP Discovery Server
Overview
The MCP Discovery Server lets AI assistants find and connect to MCP proxies managed by the Gateway — without needing to know proxy URLs, ports, or authentication details in advance.
- List all running MCP proxies with their connection details
- Generate ready-to-use
mcp.jsonconfigurations for any proxy - Get OAuth authorization URLs for proxies that require authentication
- Connect at the root path — MCP clients can point directly at
http://localhost:8080and the Gateway will route JSON-RPC requests automatically
Connecting
Add the Discovery Server to your MCP client configuration.
Claude Code (.mcp.json):
{
"mcpServers": {
"gateway-discovery": {
"url": "http://localhost:8080/api/v1/mcp"
}
}
}Cursor (.cursor/mcp.json):
{
"mcpServers": {
"gateway-discovery": {
"url": "http://localhost:8080/api/v1/mcp"
}
}
}Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"gateway-discovery": {
"url": "http://localhost:8080/api/v1/mcp"
}
}
}TIP
You can also point MCP clients directly at the Gateway root (http://localhost:8080). The Gateway detects JSON-RPC POST requests at / and routes them to the Discovery Server automatically.
Available Tools
The Discovery Server exposes 3 tools via the MCP protocol.
list_proxies
List all enabled MCP proxy servers configured in the Gateway.
Parameters: None
Example response:
{
"content": [{ "type": "text", "text": "Found 2 MCP proxy servers" }],
"proxies": [
{
"id": 1,
"name": "filesystem-server",
"description": "File system access MCP server",
"port": 9090,
"url": "http://localhost:9090/",
"oauth_enabled": false,
"auth_type": "none"
},
{
"id": 2,
"name": "code-tools",
"description": "Code analysis tools",
"port": 9091,
"url": "http://localhost:9091/",
"oauth_enabled": true,
"auth_type": "delegation",
"auth_url": "http://localhost:8080/oauth/delegate/2",
"delegation_enabled": true,
"delegation_url": "http://localhost:8080/oauth/delegate/2"
}
]
}Each proxy includes its authentication type:
| Auth Type | Meaning |
|---|---|
none | No authentication required — connect directly |
standard | OAuth enabled on the proxy — use the auth_url to authorize |
delegation | OAuth delegation enabled — the Gateway handles auth on behalf of the upstream MCP server |
get_proxy_config
Generate a ready-to-use mcp.json configuration for a specific proxy.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
proxy_id | number | Yes | The ID of the proxy (from list_proxies) |
jwt_token | string | No | JWT token to include in the generated configuration headers |
Example response:
{
"content": [{ "type": "text", "text": "{ \"mcpServers\": { ... } }" }],
"proxy_id": 1,
"proxy_name": "filesystem-server",
"config": {
"mcpServers": {
"filesystem-server": {
"url": "http://localhost:9090/"
}
}
}
}When a jwt_token is provided, the generated config includes authentication headers appropriate for the proxy's auth type:
- Delegation mode:
Authorization: Bearer <token> - Standard OAuth:
X-Session-Token: <token> - No auth:
Authorization: Bearer <token>(fallback)
get_auth_url
Get the OAuth authorization URL for a proxy that requires authentication.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
proxy_id | number | Yes | The ID of the proxy |
Example response:
{
"content": [{ "type": "text", "text": "Authentication URL for proxy 'code-tools': http://localhost:8080/oauth/delegate/2" }],
"auth_url": "http://localhost:8080/oauth/delegate/2",
"delegation_url": "http://localhost:8080/oauth/delegate/2",
"proxy_id": 2,
"proxy_name": "code-tools"
}Returns an error if the proxy does not have OAuth enabled.
Authenticated REST Endpoints
In addition to the public MCP tools, the Discovery Server provides authenticated REST endpoints that automatically include your session credentials in generated configurations. These are useful when you have already authenticated with the Gateway via OAuth.
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/mcp/discover | List all MCP proxies (public, no auth required) |
GET | /api/v1/mcp/config/{proxy_id} | Get mcp.json config with your session token baked in |
GET | /api/v1/mcp/config | List all proxy configs with your session tokens baked in |
The /api/v1/mcp/config endpoints require an active OAuth session. They automatically inject your session's JWT token into the generated configurations, so the output is ready to copy into your MCP client without manually providing a token.
Example — get a config with embedded auth:
# After authenticating via OAuth, use your session cookie
curl -s http://localhost:8080/api/v1/mcp/config/1 \
-H "Cookie: session=<your-session-cookie>" | jqResponse:
{
"success": true,
"data": {
"proxy_id": 1,
"proxy_name": "filesystem-server",
"config": {
"mcpServers": {
"filesystem-server": {
"url": "http://localhost:9090/",
"headers": {
"Authorization": "Bearer eyJhbGciOi..."
}
}
}
}
}
}Testing with curl
You can test the Discovery Server manually using JSON-RPC over HTTP:
# Initialize
curl -s -X POST http://localhost:8080/api/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": {"name": "test-client", "version": "1.0.0"}
}
}' | jq
# List available tools
curl -s -X POST http://localhost:8080/api/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}' | jq
# List proxies
curl -s -X POST http://localhost:8080/api/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "list_proxies",
"arguments": {}
}
}' | jqSkill Security Hub
Overview
The Skill Security Hub is a dedicated MCP server that enables AI assistants to submit skills for automated security analysis before using them. It scans skill source code against 43 detection rules across 21 categories, maintains a centralized approval registry, and accepts runtime behavior reports.
- Analyze skills for shell execution, credential harvesting, obfuscation, reverse shells, and more
- Check approval status before using a skill
- Report suspicious runtime behavior observed during skill execution
- Batch-check security posture across all installed skills
- Centralized registry — approve once, trusted everywhere
For a complete walkthrough of the Skill Security workflow, see the Skill Security Hub User Guide.
Connecting
Add the Skill Security Hub to your MCP client configuration.
Claude Code (.mcp.json):
{
"mcpServers": {
"skill-security": {
"url": "http://localhost:8080/api/v1/mcp/skill-security"
}
}
}Cursor (.cursor/mcp.json):
{
"mcpServers": {
"skill-security": {
"url": "http://localhost:8080/api/v1/mcp/skill-security"
}
}
}Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"skill-security": {
"url": "http://localhost:8080/api/v1/mcp/skill-security"
}
}
}Available Tools
The Skill Security Hub exposes 7 tools via the MCP protocol.
analyze_skill
Submit skill source code for security analysis. Scans against 43 detection rules covering shell execution, credential harvesting, obfuscation, reverse shells, C2 communication, prompt injection, hardcoded secrets, resource abuse, and more.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
skill_name | string | Yes | Name of the skill to analyze |
skill_source | string | Yes | The skill's source code, configuration, or definition |
agent_name | string | Yes | Name of the AI assistant submitting the skill |
description | string | No | Description of what the skill does |
author | string | No | Author or publisher of the skill |
version | string | No | Version of the skill |
Example response:
{
"content": [{ "type": "text", "text": "Skill analysis complete..." }],
"analysis": {
"submission_id": 1,
"risk_score": 50,
"risk_level": "Critical",
"findings": [
{
"rule_id": "SKILL_RCE_001",
"rule_name": "SKILL_RCE_001",
"category": "Shell Execution",
"severity": "Critical",
"description": "Shell command execution via piped download or direct invocation",
"matched_pattern": "subprocess\\.\\w+\\s*\\(",
"source_file": "main.py",
"line_number": 5,
"matched_content": "subprocess.run(cmd, shell=True)"
}
],
"approval_status": "pending",
"content_hash": "a1b2c3...",
"analysis_time_ms": 12
}
}Re-submitting unchanged source code returns cached results instantly (matched by SHA-256 hash).
check_skill_approval
Check if a skill has been approved by an admin in the registry.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
skill_name | string | Yes | Name of the skill to check |
content_hash | string | No | SHA-256 hash for exact version matching |
version | string | No | Specific version to check |
Example response:
{
"content": [{ "type": "text", "text": "Skill: file-manager\nStatus: approved\nApproved: true" }],
"approval": {
"approved": true,
"status": "approved",
"risk_score": 50,
"risk_level": "Critical",
"approved_at": "2026-02-17T10:30:00Z",
"notes": "Reviewed source - shell access expected for file operations"
}
}list_approved_skills
List skills in the registry with optional filtering.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
category | string | No | Filter by category |
risk_level | string | No | Filter by risk level: None, Low, Medium, High, Critical |
status | string | No | Filter by status: approved (default), pending, rejected, all |
search | string | No | Search skill names and descriptions |
max_results | number | No | Maximum results (default: 50, max: 100) |
get_skill_details
Get full details about a specific skill including findings, review status, categories, and tags.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
skill_name | string | Yes | Name of the skill to look up |
version | string | No | Specific version (returns latest if not specified) |
report_skill_activity
Report suspicious runtime behavior observed by an AI assistant. High and critical severity reports automatically create security alerts visible in the Gateway dashboard.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
skill_name | string | Yes | Name of the skill exhibiting suspicious behavior |
activity_type | string | Yes | Type: data_exfiltration, unexpected_network, privilege_escalation, behavior_change, credential_access |
description | string | Yes | Description of the suspicious behavior |
agent_name | string | Yes | Name of the reporting AI assistant |
evidence | string | No | Logs or evidence supporting the report |
Example response:
{
"content": [{ "type": "text", "text": "Activity report submitted for skill: data-sync\nAlert Created: true" }],
"report": {
"report_id": 1,
"alert_created": true
}
}get_skill_security_status
Batch-check the security posture for a set of installed skills. Returns per-skill approval status, risk scores, an overall risk level, and actionable recommendations.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
skill_names | string[] | Yes | Array of skill names to check |
Example response:
{
"content": [{ "type": "text", "text": "Security Status for 3 skills:\nOverall Risk: High\nUnapproved Skills: 1" }],
"status": {
"skill_statuses": [
{ "skill_name": "file-manager", "status": "approved", "risk_score": 50, "risk_level": "Critical" },
{ "skill_name": "calculator", "status": "approved", "risk_score": 0, "risk_level": "None" },
{ "skill_name": "unknown-plugin", "status": "unknown", "risk_score": 0, "risk_level": "Unknown" }
],
"overall_risk": "High",
"unapproved_count": 1,
"recommendations": [
"Review and approve 1 unapproved skill(s) before deployment",
"Skill 'unknown-plugin' has not been analyzed - submit it for security review"
]
}
}get_system_prompt
Get the recommended system prompt instructions for AI assistants with the Gateway URL pre-configured. Use this to teach AI assistants how to interact with the Skill Security Hub.
Parameters: None
The returned prompt includes instructions for analyzing skills before use, checking approvals, and reporting suspicious behavior.
Risk Scoring Reference
| Risk Level | Score Range | Meaning |
|---|---|---|
| None | 0 | No suspicious patterns found |
| Low | 1-14 | Minor patterns detected |
| Medium | 15-29 | Notable patterns (e.g., HTTP client usage) |
| High | 30-49 | Significant risk indicators |
| Critical | 50+ | Highly suspicious patterns detected |
Detection Categories
The analysis engine scans for patterns across 21 categories:
| Category | Severity | What It Detects |
|---|---|---|
| Shell Execution | Critical | Running shell commands, piping downloads to bash |
| Dynamic Code Construction | Critical | Runtime code generation, eval, dynamic imports |
| Credential Harvesting | Critical | Reading SSH keys, AWS credentials, env vars |
| Reverse Shell | Critical | Netcat connections, TCP redirects |
| Persistence | Critical | Crontab entries, system service registration |
| C2 Communication | Critical | Polling loops, DNS tunneling, .onion addresses |
| Malware Delivery | Critical | Download-and-execute chains |
| Crypto Wallet Theft | Critical | Wallet file access, seed phrase extraction |
| Obfuscation | High | Base64-encoded code, hex escape chains |
| Obfuscated Execution | High | Hidden execution through encoding |
| Filesystem Access | High | Reading sensitive paths, directory scanning |
| Privilege Escalation | High | Sudo usage, permission changes |
| Network Access | Medium | HTTP client libraries, socket connections |
| Suspicious Network | Medium | Non-standard ports, raw sockets |
| Crypto Operations | Medium | Cryptographic operations that may indicate data exfiltration |
| Social Engineering | Medium | URL impersonation, lookalike domains |
| Prompt Injection | High | Skills embedding instructions to override safety, enable jailbreak mode, or conceal actions |
| Hardcoded Secrets | Critical/High/Medium | AWS keys, GitHub tokens, private keys, Stripe keys, Google API keys, JWTs, passwords, DB connection strings |
| Resource Abuse | Critical/High | Infinite loops, fork bombs, excessive memory allocation |
Architecture and Transport
Both MCP servers use the Streamable HTTP transport, which supports three HTTP methods on each endpoint:
| Method | Purpose |
|---|---|
GET | Opens a Server-Sent Events (SSE) stream for real-time notifications |
POST | Sends JSON-RPC 2.0 messages (initialize, tools/list, tools/call) |
DELETE | Terminates the MCP session |
All MCP protocol messages follow the standard JSON-RPC 2.0 format:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "tool_name",
"arguments": { ... }
}
}Audit Logging
Both servers emit audit events for security monitoring:
- Discovery Server: Logs
initializeevents with client IP and user agent - Skill Security Hub: Logs skill analysis submissions, approval checks, activity reports, and security status checks
All events are visible in the Gateway's audit log and can be forwarded to SIEM integrations.
Configuring the Gateway URL
For remote deployments, set the GATEWAY_URL environment variable so that generated configurations and system prompts reference the correct address:
export GATEWAY_URL=https://gateway.example.com
./build/unified-adminThis affects:
- Proxy URLs returned by
list_proxiesandget_proxy_config - The Gateway URL embedded in the
get_system_promptresponse
Troubleshooting
Common Issues
MCP client cannot connect to the Discovery Server
- Verify the Gateway is running:
curl http://localhost:8080/api/v1/health - Check the endpoint URL includes the full path:
http://localhost:8080/api/v1/mcp - For Docker environments, use
host.docker.internalinstead oflocalhost
list_proxies returns an empty list
- Ensure you have MCP proxies configured in the Gateway (not LLM proxies)
- Check that proxies are enabled — only enabled proxies are returned
get_proxy_config returns config without authentication headers
- The MCP tool requires a
jwt_tokenparameter to include auth headers - For automatic token injection, use the authenticated REST endpoint at
/api/v1/mcp/config/{proxy_id}instead
Skill analysis returns no findings for known-risky code
- Ensure the full source code is submitted, not just a description or summary
- Check that the patterns in
policies/skill-security.jsoncover the language and constructs used
MCP client reports "Method not found" error
- Only
initialize,tools/list, andtools/callare supported - Verify the
methodfield in your JSON-RPC request is spelled correctly