blog

How to Build an MCP Server: A Practical Developer Guide

By khurram May 28, 2026 13 min read
 

Building an MCP server is the practical step that transforms theoretical understanding of Model Context Protocol into real capability. An MCP server you build today can be used by Claude Desktop, Cursor, Claude Code, and any future MCP-compatible AI application — connecting those tools to your databases, APIs, file systems, and services through a standardised interface. This guide walks you through the complete process: from understanding the architecture to writing your first server, testing it, and putting it into production. It is how to build an MCP server — practical, technical, and directly applicable.

Prerequisites and Setup

Building an MCP server requires Node.js 18 or later (for TypeScript/JavaScript) or Python 3.10 or later. Anthropic provides official SDKs for both languages — the TypeScript SDK (@modelcontextprotocol/sdk) is installed via npm, the Python SDK (mcp) is installed via pip. For this guide we will use TypeScript, which is the most common implementation language due to strong typing, the broad JavaScript ecosystem, and the large number of TypeScript examples in the community. The same concepts apply to Python with syntactically different implementations.

Install the SDK and create a basic project structure. A minimal MCP server project needs package.json with the SDK dependency, a TypeScript configuration file, and your server implementation file. The SDK handles all protocol-level concerns — you implement the business logic of what your tools do, and the SDK handles the MCP communication layer.

Understanding the MCP Server Structure

Server Initialisation

An MCP server is created by instantiating the Server class from the SDK with a name, version, and capability declarations. The name identifies your server in the host application’s interface. The version follows semantic versioning. Capabilities declare which MCP primitives your server supports — tools, resources, prompts, or any combination. Most servers implement tools as the primary capability; resources and prompts are optional additions.

The server instance handles three categories of requests. The tools/list handler returns an array of tool definitions — each tool’s name, description, and input schema. The tools/call handler receives a tool name and parameters and executes the corresponding function, returning the result. If your server also exposes resources, the resources/list and resources/read handlers are implemented similarly. The SDK dispatches incoming JSON-RPC requests to your registered handlers automatically.

Defining Tools

Tool definitions are the most important part of your MCP server design. Each tool requires a name (machine-readable identifier, lowercase with underscores), a description (human-readable text that the LLM will read to understand what the tool does and when to use it), and an inputSchema (JSON Schema defining the parameters the tool accepts). The description is where you invest the most care — a vague description produces unreliable tool calls from the LLM; a clear, specific description with usage guidance produces accurate, appropriate tool invocations.

A well-written tool description answers four questions: what the tool does, when the LLM should call it, what the parameters mean, and what the response contains. For a database query tool: “Executes a read-only SQL query against the production database. Use when you need to retrieve specific data that is not available through other tools. The query parameter accepts standard PostgreSQL SELECT syntax. Returns rows as JSON objects. Do not use for data modification operations — use the execute_write tool for INSERT, UPDATE, or DELETE operations.”

Implementing Tool Handlers

The tools/call handler receives the tool name and validated parameters. It switches on the tool name and calls the corresponding implementation function. Each implementation function performs the actual work — database query, API call, file operation, computation — and returns a result in the MCP response format. Tool responses contain a content array with one or more content items, typically of type “text” with a text field containing the result. For structured data, JSON.stringify the result into the text field. For errors, set isError: true and include an error message in the text field — this tells the LLM that the tool call failed and why, enabling it to handle the error gracefully rather than misinterpreting an error response as a successful result.

Practical Example: A PostgreSQL MCP Server

PostgreSQL MCP server tool design showing query database list tables and describe table tools with descriptions and parameters
PostgreSQL MCP Server — Tool Design with query_database, list_tables and describe_table

A PostgreSQL MCP server is one of the most useful servers you can build and demonstrates all the key patterns. The server initialises a database connection pool using the pg library, exposes several tools — query_database for read operations, list_tables to show available tables, describe_table to show column information for a specific table — and handles each tool call by executing the appropriate database operation and returning results.

