MCP + Tool Use
Second phase of Year 5. Tools as a standardized protocol. MCP (Model Context Protocol) lets agents discover + use tools across systems. Build a
basecamp-mcpserver that exposes your platform to any MCP-aware agent. ~6-7 weeks, ~80 hrs.
Phase 26 gave you one agent with hardcoded tools. Phase 27 takes that lesson seriously: a real platform has many agents and many systems, and each pairing should not be a bespoke integration. MCP is how the M×N problem becomes M+N — same shape as adopting a service mesh in Year 2 or a schema registry in Year 3, just applied to the tool layer.
The artifact is basecamp-mcp — a Go server living inside basecamp that exposes your platform’s read state and a small set of approval-gated write actions to any MCP-aware client. After this phase, the query-helper agent stops calling hardcoded functions and starts speaking MCP, services/aiops/ (P28) consumes the same server, and Studio’s command palette in P29 plugs into it without rewriting a single tool. One server, three Y5 consumers, plus every external MCP client a future visitor brings.
This is also the phase where tool-use-as-capability in patterns/agents/ graduates to DEEP — the proof that the typed-registry-with-allowlists pattern transferred from your one-off Python tools in P26 to a transport-agnostic protocol you’d recognize in any 2026+ agent stack.
Prerequisites
- Phase 26 complete — agent-loop + prompt-as-program deepened
- You accept: MCP is the 2024-2025 standard for tool integration. The protocol may evolve, but the pattern (typed tool registry, capability allowlists, transport-agnostic) is durable. Anthropic, OpenAI, and many others now speak MCP.
Why this phase exists
P26 built agents with hardcoded tools. Real platforms have many tools across many systems. MCP standardizes the contract: any client speaks MCP; any tool server speaks MCP; the M×N matrix collapses to M+N.
By phase end, basecamp-mcp (a server you write) exposes basecamp’s read-only state + a small set of write actions to any MCP-aware agent. P28’s services/aiops/ will consume this MCP server. The future Studio command palette (P29) consumes it.
→ Pattern: tool-use-as-capability (DEEP this phase)
1. PROBLEM
You have N agents (current and future). Each needs to call tools across many systems (Trino, ArgoCD, Loki, MLflow, Slack, GitHub). Without a standard:
- Each agent re-implements the tool client
- Each tool re-defines its API for each agent
- Capability allowlisting is per-agent + per-tool
- Discovery is “ask the team chat which tools exist”
MCP collapses this: every system runs an MCP server (or has one written for it); every agent speaks MCP client. Tool discovery is dynamic. Capability allowlisting is per-server-per-client.
2. PRINCIPLES
2.1 The MCP architecture
Three roles: host (the agent runtime), client (an MCP transport endpoint), server (exposes tools). One host can have many clients; each client connects to one server.
Investigate:
- Read the MCP spec (modelcontextprotocol.io)
- Walk through the example server + client locally
- What’s the role of “resources” vs “tools” vs “prompts” in MCP?
2.2 Tools = typed RPC
MCP tools have JSON Schema input + output. Servers list available tools; clients call them.
Investigate:
- Compare with gRPC (proto-defined typed RPC)
- Compare with OpenAPI (REST + JSON Schema)
- Why is JSON Schema the right abstraction for LLM clients? (LLMs reason about schemas natively.)
The reason JSON Schema beats proto here: LLMs read schemas like documentation. A query_trino tool whose input schema names sql_query: string and max_rows: integer<=100 is self-documenting to an LLM in a way a .proto file isn’t, because the LLM saw a billion JSON Schemas during training.
2.3 Capability allowlisting
A client doesn’t get all tools by default. Connect-time negotiation: server lists tools; client (or platform) filters; agent gets only what’s allowed.
Investigate:
- Per-agent tool allowlist as basecamp config
- Per-user OIDC token → which tools the agent can call on user’s behalf
- Audit: every cross-agent-cross-user-cross-tool call to Loki
Concrete: query-helper’s Backstage entity declares allowedTools: [query_trino, read_logs, list_services]; the MCP client negotiates against basecamp-mcp and silently drops restart_pod even though the server offers it. Defense in depth: server enforces, client filters, audit catches drift.
2.4 Server design: building basecamp-mcp
The server side: expose basecamp’s state + actions as MCP tools.
Investigate:
- Build an MCP server in Go (matching
triage+llm-gatewaystack) - Read-only tools:
query_trino,read_logs,list_services,get_metric,get_alerts - Write tools (with approval gates):
argocd_sync,restart_pod,notify_slack - Auth: server validates OIDC token from client; checks RBAC
2.5 Transport-agnostic
MCP supports stdio (local processes), HTTP+SSE (network), WebSocket. Same protocol, different wires.
Investigate:
- Build basecamp-mcp with HTTP+SSE for cluster-to-cluster usage
- Build a stdio variant for local CLI tools (e.g.,
platform-ctlexposes its commands as MCP tools)
2.6 Tool versioning + deprecation
Tools evolve. Adding fields = backward-compatible. Renaming = breaking. MCP doesn’t enforce; you do.
Investigate:
- Versioning strategy for basecamp-mcp tools
- Deprecation policy (90-day window with warning logs)
- Schema-registry pattern (Y3 P16) reapplied to tool definitions
Same shape as the schema registry from Y3, just for tool definitions: additive change is free, breaking change requires version bump and a 90-day deprecation window with warning logs that name the offending client.
3. TRADE-OFFS
| Decision | Option A | Option B | When |
|---|---|---|---|
| Tool standard | MCP | OpenAI Functions (proprietary) | gRPC |
| Server language | Go (matches platform stack) | Python (faster prototyping) | Rust (perf) |
| Transport | HTTP+SSE | WebSocket | stdio |
| Auth | OIDC bearer | service-account | mTLS |
| Approval gate | server-side | host-side | both |
4. TOOLS (as of 2025-10)
- MCP spec + reference implementations (modelcontextprotocol.io)
- Anthropic SDK (host-side; embeds MCP client)
- OpenAI SDK (also speaks MCP now)
- Go (basecamp-mcp server stack)
5. MASTERY
5.1 Reading list
| Required | Why |
|---|---|
| MCP specification | The protocol |
| Anthropic’s MCP introduction blog | The motivation |
| Sample MCP servers (Anthropic’s reference repo) | Real implementations |
5.2 Operational depth checklist
[ ] Run a sample MCP server + client locally; trace the protocol[ ] Build basecamp-mcp v0 in Go: - HTTP+SSE transport - 5 read-only tools (query_trino, read_logs, list_services, get_metric, get_alerts) - OIDC auth - audit log to Loki[ ] Refactor the query-helper agent (P26) to use basecamp-mcp instead of hardcoded tools[ ] Add 3 write tools to basecamp-mcp (argocd_sync, restart_pod, notify_slack)[ ] Add approval gates: write tools require human "yes" via Slack[ ] Per-agent capability allowlist via Backstage catalog metadata[ ] Deploy basecamp-mcp via ArgoCD; expose internally via mesh mTLS[ ] Test: connect Claude Desktop / Claude Code / mcp-cli to basecamp-mcp; use the tools[ ] Versioning + deprecation policy documented[ ] Document MCP server architecture in basecamp/README.md5.3 Project: basecamp-mcp
Lives inside basecamp at basecamp/charts/basecamp-mcp/. Not a standalone repo (similar to services/llm-gateway).
basecamp-mcp scope: Go service (cobra not needed — pure server) HTTP+SSE transport ~10 tools (5 read-only + 5 with approval gate) OIDC auth via Dex mesh mTLS Backstage catalog entry with allowlist metadata audit log to Loki Prometheus metrics: tool_calls_total, tool_call_duration, approval_requests_total
This is the gateway from "any MCP-aware agent" → "your platform."P28 aiops uses it. P29 command palette uses it. Future agents use it.6. COMPARE: MCP vs custom REST API for tools
You could expose the same tools as a custom REST API + per-language clients. When does MCP earn its abstraction?
400 words. Argue both directions: when REST is fine (single consumer, stable API, internal-only) and when MCP is the right tax to pay (N>2 consumers, cross-vendor agents, tool churn).
7. OPERATE
- 2+ runbooks (
mcp-tool-call-stuck,mcp-approval-gate-debug) - 1+ ADR (
why-mcp-over-custom-rest) - Weekly log
8. CONTRIBUTE
MCP spec itself, sample MCP servers (Anthropic’s reference repo), MCP clients in different languages.
Validation criteria
[ ] All 10 operational depth checks[ ] basecamp-mcp running with 10+ tools; OIDC + audit + metrics[ ] query-helper (P26) refactored to use basecamp-mcp[ ] At least one external MCP client (Claude Desktop / mcp-cli) successfully uses basecamp-mcp[ ] MCP vs custom-REST writeup[ ] 2+ runbooks; 1+ ADR; 6+ weekly log entries[ ] Pattern entries deepened: - tool-use-as-capability → DEEP[ ] Exit Test passedExit Test
Time: 2.5 hours.
- Build (60 min): add a new tool to basecamp-mcp:
query_icebergthat takes a SQL string + table name, executes via Trino, returns up to 100 rows. With OIDC, audit, deprecation policy doc. - Diagnose (60 min): scenario: an MCP tool call returns “permission denied” but the user has the role; trace the OIDC token through the chain.
- Articulate (30 min): 600 words: “Walk a tool call from agent intent to result: agent → MCP client → MCP server → underlying system → response. What controls fire at each layer?”
Anti-patterns
| Anti-pattern | Why |
|---|---|
| Tools without typed schemas | LLMs hallucinate inputs; runtime errors |
| Single all-powerful MCP server | Allowlisting per-agent breaks; security disaster |
| Synchronous write tools without approval gates | Agent runs away; rollback nightmare |
| Skipping audit logs | ”Who deleted production?” — agent — “which one?” — unknown |
| Versioning by “just rename it” | Breaks every consumer; deprecation policy is non-negotiable |
Patterns deepened this phase
- tool-use-as-capability → DEEP