MCP Server Design: Tools, Boundaries, and Context

Good MCP server design happens before the first line of code. Defining focused tools, clear data boundaries, authorization rules, and useful response formats upfront saves significant rework once an AI assistant starts using the server in real conditions.

Updated 6 min read

MCP server design is the work you do before writing the first handler. It answers three questions: what exactly will each tool do, what data may the server expose or modify, and how will the server know whether a caller is authorized to ask. Getting those answers right on paper is faster than correcting them in code.

The design decisions you make also need to survive the next person picking up the work. Tools like fenbs store those architecture decisions where every connected AI reads them first, so a change to a tool contract is recorded as a decision, not silently lost in a diff.

Start with the workflow, not the tools

Begin with a specific workflow you want an AI assistant to complete. "A support agent should be able to look up an order by ID and see its current status" is a workflow. "Give the AI access to the orders system" is not.

Write the workflow as a short sequence of steps the AI will follow. Identify which steps require data the AI does not have in the chat. Each of those becomes a tool candidate. Avoid designing tools that "might be useful later" — every unused tool adds noise to the server's tool list that the AI reads on every call.

One tool, one clear action

A well-designed MCP tool does one thing. It has a name that is an unambiguous verb-noun pair (get_order_status, list_open_tickets, create_draft_email). It takes the minimum inputs needed to complete the action. It returns exactly the information the caller needs, not a dump of the underlying record.

Avoid combining two actions into one tool "for convenience." A search_and_update tool is harder to describe, harder to test, and harder to authorize safely. Two tools — one that searches, one that updates with an explicit id — are easier to audit and easier to explain to an AI that needs to decide whether to call them.

  • Name: a specific verb-noun pair that leaves no ambiguity about what the tool does.
  • Description: one or two sentences explaining when to call this tool and what it returns.
  • Inputs: the minimum set needed; every additional parameter is a decision surface.
  • Output: the information the caller needs, not the raw database record.
  • Errors: a clear isError: true response with a plain explanation for each failure mode.

Define data boundaries first

Before designing the tools, define what data the server may and may not expose. This is a human decision, not a technical one. Which tables, fields, or records are in scope? Which contain personal data, financial records, or audit trails that must not be exposed to an AI?

Write down the boundaries as explicit rules: "The server may read the orders table but not the payment_methods table." That rule belongs in a Decisions and rules entry in your project, not just in a comment in the code. Code can be changed quietly; a recorded decision requires a recorded reason.

Data boundaries also determine the shape of your tools. If a tool may only return non-personal fields from an order record, design the response schema to include only those fields. A response that includes everything and relies on the AI to ignore sensitive parts is not a boundary — it is a hope.

How fenbs helps

Store architecture decisions where your team shares them

Add the data boundaries, tool contracts, and authorization rules for your MCP server as Decisions and rules in fenbs. When a tool's contract changes, record it as a new decision linked to the original. Every AI assistant connected to the project reads these decisions first, so changes to the design are visible before anyone builds on an old assumption.

Create a free account

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

Design for refusal

Every tool needs a defined behavior when it should not proceed. An AI assistant that calls a write tool with an id that does not exist, or with a caller who lacks permission, should receive a clear error it can describe — not a silent failure or an unhandled exception.

Design the refusal paths explicitly. For each tool, write down: what happens when the input is invalid, when the caller lacks authorization, and when the underlying service is unavailable. Return isError: true with a plain explanation in the content. The AI can relay that explanation; it cannot recover gracefully from a crash.

Authorization and caller context

An MCP server needs to know who is calling it before it runs a tool that reads or writes sensitive data. For local stdio servers, the caller is the user who started the AI client — you can treat that as implicit authorization for that user's tools.

For remote servers used by a team, authorization is more explicit. The MCP specification supports OAuth for remote server authentication. The server receives a token with the caller's identity and permissions, and tools check that token before acting. Design the permission model before you build the tools, so the checks are built in rather than bolted on.

See the mcp server spec for the authentication details the protocol defines.

Write useful response formats

A tool's output is what the AI reads and then uses or reports. Responses that are too long waste the context window. Responses that are too terse leave the AI guessing.

For lookup tools, return the fields the next step needs plus a human-readable summary line. For list tools, return a short summary of each item rather than every field of every record. For write tools, confirm what changed with enough detail for the AI to report the result accurately.

Avoid returning HTML, markdown with heavy formatting, or raw JSON blobs as tool output. Plain text or minimal structured text is easier for the AI to incorporate into a response.

How to do this with fenbs

  1. Create a free account and set up a project for the MCP server you are designing.
  2. Write each planned tool as a task: its name, its action, its inputs, its output, and its refusal paths. Note which tools are in scope for the first version.
  3. Record the data boundaries as Decisions and rules: which data may be exposed, which tables or fields are off limits, and who decided this.
  4. Record the authorization model: who may call each tool, what token or credential the server expects, and what the refusal looks like.
  5. When the design changes during implementation, update the decisions and add notes about what changed and why. Link changes to the tasks they affected.

fenbs does not run MCP servers or execute tool calls. It is the shared record where the decisions behind the server live, so the next developer or AI assistant reading the project knows the agreed design rather than guessing from the code.

Questions people ask.

How many tools should an MCP server expose?

As few as needed for the workflows you are supporting. Every tool the server declares appears in the list the AI reads before each call. A large, unfocused tool list makes it harder for the AI to pick the right tool and easier for it to call the wrong one.

Should I design tools around the data model or around the workflows?

Design around the workflows. A tool that matches a specific workflow step is more useful than a generic CRUD tool that maps to a database table. Workflow-oriented tools are also easier to describe clearly, which makes them more reliable in practice.

How do I handle tools that need to be called in a sequence?

Design each tool to be useful in isolation. If a tool requires the output of another tool as input, make that dependency clear in both tools' descriptions. Avoid tools that silently depend on undocumented state from a previous call.

Where should authorization checks live in an MCP server?

In the tool handler, before any data is read or written. Checking authorization at the tool level means every call path is covered. Do not rely on the client to filter calls — an AI assistant may call any tool the server declares.

What is the best way to document the design decisions for an MCP server?

Record them as Decisions and rules in a shared project record like fenbs, linked to the tasks they affect. A comment in code can be changed without discussion; a recorded decision requires a recorded reason and makes changes visible to the whole team.

More in Connect your AI tools

All Connect your AI tools articles

Start with one thing.

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

There is nothing to set up first. Write one line and you’ve started.