AI Engineering

How to Build an MCP Server: A Practical Guide for Business Systems

Two dark towers joined by a sky bridge, in black and white Start with read-only tools.

To build an MCP server, pick one system you want an AI assistant to reach and expose a few read-only tools over it with an official SDK. Test them in the MCP Inspector, then connect the result to Claude or ChatGPT. The first version is small. Authentication, permissions and hosting need more care than the protocol itself.

This guide is for a technical lead, or a business owner briefing one, who wants an MCP server over a CRM, database or document store. It follows the build in order, from what to expose to how to deploy and secure it. If you want the definition first, read what an MCP server is. If you would rather hand the build over, our MCP server development service starts from £5,000.

Key takeaways

  • Start with read-only tools over one system. Add write tools later, behind human approval.
  • Use an official SDK in a language your team already runs. Build over stdio, then switch to Streamable HTTP when others need to share the server.
  • A remote server should use OAuth, check that every token was issued for it, and never pass a client’s token on to another service.
  • Write each tool description as a brief to a new colleague, and test every tool in the MCP Inspector first.
  • A technical team can follow the official quickstart to a first server. Ours starts from £5,000, with authentication, per-user permissions and deployment included.

How to build an MCP server: the decisions in order

Six decisions shape the build, and each has a sensible default. The table lists them in the order you meet them, with what we would start with.

DecisionOptionsWhat we would start with
What to exposeTools, resources, promptsRead-only tools
SDKTen official languagesYour team’s usual language
Transportstdio, Streamable HTTPstdio to build, HTTP to share
AuthenticationEnvironment credentials, OAuthOAuth via your identity provider
ClientClaude, ChatGPT, othersWhatever your team uses today
WritesOff, or on with approvalOff until the reads work

One note on versions. We read revision 2026-07-28 of the specification, the one at modelcontextprotocol.io’s “latest” address on 1 November 2026. Its changelog records that it removed protocol-level sessions and the initialize handshake, so every request now carries its own protocol version.

What should an MCP server expose?

Start with tools, and make the first ones read-only. The specification describes tools as model-controlled, meaning the language model can discover and call them on its own (tools specification). Resources and prompts exist too, but tools are what an assistant reaches for when someone asks a question about your data.

For a CRM, database or document store, start with the questions your team already pastes into an assistant by hand, such as “What is the status of this deal?” Each becomes one tool with a narrow job. Anthropic’s engineering team, in a September 2025 post on writing tools for agents, notes that one tool can handle several API calls under the hood. A single “find a customer’s open orders” tool can therefore replace several raw endpoints. The same post says, “More tools don’t always lead to better outcomes.”

Add write tools, such as updating a deal, only once the reads behave. OpenAI’s documentation says ChatGPT requires confirmation for write actions by default and respects the readOnlyHint annotation. Do not rely on an annotation for safety, though. The specification tells clients to treat tool annotations as untrusted unless they come from trusted servers. Enforce read-only access in the server’s own credentials, for example with a read-only database role.

Keep tools stateless where you can. The current revision has no protocol-level session, so a task spanning several calls needs an explicit handle that the server creates and checks belongs to the caller on every call.

Which SDK and transport should you choose?

Pick an official SDK

Use the official SDK for a language your team already runs. The SDKs page lists TypeScript, Python, C#, Go, Rust and Ruby as Tier 1, Java as Tier 2, and Swift, PHP and Kotlin as Tier 3. The tiers rate feature completeness, protocol support and maintenance commitment. When the choice is open, we would take TypeScript or Python.

The quickstart builds a weather server with two tools, get_alerts and get_forecast. In Python (3.10 or higher, with version 2.0.0 or higher of the Python MCP SDK) you create an MCPServer object and mark each tool function with @mcp.tool(). The SDK generates the tool definition from the function’s type hints and docstring. In TypeScript (Node.js 20 or higher) you install @modelcontextprotocol/server, create an McpServer and register each tool with registerTool.

Match any tutorial to the SDK version you install, since earlier releases may name things differently. The SDKs page also says SDKs adopt new revisions on their own schedules, so check which revision yours supports.

Local (stdio) or remote (Streamable HTTP)?

With stdio, the client launches your server as a subprocess on the same machine. With Streamable HTTP, the server exposes one endpoint that accepts POST requests, such as https://example.com/mcp. The older HTTP+SSE transport is deprecated, and the Streamable HTTP page says new implementations should not adopt it.

Build over stdio first. Nothing is exposed to a network, and Claude Desktop can launch the server from its claude_desktop_config.json file. A stdio server must never write to standard output, because that corrupts the JSON-RPC messages. Python’s print() does exactly that, so log to stderr instead.

Move to Streamable HTTP when more than one person needs the server. Claude’s help centre treats local servers in claude_desktop_config.json as separate from custom connectors, and ChatGPT asks for a server address or a tunnel.

How does authentication work on a remote server?

