·9 min read·By Vijay Amin

How to Build an MCP Server: Step-by-Step Guide (2026)

MCPAI AgentsGuideArchitecture

An MCP server is a program that exposes tools, data and prompt templates to AI clients through the Model Context Protocol, an open JSON-RPC standard. Building one means defining what the AI may do (tools), what it may read (resources) and which reusable workflows it can start (prompts), then serving them over stdio for local use or Streamable HTTP for remote use. With the official SDKs, a working first server takes an afternoon; a production server with authentication, audit logging and monitoring takes a few weeks. This guide walks through each step.

What exactly are you building?

An MCP server sits between an AI client — Claude, ChatGPT, an IDE assistant like VS Code or Cursor, or your own agent — and the system you want the AI to use: a database, an internal API, a SaaS product. The client discovers what your server offers and the model decides when to use it. You expose three kinds of capability:

  • ›Tools — actions the model can invoke, each with a name, a description and a JSON Schema for its inputs. Examples: search_orders, create_ticket, get_invoice_pdf. Tools are model-controlled: the LLM chooses when to call them.
  • ›Resources — read-only data the client can load into context, addressed by URI. Examples: a customer record, a configuration file, a product catalogue.
  • ›Prompts — reusable templates a user can pick, such as 'summarise this account' or 'draft a renewal email', that package instructions and arguments.

Most business servers are tool-heavy. A good first version usually exposes 3–5 tools that map to the questions people actually ask — not a one-to-one mirror of every API endpoint you have.

Step 1: Which tools should the server expose?

Start from tasks, not endpoints. List the 5–10 things you want an assistant to do, then design one tool per task. A tool called find_customer_by_email that returns the five fields an agent needs is far easier for a model to use correctly than a generic call_api tool that takes a URL and a JSON body.

  • ›Write descriptions for the model, not for humans: say what the tool does, when to use it, and what it returns. The description is effectively part of your prompt.
  • ›Keep input schemas tight — enums instead of free text, required fields marked, formats stated (ISO dates, currency codes).
  • ›Split read and write tools. get_order and refund_order should be separate tools so you can scope, confirm and log them differently.
  • ›Return compact, structured results. Large raw payloads waste context and confuse the model; the spec supports structured output with an optional outputSchema.
  • ›Return actionable errors. The spec distinguishes protocol errors from tool execution errors (isError: true); a message like 'date must be in the future' lets the model correct itself and retry.

Step 2: Which SDK and language should you use?

The protocol has official SDKs in TypeScript, Python, C#, Go, Rust and Ruby (the Tier 1 SDKs), plus Java, Swift, PHP and Kotlin. Pick the language your team already runs in production, because the server will live alongside your existing services. TypeScript and Python have the most examples and community servers to learn from.

In TypeScript, install @modelcontextprotocol/server and zod, create an McpServer with a name and version, and call registerTool with a tool name, a description, a zod input schema and an async handler that returns content. The official quickstart then serves it over stdio with serveStdio(createServer), which negotiates protocol versions with each client.

In Python, add the mcp package (uv add "mcp[cli]"), create the server with from mcp.server import MCPServer and mcp = MCPServer("orders"), decorate a typed async function with @mcp.tool() — the docstring becomes the tool description and the type hints become the input schema — and finish with mcp.run(transport="stdio").

One rule catches almost everyone on day one: a stdio server must never write to stdout. stdout carries the JSON-RPC messages, so a stray print() or console.log() corrupts the stream. Log to stderr or to a file instead.

Step 3: Should the server run locally (stdio) or remotely (Streamable HTTP)?

MCP defines two standard transports. The choice depends on who uses the server and where the data lives.

MCP transports compared
stdioStreamable HTTP
How it runsClient launches the server as a local subprocessServer runs as a web service at one MCP endpoint, e.g. https://api.example.com/mcp
Typical usersOne developer on one machineMany users, teams or customers
Good forIDE tools, filesystem, git, local CLIsInternal APIs, SaaS integrations, shared business data
CredentialsFrom the local environmentOAuth 2.1 access tokens per request
DeploymentPackage (npm, PyPI, binary)Container or serverless behind HTTPS

Streamable HTTP replaced the older HTTP+SSE transport in the 2025-03-26 protocol revision, and the old transport is now deprecated — don't start new work on it. In the current revision (2026-07-28) each client message is its own HTTP POST and the server replies with JSON or a stream scoped to that request; there are no protocol-level sessions. That makes remote servers simpler to scale: any instance can answer any request.

Step 4: How do you test an MCP server?

