Compare commits
4 Commits
f3ca5b9c3a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f03e808c37 | |||
| 8f2584c1a0 | |||
| f061364951 | |||
| 9f64d6926a |
@@ -1,19 +1,21 @@
|
|||||||
## Stack
|
## Stack
|
||||||
|
|
||||||
<!-- TODO: Fill in language, frameworks, and key dependencies -->
|
- **Language:** Python (FastAPI MCP bridge) + Ansible/Helm/K8s deploy assets
|
||||||
- **Language:**
|
- **Key deps:** FastAPI, uvicorn, httpx; kube-prometheus-stack, Loki, Promtail
|
||||||
- **Key deps:**
|
|
||||||
|
|
||||||
## Dev Commands
|
## Dev Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# TODO: Fill in the standard commands for this repo
|
# MCP bridge — local (no cluster)
|
||||||
|
make bridge-install # once
|
||||||
|
make bridge-test # pytest smoke tests
|
||||||
|
make bridge-run # uvicorn on :8080
|
||||||
|
|
||||||
# Install dependencies
|
# Deploy observability stack (from repo root)
|
||||||
|
cd ansible && ansible-playbook -i inventories/local.ini playbook.yml
|
||||||
|
|
||||||
# Run tests
|
# Smoke (requires cluster access)
|
||||||
|
kubectl get pods -n monitoring
|
||||||
# Lint / type check
|
kubectl port-forward -n mcp svc/mcp-telemetry-bridge 8080:80
|
||||||
|
make bridge-smoke # pytest + live curl against :8080
|
||||||
# Build / package (if applicable)
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,27 +1,18 @@
|
|||||||
<!-- custodian-brief: generated by statehub register; fix-consistency may replace this file -->
|
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
|
||||||
# Custodian Brief - tele-mcp
|
# Custodian Brief — tele-mcp
|
||||||
|
|
||||||
**Project:** tele-mcp
|
|
||||||
**Domain:** infotech
|
**Domain:** infotech
|
||||||
**State Hub:** http://127.0.0.1:8000
|
**Last synced:** 2026-06-24 16:19 UTC
|
||||||
**Topic ID:** `cee7bedf-2b48-46ef-8601-006474f2ad7a`
|
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
|
||||||
|
|
||||||
## Open Workplans
|
## Active Workstreams
|
||||||
|
|
||||||
### Bootstrap State Hub integration
|
*(none — repo may need first-session setup)*
|
||||||
|
|
||||||
Workplan file: `workplans/TELE-WP-0001-statehub-bootstrap.md`
|
---
|
||||||
|
## MCP Orientation (when available)
|
||||||
|
|
||||||
Open tasks:
|
If the state-hub MCP server is reachable, call:
|
||||||
- T01 - Review generated integration files
|
`get_domain_summary("infotech")`
|
||||||
- T02 - Verify local developer workflow
|
This provides richer cross-domain context.
|
||||||
- T03 - Seed first real workplan
|
If the MCP call fails, use this file as your orientation source.
|
||||||
|
|
||||||
## Session Start
|
|
||||||
|
|
||||||
1. Read `INTENT.md`, `SCOPE.md`, and `AGENTS.md`.
|
|
||||||
2. Check inbox: `GET /messages/?to_agent=tele-mcp&unread_only=true`.
|
|
||||||
3. Scan `workplans/`.
|
|
||||||
4. Update task statuses in workplan files as work progresses.
|
|
||||||
|
|
||||||
Last generated: 2026-06-22
|
|
||||||
|
|||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.venv/
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.pytest_cache/
|
||||||
|
*.egg-info/
|
||||||
15
Makefile
Normal file
15
Makefile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.PHONY: bridge-install bridge-run bridge-test bridge-verify bridge-smoke
|
||||||
|
|
||||||
|
bridge-install:
|
||||||
|
cd mcp-telemetry-bridge && python3 -m venv .venv && . .venv/bin/activate && pip install -r requirements-dev.txt
|
||||||
|
|
||||||
|
bridge-run:
|
||||||
|
cd mcp-telemetry-bridge && ./scripts/run-local.sh
|
||||||
|
|
||||||
|
bridge-test:
|
||||||
|
cd mcp-telemetry-bridge && ./scripts/verify-local.sh
|
||||||
|
|
||||||
|
bridge-verify: bridge-test
|
||||||
|
|
||||||
|
bridge-smoke:
|
||||||
|
cd mcp-telemetry-bridge && RUN_LIVE=1 ./scripts/verify-local.sh
|
||||||
65
README.md
65
README.md
@@ -15,7 +15,68 @@ TeleMcp deploys a standard observability stack onto a Linux Kubernetes host via
|
|||||||
| **OpenTelemetry Collector** | `observability` | Optional OTLP fan-out to Prometheus and Loki |
|
| **OpenTelemetry Collector** | `observability` | Optional OTLP fan-out to Prometheus and Loki |
|
||||||
| **mcp-telemetry-bridge** | `mcp` | FastAPI service exposing MCP resources, tools, and prompts |
|
| **mcp-telemetry-bridge** | `mcp` | FastAPI service exposing MCP resources, tools, and prompts |
|
||||||
|
|
||||||
## Quick Start
|
## Local development (no cluster)
|
||||||
|
|
||||||
|
Work on the MCP bridge without deploying the full observability stack.
|
||||||
|
|
||||||
|
### Install and verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make bridge-install # venv + deps (once)
|
||||||
|
make bridge-test # pytest smoke: /healthz, /mcp/schema, /mcp/resource
|
||||||
|
```
|
||||||
|
|
||||||
|
Or from `mcp-telemetry-bridge/`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/verify-local.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make bridge-run
|
||||||
|
# or: cd mcp-telemetry-bridge && ./scripts/run-local.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
With the server up, optional live HTTP checks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make bridge-smoke
|
||||||
|
# or: RUN_LIVE=1 ./mcp-telemetry-bridge/scripts/verify-local.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Manual curls:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://127.0.0.1:8080/healthz
|
||||||
|
curl http://127.0.0.1:8080/mcp/schema | jq .
|
||||||
|
curl "http://127.0.0.1:8080/mcp/resource?uri=res://dashboards/top-pods-by-cpu.promql"
|
||||||
|
```
|
||||||
|
|
||||||
|
Tool calls use `POST /tools/<name>` with a JSON body (Prometheus/Loki/K8s backends are only reachable in-cluster).
|
||||||
|
|
||||||
|
### Agent quickstart
|
||||||
|
|
||||||
|
When changing the bridge, agents should:
|
||||||
|
|
||||||
|
1. Run `make bridge-test` after edits — fast, no cluster needed.
|
||||||
|
2. Introspect `GET /mcp/schema` for the current tools, resources, and prompts.
|
||||||
|
3. Call tools via `POST /tools/<tool-name>` (e.g. `POST /tools/promql.query` with `{"expr":"up"}`).
|
||||||
|
4. Fetch saved queries via `GET /mcp/resource?uri=<uri>`.
|
||||||
|
|
||||||
|
Expected smoke-test surface:
|
||||||
|
|
||||||
|
| Endpoint | Method | Purpose |
|
||||||
|
|----------|--------|---------|
|
||||||
|
| `/healthz` | GET | Liveness |
|
||||||
|
| `/mcp/schema` | GET | MCP catalog (tools, resources, prompts) |
|
||||||
|
| `/mcp/resource` | GET | Saved PromQL/LogQL query by URI |
|
||||||
|
| `/tools/*` | POST | Execute a tool (needs in-cluster backends) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Start (full cluster deploy)
|
||||||
|
|
||||||
### 0) Prereqs
|
### 0) Prereqs
|
||||||
|
|
||||||
@@ -75,6 +136,8 @@ tele-mcp/
|
|||||||
values/ # Chart values for monitoring, logging, OTel
|
values/ # Chart values for monitoring, logging, OTel
|
||||||
mcp-telemetry-bridge/ # Bridge Helm chart
|
mcp-telemetry-bridge/ # Bridge Helm chart
|
||||||
mcp-telemetry-bridge/ # FastAPI bridge application
|
mcp-telemetry-bridge/ # FastAPI bridge application
|
||||||
|
scripts/ # run-local.sh, verify-local.sh
|
||||||
|
tests/ # pytest smoke tests
|
||||||
environments/ # Per-environment overrides
|
environments/ # Per-environment overrides
|
||||||
wiki/ # Extended project and design docs
|
wiki/ # Extended project and design docs
|
||||||
```
|
```
|
||||||
|
|||||||
2
mcp-telemetry-bridge/requirements-dev.txt
Normal file
2
mcp-telemetry-bridge/requirements-dev.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
-r requirements.txt
|
||||||
|
pytest==8.3.3
|
||||||
22
mcp-telemetry-bridge/scripts/run-local.sh
Executable file
22
mcp-telemetry-bridge/scripts/run-local.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Run the MCP bridge locally (no Kubernetes required).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
PORT="${PORT:-8080}"
|
||||||
|
HOST="${HOST:-127.0.0.1}"
|
||||||
|
|
||||||
|
if [[ ! -d .venv ]]; then
|
||||||
|
python3 -m venv .venv
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
source .venv/bin/activate
|
||||||
|
|
||||||
|
pip install -q -r requirements.txt
|
||||||
|
|
||||||
|
echo "Starting MCP bridge at http://${HOST}:${PORT}"
|
||||||
|
echo "Health: curl http://${HOST}:${PORT}/healthz"
|
||||||
|
echo "Schema: curl http://${HOST}:${PORT}/mcp/schema | jq ."
|
||||||
|
exec uvicorn app.main:app --reload --host "$HOST" --port "$PORT"
|
||||||
36
mcp-telemetry-bridge/scripts/verify-local.sh
Executable file
36
mcp-telemetry-bridge/scripts/verify-local.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Local verification harness: pytest smoke tests + optional live HTTP checks.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
BASE_URL="${BASE_URL:-http://127.0.0.1:8080}"
|
||||||
|
RUN_LIVE="${RUN_LIVE:-0}"
|
||||||
|
|
||||||
|
if [[ ! -d .venv ]]; then
|
||||||
|
python3 -m venv .venv
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
source .venv/bin/activate
|
||||||
|
|
||||||
|
pip install -q -r requirements-dev.txt
|
||||||
|
|
||||||
|
echo "==> Running pytest smoke tests"
|
||||||
|
pytest -q
|
||||||
|
|
||||||
|
if [[ "$RUN_LIVE" == "1" ]]; then
|
||||||
|
echo "==> Live HTTP smoke against ${BASE_URL}"
|
||||||
|
curl -fsS "${BASE_URL}/healthz" | python3 -m json.tool
|
||||||
|
curl -fsS "${BASE_URL}/mcp/schema" | python3 -c "
|
||||||
|
import json, sys
|
||||||
|
schema = json.load(sys.stdin)
|
||||||
|
assert 'tools' in schema and 'resources' in schema and 'prompts' in schema
|
||||||
|
print(f\"tools={len(schema['tools'])} resources={len(schema['resources'])} prompts={len(schema['prompts'])}\")
|
||||||
|
"
|
||||||
|
echo "Live smoke passed."
|
||||||
|
else
|
||||||
|
echo "Skipping live HTTP checks (set RUN_LIVE=1 to curl a running server)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Local verification complete."
|
||||||
0
mcp-telemetry-bridge/tests/__init__.py
Normal file
0
mcp-telemetry-bridge/tests/__init__.py
Normal file
62
mcp-telemetry-bridge/tests/test_smoke.py
Normal file
62
mcp-telemetry-bridge/tests/test_smoke.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
"""Smoke tests for the MCP bridge HTTP surface (no cluster required)."""
|
||||||
|
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
|
from app.main import PROMPTS, RESOURCES, TOOLS, app
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
EXPECTED_TOOL_NAMES = {
|
||||||
|
"promql.query",
|
||||||
|
"loki.query",
|
||||||
|
"k8s.get",
|
||||||
|
"k8s.events",
|
||||||
|
"inventory.snapshot",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_healthz_returns_ok():
|
||||||
|
response = client.get("/healthz")
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.json()
|
||||||
|
assert body["status"] == "ok"
|
||||||
|
assert isinstance(body["ts"], int)
|
||||||
|
|
||||||
|
|
||||||
|
def test_mcp_schema_exposes_resources_tools_and_prompts():
|
||||||
|
response = client.get("/mcp/schema")
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.json()
|
||||||
|
|
||||||
|
assert "resources" in body
|
||||||
|
assert "tools" in body
|
||||||
|
assert "prompts" in body
|
||||||
|
|
||||||
|
assert len(body["resources"]) == len(RESOURCES)
|
||||||
|
assert len(body["tools"]) == len(TOOLS)
|
||||||
|
assert len(body["prompts"]) == len(PROMPTS)
|
||||||
|
|
||||||
|
tool_names = {tool["name"] for tool in body["tools"]}
|
||||||
|
assert tool_names == EXPECTED_TOOL_NAMES
|
||||||
|
|
||||||
|
for tool in body["tools"]:
|
||||||
|
assert "inputSchema" in tool
|
||||||
|
assert tool["inputSchema"]["type"] == "object"
|
||||||
|
|
||||||
|
|
||||||
|
def test_mcp_resource_returns_saved_query():
|
||||||
|
uri = "res://dashboards/top-pods-by-cpu.promql"
|
||||||
|
response = client.get("/mcp/resource", params={"uri": uri})
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.json()
|
||||||
|
assert body["uri"] == uri
|
||||||
|
assert body["mimeType"] == "text/plain"
|
||||||
|
assert "container_cpu_usage_seconds_total" in body["content"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_mcp_resource_unknown_uri():
|
||||||
|
response = client.get("/mcp/resource", params={"uri": "res://does-not-exist"})
|
||||||
|
assert response.status_code == 200
|
||||||
|
body = response.json()
|
||||||
|
assert body["error"] == "not found"
|
||||||
|
assert body["uri"] == "res://does-not-exist"
|
||||||
@@ -4,11 +4,12 @@ type: workplan
|
|||||||
title: "Bootstrap State Hub integration"
|
title: "Bootstrap State Hub integration"
|
||||||
domain: infotech
|
domain: infotech
|
||||||
repo: tele-mcp
|
repo: tele-mcp
|
||||||
status: ready
|
status: finished
|
||||||
owner: codex
|
owner: codex
|
||||||
topic_slug: custodian
|
topic_slug: custodian
|
||||||
created: "2026-06-22"
|
created: "2026-06-22"
|
||||||
updated: "2026-06-22"
|
updated: "2026-06-22"
|
||||||
|
state_hub_workstream_id: "f8a00337-b34e-40a1-a720-ce968d8a575e"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Bootstrap State Hub integration
|
# Bootstrap State Hub integration
|
||||||
@@ -19,10 +20,13 @@ updated: "2026-06-22"
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: TELE-WP-0001-T01
|
id: TELE-WP-0001-T01
|
||||||
status: todo
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
|
state_hub_task_id: "b91614b5-1524-4871-8f9e-532be354ce9f"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Result 2026-06-22: INTENT.md, SCOPE.md, AGENTS.md reviewed.
|
||||||
|
|
||||||
Review `INTENT.md`, `SCOPE.md`, `AGENTS.md`, and `.custodian-brief.md`.
|
Review `INTENT.md`, `SCOPE.md`, `AGENTS.md`, and `.custodian-brief.md`.
|
||||||
Replace generated placeholders with repo-specific facts where needed.
|
Replace generated placeholders with repo-specific facts where needed.
|
||||||
|
|
||||||
@@ -30,10 +34,13 @@ Replace generated placeholders with repo-specific facts where needed.
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: TELE-WP-0001-T02
|
id: TELE-WP-0001-T02
|
||||||
status: todo
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
|
state_hub_task_id: "ede18111-be6a-4191-b9ef-752fa99ec6c6"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Result 2026-06-22: Documented Ansible/kubectl/uvicorn workflow.
|
||||||
|
|
||||||
Identify the repo's install, test, lint, build, and run commands. Add or refine
|
Identify the repo's install, test, lint, build, and run commands. Add or refine
|
||||||
those commands in the agent instructions so future coding sessions can verify
|
those commands in the agent instructions so future coding sessions can verify
|
||||||
changes confidently.
|
changes confidently.
|
||||||
@@ -42,10 +49,13 @@ changes confidently.
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: TELE-WP-0001-T03
|
id: TELE-WP-0001-T03
|
||||||
status: todo
|
status: done
|
||||||
priority: medium
|
priority: medium
|
||||||
|
state_hub_task_id: "ff0d4282-b831-4b2a-a1d7-24b67286acab"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Result 2026-06-22: Created TELE-WP-0002.
|
||||||
|
|
||||||
Create the first implementation workplan for the repository's most important
|
Create the first implementation workplan for the repository's most important
|
||||||
next change. After workplan file updates, run from `~/state-hub`:
|
next change. After workplan file updates, run from `~/state-hub`:
|
||||||
|
|
||||||
|
|||||||
31
workplans/TELE-WP-0002-mcp-bridge-local-verification.md
Normal file
31
workplans/TELE-WP-0002-mcp-bridge-local-verification.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
id: TELE-WP-0002
|
||||||
|
type: workplan
|
||||||
|
title: "MCP bridge local verification loop"
|
||||||
|
domain: infotech
|
||||||
|
repo: tele-mcp
|
||||||
|
status: finished
|
||||||
|
owner: codex
|
||||||
|
topic_slug: custodian
|
||||||
|
created: "2026-06-22"
|
||||||
|
updated: "2026-06-24"
|
||||||
|
state_hub_workstream_id: "c617a044-bf57-4671-9afd-0112e7f462fd"
|
||||||
|
---
|
||||||
|
|
||||||
|
# MCP bridge local verification loop
|
||||||
|
|
||||||
|
Harden the local dev/test loop for `mcp-telemetry-bridge` independent of full cluster deploy.
|
||||||
|
|
||||||
|
## Local verification harness
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: TELE-WP-0002-T01
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "7bad3ebf-f42c-4069-9c13-28bcf231f6f9"
|
||||||
|
```
|
||||||
|
|
||||||
|
Result 2026-06-24: Added pytest smoke tests, run/verify scripts, Makefile targets,
|
||||||
|
and README local-dev + agent quickstart sections.
|
||||||
|
|
||||||
|
Add documented local run path, health/schema smoke tests, and agent-oriented quickstart in README.
|
||||||
Reference in New Issue
Block a user