Use OAuth through an identity provider you already run, and have your server check tokens rather than issue them. In revision 2026-07-28 authorization is optional. A server on an HTTP-based transport should follow the authorization specification, which builds on OAuth 2.1. A stdio server should take its credentials from the environment instead.

The specification gives each party a role. Your MCP server is an OAuth resource server and the client acts for the user. A separate authorization server signs the user in and issues tokens, and it can be your existing identity provider.

Your server has four jobs:

  • Publish OAuth Protected Resource Metadata, so clients can find your authorization server.
  • Answer a request without a valid token with HTTP 401 and a WWW-Authenticate header that points to that metadata.
  • Check that every access token was issued for your server as its intended audience.
  • Accept no token that is not valid for your own resources, and never forward a client’s token to a downstream API.

The security guidance calls the last point token passthrough, and the authorization specification forbids it. It means your server needs its own credential for the CRM, and applying each user’s access rules is your job inside the server.

Authentication says who is asking, and permissions decide what that person can see. The specification lets a server vary its tool list by the authorization presented, for example returning only the tools the caller’s granted scopes permit.

Two things are worth checking with your identity provider. It should support OAuth Client ID Metadata Documents, which the revision prefers, because Dynamic Client Registration is deprecated and kept only for compatibility. It should also issue narrow scopes. The security guidance recommends starting with low-risk read scopes, requesting more only when a privileged operation is first attempted, and avoiding wildcard scopes such as *.

How do you write tool descriptions the model can use?

Write each description as you would brief a new colleague. Anthropic’s engineering post gives that test, and suggests naming parameters unambiguously, with user_id rather than user. Add what a newcomer would need, such as what the tool returns, when to use it instead of a neighbouring tool and what a valid input looks like.

Per the tools specification, each tool has a name, a description and an inputSchema in JSON Schema. Names should be 1 to 128 characters of letters, digits, underscores, hyphens and dots. Three habits help:

  • Return what the person needs. Names and statuses beat internal identifiers. Anthropic’s post advises prioritising contextual relevance and avoiding low-level technical identifiers.
  • Limit the size of results. The same post suggests pagination, range selection, filtering or truncation, so a large table does not flood the model’s context.
  • Report failures in the result. The specification separates protocol errors from tool execution errors. Put API failures and invalid inputs in the tool result with isError: true, and say what was wrong, so the model can correct itself and retry.

Then test the descriptions on real tasks. Anthropic recommends evaluation tasks built from real-world use, and notes that many errors on invalid parameters can mean the descriptions need to be clearer.

Test with the MCP Inspector, then connect Claude or ChatGPT

Test every tool in the MCP Inspector before an assistant sees it. It is the reference developer tool for testing and debugging servers, shipped as the @modelcontextprotocol/inspector package, and it needs Node 22.19.0 or newer. Run npx @modelcontextprotocol/inspector for the web client, add --cli for a scriptable command-line client, or --tui for a terminal interface.

Pass the command that starts your server as arguments, or use --server-url with --transport http for a remote one. On the command line, --method tools/list lists the tools and --method tools/call calls one. The Inspector can exercise both protocol eras, and the quickstart runs its TypeScript check once for each with --protocol-era.

Connect Claude

Menu names change, so these steps follow the vendors’ help pages as of 1 November 2026. For a local stdio server, add it under the mcpServers key of Claude Desktop’s claude_desktop_config.json, using absolute paths, as the quickstart shows.

For a remote server, add a custom connector under Customize > Connectors, or under Organization settings > Connectors on Team and Enterprise plans. The Claude Help Center adds four points:

  • Custom connectors are available on Free, Pro, Max, Ultra, Team and Enterprise plans, and Free users are limited to one.
  • On Team plans, only Owners and Primary Owners can add one.
  • Your server must be reachable over the public internet from Anthropic’s IP ranges, so on a private network allowlist those addresses in your firewall.
  • Sign-in is typically OAuth, although some connectors use an API key or other fixed credential.

The MCP documentation’s remote-server guide adds that you can enable or disable individual tools in the connector’s settings, a useful second layer of least privilege.

Connect ChatGPT

OpenAI’s page says to use ChatGPT on the web. Open Plugins, select the plus button and choose Add custom MCP server. Name it, then under Connection enter the server address or select Tunnel for a Secure MCP Tunnel. The supported protocols are SSE and streaming HTTP, and the authentication options are OAuth, no authentication, or OAuth or no authentication. You then accept a risk warning and create the plugin.

Workspace permissions and security restrictions, including Lockdown, apply. The page does not say which plans can add a custom server, so check yours. Build to the specification’s remote transport and test against each client’s connector.

Deploy, monitor and secure the server

Deploy and monitor

A remote MCP server is a web service with one HTTPS endpoint. The Streamable HTTP specification sets rules worth building in from the start:

  • Validate the Origin header on every connection and reject an invalid one with HTTP 403, which guards against DNS rebinding.
  • Bind a locally running server to 127.0.0.1 instead of all network interfaces.
  • Behind a proxy such as nginx, send X-Accel-Buffering: no on streamed responses so events are not buffered.

