What Is MCP? MCP Servers Explained and Kept Safe

MCP (Model Context Protocol) is an open standard that lets AI apps like Claude, ChatGPT and Cursor connect to outside tools and data through small programs called MCP servers.

Gary · Published · Updated · 15 min read

Isometric illustration of a glowing emerald hub block on a dark slate base, linked by light cables to three smaller tool blocks.
On this page
  1. What is MCP?
  2. What is an MCP server?
  3. How MCP works: hosts, clients, servers and transports (stdio vs HTTP)
  4. What does a tool call look like?
  5. MCP vs API: what's the difference?
  6. How to use MCP with Claude (and Claude Code)
  7. How to build a tiny MCP server (official Python SDK)
  8. What happened when we ran it?
  9. MCP security: what can go wrong and how to stay safe
  10. 1. A local server can do anything you can
  11. 2. Limit who can reach a local server
  12. 3. Never pass tokens straight through
  13. 4. Ask for the smallest scopes
  14. 5. Give data servers read-only access
  15. 6. Keep keys out of shared config
  16. What does a safe MCP setup look like?
  17. 7. Keep servers updated, and watch advisories
  18. Is an MCP server free or paid?
  19. FAQ

What is MCP? MCP, the Model Context Protocol, is an open standard that lets an AI app such as Claude, ChatGPT or Cursor plug into outside tools and data. Each tool sits behind a small program called an MCP server. The AI app asks the server what it can do, then calls those tools for you, so the model can read a file, query a database or open a ticket instead of only chatting.

By Gary, Greenlight My App. Checked Nov 2, 2026. How we checked this: we read the official MCP docs (intro, architecture, server tutorial and security best practices) and Anthropic's Claude Code MCP docs on Nov 2, 2026, and quote them below. Our team also built and ran the tiny server below with the official Python SDK (mcp 2.3.0) and the official MCP Inspector in a throwaway folder on Nov 2, 2026; the screenshots are from that run. Drafted with AI tools and reviewed by a person before publishing.

What is MCP?

MCP stands for Model Context Protocol. The official MCP docs (external) define it as "an open-source standard for connecting AI applications to external systems." Instead of every AI app writing its own plug-in for every tool, a tool is wrapped once as an MCP server, and any app that speaks MCP can use it.

The docs use a hardware comparison: "Think of MCP like a USB-C port for AI applications." One port shape, many devices.

Screenshot of the official MCP introduction page at modelcontextprotocol.io, taken Nov 2, 2026, describing MCP as an open-source standard for connecting AI applications to external systems.

It's already broadly supported. Per the same page: "AI assistants like Claude and ChatGPT, development tools like Visual Studio Code, Cursor, MCPJam, and many others all support MCP."

Other meanings: MCP also stands for Microsoft Certified Professional, and in medicine for the metacarpophalangeal (knuckle) joint. This page is about the AI protocol.

What is an MCP server?

An MCP server is a small program that exposes a set of abilities to an AI app in a standard format. Those abilities come in three kinds: tools the model can call, resources it can read, and prompts it can reuse. A GitHub server might offer "create issue"; a database server might offer "run read-only query."

The architecture docs call these "primitives":

PrimitiveWhat it isExample
ToolsActions the AI app can callcreate_issue, run_query, send_message
ResourcesData the app can read as contextA file, a database schema, a doc page
PromptsReusable prompt templates"Summarize this pull request"

A server can run on your own machine (a local server) or on someone else's (a remote server). That one fact decides most of the security questions later in this post.

How MCP works: hosts, clients, servers and transports (stdio vs HTTP)

MCP has three roles. The host is the AI app you use, such as Claude Code or Claude Desktop. For each server it connects to, the host creates one client. Each client talks to one server. They exchange JSON-RPC 2.0 messages over a transport: stdio for local servers, Streamable HTTP for remote ones.

The architecture page (external) puts it this way: an "MCP host — an AI application like Claude Code or Claude Desktop — establishes connections to one or more MCP servers," creating "one MCP client for each MCP server."

Diagram of how MCP works: an AI app (the MCP host) holds one MCP client per server; a local server connects over stdio and reaches files, while a remote server connects over Streamable HTTP with an OAuth token and reaches a SaaS API.

The two transports, in the docs' words:

  • Stdio: "Uses standard input/output streams for direct process communication between local processes on the same machine."
  • Streamable HTTP: "Uses HTTP POST for client-to-server messages with optional Server-Sent Events for streaming capabilities." It "supports standard HTTP authentication methods including bearer tokens, API keys, and custom headers. MCP recommends using OAuth to obtain authentication tokens."

