Blog
Practical notes on design, product, and shipping for startups.
Practical notes on design, product, and shipping for startups.
An MCP server exposes your SaaS tools to AI clients like Claude, Cursor, and ChatGPT in a standard way. Ship one when agents need safe access to real actions in your product; skip it if an in-app chatbot is enough. Start small with auth, scopes, and a few clear tools.
An MCP server is a small, standardized service that exposes your product's tools and data to AI clients like Claude, Cursor, ChatGPT, and custom agents. Ship one when third-party AI apps need safe, repeatable access to your SaaS, not when a single in-app chatbot is enough. Start with a few well-scoped tools, auth, and logging before you add more.
MCP stands for Model Context Protocol. It is an open protocol that lets AI apps discover and call tools you define, in a consistent shape, instead of inventing a one-off API for every assistant.
In practice an MCP server is a process (or HTTP endpoint) that lists tools, accepts tool calls, and returns structured results. The AI client decides when to call a tool. Your server decides what is allowed.
Think of it as a controlled bridge between your product and AI agents, not as a replacement for your public REST API.
| Approach | Who calls it | Best for | Main risk |
|---|
| In-app chatbot | Only your UI | Guided help inside your product | Stays siloed; other AI tools cannot use it |
| Public REST API | Any developer | Integrations, scripts, partners | Agents need custom glue for each model |
| MCP server | MCP-capable AI clients | Letting Claude, Cursor, and agents use your product as tools | Over-exposing actions without auth and scopes |
If you already have a solid REST API, an MCP server often wraps a thin, agent-friendly slice of that API rather than duplicating business logic.
Ship one when at least two of these are true:
Skip it (or wait) when:
Keep the first MCP surface small. Three to six tools beat twenty vague ones.
| Tool type | Example | Why it works |
|---|---|---|
| Read / search | search_projects, get_invoice | Low risk, high usefulness for agents |
| Create draft | create_task_draft | Useful without committing money or deletes |
| Status check | get_job_status | Fits long-running jobs agents poll |
| Export | export_report_csv | Clear output agents can hand to the user |
Avoid shipping "delete everything" or "charge card" tools until you have confirmation flows, scopes, and human-in-the-loop checks.
Here is a simplified tool definition pattern many servers use. Names and schemas should match what an agent can reason about.
import { z } from "zod";
export const searchProjects = {
name: "search_projects",
description:
"Search the user's projects by name or status. Returns id, name, and status.",
inputSchema: z.object({
query: z.string().min(1).max(200),
status: z.enum(["active", "archived", "all"]).default("active"),
limit: z.number().int().min(1).max(25).default(10),
}),
async handler({ query, status, limit }, ctx) {
// ctx.userId comes from OAuth or API key after auth
return ctx.db.projects.search({
userId: ctx.userId,
query,
status,
limit,
});
},
};Wire auth before you wire cleverness. Every tool call should know which tenant and user it belongs to, and should refuse cross-tenant reads.
| Control | What to do |
|---|---|
| Auth | OAuth or per-workspace API keys; never anonymous write tools |
| Scopes | Separate read vs write; default to read-only for early users |
| Input limits | Cap string length, page size, and fan-out |
| Idempotency | Prefer create-draft tools; make writes safe to retry |
| Logging | Log tool name, user, latency, and error class (not raw secrets) |
| Kill switch | Feature-flag tools so you can disable one without redeploying clients |
Agents will call tools in loops. Design for retries and partial failure the way you would for a webhook consumer.
Luminix Studio builds web and mobile apps and the AI automations around them for startups worldwide. When a product needs agent access, we usually start from the existing API, pick a short list of tools, add auth and logging, then expose an MCP (or similar) surface only after the in-product flows are solid. See luminixstudio.com if you want help scoping that path.