Use MCP Inspector, the official testing tool. Run npx @modelcontextprotocol/inspector against your server to list its tools, call them with sample inputs and inspect the raw responses — before any LLM is involved. Its CLI mode is useful in CI, for example to assert that tools/list returns the tools you expect.

  • ›Unit-test each tool handler like any other function: valid input, invalid input, upstream API failure.
  • ›Test with a real client next. For Claude Desktop, add the server to claude_desktop_config.json and restart; other clients (VS Code, Cursor, ChatGPT connectors for remote servers) have their own configuration screens.
  • ›Evaluate tool selection, not just tool execution. Give the model 20–30 realistic requests and check it picks the right tool with the right arguments. Most production fixes are description and schema rewrites, not code changes.

Step 5: How do you deploy a remote MCP server on AWS?

A remote MCP server is an HTTPS service, so the usual AWS options apply. Because the current protocol is stateless per request, both serverless and container hosting work; the deciding factors are request duration and streaming.

Hosting a remote MCP server on AWS
AWS LambdaECS on Fargate
Best forShort request/response tools, spiky or low trafficLong-running tools, streamed progress, steady traffic
Cost profilePay per invocation; near zero when idlePay for running tasks; predictable
Limits to check15-minute maximum run time; response streaming support in your front doorTask sizing and auto-scaling rules
Typical front doorAPI Gateway or a Lambda function URLApplication Load Balancer

Whichever you choose, keep secrets in AWS Secrets Manager, give the server's IAM role only the permissions its tools need, run it in a private subnet when it calls internal systems, and ship logs and traces to CloudWatch or your observability stack. For teams standardising on AWS agents, Bedrock AgentCore can also consume MCP servers as tools — see our AgentCore guide linked below.

Step 6: How do you add authentication to a remote server?

The MCP authorization spec is built on OAuth 2.1. Your server acts as an OAuth resource server: it publishes Protected Resource Metadata (RFC 9728) pointing to your authorization server, answers unauthenticated requests with 401 and a WWW-Authenticate header, and validates every access token — including that it was issued for this server (audience binding). Clients use PKCE and the resource parameter (RFC 8707) to obtain tokens. In practice you plug in the identity provider you already run — Amazon Cognito, Okta, Microsoft Entra ID or Auth0 — rather than writing an authorization server.

Two rules matter most. Never pass the client's token through to downstream APIs (the spec forbids token passthrough) — call them with the server's own credentials. And scope tools to the caller: a read-only role should not even see write tools in tools/list. Our MCP server security checklist covers this in depth.

What are the most common mistakes?

  • ›Wrapping the whole API one-to-one — 80 tools with vague names overwhelm the model and inflate context. Fewer, task-shaped tools work better.
  • ›Writing to stdout in a stdio server, which silently breaks the connection.
  • ›Building new remote servers on the deprecated HTTP+SSE transport instead of Streamable HTTP.
  • ›Skipping Origin header validation on HTTP servers (the spec requires it, to block DNS rebinding) or binding a local server to 0.0.0.0 instead of localhost.
  • ›No confirmation step for destructive tools such as delete, refund or send.
  • ›No audit log — when an agent does something unexpected, you need to see which tool was called, by whom, with what arguments.
  • ›Returning raw stack traces to the model, which leaks internals and doesn't help it recover.

How long does it take and what does it cost?

A focused proof-of-concept exposing 3–5 tools from an existing API typically takes 1–2 weeks. A production server with 5–15 tools, OAuth 2.1, scoped permissions, rate limiting, audit logging and observability typically takes 3–6 weeks. At iMagic Solutions we deliver these as a fixed-price PoC ($8K–$15K) followed by a production build ($15K–$40K); multi-tenant servers for SaaS products shipping MCP to their own customers run 6–10 weeks. If you'd like a second opinion on which tools to expose first, book a free 30-minute call through our MCP server development page.

Frequently asked questions

Do I need an MCP server if I already have a REST API?

You need one if you want AI clients to use that API safely and portably. The MCP server translates task-level tool calls into your API's calls, and adds the controls an AI caller needs — scoping, confirmation and audit — without changing the API itself. See MCP vs API vs function calling for the trade-offs.

Can one MCP server work with Claude, ChatGPT and other clients?

Yes — that is the point of the protocol. A standards-compliant server works with any MCP client. Client support for individual features (for example remote OAuth flows or prompts) varies, so test with each client your users rely on.

Should I use an existing open-source MCP server instead?

For common systems such as GitHub, Slack or Postgres, a maintained open-source server is often the fastest start. Review its code and permissions first — third-party servers run with real credentials — and build your own for proprietary APIs and business logic.

Last updated October 21, 2026 · Written by Vijay Amin, iMagic Solutions.

Let's talk

Have a project like this in mind?

Tell us what you're working on and we'll get back within one business day.