All articles

What Is an MCP Server? How AI Agents Connect to Tools Safely

An MCP server is the plug a model uses to reach a real system. Here's what that actually means — and what an enterprise-grade version of it has to do that a vanilla one doesn't.

The one-line answer

An MCP server is a small program that exposes a set of tools, data sources, or prompts to an AI model over a standard protocol — the Model Context Protocol. The model (or the agent wrapping it) is the client. The MCP server is the thing on the other end of the wire that actually knows how to read your Gmail, query your Postgres, hit your Jira API, or run a shell command.

If you've ever wired a function-calling tool into an LLM by hand, an MCP server is that, standardised. Same idea — describe a tool, accept structured calls, return structured results — but published over a protocol so any compliant client (Claude Desktop, Cursor, an in-house agent, a workflow runner) can pick it up without bespoke glue code.

Why it exists

Before MCP, every "connect this AI to that system" integration was its own snowflake. OpenAI's function-calling shape, Anthropic's tool-use shape, LangChain's tool abstraction, your internal team's wrapper around all of the above. Each pairing of (model framework × target system) was a one-off.

Anthropic published MCP in late 2024 to fix that. It's an open, JSON-RPC-based protocol with three things in its vocabulary:

  • Tools — functions the model can call. (Read this file, send this email, query this database.)
  • Resources — read-only context the model can pull. (A file, a row, a doc snippet.)
  • Prompts — reusable templated prompts the server hands to the client.

Pick a client. Pick a server. They speak the same language. That's the whole pitch.

MCP client vs MCP server

This trips people up because "client" and "server" feel backwards from the web sense. The client is the AI app — Claude Desktop, Cursor, your custom agent — the thing the human talks to. The server is the integration that sits next to (or inside) the system being accessed and answers the client's tool calls.

One agent can be connected to many MCP servers at once. A coding agent might have:

  • A filesystem MCP server (read/write files in a project)
  • A GitHub MCP server (open PRs, read issues)
  • A Postgres MCP server (run read-only queries against a dev DB)
  • A Slack MCP server (post to a channel when something finishes)

Each server runs as its own process. The agent's host (the MCP client) negotiates with each one over stdio or HTTP, gets back a list of advertised tools, and starts calling them when the model decides to.

MCP server examples

To make this concrete, here are the kinds of MCP servers people actually run today:

  • Filesystem — read, write, list, search files in a sandboxed directory.
  • Git / GitHub — clone a repo, open PRs, read issues, fetch diffs.
  • Postgres / SQLite / Snowflake — execute SQL, describe schemas.
  • Slack / Linear / Notion — post messages, create tickets, search docs.
  • Browser automation (Playwright, Puppeteer) — let an agent click around a real browser.
  • Internal APIs — wrap a company's own REST or gRPC services so an agent can use them without leaking how they're auth'd.

Most of these are a few hundred lines of code. The protocol does the hard work; the server just needs to declare what tools it has and answer each call.

What an MCP call actually looks like

A simplified round-trip. The agent decides it wants to read a file. The MCP client sends:

{
  "jsonrpc": "2.0",
  "id": 17,
  "method": "tools/call",
  "params": {
    "name": "read_file",
    "arguments": { "path": "src/auth/session.py" }
  }
}

The MCP server runs the read, returns:

{
  "jsonrpc": "2.0",
  "id": 17,
  "result": {
    "content": [{ "type": "text", "text": "..." }]
  }
}

That's it. The model sees the text in its context and decides what to do next. Multiply that loop across a session and you have an agent that can actually do things — not just describe them.

The bit nobody likes to talk about: MCP server security

This is where the "AI agents connect to tools safely" part of the title earns its keep. The protocol gives you the wire format. It does not give you any of the following:

  • Identity. The MCP server has no native idea which human is behind the agent making the call. The auth model is whatever you bolt on — usually a long-lived API key in an env var.
  • Authorization. If the server exposes delete_file, every agent connected to it can call delete_file. There's no "this user can read but not write" without you building it.
  • Data exfiltration controls. Tools return raw rows. If a row contains a customer's email, SSN, or API key, that goes straight into the model's context — and from there, potentially to logs, to fine-tuning data, to a Slack message the model decides to post.
  • Audit. By default, the server logs what it sees. The client logs what it sees. Nobody is logging the joined story of this agent, acting for this user, called this tool with these arguments and got this result, and here's why it decided to.
  • Tool scoping. An agent given access to a filesystem server can usually walk wherever the OS user can walk. "Sandboxed to the project directory" is a convention, not a guarantee, unless the server author was careful.

None of this is a flaw in MCP. It's the same situation as HTTP — the protocol is intentionally thin, and everything above it (auth, RBAC, audit, DLP) is your problem. The risk is that "let an agent loose with this MCP server" feels casual. It looks like wiring up a plugin. It's actually granting a non-deterministic process the ability to act inside your systems.

What changes at enterprise scale

One developer running an MCP server against their own laptop and their own GitHub token: fine. A team of fifty agents acting on behalf of a thousand customers across a dozen MCP servers: a different problem entirely. The shift looks like this:

  • Who is the agent acting for? A support agent answering tickets for customer A must not be able to read customer B's data, even if both are reachable via the same MCP server. You need user-scoped credentials, not a single service account.
  • What tools is this agent allowed to call? An MCP server might advertise twenty tools; this particular agent should only see three of them. Tool-level enabling, not server-level on/off.
  • What data is allowed to come back? Outputs need to be scrubbed for PII, secrets, and other sensitive fields before they hit the model's context — otherwise you've just laundered a data leak through the LLM.
  • Was the request itself sensible? Sometimes the right answer to a tool call isn't "redact the result" but "don't run it at all." A policy check can intercept the call, ask an evaluator model whether it matches the agent's stated intent, and block it if not.
  • What got called, by whom, with what, when? Every tool call needs to land in an audit log you can query later — for debugging, for compliance, for the inevitable incident review.

None of this is in the MCP spec. All of it is required to put MCP-connected agents into anything that resembles production.

Secure MCP access in practice

The pattern that's emerging looks like a governed proxy in front of the raw MCP servers. The agent doesn't connect to github-mcp, postgres-mcp, and slack-mcp directly. It connects to one endpoint — a toolbox — that:

  1. Knows which user the agent is acting for.
  2. Filters the advertised tool list down to what that user (and that agent) is allowed to see.
  3. Runs the call against the real MCP server using user-scoped credentials.
  4. Applies policies on the way out — PII redaction, pattern blocking, optional LLM-based governance checks.
  5. Logs the full call: agent, user, tool, arguments, result, policy decisions, latency.

From the agent's perspective, it's still just MCP. From your perspective, you've gained an answer to every one of the awkward questions in the previous section.

This is what ContextGate does for MCP, among other things. You point your agent (Claude Code, Cursor, an internal one) at a ContextGate toolbox URL; ContextGate brokers the connection to the underlying MCP servers; you get user-scoped access, tool-level enabling, PII redaction, and an audit trail without rewriting any of the servers. Same protocol, harder edges.

So — what is an MCP server, really?

Mechanically: a JSON-RPC service that advertises tools, resources, and prompts to an AI client. Practically: the bridge between a model's reasoning and your real systems. Strategically: the place where most of the next decade's AI integration work is going to happen, and where most of the next decade's AI incidents are going to start.

Use one. Run one. Just don't put it in production naked.

Ready to ship governed AI agents?

ContextGate is the evaluation and governance layer for the agent economy. Get started in minutes.

Create your first agent