Monitoring starts with a log line for every tool call, recording who called it, which tool, how long it took and whether it succeeded. The specification says servers must rate limit tool invocations. Never log tokens or full customer records, and alert on authentication failures and error rates.

Secure it

  • Keep a person in the loop. The specification says there should always be a human in the loop with the ability to deny tool invocations. Keep write tools narrow, so update_deal_stage is easier to approve than run_crm_action.
  • Validate on the server. The specification says servers must validate all tool inputs, implement proper access controls, rate limit invocations and sanitise outputs.
  • Treat returned text as untrusted. The model reads whatever a tool returns, so a note a customer typed into your CRM could contain instructions aimed at the model. The National Cyber Security Centre’s blog post Prompt injection is not SQL injection (it may be worse) says these attacks may never be totally mitigated. It argues for reducing risk and impact. Keep read scopes narrow, return only the fields a task needs, and keep writes behind approval.
  • Be careful with other people’s servers. OpenAI’s page says to connect only to servers you trust, and the specification treats descriptions of tool behaviour as untrusted unless they come from a trusted server.
  • Remember that a local server runs with the client’s privileges. The security guidance recommends stdio for locally run servers because it limits access to the client. Install them only from sources you trust.

What it costs, and your next step

A technical team can follow the quickstart to a working first server without outside help. In our view the effort sits in making it safe for work, meaning OAuth against your identity provider, per-user permissions, hosting, monitoring and a security review. It grows with the number of systems and the quality of their APIs. Our API integration guide covers the layer underneath.

We build and run MCP servers every day in our own engineering work. We have no client MCP server to point at yet, and we would rather say so than invent one. The standard is young, so we treat security as the first requirement. Our published prices:

  • First MCP server, from £5,000. One system connected to Claude or ChatGPT, with authentication and per-user permissions built in, deployed as a remote server your team can use.
  • AI integration build, from £10,000. MCP servers across several systems, such as a CRM, a database and documents. It includes remote hosting on AWS that is monitored and maintained, with access scoped per user.
  • Ongoing support, from £400 a month.

Scope and price are fixed and agreed before work starts. On a build you can cancel in the first 21 days and get your money back in full. The code and IP are yours once the work is delivered and paid for.

If the system you want to connect has no usable API, the connection is the larger job. Our enterprise software integration service connects ERP, CRM and finance systems and wraps legacy systems with modern APIs. If you want an AI agent to act through the server, with sign-off where it matters, that is our AI agents work.

Your next step is to choose one system and list the five questions people paste into an assistant by hand. That list is the scope of a first server, and the brief we would ask for on a call. Build it yourself with the quickstart, or hand it to us through our MCP server development page, which has the fixed prices.

Frequently asked questions

How do I build an MCP server?

Pick one system, choose an official SDK and expose a few read-only tools. Test them in the MCP Inspector, then connect the server to Claude or ChatGPT. Build over stdio first, and move to Streamable HTTP with OAuth when a team needs to share it. The official quickstart walks through a two-tool server in Python or TypeScript. Add write tools only after the reads behave, and keep them behind human approval.

Which language should I use to build an MCP server?

Use the language your team already runs. The official SDKs cover TypeScript, Python, C#, Go, Rust and Ruby at Tier 1, Java at Tier 2, and Swift, PHP and Kotlin at Tier 3. If the choice is open, TypeScript or Python is a safe start, because both are Tier 1 and the official quickstart builds a server in each.

Does an MCP server need authentication?

Not always. The specification makes authorization optional, and says a stdio server should take its credentials from the environment instead. A remote server on an HTTP transport should follow the authorization specification, which is based on OAuth 2.1. Your server acts as a resource server, checks that each token was issued for it, and accepts no others. Any server that touches business data should authenticate its users.

How do I test an MCP server?

Use the MCP Inspector, the official testing tool. Run npx @modelcontextprotocol/inspector followed by the command that starts your server, or add the --cli flag to script it. It needs Node 22.19.0 or newer. List the tools, call each one with valid and invalid inputs, and read the raw messages. For a remote server, pass its address with --server-url and --transport http.

How much does it cost to build an MCP server?

Our First MCP server starts from £5,000. It connects one system to Claude or ChatGPT, with authentication and per-user permissions, deployed as a remote server your team can use. The AI integration build, covering several systems with AWS hosting that we monitor and maintain, starts from £10,000. Ongoing support starts from £400 a month. Scope and price are fixed and agreed before work starts.

Connecting AI to your own systems?

Book a free 20-minute consultation and we'll scope a first MCP server for the system you want your AI assistant to reach.

Book a consultation

Keep exploring

Back to all insights

Book a free call with Vivian

COO and co-founder · London

Request a callback

Leave your name and number and we'll call you back.