Key implementation details: use a connection pool rather than individual connections for efficiency; limit query results to a reasonable maximum row count to prevent large responses that consume excessive tokens; implement query allowlisting or read-only database user credentials to prevent the AI from inadvertently executing destructive queries; return column names alongside data so the LLM understands the structure of results; and include row count in responses so the LLM knows whether results were truncated.

The describe_table tool is particularly valuable — it allows the LLM to discover the database schema dynamically rather than requiring you to document it in the tool descriptions. An LLM that can list available tables and describe their schemas can construct appropriate queries for any table, making the server useful across different databases without code changes.

Practical Example: A REST API MCP Server

Wrapping a REST API as an MCP server is the most common pattern in enterprise AI deployments. The server accepts API credentials from environment variables, implements tools that correspond to meaningful operations (not necessarily one-to-one with REST endpoints), and translates MCP tool calls into HTTP requests using fetch or axios.

Good design for a REST API wrapper: choose tools that represent complete, meaningful operations rather than raw endpoint mappings. A CRM API wrapper should have tools like “find_customer_by_email,” “create_support_ticket,” and “update_opportunity_stage” — not “GET /v2/contacts,” “POST /v2/tickets,” “PATCH /v2/opportunities/{id}.” The MCP abstraction layer translates AI-natural operations into the appropriate API calls, potentially combining multiple API calls into a single logical tool. This abstraction also insulates your AI applications from API versioning changes — update the MCP server implementation when the underlying API changes, and your AI applications continue working unchanged.

Transport: Stdio vs HTTP/SSE

MCP servers connect to hosts through one of two transports. Stdio transport runs the MCP server as a child process of the host application, communicating through standard input and output streams. This is the standard transport for local MCP servers used with Claude Desktop and most developer tools — it is simple, requires no network configuration, and the server process is managed by the host. The host application’s config file specifies the command to start the server process and any environment variables it needs.

HTTP with Server-Sent Events (SSE) transport runs the MCP server as a standalone HTTP service that clients connect to over the network. This is appropriate for shared MCP servers used by multiple developers on a team, servers that need to run on cloud infrastructure, or servers that must be accessible from multiple host applications simultaneously. The HTTP/SSE transport requires the server to listen on a port and handle connection management, but the SDK provides this infrastructure — you implement the same tool handlers regardless of transport.

Testing Your MCP Server

MCP server testing workflow showing MCP Inspector unit tests and Claude Desktop integration testing steps
MCP Server Testing Workflow — Unit Tests, MCP Inspector and Claude Desktop

Using the MCP Inspector

The MCP Inspector is a browser-based testing tool provided by Anthropic that connects to your local MCP server and lets you test tool calls directly without going through a host application. Install it via npx @modelcontextprotocol/inspector and run it alongside your server. The Inspector shows your server’s tool definitions, lets you manually trigger tool calls with custom parameters, and displays the raw responses — invaluable for verifying tool descriptions look correct, parameters validate as expected, and responses are formatted appropriately before you test with an actual AI model.

Testing with Claude Desktop

Claude Desktop provides the most realistic testing environment for your MCP server. Add your server to the Claude Desktop config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%Claudeclaude_desktop_config.json on Windows), restart Claude Desktop, and your tools are available in the interface. Testing with Claude Desktop lets you observe how Claude actually uses your tools — whether it calls them at appropriate times, whether the descriptions are clear enough for correct parameter selection, and whether the responses provide what Claude needs to continue reasoning. This testing often reveals description improvements that the MCP Inspector cannot catch because it does not involve LLM reasoning.

Automated Testing

MCP server tool handlers are ordinary functions that can be unit tested independently of the MCP protocol. Test the underlying implementation functions directly for correctness, edge cases, and error handling. For integration tests, the MCP SDK provides utilities for creating test client connections to your server process, enabling programmatic test scenarios that verify the full MCP protocol interaction. Include tests for invalid parameter inputs, missing required fields, database connection failures, API timeout scenarios, and rate limit responses — the error conditions that AI models will encounter in production and need to handle gracefully.

Production Deployment Considerations

Security Hardening

