Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

observability-mcp

Read-only MCP server exposing Telegraf/InfluxDB lab metrics as no-input recipe tools. Built for Hermes Agent and any MCP-compatible client (Claude Code, Cursor, Goose, Continue.dev, etc).

License: MIT Python: 3.11+ MCP

Why this exists

If you run a homelab or small infrastructure setup with Telegraf + InfluxDB, you already have rich metrics. But asking your AI agent "what's the current load on my server?" usually means one of these:

  1. The agent doesn't know how to query InfluxDB at all
  2. The agent tries to compose a Flux query from scratch and gets the syntax wrong
  3. The agent calls a generic query_database tool and dumps raw CSV at you
  4. You give up and check Grafana yourself

observability-mcp solves this with the no-input recipe pattern: instead of asking the agent to compose a Flux query, you give it a menu of pre-written recipe tools. Each tool takes no arguments, runs a known-good query internally, and returns a clean human-readable answer. The agent just picks the right recipe by name.

Recipe tools currently shipped:

  • get_lab_load1 — Current 1-minute system load average
  • get_lab_memory_pct — Current memory used percentage
  • get_top_cpu_containers — Top 10 Docker containers by mean CPU% over the last 15 minutes

More coming. Adding a recipe is ~30 lines of Python.

Why "no-input" recipes

We learned this the hard way. When you give a local LLM (qwen2.5, llama3.1, even larger ones) a tool that requires a complex string input (like a Flux query), it will either:

  • Generate empty output (the model can't format the input correctly in ReAct text)
  • Hallucinate a different tool's output
  • Repeat the prompt back to you

Local models are good at selecting from a menu but weak at composing structured inputs. Recipe tools play to that strength: each tool is a single named capability with no arguments. The agent picks the right one and reads the result.

This pattern works equally well with Anthropic Claude, OpenAI GPT, and any local model with tool-calling support.

Quick start

Install

pip install observability-mcp
# OR
pipx install observability-mcp

Configure

Set environment variables (or copy .env.example and source it):

export INFLUXDB_URL=http://localhost:8086
export INFLUXDB_TOKEN_FILE=/path/to/your/influxdb-readonly-token
export INFLUXDB_ORG=your-org-id
export INFLUXDB_BUCKET_METRICS=telegraf
export INFLUXDB_BUCKET_LLM=llm_usage  # optional

The token must be read-only and scoped to the buckets you want exposed. Create one with:

influx auth create \
  --read-bucket <your-telegraf-bucket-id> \
  --description "observability-mcp readonly" \
  --org-id <your-org-id>

Run

observability-mcp

This starts a stdio MCP server. Connect it to your MCP client.

Connect to Hermes Agent

Add to your Hermes config (~/.hermes/config.toml or via hermes mcp add):

[mcp.observability]
command = "observability-mcp"
env = { INFLUXDB_URL = "http://host.docker.internal:8086", ... }

Then in any Hermes conversation:

"What's my Mac Mini load?"

Hermes calls get_lab_load1 and returns the current value.

Connect to Claude Code

Add to ~/.config/claude/claude.json:

{
  "mcpServers": {
    "observability": {
      "command": "observability-mcp",
      "env": {
        "INFLUXDB_URL": "http://localhost:8086",
        "INFLUXDB_TOKEN_FILE": "/path/to/token",
        "INFLUXDB_ORG": "your-org-id",
        "INFLUXDB_BUCKET_METRICS": "telegraf"
      }
    }
  }
}

Connect to any other MCP client

This server speaks standard stdio MCP. It works with Cursor, Goose, Continue.dev, and any other client that supports the protocol.

What it deliberately does NOT do

  • No write capability. This server is read-only by design. It cannot create, update, or delete anything in InfluxDB. The token should be scoped read-only too, defense in depth.
  • No arbitrary Flux queries. Each recipe runs a hardcoded query. If you want to expose ad-hoc Flux, that's a separate tool with separate safety considerations.
  • No mutation of the host or containers. This server reads metrics. It doesn't restart services, delete files, or call out to anything other than your InfluxDB instance.

Adding a new recipe

Each recipe is one Python file in src/observability_mcp/recipes/. The contract:

from observability_mcp.influx import query

async def get_my_metric() -> str:
    """Returns the current foo metric. No input."""
    flux = '''
    from(bucket: "telegraf")
      |> range(start: -5m)
      |> filter(fn: (r) => r._measurement == "foo" and r._field == "bar")
      |> last()
      |> keep(columns: ["_value"])
    '''
    result = await query(flux)
    # Parse the CSV result and return a clean string
    return f"Current foo: {result}"

Then register it in server.py:

mcp.tool()(get_my_metric)

That's it. PRs welcome — see CONTRIBUTING.md.

Architecture

┌─────────────────────────┐
│  MCP Client (Hermes,    │
│  Claude Code, Cursor)   │
└────────────┬────────────┘
             │ stdio (MCP)
┌────────────▼────────────┐
│  observability-mcp      │
│  ├── server.py (FastMCP)│
│  ├── influx.py (HTTP)   │
│  └── recipes/           │
└────────────┬────────────┘
             │ HTTPS
┌────────────▼────────────┐
│  InfluxDB v2            │
│  (your lab metrics)     │
└─────────────────────────┘

License

MIT — see LICENSE.

Built by

Charlie Seay — solo developer, homelab operator, and founder of Seaynic Labs. Building the tools I want to use, then sharing them.

Part of the Seaynic Labs ecosystem

Seaynic Labs ships homelab tools, MCP servers, and self-hosted infrastructure for solo operators and small teams.

Related projects

About

Read-only MCP server exposing Telegraf/InfluxDB lab metrics as no-input recipe tools. Built for Hermes Agent and any MCP-compatible client (Claude Code, Cursor, Goose). Part of Project Alchemist.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages