Add Cloudflare and Loki MCP server integrations
Features: - Cloudflare Code Mode MCP: Exposes entire Cloudflare API (2,500+ endpoints) via remote MCP server at https://mcp.cloudflare.com/mcp * Two tools: search() to query OpenAPI spec, execute() to run JS code * Uses npx mcp-remote as stdio bridge * Auth via CLOUDFLARE_API_TOKEN as Bearer header - Loki MCP Server: Log querying and analysis via Loki HTTP API * Query logs with LogQL syntax * Real-time log streaming support * Label introspection and metrics queries * Configurable via LOKI_URL environment variable Technical changes: - Created mcp_servers/cloudflare/ with config and connection logic - Created mcp_servers/loki/ with HTTP client and MCP tool wrappers - Added promtail-config-optimized.yaml for syslog ingestion config - Updated .env.example with Cloudflare and Loki configuration templates Both integrations: - Use environment variables for configuration (no hardcoded credentials) - Include feature flags (CLOUDFLARE_MCP_ENABLED, LOKI_MCP_ENABLED) - Follow existing MCP server patterns for consistency Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
9
mcp_servers/cloudflare/__init__.py
Normal file
9
mcp_servers/cloudflare/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Cloudflare Code Mode MCP Server
|
||||
#
|
||||
# Remote MCP server at https://mcp.cloudflare.com/mcp
|
||||
# Uses "Code Mode" — 2 tools (search + execute) covering the entire
|
||||
# Cloudflare API (2,500+ endpoints) in ~1,000 tokens.
|
||||
#
|
||||
# Auth: Cloudflare API Token (Bearer header via mcp-remote bridge)
|
||||
# Docs: https://blog.cloudflare.com/code-mode-mcp/
|
||||
# Repo: https://github.com/cloudflare/mcp
|
||||
81
mcp_servers/cloudflare/cloudflare_mcp.py
Normal file
81
mcp_servers/cloudflare/cloudflare_mcp.py
Normal file
@@ -0,0 +1,81 @@
|
||||
"""Cloudflare Code Mode MCP Server Integration.
|
||||
|
||||
Manages the remote Cloudflare MCP server connection via mcp-remote bridge.
|
||||
The server exposes the entire Cloudflare API (2,500+ endpoints) through
|
||||
just two tools: search() and execute(), using ~1,000 tokens total.
|
||||
|
||||
Architecture:
|
||||
Your bot → npx mcp-remote → https://mcp.cloudflare.com/mcp
|
||||
Auth is via Cloudflare API Token passed as Bearer header.
|
||||
|
||||
Pattern mirrors obsidian_mcp.py for consistency.
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
from typing import Any, Dict, List
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _load_config() -> Dict[str, Any]:
|
||||
"""Load Cloudflare MCP configuration from environment."""
|
||||
from mcp_servers.cloudflare.config import (
|
||||
CLOUDFLARE_API_TOKEN,
|
||||
CLOUDFLARE_MCP_URL,
|
||||
CLOUDFLARE_MCP_ENABLED,
|
||||
)
|
||||
|
||||
return {
|
||||
"enabled": CLOUDFLARE_MCP_ENABLED,
|
||||
"api_token": CLOUDFLARE_API_TOKEN,
|
||||
"mcp_url": CLOUDFLARE_MCP_URL,
|
||||
}
|
||||
|
||||
|
||||
def is_cloudflare_enabled() -> bool:
|
||||
"""Check if the Cloudflare MCP integration is enabled and has a token."""
|
||||
config = _load_config()
|
||||
if not config["enabled"]:
|
||||
return False
|
||||
if not config["api_token"]:
|
||||
logger.warning(
|
||||
"[Cloudflare MCP] Enabled but CLOUDFLARE_API_TOKEN is not set"
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def get_cloudflare_server_config() -> Dict[str, Any]:
|
||||
"""Build the MCP server configuration for Agent SDK registration.
|
||||
|
||||
Returns the config dict suitable for ClaudeAgentOptions.mcp_servers.
|
||||
Uses npx mcp-remote as a stdio bridge to the remote Cloudflare server.
|
||||
|
||||
The API token is passed via the --header flag as a Bearer token.
|
||||
"""
|
||||
config = _load_config()
|
||||
|
||||
return {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"mcp-remote",
|
||||
config["mcp_url"],
|
||||
"--header",
|
||||
f"Authorization: Bearer {config['api_token']}",
|
||||
],
|
||||
"env": {
|
||||
# Pass through any needed env vars for npx/node resolution
|
||||
"PATH": os.environ.get("PATH", ""),
|
||||
"HOME": os.environ.get("HOME", os.environ.get("USERPROFILE", "")),
|
||||
"APPDATA": os.environ.get("APPDATA", ""),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# Tools exposed by the Cloudflare Code Mode MCP server.
|
||||
# These are the only two tools — that's the whole point of Code Mode.
|
||||
CLOUDFLARE_TOOLS: List[str] = [
|
||||
"search",
|
||||
"execute",
|
||||
]
|
||||
37
mcp_servers/cloudflare/config.py
Normal file
37
mcp_servers/cloudflare/config.py
Normal file
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
Cloudflare Code Mode MCP Server - Configuration
|
||||
|
||||
Remote MCP server that exposes the entire Cloudflare API through just two tools:
|
||||
- search(): Query the OpenAPI spec to find endpoints
|
||||
- execute(): Run JavaScript against the Cloudflare API
|
||||
|
||||
Environment variables:
|
||||
CLOUDFLARE_API_TOKEN - Your Cloudflare API token (required)
|
||||
CLOUDFLARE_MCP_URL - Remote MCP server URL (default: https://mcp.cloudflare.com/mcp)
|
||||
CLOUDFLARE_MCP_ENABLED - Enable/disable integration (default: true)
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Connection settings
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Cloudflare API token — create one at https://dash.cloudflare.com/profile/api-tokens
|
||||
# Recommended permissions: Account Resources (Read) + whatever you need
|
||||
CLOUDFLARE_API_TOKEN = os.getenv("CLOUDFLARE_API_TOKEN", "")
|
||||
|
||||
# The remote MCP server URL (Cloudflare runs this as a Worker)
|
||||
CLOUDFLARE_MCP_URL = os.getenv(
|
||||
"CLOUDFLARE_MCP_URL", "https://mcp.cloudflare.com/mcp"
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Feature flag
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Set to "false" to disable the integration without removing config
|
||||
CLOUDFLARE_MCP_ENABLED = os.getenv(
|
||||
"CLOUDFLARE_MCP_ENABLED", "true"
|
||||
).lower() in ("true", "1", "yes")
|
||||
Reference in New Issue
Block a user