Skip to content
esc
↑ ↓ navigate↵ select
All posts

Designing MCP Servers That Age Well

2 min read

  • MCP
  • LLM
  • Developer Tools
  • APIs
On this page

An MCP server gives an AI client a discoverable interface to data and actions. The useful abstraction is not “an API for a model.” It is a contract that helps a model understand what it can do, what it needs and what can go wrong.

Expose Capabilities, Not Internals

A tool should represent a meaningful operation:

search_incidents(query, status, limit)

It should not expose an internal database query with dozens of optional fields. Narrow tools reduce invalid calls, make authorization easier and give the model a clearer choice among capabilities.

Tool descriptions should answer three questions:

  1. When should this tool be used?
  2. What does each argument mean?
  3. What does the result guarantee?

Treat Schemas as Runtime Boundaries

Validate every argument at the server boundary. Use enums for finite values, bounded integers for limits and explicit formats for identifiers. Never rely on the client to enforce a schema.

Errors should be useful and safe:

{
  "code": "INVALID_ARGUMENT",
  "message": "limit must be between 1 and 50",
  "retryable": false
}

Do not return stack traces, connection strings or unfiltered upstream errors to the model.

Authorization Must Follow the User

The MCP server should receive and enforce the caller identity. A tool that searches company documents must apply tenant and role filters before returning data. A tool that changes production state should require a stronger permission than a read-only tool.

Prompt instructions are not authorization. A malicious document or user can ask the model to ignore them. The server must make forbidden operations impossible regardless of what the model says.

Make Results Easy to Use

Return concise structured data with stable field names. Include identifiers, timestamps and links back to the source system. For large results, paginate or provide a follow-up handle instead of returning an unbounded payload.

Version tools when their contract changes. Adding an optional field is usually safe; changing the meaning of an existing field is not. Contract tests should exercise valid calls, invalid arguments, permission failures and upstream outages.

The best MCP servers feel boring: predictable tools, strict validation, least-privilege access and errors that help the client recover without guessing.

Found this useful? Pass it on.

AK

Written by Adarsh Gupta

Full Stack Developer building admin panels · backend apis from Jaipur, India.

Say hi