What does a tool call look like?

When a host connects, it asks the server for its tool list with tools/list, then calls one with tools/call. A trimmed call looks like this:

JSON

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "word_count",
    "arguments": { "text": "ship it safe" }
  }
}

The real message in today's docs also carries a _meta block with the protocol version (2026-07-28 on Nov 2, 2026); we trimmed it to show the parts that matter.

The model never runs code itself. It asks the host to call a tool; the host passes the request to the right server; the server runs its own code and sends back a result.

MCP vs API: what's the difference?

An API is how one service lets programs talk to it, and each API has its own shape. MCP is a layer above APIs: one common format that AI apps use to discover and call tools, whatever API sits behind them. Many MCP servers are thin wrappers around an existing API.

A regular APIMCP
Who it's forAny programAI apps (hosts) and their models
ShapeDifferent for every serviceOne protocol for every server
DiscoveryYou read the docsThe host asks tools/list at runtime
AuthWhatever the service usesstdio inherits your local access; HTTP uses tokens, OAuth recommended
ExampleA REST call to create a GitHub issueA create_issue tool on a GitHub MCP server

So it's not MCP or an API. The GitHub MCP server still calls GitHub's API; MCP just gives every AI app the same way to ask for it. If API keys are new to you, start with what is an API key.

How to use MCP with Claude (and Claude Code)

In Claude Code, you add a server with one command: claude mcp add, plus --transport http and a URL for a remote server, or -- and a launch command for a local one. Then type /mcp inside Claude Code to check its status and sign in. Claude Desktop reads servers from a JSON config file.

From Anthropic's Claude Code MCP docs (external), a remote server:

Bash

claude mcp add --transport http notion https://mcp.notion.com/mcp

A local stdio server, with a key passed as an environment variable (fake key shown):

Bash

claude mcp add --env AIRTABLE_API_KEY=XXXX --transport stdio airtable -- npx -y airtable-mcp-server

The docs explain the --: "Everything after -- is passed to the server untouched." Manage servers with claude mcp list, claude mcp get <name> and claude mcp remove <name>.

Scopes matter for secrets. Claude Code stores servers in three scopes. Local (the default) and user scope live in ~/.claude.json; project scope writes a .mcp.json file meant to be committed. The docs suggest local scope for "servers with credentials you don't want in version control." If you use project scope, reference keys as ${API_KEY} variables instead of pasting them. Claude Code expands those from your environment. This is the docs' own example of a committed .mcp.json that holds no secret at all:

JSON

{
  "mcpServers": {
    "api-server": {
      "type": "http",
      "url": "${API_BASE_URL:-https://api.example.com}/mcp",
      "headers": {
        "Authorization": "Bearer ${API_KEY}"
      }
    }
  }
}

The :- part sets a default. One catch from the docs: if a variable isn't set and has no default, the config still loads, and Claude Code "uses the unexpanded $ text as-is," with a warning in claude mcp list. So check that list after a fresh clone.

For Claude Desktop, servers go in claude_desktop_config.json under an mcpServers key, each with a command and args.

How to build a tiny MCP server (official Python SDK)

The official server tutorial (external) builds servers with the Python SDK in about a dozen lines: create a project with uv, add the mcp package, decorate a function with @mcp.tool(), and run it over stdio. The docs require Python 3.10 or newer and "the Python MCP SDK 2.0.0 or higher."

Set up the project, following the tutorial's commands:

Bash

uv init notes
cd notes
uv add "mcp[cli]"

Then save this as server.py. This is the exact file we ran on Nov 2, 2026 with mcp 2.3.0. It offers one harmless tool that adds two numbers, holds no secrets, and only listens on localhost when you switch it to HTTP:

Python

import sys
from mcp.server.mcpserver import MCPServer

mcp = MCPServer("demo-tools")

@mcp.tool()
def add_numbers(a: float, b: float) -> float:
    """Add two numbers and return the sum."""
    return a + b

if __name__ == "__main__":
    if "--http" in sys.argv:
        mcp.run(transport="streamable-http", host="127.0.0.1", port=8765)
    else:
        mcp.run(transport="stdio")

Terminal screenshot from our Nov 2, 2026 run: the demo server.py using MCPServer from the official Python SDK with one add_numbers tool, and pip showing mcp version 2.3.0.

