All essays

ENGINEERING & ARCHITECTURE7 min read

Shipping an MCP Server in Production: What We Learned Building for Claude & ChatGPT

The Model Context Protocol is revolutionizing how LLMs interface with private tools and databases. Here are the architectural lessons, schema optimizations, and security patterns we learned while deploying production MCP servers.

Why We Ship a Copilot *and* a Protocol Server

For the past three years, software teams built "AI wrappers": standalone web applications wrapped around OpenAI or Anthropic API endpoints. Most of them failed for the same reason — the chatbox knew nothing about the job the product was for.

We took the opposite lesson. Each of our products — Billable Copilot AI (scope creep radar), Money Copilot AI (private spending tracking), and Frame Copilot AI (visual art direction) — ships with its own AI copilot built in, and that copilot is domain-specific from the first message. Open the product and it already understands invoices, or budgets, or negative space. That is the product.

Anthropic's Model Context Protocol (MCP) then solves a second, narrower problem: some users already live in Claude Desktop, ChatGPT, Gemini, Cursor or VS Code and would rather not switch windows. So each product also exposes an MCP server that reaches the same copilot from those clients. It is an additional door into the product, not the product itself — and plenty of our users never open it.

Here is what we learned building and running those MCP servers in production.


Lesson 1: Tool Schemas Are Prompts (Treat Them Like UX)

In standard REST API design, parameter descriptions are optional documentation for developers. In MCP, tool descriptions and JSON schemas are directly consumed by the LLM as system instructions.

If your parameter description is vague, the model will hallucinate arguments or fail to trigger the tool at the right time:

// ❌ Poor MCP Tool Schema:
{
  name: "log_client_work",
  description: "Logs work done for a client",
  parameters: {
    hours: { type: "number" },
    client: { type: "string" }
  }
}

// ✅ Production MCP Tool Schema: { name: "billable_copilot_log_unbilled_activity", description: "Records out-of-scope requests, revisions, or emergency weekend messages to safeguard against scope creep. Call this whenever the user mentions extra client revisions, after-hours Slack threads, or unplanned feature requests.", parameters: { type: "object", properties: { client_name: { type: "string", description: "Exact client or project identifier (e.g., 'Acme Corp', 'Stripe Redesign')" }, duration_minutes: { type: "integer", description: "Estimated or actual time spent in minutes (e.g., 45)" }, creep_category: { type: "string", enum: ["revision_excess", "after_hours_communication", "unplanned_deliverable", "meeting_overrun"], description: "Classification of how the out-of-scope work originated" }, notes: { type: "string", description: "Raw context or snippet from the client message justifying the billable adjustment" } }, required: ["client_name", "duration_minutes", "creep_category"] } } ```

The production schema explicitly teaches the LLM when to invoke the tool and constrains the output with clear enums.


Lesson 2: Stateless Auth with Granular Scope Tokens

One of the biggest hurdles in building consumer MCP tools is authentication. When an MCP client runs on a user's machine (via stdio or SSE), it communicates via standard input/output.

We standardized on scoped studio API tokens: - Users generate a revocable API key inside their web dashboard. - The key is supplied via environment variables in the client's MCP configuration:

{
  "mcpServers": {
    "billable-copilot": {
      "command": "npx",
      "args": ["-y", "@copilotai/billable-mcp@latest"],
      "env": {
        "COPILOT_API_KEY": "copilot_live_sec_9941..."
      }
    }
  }
}

Tokens have strict read/write boundaries. A compromised MCP config can never delete user accounts or alter billing details.


Lesson 3: Latency & Response Density Matter

When Claude or Cursor calls your MCP tool in the middle of a coding or writing session, a 3-second delay breaks the flow state. Furthermore, returning huge JSON payloads wastes the model's context window.

Our rules for production MCP responses: 1. P95 latency under 150ms: Keep tool endpoints edge-cached and optimized. 2. Compact Response Summaries: Return crisp, token-efficient markdown summaries rather than bloated database rows. 3. Actionable Follow-ups: Include deep-links back to the web dashboard for full visual reporting.


The Future: One Studio, Unified MCP Ecosystem

MCP is not just an API; it is the universal USB-C cable for AI assistants. By building high-leverage, single-purpose utilities on this open standard, we give users superpowers inside the tools they already love.

NEXT ESSAYWhy We Don't Connect to Your Bank (And Why You Shouldn't Let Other AI Apps Either)

Try a copilot for yourself

Five focused products, each with its own built-in assistant. Pick the one that fits your day — connecting it to your own AI client is optional.

Notes from the work

Ideas become clearer when they are written down.

The journal documents product decisions, privacy principles, technical lessons, and the details behind every release.

Notebook and laptop arranged for focused writing and research
01Document the reasoning
Rows of books on library shelves in warm light
02Learn in public
Organized editorial desk with notebook, coffee, and computer
03Make complexity readable