CyberFreezeDev Loading
  1. Home
  2. Blog
  3. How-to guides
  4. How to build an MCP server for your internal tools

How-to guides

How to build an MCP server for your internal tools

An MCP server lets Claude and other AI clients use your CRM, database or ticket queue through tools you define. Here is how to design one for the current 2026-07-28 spec, starting read-only.

Blue and white network cables packed into the ports of a rack switch
Blue and white network cables packed into the ports of a rack switch

To build an MCP server, you wrap one internal system, such as a CRM, a database or a ticket queue, in a small program that speaks the Model Context Protocol: it lists tools with JSON Schema inputs, runs them when an AI client calls, and returns the results. Start with one read-only tool over stdio, add OAuth when you move it to Streamable HTTP, and log every call.

People writing in notebooks around a cafe table with a laptop and coffee
Most internal tools worth exposing to an AI client already hold the records a sales or support team looks up all day.

What is an MCP server?

The Model Context Protocol is an open protocol that connects AI applications to tools and data. A host (Claude, an IDE, your own app) runs a client for each server it connects to, and they exchange JSON-RPC 2.0 messages.

The current revision is 2026-07-28, published on 28 July 2026, and it changed a lot. The protocol is now stateless: there is no initialize handshake, and every request carries its protocol version and client capabilities in _meta. Servers must answer server/discover with the versions they support. The TypeScript, Python, Go and C# SDKs support this revision; Rust support is in beta. Older guides that open with a handshake describe 2025-11-25 and earlier.

If you know function calling, a tool is the same idea: a name, a description and an input schema. MCP makes it portable, so one server works with any compliant client.

Tools, resources or prompts?

A server can offer three things, and the spec says who is in control of each:

Primitive Controlled by Use it for CRM example
Tools The model Lookups and actions find_contact, get_deal
Resources The application Context the client attaches The list of pipeline stages
Prompts The user Templates picked from a menu "Brief me on this account"

Most internal servers are mostly tools. The 2026-07-28 revision also deprecates Roots, Sampling and Logging, so new servers should not build on them.

stdio or Streamable HTTP?

stdio is for a server on the user's own machine. The client launches it as a subprocess and talks over stdin and stdout. Nothing but MCP messages may go to stdout, so write logs to stderr. Credentials come from the environment, not from OAuth.

Streamable HTTP is for a shared server your whole team uses. It exposes one endpoint, each message is an HTTP POST, and the server answers with JSON or a short SSE stream for that request. The current spec has no sessions; if a tool needs state across calls, return a handle (an opaque ID) and accept it as an argument. Three rules from the spec: validate the Origin header on every request, bind to 127.0.0.1 when running locally, and authenticate every connection. The older HTTP+SSE transport is deprecated.

How should authentication work?

Authorization is optional in the spec, but for company data treat it as required. On HTTP, your server is an OAuth 2.1 resource server. It must publish Protected Resource Metadata (RFC 9728) so clients can find the authorization server, check that each token was issued for this server, and refuse any other token. Never pass the user's token through to the CRM; call the CRM with credentials the server controls, scoped to that user.

Two useful details: tools/list may vary with the caller's scopes, so a sales rep can see fewer tools than a manager, and an under-scoped call should get a 403 naming the scope it needs.

Example design: a CRM lookup server

  1. find_contact: input query (string, up to 100 characters) and limit (integer, 1 to 10). Returns id, name, company, owner and last_activity as structuredContent that matches an outputSchema. Annotations: readOnlyHint: true, openWorldHint: false.
  2. get_deal: input a deal id; returns stage, value, next step and owner, filtered by what this user may see in the CRM.
  3. Resource crm://pipelines: stage names, so the model uses your real vocabulary.
  4. Prompt account-brief: a template the user picks, which calls both tools.
  5. Errors come back as isError: true with a message the model can act on: "No contact matches 'Acme Ltd'; try the company's short name."
  6. Limits: validate every input, rate limit per user and set a timeout on each CRM call. The spec says servers must validate inputs, apply access controls, rate limit and sanitise outputs.

Leave phone numbers and email addresses out of the first version unless a scope asks for them. Less data in the model's context means less to leak.

A hand turning a key in the lock of a wooden door
An MCP server should check who the user is on every call, the way a door reader checks each card rather than the person holding the door.

Read-only first, then writes behind approval

Ship the read-only tools, watch how people use them for a few weeks, then add writes. The spec says there should always be a human able to deny a tool call, and that clients must treat annotations as untrusted unless the server is trusted. So do not rely on readOnlyHint for safety; the server itself must refuse what the user may not do.

For writes, prefer tools that create a draft or a proposal a person confirms. In Fint, our accounting product, an AI agent proposes records and a person confirms them before any money is recorded. Remember too that CRM notes contain text written by outsiders, so tool output is data for the model, never instructions.

Log every call: user, tool, arguments, result size, duration and outcome. The 2026-07-28 spec carries OpenTelemetry trace context in _meta, so MCP calls can join your existing traces. Do not log tokens.

We use the same patterns in our lab: agent-talk, a mailbox that lets AI agents in different projects message each other, gives agents its mailbox as MCP tools.

Getting it built

Our MCP server development work follows this path: one system, read-only tools, OAuth on HTTP, audit logs, then approved writes. We build MCP servers for our own products, Fint, Desk and Cybe Social.


If you have an internal system your team wants to reach from Claude or another AI client, tell us what it is and who should see what, and we will sketch the first tools with you. Book a consultation.