feat: Add Loki MCP server scaffold, fix adapter blocking, upgrade model
- Scaffold mcp_servers/loki/ with config and async HTTP client - Fix Slack/Telegram adapters to use non-blocking connections - Upgrade default model to claude-sonnet-4-6 - Improve Agent SDK message collection for empty ResultMessage cases - Add Message-ID to email summaries, increase body truncation limit - Fix .gitignore inline comments that broke sensitive file exclusions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1
mcp_servers/loki/__init__.py
Normal file
1
mcp_servers/loki/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Loki MCP Server - Query homelab logs via Loki's HTTP API
|
||||
38
mcp_servers/loki/config.py
Normal file
38
mcp_servers/loki/config.py
Normal file
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
Loki MCP Server - Configuration
|
||||
|
||||
This is where we store settings for connecting to your Loki instance.
|
||||
We use environment variables with sensible defaults so you can override
|
||||
them without editing code.
|
||||
|
||||
Environment variables:
|
||||
LOKI_URL - Base URL for your Loki instance
|
||||
LOKI_TIMEOUT - Request timeout in seconds (default: 30)
|
||||
LOKI_DEFAULT_LIMIT - Default number of log lines to return (default: 100)
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Connection settings
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# The URL where Loki is reachable. This goes through your Caddy reverse proxy.
|
||||
LOKI_URL = os.getenv("LOKI_URL", "https://loki.apophisnetworking.net")
|
||||
|
||||
# How long (seconds) to wait for Loki to respond before giving up.
|
||||
LOKI_TIMEOUT = int(os.getenv("LOKI_TIMEOUT", "30"))
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Query defaults
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# How many log lines to return if the caller doesn't specify.
|
||||
# 100 is a good balance — enough to see what's happening, not so many
|
||||
# that it floods the response.
|
||||
DEFAULT_LIMIT = int(os.getenv("LOKI_DEFAULT_LIMIT", "100"))
|
||||
|
||||
# Default time range for queries if none specified (in hours).
|
||||
# "1" means "show me the last hour of logs."
|
||||
DEFAULT_RANGE_HOURS = 1
|
||||
32
mcp_servers/loki/loki_client.py
Normal file
32
mcp_servers/loki/loki_client.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import httpx
|
||||
from config import LokiConfig
|
||||
|
||||
|
||||
class LokiClient:
|
||||
"""Talks to Loki's HTTP API to fetch logs."""
|
||||
|
||||
def __init__(self, config: LokiConfig):
|
||||
# Store the config so we can use it later
|
||||
self.config = config
|
||||
|
||||
# Create an HTTP client
|
||||
# already knows Loki address and wait time
|
||||
self.client = httpx.AsyncClient(
|
||||
base_url=config.url,
|
||||
timeout=config.timeout
|
||||
)
|
||||
|
||||
async def query_range(self, query: str, start: str, end: str, limit: int = 100):
|
||||
# Makes GET request to Loki's query endpoint with search parameters
|
||||
response = await self.client.get(
|
||||
"/loki/api/v1/query_range",
|
||||
params={
|
||||
"query": query,
|
||||
"start": start,
|
||||
"end": end,
|
||||
"limit": limit
|
||||
}
|
||||
)
|
||||
|
||||
# Returns response into Python Dict
|
||||
return response.json()
|
||||
Reference in New Issue
Block a user