MCP Explained: A Practical Guide to the Model Context Protocol

What MCP is, how it differs from function calling and APIs, how to build MCP servers for internal systems, and how to secure them with OAuth and audit logs.

S
Softzee EngineeringSeptember 22, 2026 · 6 min read

Every AI assistant eventually needs to reach your real systems: the CRM, the ticketing tool, the database, the internal wiki. Until recently, each of those connections was custom glue code written for one model and one app, rebuilt every time you switched vendors. MCP, the Model Context Protocol, is the standard that replaces that glue, and it is now the default way AI clients connect to tools and data.

This guide explains what MCP is, how it differs from function calling and ordinary APIs, how to build MCP servers for internal systems, and what security work you need to do before you let an agent loose on production data.

What MCP is

MCP is an open protocol introduced by Anthropic in late 2024. In December 2025 it was donated to the Agentic AI Foundation under the Linux Foundation, which OpenAI and Block co-founded. It is supported across most of the major AI clients, including Claude, ChatGPT, Gemini, Microsoft Copilot, GitHub Copilot, Cursor and VS Code.

The architecture has three parts:

  • Host: the AI application the user works in, such as a desktop assistant or an IDE.
  • Client: the component inside the host that manages a connection to one server.
  • Server: a program that exposes capabilities from some system (your CRM, a database, a file store) in a standard shape.

Servers expose three main kinds of capability: tools (actions the model can call, like "create ticket"), resources (data the client can read, like a document or a record), and prompts (reusable templates a user can invoke). Messages use JSON-RPC 2.0. There are two standard transports: stdio for servers running locally next to the client, and Streamable HTTP for remote servers.

The practical result: build one MCP server for your ticketing system, and any MCP-capable client can use it without new integration code.

MCP vs function calling vs plain APIs

These three are often confused because they overlap. They sit at different layers.

Plain APIFunction callingMCP
What it isYour system's interface for any softwareA model feature: the model outputs a structured call to a tool you definedA protocol for discovering and invoking tools and data across apps
Who defines the toolsN/AYour app, per request, in vendor-specific formatThe server, once, discovered by any client at runtime
PortabilityHigh, but not model-awareTied to one app and often one vendor's schemaWorks across any MCP-capable host
Best forSystem-to-system integrationA single app with a fixed, small tool setTools shared across many assistants, agents and teams

MCP does not replace your APIs. An MCP server is usually a thin, model-friendly layer on top of an existing API. And under the hood, the host still uses the model's function calling to decide which MCP tool to call. MCP standardizes everything around that decision: discovery, schemas, transport and auth.

If you are building one product with three tools that will never be used elsewhere, direct function calling is fine. If you want your internal systems available to several assistants, agents and staff using different AI clients, MCP saves you from writing the same integration many times.

Building MCP servers for internal systems

Official SDKs exist for the common languages, and a minimal server is a few dozen lines. The hard part is design, not code.

Design tools around tasks, not endpoints

Wrapping every REST endpoint as a tool is the most common mistake. A model given 60 low-level tools picks the wrong one more often, and every tool definition costs context tokens. Instead, design a small set of task-level tools: find_customer, get_open_invoices, create_support_ticket. Each should do one clear thing and return only the fields the model needs.

Write descriptions for the model

The tool description is the model's only documentation. Say what the tool does, when to use it, what the inputs mean and what it returns. Include constraints ("dates in YYYY-MM-DD", "returns at most 20 results").

@server.tool()
def get_open_invoices(customer_id: str, limit: int = 20) -> list[dict]:
    """Return unpaid invoices for one customer, newest first.
    Use after find_customer. Returns id, amount, currency, due_date only."""
    rows = billing_api.invoices(customer_id, status="open", limit=min(limit, 50))
    return [{"id": r.id, "amount": r.amount, "currency": r.currency,
             "due_date": r.due_date} for r in rows]

Separate reads from writes

Put read-only tools and state-changing tools in clearly named groups, or in separate servers. That makes it easy to give a reporting assistant read access only, and to require human confirmation for anything that sends, deletes, pays or modifies records.

Return errors the model can act on

"Customer not found. Try find_customer with a phone number instead" lets the agent recover. A stack trace does not.

Version and test like any other service

Changing a tool name or its input schema can break every assistant that relies on it, often silently, because the model just stops calling the tool correctly. Version your servers, keep old tool names working for a deprecation period, and run a small evaluation suite against each release: a set of realistic requests with the tool calls you expect the model to make. Deploy remote servers through the same pipeline, monitoring and secrets management as your other internal services. An MCP server is production software, not a script on someone's laptop.

Security: OAuth, least privilege and audit

An MCP server is a new entry point into your systems that takes instructions from a language model. Treat it with the same seriousness as a public API, because a prompt injection hidden in an email or a web page can try to steer the model into calling your tools.

Authentication with OAuth 2.1

Local stdio servers run with the user's own permissions on their machine. Remote servers over Streamable HTTP should use the OAuth 2.1 flow defined in the specification, with PKCE. The key point: the server should act as the user, with the user's own permissions in the downstream system, not as a shared service account with access to everything. If a sales rep cannot see finance records in the ERP, the assistant working on their behalf should not either.

Least privilege

  • Use narrow OAuth scopes per server and per tool group.
  • Expose only the tools a given assistant needs. A support bot does not need a refund tool with no limit.
  • Validate every input on the server. Never pass model-generated text straight into SQL, shell commands or file paths.
  • Require explicit human approval for irreversible or high-value actions.
  • Avoid static API keys in config files. They are still common in MCP setups, and they tend to be long-lived, over-scoped and copied around.

Audit and the known gaps

The protocol itself does not yet solve several things enterprises care about: complete audit trails, multi-tenant isolation, and rate limiting and cost attribution for agent tool calls. You need to build these yourself, typically in a gateway in front of your MCP servers. At minimum, log every tool call with the user identity, the client, the tool name, the arguments, the result status and a timestamp, and keep those logs where your security team can query them. Add per-user and per-tool rate limits so a looping agent cannot hammer your billing system.

In regulated Gulf environments, these logs also matter for data protection. Saudi Arabia's PDPL and the UAE federal PDPL both apply when personal data passes through these tools, and in the DIFC, Regulation 10 specifically covers personal data processed by autonomous and semi-autonomous systems.

A sensible rollout path

  1. Pick one internal system with clear value and low risk, often a read-only knowledge source or a ticketing system.
  2. Build a server with five to ten task-level tools, read-only first.
  3. Put it behind OAuth and a gateway that logs and rate-limits every call.
  4. Test it with the clients your team actually uses, and with adversarial prompts that try to misuse the tools.
  5. Add write tools with human confirmation once the read path has proven stable.

Done this way, MCP turns integration work into a reusable asset. Each server you build makes every future agentic AI project faster, because the hard part, safe access to your systems, is already done.

How Softzee can help

We design and build MCP servers and agent integrations for internal systems, with auth, permissions and audit logging in place from the start. If you want your CRM, ERP or support tools available to AI assistants without opening a security hole, our API and integration engineering team can help. Get in touch to talk through your systems.

MCPModel Context ProtocolAI agentsAI securityIntegrations

Have a project in mind?

Tell us what you are trying to build. You will get an honest take on scope, timeline and cost, usually within one business day.

Keep reading

All articles