All articles
    MCP

    How to Build an MCP Server: A Step-by-Step Developer Guide

    A practical walkthrough for building an MCP server — choosing a transport, defining tools and schemas, handling auth and errors, testing with MCP Inspector, and shipping it to Claude, ChatGPT and Cursor.

    VeriMailX Team August 11, 2026 13 min read
    How to Build an MCP Server: A Step-by-Step Developer Guide

    Key takeaways

    • Start by listing the 3–8 actions a model should be able to take; each becomes a tool with a strict JSON schema.
    • Use stdio transport for local developer tools and streamable HTTP for hosted, multi-user servers.
    • Tool descriptions are prompt engineering: say when to use the tool, what it costs, and what it returns.
    • Validate every input, return structured errors, and keep responses compact so you do not flood the model's context.
    • Test with MCP Inspector before connecting to a real assistant, then verify the same flow in Claude and Cursor.

    Building an MCP server is less about protocol plumbing than about designing a small, opinionated interface a language model can use correctly on the first attempt. This guide walks the whole path, from tool design to a hosted server your users can add to Claude, ChatGPT or Cursor.

    Step 1 — Decide what the model should be able to do

    Write the list before you write any code. For each candidate action, ask:

    • Would a user ever ask an assistant for this in plain language?
    • Can it be described with fewer than six parameters?
    • Is the result something a model can summarise usefully?

    For VeriMailX the answer produced five tools: verify a single address, verify a small batch, check whether a domain is disposable, read the account's credit balance, and list recent verification jobs. Everything else — billing, team management, white-label settings — stays in the dashboard, because nobody wants an assistant doing that.

    A good rule: if a mistaken call would be expensive or irreversible, either do not expose it as a tool or require an explicit confirmation parameter.

    Step 2 — Choose your transport

    stdio (local)

    The server runs as a child process of the client. Configuration looks like a command plus arguments. Best for filesystem access, local repos, developer utilities. No auth layer is needed because the process already runs as the user.

    Streamable HTTP (remote)

    The server is a web endpoint, for example `https://yourapp.com/mcp`. Users paste the URL into their client and authorise it. This is the correct choice for any SaaS product: one deployment serves every customer, updates ship instantly, and you can identify and meter each caller.

    Step 3 — Define tools with strict schemas

    Every tool needs a name, a description and an input schema. The schema is your guardrail; the description is your prompt.

    Aim for descriptions that answer three questions in two sentences: what does this do, when should the model use it, and what does it cost?

    A weak description: *"Verifies an email."*

    A strong description: *"Performs a full SMTP-level deliverability check on one email address and returns valid / invalid / risky / catch-all / disposable. Consumes one credit per call. Use for a single address; for more than one address use verify_email_list."*

    Notes that pay off immediately:

    • Use enums rather than free-text strings wherever the value set is known.
    • Mark optional parameters optional; do not force the model to invent values.
    • Cap array sizes in the schema itself (for example, at most 20 addresses) instead of only rejecting at runtime.

    Step 4 — Implement the handlers

    Each handler should follow the same shape:

    • Authenticate the caller and resolve them to an internal user.
    • Validate the arguments against the schema, then again against business rules.
    • Check entitlements: plan, quota, credits, feature flags.
    • Execute by calling your existing service layer — never duplicate business logic in the MCP layer.
    • Return a compact, structured result.

    Keep responses small. A model reads the entire response into context, so returning 4,000 rows of raw JSON is worse than returning counts plus the first twenty examples plus a link to the full export.

    Step 5 — Handle authorization properly

    For remote servers, OAuth 2.1 with dynamic client registration is the expected pattern. Practically:

    • The client discovers your authorization server from protected-resource metadata.
    • The user is redirected to a consent screen where they sign in to your product.
    • Your server issues a token bound to that user.
    • Every tool call is executed as that user, with the same row-level permissions the dashboard applies.

    Never expose a shared admin token in an MCP server. If a tool can read records, it must only read records the signed-in user already owns.

    We cover the full flow in remote MCP servers and OAuth.

    Step 6 — Make errors useful to a model

    Models recover from errors surprisingly well if you tell them what happened and what to do next.

    • Bad: `500 Internal Server Error`.
    • Good: `insufficient_credits: 12 credits remaining, 40 required. Suggest verifying a smaller batch or topping up at /dashboard/billing.`
    • Good: `invalid_argument: 'emails' must contain at most 20 items; received 63. Split the list into batches.`

    Return errors as normal tool results with an error field rather than crashing the transport, so the assistant can retry intelligently.

    Step 7 — Test before you ship

    • Run the MCP Inspector against your server and confirm the tool list, schemas and descriptions render as intended.
    • Call each tool with valid, invalid and edge-case arguments.
    • Connect to a real client and test with vague natural-language prompts, not the exact tool name. If the model picks the wrong tool, the description is the bug.
    • Test the unauthenticated path: an anonymous request must return 401 with the correct metadata pointer, not data.

    Step 8 — Document the connection for users

    Your users need three lines: the server URL, how to add it in their client, and what happens on first sign-in. Add a short list of example prompts — people adopt MCP servers far faster when they can copy a prompt that already works.

    Common mistakes

    • Too many tools. Merge near-duplicates into one tool with a parameter.
    • Chatty output. Summarise; do not dump.
    • No cost signalling. If a call spends credits, say so in the description.
    • Ignoring idempotency. Assistants retry. Make repeated calls safe.
    • Forgetting rate limits. A looping agent can call a tool hundreds of times in a minute.

    A working example

    VeriMailX's own MCP server is a thin layer over the same verification engine the dashboard and REST API use. It is remote, OAuth-protected, and meters credits per user. That means a developer can ask Claude "verify these 18 addresses and tell me which to keep" and get a real SMTP-level answer without leaving the chat.

    Start with what an MCP server is if you need the conceptual grounding, or see the email verification MCP server in action.

    Frequently asked questions

    Ready to clean your list?

    Verify your emails with VeriMailX and send your next campaign with more confidence, fewer bounces and better results. Unlimited free single email verification — no card required.

    Keep reading

    MCP

    What Is an MCP Server? A Plain-English Guide to Model Context Protocol

    An MCP server lets AI assistants like Claude, ChatGPT and Cursor call real tools and read real data. Here is what Model Context Protocol is, how an MCP server works, and when you need one.

    Read
    MCP

    Remote MCP Servers and OAuth: How Authentication Works

    Remote MCP servers let anyone connect a hosted tool to Claude, ChatGPT or Cursor with a URL. Here is how OAuth 2.1, dynamic client registration and per-user scoping keep those connections safe.

    Read
    MCP

    Email Verification Inside Claude and ChatGPT: Using an MCP Server

    Connect the VeriMailX MCP server to Claude, ChatGPT or Cursor and verify email addresses, clean lists and check disposable domains without leaving the chat. Setup, tools and example prompts.

    Read