Two rules from the tutorial that trip people up:

  1. Never print to stdout in a stdio server. The tutorial says: "For STDIO-based servers: Never write to stdout." Stdout carries the protocol messages, so a stray print() breaks them. Log to stderr instead.
  2. Tools run with approval. The tutorial describes tools as "Functions that can be called by the LLM (with user approval)." Keep that approval step on.

To connect it to Claude Code, point a stdio entry at your start command (use your own absolute path):

Bash

claude mcp add --transport stdio notes -- uv --directory /ABSOLUTE/PATH/notes run server.py

The docs also ship an inspector for testing a server without any AI app. For a built TypeScript server, their example is npx @modelcontextprotocol/inspector --cli node build/index.js --protocol-era modern --method tools/list.

What happened when we ran it?

We pointed the official MCP Inspector (CLI mode) at our server over stdio. Asking for tools/list returned one tool, add_numbers, with an input schema the SDK built from the Python type hints: two required numbers, a and b.

Terminal screenshot from our run: the MCP Inspector CLI calling tools/list on the demo server and getting back one tool, add_numbers, with a JSON input schema for numbers a and b.

Then we called the tool with a=2 and b=40. It returned 42, both as text and as structuredContent, with "isError": false:

Bash

npx -y @modelcontextprotocol/inspector@latest --cli venv/bin/python server.py --method tools/call --tool-name add_numbers --tool-arg a=2 --tool-arg b=40

Terminal screenshot from our run: tools/call for add_numbers with a=2 and b=40 returns a text result of 42.0 and structuredContent result 42, with isError false.

Next, the HTTP transport. Started with --http, the server listened on 127.0.0.1:8765 only, and the inspector reached it at http://127.0.0.1:8765/mcp. Nothing on another machine could connect.

Terminal screenshot from our run: ss shows the MCP server listening on 127.0.0.1:8765 only, and the inspector lists the add_numbers tool over the Streamable HTTP transport.

Finally, we added it to Claude Code 2.1.316 as a project server in a .mcp.json file. claude mcp list showed it as "Pending approval (run claude to approve)". A project server from a shared .mcp.json waits for your approval before it runs. We didn't sign in to a paid Claude account for this post, so we stopped there.

Terminal screenshot from our run: Claude Code 2.1.316 with a project .mcp.json for the demo server, and claude mcp list showing demo-tools as Pending approval.

MCP security: what can go wrong and how to stay safe

An MCP server is code you run, holding keys you give it. The official security guide warns about malicious local servers, token passthrough, server-side request forgery, session hijacking and over-broad scopes. The short version: install only servers you trust, give each one the smallest key it needs, and keep tool approvals on.

1. A local server can do anything you can

The MCP security best practices guide (external) tells clients to "Warn that MCP servers run with the same privileges as the client." Its example of a malicious startup command is one that installs a package and then uploads your SSH private key with curl. A one-line config entry is a program install. Read it like one.

The guide's advice for clients: show the exact command before running it and require explicit approval. Anthropic's Claude Code docs add: "Verify you trust each server before connecting it. Servers that fetch external content can expose you to prompt injection risk."

2. Limit who can reach a local server

For local servers, the guide says: "Use the stdio transport to limit access to just the MCP client." If a local server must use HTTP, it should "Require an authorization token" or use unix domain sockets or other restricted IPC, so other websites and programs on your machine can't call it.

3. Never pass tokens straight through

Server authors: the guide is blunt. "MCP servers MUST NOT accept any tokens that were not explicitly issued for the MCP server." A server that forwards whatever token it receives to an upstream API becomes a way around that API's own checks.

4. Ask for the smallest scopes

The guide warns against wildcard or "everything" scopes. For a GitHub server, that means a fine-grained token for the one repo it needs, read-only if possible, instead of a classic token with full repo access.

5. Give data servers read-only access

Anthropic's own database example in the Claude Code docs carries the advice "Use a read-only database user." The same idea applies to any data server: if the AI only needs to read, the credential shouldn't be able to write or delete. A prompt-injected instruction can't drop a table that the key can't touch.

6. Keep keys out of shared config

Terminal screenshot from our run: an MCP client config that passes DEMO_API_TOKEN as a $DEMO_API_TOKEN variable from the environment, with grep confirming the file itself holds no token.

Keys in a committed .mcp.json end up in Git history. Use local scope or ${VAR} references, and keep the real values in your shell or a secret manager. If a key did leak, our guide on what to do when an AI API key is stolen walks through revoking it.