MCP servers in production require careful security hardening. Store all credentials in environment variables — never in code or config files. Implement the principle of least privilege: database users used by MCP servers should have only SELECT on the tables they need, not broad database access. Add rate limiting to prevent runaway AI agent loops from overwhelming your backend services. Validate and sanitise all tool parameters even though the SDK validates against the schema — schema validation catches type errors but does not validate business logic constraints. Implement audit logging for all tool invocations in regulated environments. Consider IP allowlisting for HTTP/SSE servers to restrict which clients can connect.

Monitoring and Observability

Instrument your MCP server with structured logging that records each tool invocation with its parameters (sanitised of sensitive data), execution time, success or failure, and error details. This log data is invaluable for debugging AI agent failures — when an AI agent produces unexpected results, the tool invocation log shows exactly what tools were called, in what order, with what parameters, and what responses were returned. Export metrics on tool call frequency, latency distribution, and error rates to your monitoring platform. Unusual patterns — tools called at very high frequency, tools consistently returning errors, unexpected parameter patterns — are signals worth alerting on.

Versioning Your MCP Server

MCP servers in production are consumed by AI applications that have built expectations around your tool interfaces. Treat your MCP tool interface with the same discipline as a public API: add new tools and new optional parameters freely, but avoid removing tools or changing required parameter names — these are breaking changes that require coordinated updates across all consumers. Use semantic versioning in your server declaration, and maintain a changelog of tool interface changes. When breaking changes are necessary, provide a deprecation period with both old and new tool interfaces available simultaneously.

Frequently Asked Questions

How long does it take to build a basic MCP server?

A functional MCP server with 2 to 3 tools can be built and tested in 2 to 4 hours for a developer familiar with TypeScript or Python and the underlying service being integrated. The MCP SDK handles the protocol complexity, leaving only the business logic of the tools themselves. A PostgreSQL MCP server with query, list_tables, and describe_table tools — including testing with the MCP Inspector and Claude Desktop — is a realistic first-day project. More complex servers with many tools, authentication flows, error handling, and production hardening take longer proportionally — budget a full day for a production-ready server with 5 to 10 tools and comprehensive error handling. The most time-intensive part is usually writing clear tool descriptions that produce reliable LLM behaviour, not the implementation code itself.

Should I build one large MCP server or many small ones?

The MCP architecture supports connecting multiple servers simultaneously, which enables a modular approach: one server per service or domain. A database server, a GitHub server, an internal API server, and a file system server each focus on their domain and can be developed, tested, and deployed independently. This is generally preferable to one monolithic server containing all tools — smaller servers are easier to test, easier to maintain, and can be updated independently. The practical limit is that too many connected MCP servers with too many tools can overwhelm the LLM’s tool selection — if a host has 50 servers with 300 total tools, the model may struggle to choose appropriately. Group related tools into coherent servers, and limit the number of connected servers to what the AI actually needs for the current task context.

Can I monetise an MCP server?

Yes — MCP server monetisation is an emerging area as the ecosystem grows. The most straightforward approach is building MCP servers that provide access to paid data sources or services, where the MCP server handles authentication and billing for API access. SaaS products are increasingly publishing official MCP servers as a way to make their services accessible to AI-powered tools — this is a distribution channel rather than a direct revenue source, driving adoption of the underlying paid service. Some developers are publishing MCP servers as open-source with commercial support contracts for enterprise deployments. The MCP ecosystem is early enough that commercial models are still forming — building high-quality MCP servers for popular services and publishing them publicly builds credibility and developer community goodwill even before direct monetisation is clear.

Conclusion

Building an MCP server is one of the highest-leverage activities available to a developer in 2026. The skills are straightforward, the SDK removes most of the protocol complexity, and the output — a portable, standardised integration usable by any MCP-compatible AI application — delivers compounding value as the MCP ecosystem grows. Start with the service your team most needs AI access to, build a focused server with well-described tools, test it thoroughly with the MCP Inspector and Claude Desktop, and deploy it for your team. The feedback loop of watching AI models use your tools and refining descriptions based on observed behaviour rapidly improves quality. The best way to learn MCP server development is to build one.

Need help building MCP servers for your enterprise data and services? Talk to Lycore — we design and build custom MCP integrations and AI application infrastructure for businesses across the United States and Europe.