使用说明
Local Infra Assistant — MCP Server for Infrastructure Troubleshooting
What Is This?
A local Model Context Protocol (MCP) server that gives VS Code Copilot deep awareness of your infrastructure repository — Helm charts, Kubernetes manifests, ArgoCD applications, Gateway API routes, and more.
Instead of copying YAML into chat and hoping the AI understands your cluster layout, this server indexes your GitOps repo and exposes specialized tools that Copilot can call autonomously to search, read, summarize, and diagnose infrastructure problems.
The core idea: Copilot becomes an infrastructure-aware pair programmer that can look things up in your repo, follow troubleshooting playbooks, and learn from past issues — all running locally with no cloud dependencies beyond Ollama.
What It Does
Three-Layer Tool Architecture
The server organizes MCP tools into layered capabilities that work together:
Layer 1 — Retrieval (find and fetch)
| Tool | Purpose |
|---|---|
search_repo |
FAISS-indexed semantic search across the repo |
read_file_slice |
Read specific line ranges from files |
find_related_files |
Discover sibling manifests and configs |
find_k8s_objects |
Find K8s resources by kind/name/namespace |
Layer 2 — Summarization (compress and prepare)
| Tool | Purpose |
|---|---|
summarize_files |
Structured overview of multiple files |
review_yaml |
Detect hostname conflicts, Gateway misconfigs, LoadBalancer issues |
compress_logs |
Distill K8s/Tekton/ArgoCD logs into signals and suggestions |
render_helm |
Template a Helm chart and summarize produced objects |
inspect_argocd |
Check ArgoCD Application sync policy and drift risks |
inspect_gateway |
Inspect Gateway/HTTPRoute resources for broken refs |
prepare_copilot_brief |
Final handoff: package findings into a structured brief for Copilot |
Layer 3 — Diagnostic (classify, guide, remember)
| Tool | Purpose |
|---|---|
classify_problem |
Pattern-match text/logs against 11 known problem types |
get_playbook |
Get ordered troubleshooting steps for a detected pattern |
record_issue |
Save diagnostic sessions to persistent SQLite history |
query_history |
Surface past root causes and best tool order for a pattern |
Layer 4 — Runtime and IaC CLI (cluster/runtime execution hooks)
| Tool Group | Purpose |
|---|---|
graphify_* |
Query an existing Graphify knowledge graph (status, query, path, explain) |
runtime_environment_info |
Snapshot active repo path, index stats, env selectors, and CLI availability |
kubectl_* |
Run kubectl commands directly (requires existing kube context/auth; no login flow) |
argocd_* |
Runtime ArgoCD checks (app, app events, app resources) |
opentofu_* |
OpenTofu checks (version, fmt, validate, plan, show plan) |
terraform_* |
Terraform checks (version, fmt, validate, plan, show plan) |
Why Graphify Helps
Graphify turns the repository into a knowledge map so Copilot can answer questions about relationships instead of only matching text. In this repo, the Graphify CLI builds graphify-out/graph.json, and the MCP tools query that existing graph with:
graphify_statusto check whether the graph and CLI are readygraphify_queryto ask natural-language questions about the mapgraphify_pathto trace how two concepts are connectedgraphify_explainto get a plain-language explanation of one node
That helps when you want to understand how modules, docs, and tooling fit together, spot bridge nodes, and navigate the repo faster than reading files one by one.
How Copilot Uses the Tools
When you ask "Why is Harbor out of sync in ArgoCD?", Copilot can autonomously:
flowchart LR
A["🗣️ User Question"] --> B["classify_problem"]
B -->|argocd_out_of_sync| C["get_playbook"]
C -->|8 steps| D["search_repo"]
D --> E["inspect_argocd"]
D --> F["render_helm"]
E --> G["summarize_files"]
F --> G
G --> H["prepare_copilot_brief"]
H --> I["🤖 Copilot Answer"]
H --> J["record_issue"]
J --> K[("SQLite History")]
style A fill:#4CAF50,color:#fff
style I fill:#2196F3,color:#fff
style K fill:#FF9800,color:#fff
- Classify →
classify_problemdetectsargocd_out_of_sync(confidence: 0.71) - Get playbook →
get_playbookreturns 8 ordered steps with common root causes - Search →
search_repofinds ArgoCD Application manifests and Helm values - Inspect →
inspect_argocdchecks sync policy,render_helmcompares chart output - Summarize →
summarize_filescompresses relevant files - Brief →
prepare_copilot_briefpackages everything into a structured handoff - Record →
record_issuesaves the session for future reference
Performance Features
- LRU content-hash cache — repeated tool calls return in <1ms (86% hit rate in benchmarks)
- Cached LLM client — Ollama client is reused across requests when settings are unchanged, avoiding per-request initialization overhead
- Strict LLM prompts — structured Summary/Details/Files output from Ollama
- Smart output limits — head+tail preview for large files, per-file and total character budgets
- Verbosity modes — compact (≤500 chars), normal (≤1500), detailed (≤5000)
- Tuned Ollama settings — temperature=0.1, repeat_penalty=1.1 for deterministic output
How to Use
Prerequisites
- Docker and Docker Compose
- A Git repository with infrastructure code (Helm charts, K8s manifests, ArgoCD apps)
- Ollama runs inside Docker — no local GPU needed (CPU inference works)
Quick Start
# Clone and start
git clone <this-repo>
cd MCP-server
# Point at your infra repo (or use the current directory)
export HOST_REPO_PATH=/path/to/your/gitops-repo
# Optional for multi-repo dynamic selection:
# export HOST_REPO_ROOT=/path/to/parent-containing-multiple-repos
# Start the stack
docker compose up -d --build
# Pull the model (first time only)
docker exec ollama ollama pull granite-code:8b
# Verify
curl -s http://127.0.0.1:8081/healthz | python3 -m json.tool
Smoke Test
# List all tools
curl -s http://127.0.0.1:8081/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
| python3 -c "import sys,json; [print(t['name']) for t in json.load(sys.stdin)['result']['tools']]"
# Classify a problem
curl -s http://127.0.0.1:8081/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"classify_problem","arguments":{"text":"pod CrashLoopBackOff exit code 137"}}}'
# Get the troubleshooting playbook
curl -s http://127.0.0.1:8081/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_playbook","arguments":{"pattern":"crashloop_backoff"}}}'
Environment Variables
| Variable | Default | Description |
|---|---|---|
HOST_REPO_PATH |
. (current dir) |
Host path to the repo to index (mounted read-only) |
HOST_REPO_ROOT |
.. (parent dir) |
Optional host parent directory mounted at /repos for multi-repo dynamic selection |
REPO_PATH |
/repo |
Container path for the indexed repo. Also supports glob patterns like /repos/* |
WORKSPACE_REPO_NAME |
unset | Optional selector when REPO_PATH is a glob (for example aws) |
TARGET_REPO_NAME |
unset | Backward-compatible selector alias for WORKSPACE_REPO_NAME |
OLLAMA_MODEL |
granite-code:8b |
Model for optional LLM reasoning |
OLLAMA_BASE_URL |
http://ollama:11434 |
Ollama API URL |
VSCODE_MCP_JSON_PATH |
/workspace/.vscode/mcp.json |
Optional JSON config file used for runtime overrides |
VSCODE_MCP_SERVER_NAME |
local-infra-assistant |
Server key inside the MCP JSON used for overrides |
GRAPHIFY_BIN |
graphify |
Optional Graphify CLI binary name or absolute path |
ISSUE_DB_PATH |
/app/data/issues.db |
SQLite path for issue memory |
REST API
The server also exposes direct REST endpoints on port 8081:
| Endpoint | Method | Description |
|---|---|---|
/healthz |
GET | Health check with repo index stats |
/models |
GET | List available Ollama models |
/search-repo |
POST | Search indexed repo |
/read-file-slice |
POST | Read file lines |
/find-related-files |
POST | Find sibling files |
/find-k8s-objects |
POST | Find K8s resources |
/summarize-files |
POST | Summarize files |
/review-yaml |
POST | Review YAML for issues |
/compress-logs |
POST | Compress logs |
/render-helm |
POST | Render Helm chart |
/inspect-argocd |
POST | Inspect ArgoCD apps |
/inspect-gateway |
POST | Inspect Gateway routes |
/graphify-status |
GET | Check Graphify CLI and graph availability |
/graphify-query |
POST | Run Graphify natural-language query |
/graphify-path |
POST | Find shortest path between graph nodes |
/graphify-explain |
POST | Explain a graph node |
/prepare-copilot-brief |
POST | Build Copilot handoff brief |
/classify-problem |
POST | Classify problem pattern |
/get-playbook |
POST | Get troubleshooting playbook |
/record-issue |
POST | Record issue to history |
/query-history |
POST | Query past issues |
/ask-repo |
POST | LLM-powered repo Q&A |
/fullcontext |
POST | LLM reasoning with provided context |
/mcp |
POST | MCP JSON-RPC 2.0 endpoint |
VS Code Integration
Setup
- Start the server (
docker compose up -d --build) - Add
.vscode/mcp.jsonto your workspace (already included):
{
"servers": {
"local-infra-assistant": {
"type": "http",
"url": "http://127.0.0.1:8081/mcp",
"env": {
"REPO_PATH": "/repos/*",
"WORKSPACE_REPO_NAME": "${workspaceFolderBasename}",
"OLLAMA_MODEL": "granite-code:8b",
"OLLAMA_BASE_URL": "http://ollama:11434"
}
}
}
}
Values under servers.local-infra-assistant.env override .env values for matching keys inside the running assistant service.
- In VS Code, open the Command Palette and run MCP: List Servers
- Trust the
local-infra-assistantworkspace server - MCP tools now appear in Copilot Chat — Copilot will call them automatically when relevant
How It Looks in Practice
In Copilot Chat (Agent mode), ask infrastructure questions naturally:
- "Why is the Harbor app out of sync in ArgoCD?"
- "What's wrong with this pod that keeps crashlooping?"
- "Check if the HTTPRoute for grafana has the right backendRef"
- "Review the Helm values for the tekton chart"
Copilot will call the MCP tools, gather evidence from your repo, and provide grounded answers with file references.
Pros and Cons
Pros
- Fully local — no data leaves your machine. Repo content, logs, and issue history stay on disk. Suitable for air-gapped or security-sensitive environments.
- Repo-grounded answers — Copilot no longer guesses about your infrastructure. It searches your actual files, reads your actual manifests, and references real paths.
- Structured troubleshooting — 11 problem patterns with step-by-step playbooks mean Copilot follows a consistent diagnostic process instead of ad-hoc reasoning.
- Persistent issue memory — SQLite-backed history lets the system learn which root causes are common and which tool order works best. Answers improve over time.
- Low resource overhead — the assistant container runs with 2GB RAM and 1 CPU. Ollama handles the heavy LLM work separately.
- Security hardened — path traversal protection via
Path.is_relative_to(), parameterized SQL, non-root Docker user, read-only repo mount, and.dockerignoreexcluding build artifacts. - Pinned dependencies — all Python packages are version-pinned in
requirements.txtfor reproducible builds. - No vendor lock-in — built on open standards (MCP protocol, JSON-RPC 2.0, Ollama, FAISS). Swap models, switch editors, or extend tools without rewriting.
- Works with any Git repo — point
HOST_REPO_PATHat any repo and the FAISS index rebuilds automatically on startup. - Performance-optimized — LRU caching, character budgets, smart previews, and compact output modes keep token usage low and responses fast.
Cons
- No live cluster access — the server indexes Git repos only. It cannot query running pods, live ArgoCD status, or cluster events. Cluster tool stubs are provided for future integration.
- CPU-only LLM by default — Ollama on CPU is slower than GPU. The 7B model works but larger models may be impractical without a GPU.
- Pattern coverage is finite — the classifier knows 11 problem types. Novel or unusual failure modes won't match any pattern and fall back to generic search.
- Broad repo roots can reduce precision — wildcard indexing can include multiple repos. Use
WORKSPACE_REPO_NAME(orTARGET_REPO_NAME) to select the right one for each workspace. - Docker required — the stack runs in Docker Compose. Native installation is possible but not documented.
- Ollama model pull needed — first startup requires downloading the model (~4GB), which takes time on slow connections.
- MCP protocol maturity — MCP is still evolving. Breaking changes in the protocol spec or VS Code's MCP client may require updates.
Architecture
System Overview
flowchart TB
subgraph VSCode["VS Code"]
Copilot["🤖 Copilot Agent Mode"]
end
Copilot <-->|"MCP JSON-RPC 2.0"| MCP
subgraph Server["FastAPI + MCP Server :8081"]
MCP["MCP Endpoint /mcp"]
Cache["LRU Cache\n256 entries · SHA-256"]
MCP --> Cache
subgraph L1["Layer 1 — Retrieval"]
search_repo["search_repo"]
read_file["read_file_slice"]
find_rel["find_related_files"]
find_k8s["find_k8s_objects"]
end
subgraph L2["Layer 2 — Summarization"]
summarize["summarize_files"]
yaml["review_yaml"]
logs["compress_logs"]
helm["render_helm"]
argo["inspect_argocd"]
gw["inspect_gateway"]
brief["prepare_copilot_brief"]
end
subgraph L3["Layer 3 — Diagnostic"]
classify["classify_problem"]
playbook["get_playbook"]
record["record_issue"]
history["query_history"]
end
Cache --> L1
Cache --> L2
Cache --> L3
end
subgraph Storage["Persistent Storage"]
FAISS[("FAISS Index\n256-dim")]
SQLite[("SQLite\nissues.db")]
Repo[("Git Repo\nread-only mount")]
end
subgraph OllamaC["Ollama Container :11434"]
Model["granite-code:8b"]
end
L1 --> FAISS
L1 --> Repo
L2 --> Repo
L2 -.->|"optional reasoning"| Model
L3 --> SQLite
style VSCode fill:#1e1e1e,color:#fff,stroke:#007ACC
style Server fill:#f5f5f5,stroke:#333
style L1 fill:#E3F2FD,stroke:#1565C0
style L2 fill:#FFF3E0,stroke:#E65100
style L3 fill:#F3E5F5,stroke:#6A1B9A
style Storage fill:#E8F5E9,stroke:#2E7D32
style OllamaC fill:#FFF8E1,stroke:#F57F17
Docker Compose Topology
flowchart LR
subgraph compose["docker compose"]
subgraph assistant["infra-assistant\n2GB RAM · 1 CPU"]
FastAPI["FastAPI :8081"]
FAISS2["FAISS Index"]
SQLite2["SQLite DB"]
end
subgraph ollama["ollama\n10GB RAM · 10 CPU"]
LLM["granite-code:8b"]
end
FastAPI -->|"HTTP :11434"| LLM
end
Repo2[("Host Repo\n:ro mount")] --> FastAPI
Vol1[("langchain_data\nvolume")] --- SQLite2
Vol2[("ollama\nvolume")] --- LLM
User["👤 VS Code / curl"] -->|":8081"| FastAPI
style compose fill:#f0f0f0,stroke:#333
style assistant fill:#E3F2FD,stroke:#1565C0
style ollama fill:#FFF8E1,stroke:#F57F17
Three-Layer Tool Flow
flowchart TD
Q["User Question"] --> Classify
subgraph Diagnostic["Layer 3: Diagnostic"]
Classify["classify_problem"] --> Playbook["get_playbook"]
Playbook -->|"step list"| Execute
Record["record_issue"] --> DB[("Issue History")]
History["query_history"] --> DB
end
subgraph Retrieval["Layer 1: Retrieval"]
Execute["Execute steps"] --> Search["search_repo"]
Execute --> Read["read_file_slice"]
Execute --> FindK8s["find_k8s_objects"]
Execute --> FindRel["find_related_files"]
end
subgraph Summarization["Layer 2: Summarization"]
Search --> Summarize["summarize_files"]
Read --> YAML["review_yaml"]
FindK8s --> Inspect["inspect_argocd / inspect_gateway"]
Summarize --> Brief["prepare_copilot_brief"]
YAML --> Brief
Inspect --> Brief
end
Brief --> Answer["Copilot Answer"]
Brief --> Record
History -.->|"past causes"| Brief
style Diagnostic fill:#F3E5F5,stroke:#6A1B9A
style Retrieval fill:#E3F2FD,stroke:#1565C0
style Summarization fill:#FFF3E0,stroke:#E65100
style Q fill:#4CAF50,color:#fff
style Answer fill:#2196F3,color:#fff
Running Tests
python3 -m pytest app/test_main.py -v
50 tests covering all three layers, REST endpoints, MCP tool calls, cache behavior, and issue memory.
Note: Test files are excluded from the Docker image via .dockerignore — run tests locally against the source tree.
Additional Guides
- QUICK_START_SIMPLE.md — 3-step setup for first-time users
- COPILOT_MCP_OLLAMA_GUIDE.md — detailed Copilot + MCP + Ollama integration guide