What does a safe MCP setup look like?

Most risk comes down to four choices you make at install time. Here's the same server set up two ways:

ChoiceSafer setupRiskier setup
Where it comes fromThe vendor's official server, or code you've readA random repo or package you found in a thread
How it's reachedstdio, or HTTP with a token on localhostHTTP on a public port with no auth
What key it holdsA scoped, read-only token for one serviceA full-access token or an admin database login
Where the key livesAn environment variable or ${VAR} referencePasted into a committed .mcp.json

Diagram comparing a safer MCP setup (trusted server, stdio or localhost, scoped read-only token in an environment variable) with a riskier one (unknown server, public port, full-access token pasted in a committed config).

Worked example: a GitHub server for code review. You want Claude Code to read pull requests in one repo. The safer path is a fine-grained GitHub token limited to that repo with read access to pull requests and contents, stored as GITHUB_TOKEN in your shell and referenced as ${GITHUB_TOKEN}. If that token ever leaks, the damage is one repo, read-only, and you revoke it on GitHub in a minute. A classic token with full repo scope pasted into the config could push code to every repo you own.

7. Keep servers updated, and watch advisories

MCP servers are software, and software gets security fixes. Update servers like any dependency, remove ones you no longer use, and check the project's security advisories before upgrading. When a CVE lands for a server you run, read the official advisory or the NVD entry for the fixed version rather than a summary.

A checklist you can copy:

  • I know who publishes this server and I've read its install command
  • It runs over stdio, or over HTTP with a token or OAuth
  • Its key is scoped to one service and the least access that works
  • The key lives in an environment variable, not in a committed file
  • Tool approval prompts are on in my AI app
  • I've removed servers I no longer use. For remote servers, Claude Code's docs say to run claude mcp logout <name> before claude mcp remove <name> so the OAuth tokens are revoked where the server supports it

For coding agents specifically, pair this with Claude Code permissions and sandboxing and our Cursor security checklist. If you route several model providers through one gateway, LiteLLM shows the same least-privilege idea for API keys. And for the bigger picture of tools that act on their own, see what is an AI agent.

Is an MCP server free or paid?

The protocol and its official SDKs are open source and free to use. Most community servers are free to run too. But a server is often a front door to a paid service, so the calls it makes can cost money on that service's bill, and hosted remote servers may need a paid account.

Kind of serverCost of the serverWhat can still cost money
A server you write yourselfFreeHosting, if you run it remotely
Open-source local serverFreeThe API it calls with your key
A vendor's hosted remote serverUsually included with the vendor accountThat vendor's plan or usage pricing

Check each vendor's pricing page before connecting a server that can spend on your behalf, and set a spending limit on any API key you hand it.

FAQ

What is MCP in simple terms? A standard plug that lets AI apps use outside tools. A tool is wrapped once as an MCP server, and any app that speaks MCP can call it.

What are MCP servers? Small programs that offer tools, resources and prompts to an AI app. They run locally over stdio or remotely over Streamable HTTP.

What is MCP vs API? An API is one service's interface. MCP is a shared protocol AI apps use to discover and call tools, and many MCP servers wrap an existing API.

Does ChatGPT use MCP? Yes. The official MCP docs list Claude and ChatGPT among the AI assistants that support MCP, along with Visual Studio Code and Cursor.

Is MCP server free or paid? The protocol and SDKs are open source and free. A server can still call a paid API with your key, and hosted servers may need a paid account.

Is MCP safe? It's as safe as the servers you install. Local servers run with your privileges, so use trusted servers, least-privilege keys and approval prompts.

Do I need MCP for my app? Usually not. MCP connects AI apps to tools. If your app just calls one model API from its server, a normal API call is simpler.

How do I add an MCP server to Claude Code? Run claude mcp add with --transport http and a URL, or -- and a launch command for a local server. Then check it with /mcp.


Connected your app to AI tools? Run a free scan with Greenlight My App to check your live site's public code for exposed API keys and missing security headers.

Sources

On this site

Related posts

Claude and Claude Code are trademarks of Anthropic; ChatGPT is a trademark of OpenAI; Cursor and Visual Studio Code belong to their owners. None is affiliated with Greenlight My App. Keys shown are fake placeholders. This page is general information, not professional security advice, legal advice, a security audit or a guarantee. Check your own setup against the vendor's current docs.