| name | mcp-server-blueprint |
| description | Design and build a safe, useful MCP server that exposes your app's own data (analytics, funnel, revenue, crashes) to an AI assistant: read-only, least-privilege, AI-consumable. Use when someone asks "how do i build an MCP server for my app", "expose my analytics/funnel to my AI", "make my app's data reachable by Claude/Cursor", "wire an MCP over my backend", or "MCP security best practices". Enforces a security layer (read-only, field allowlist, no secrets in tool output, aggregate-not-row-level) and usability rules (Markdown output, few well-named tools) so the server helps without leaking. |
mcp-server-blueprint
Use this when you're building the reachability layer: the MCP server that lets an AI assistant read your app's real numbers. It exists to make sure that server is useful and safe, not just wired. Most homemade MCPs over app data fail one of two ways: they leak (row-level PII, a secret in a tool response, a write tool on production) or they're unusable (raw JSON dumps the model can't reason about, thirty granular tools no assistant picks correctly).
This skill gives you the design and a hard checklist for both. Read the two references before you write a tool.
The core rule
An MCP server over your own data is a read-only, least-privilege window onto aggregates: not an API. Every tool you add is a new way for an agent (and anyone who can drive it) to pull data. Default to the smallest, safest surface that answers the question, and widen only on evidence you need to.
Two lines to keep in front of you:
- Reachable ≠ exposed-raw. The goal is the funnel reachable, not the user table dumped. Aggregate first.
- A tool response is untrusted output surface. Assume anything a tool returns can end up in a log, a prompt, or a screenshot. Never let a secret or a raw PII record ride out in one.
How to design one (in order)
- Start from the question, not the schema. Write the 2–4 questions the assistant should be able to answer: "where does onboarding leak", "what's the trial→paid rate", "is a drop-off actually a crash spike". Each becomes one tool. Do not mirror your database tables into tools.
- Pick the transport. For a local dev assistant (Claude Code, Cursor), stdio is the default: the server runs locally, secrets stay in the environment, nothing is exposed to the network. Use a remote/HTTP MCP only when the assistant genuinely can't run the server locally, and then it's an authenticated service, not a public endpoint.
- Apply the security layer. Read
references/security-best-practices.md and satisfy every item in its checklist before the server touches real data. Read-only, field allowlist, secrets excluded from output, aggregate-not-row-level, authenticated source, keys in env not in .mcp.json. This is not optional polish: it's the difference between a helper and a breach.
- Apply the usability layer. Read
references/usability-best-practices.md. Return Markdown, not raw JSON (an AI reasons over a labeled brief far better than over a row array). Few, well-named, well-described tools. Bounded, summarized output. Self-documenting: say what each number means.
- Wire it in
.mcp.json with env references, never literal keys. The config points at the server and reads secrets from the environment. A key pasted into .mcp.json is a key committed to git.
- Verify with the audit. Run
mcp-readiness-audit against the repo afterwards: section 5 (reachability) should flip to pass, and the new section 7 (security posture) confirms you didn't open a hole doing it.
What "good" looks like (the reference shape)
A well-built app-analytics MCP tends to converge on the same shape, whatever the vendor:
- One or two read tools returning a Markdown brief: e.g.
get_insights → a funnel summary (completion rate, drop-by-step, time-per-screen) rendered as Markdown, not JSON.
- A read key with least privilege: scoped to the analytics read, revocable, separate from any admin/write credential.
- An allowlist of fields the tool may return, with secrets (
api_key, tokens) and raw PII (emails, device IDs) excluded by construction: not filtered after the fact.
- Aggregates, not rows: "38% complete onboarding, biggest drop at step 3," not a dump of user records.
- A versioned, authenticated source (
GET /v1/insights.md behind a key), so the contract is stable and the data isn't public.
If your design doesn't look roughly like this, re-check it against the two references before shipping.
Files in this skill
references/security-best-practices.md: the security layer: read-only, least privilege, field allowlist, no-secrets-in-output, aggregate-not-row-level, transport & key handling, rate/cost guards, logging. Includes a pre-ship checklist.
references/usability-best-practices.md: the usability layer: Markdown-over-JSON, tool count & naming, descriptions that route the agent, bounded/self-documenting output, latency.
Heavy detail lives in references/, loaded only when you're actually building, so the skill stays small until you point it at a real server.
Notes
- Stack-agnostic. The rules hold for a Node MCP over Firebase, a Python MCP over a warehouse, or a hosted analytics MCP. Only the SDK changes; the security and usability bars don't.
- Companion skill:
mcp-readiness-audit (the checker). Companion guide: guide/why-an-mcp-server-for-your-app.md. Companion article: "Why you need an MCP server for your app" on Code Meet AI.