Skip to content

What is an MCP server?

On this page

An MCP server is a program that gives AI applications a standard way to use an outside system: it publishes a list of tools the model can call, data it can read and prompt templates, all over the Model Context Protocol. Claude Code, Cursor and other AI apps connect to it, ask what it offers, and call its tools when a task needs them, such as searching GitHub issues or reading a Sentry stack trace.

MCP itself, the Model Context Protocol, is the open standard that defines those messages. Anthropic open-sourced it in November 2024, and the specification describes it as a protocol that uses JSON-RPC 2.0 messages to connect LLM applications with "external data sources and tools". This guide was checked against specification revision 2026-07-28 on 30 October 2026.

Hosts, clients and servers

MCP has three roles. The architecture overview defines them like this:

RoleWhat it isExample
HostThe AI application the person uses. It manages one or more MCP clientsClaude Code, Cursor, Claude Desktop, VS Code
ClientA connector inside the host that keeps one connection to one serverThe object Claude Code creates when you add a server named sentry
ServerA program that provides tools, resources and prompts to clientsThe Sentry, GitHub or Linear MCP server

The host creates one client per server. If Cursor is connected to GitHub and Sentry, it runs two MCP clients, each talking to its own server. The host is also where the model lives: it collects the tool lists from every client, shows them to the model, and routes each tool call the model makes to the right client.

The server exchanges MCP messages with the host's client and doesn't need to depend on which model the host uses. That is what makes one server usable from many apps, and it's the reason the spec compares MCP to the Language Server Protocol: write the integration once, and every compatible app can use it.

What a server offers: tools, resources and prompts

The specification defines three things a server can offer. A server can expose any combination of them.

Tools are functions the model can call: create an issue, run a query, fetch a deployment log. Each tool has a name, a description and a JSON Schema for its arguments. Tools are model-controlled, meaning the model decides when to call one based on the conversation. Because a tool can change real data, the spec says there should always be a human in the loop who can deny a call, and that hosts must get the user's consent before invoking any tool.

Resources are data the server makes readable, each identified by a URI: a file, a database schema, a document. Resources are application-driven. The host decides how they reach the model, for example through a picker where you attach one to the conversation. Clients find them with resources/list and fetch them with resources/read.

Prompts are reusable message templates with arguments, such as a code-review prompt that takes a diff. They are user-controlled: the person picks one, often as a slash command. Clients use prompts/list and prompts/get.

A database server shows how the three fit together. The architecture overview's own example has tools for running queries, a resource containing the schema and a prompt with few-shot examples of good queries.

What the client offers back

Communication isn't one-way. In revision 2026-07-28, elicitation lets a server ask the user for more information or a confirmation in the middle of a request, using elicitation/create, when the client advertises support for it. The host then shows the question to the person. Three older client features (sampling, which let a server borrow the host's model; roots, which told a server which folders mattered; and logging to the client) are deprecated as of this revision. They remain in the spec for now, but new servers shouldn't adopt them.

What the messages look like

Every MCP message is JSON-RPC 2.0. A client finds a server's tools with tools/list and runs one with tools/call. The shapes below follow the tools section of the spec; the issue-tracker tool is an illustration, not a real server's tool.

First the client asks what tools exist. Since revision 2026-07-28, MCP is stateless: there's no handshake that sets up a session, so every request carries the protocol version and the client's capabilities in _meta:

JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": { "elicitation": {} }
    }
  }
}

The server answers with each tool's name, description and input schema:

JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "tools": [
      {
        "name": "search_issues",
        "title": "Search issues",
        "description": "Search issues by text, state or assignee",
        "inputSchema": {
          "type": "object",
          "properties": {
            "query": { "type": "string", "description": "Text to search for" },
            "state": { "type": "string", "enum": ["open", "closed"] }
          },
          "required": ["query"]
        }
      }
    ],
    "ttlMs": 300000,
    "cacheScope": "public"
  }
}

ttlMs tells the client it can cache this list for five minutes. The host passes the names, descriptions and schemas to the model. When you ask "find open issues about the login timeout", the model chooses search_issues, and the client sends the call (with the same _meta block, left out here for brevity):

JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "search_issues",
    "arguments": { "query": "login timeout", "state": "open" }
  }
}

The server runs the search against its system and returns content for the model to read:

JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "resultType": "complete",
    "content": [
      {
        "type": "text",
        "text": "2 open issues: ENG-412 \"Login times out after SSO redirect\", ENG-398 \"Session timeout too short on mobile\""
      }
    ],
    "isError": false
  }
}

Two kinds of failure are kept apart. An unknown tool or malformed request gets a JSON-RPC error. A tool that ran but failed, say because a date was in the wrong format, returns a normal result with isError: true, so the model can read the message and try again with different arguments. Tools can also declare an outputSchema and return machine-readable structuredContent next to the text.

That loop is most of MCP in practice. Clients that want to know what a server supports before calling anything can send server/discover, which every server must answer with its supported versions and capabilities.

Local and remote MCP servers

The spec defines two standard transports, and they produce two quite different kinds of server.

Local servers use stdio. The host launches the server as a subprocess on your machine and exchanges newline-delimited JSON-RPC over its standard input and output. You install it, usually as an npx package or a Docker image, and it runs with your local permissions. Credentials come from environment variables in the host's config. Local servers suit things that live on your machine: the filesystem, a local database, a browser you control.

Remote servers use Streamable HTTP. Each message is an HTTP POST to a single MCP endpoint, and replies come back as JSON or a server-sent event stream. The vendor runs the server, and you connect to a URL. Many remote servers use the spec's OAuth-based authorization, so you sign in through the browser; others accept an API key or another bearer token. MCP authentication walks through that flow.

Local (stdio)Remote (Streamable HTTP)
Where it runsOn your machine, started by the hostOn the vendor's infrastructure
How you add itA command, such as npx -y <package>A URL
CredentialsEnvironment variables, often an API keyUsually OAuth sign-in in the browser
UpdatesYou update the packageThe vendor updates it
Typical clientsUsually oneMany

A local server typically serves one client, and a remote server serves many. When a vendor offers both, as GitHub does, the remote one is less to maintain.

Examples of official MCP servers

Many companies now publish their own servers. These three official servers show different engineering workflows, as documented by each vendor:

  • GitHub. The GitHub MCP server lets agents "read repositories and code files, manage issues and PRs, analyze code, and automate workflows". The hosted version is at https://api.githubcopilot.com/mcp/. It also ships as a local Docker image, ghcr.io/github/github-mcp-server, that reads a GITHUB_PERSONAL_ACCESS_TOKEN and accepts --toolsets and --read-only flags to narrow what it exposes.
  • Linear. Linear's server at https://mcp.linear.app/mcp has tools for "finding, creating, and updating objects in Linear like issues, projects, and comments". It signs in with OAuth 2.1 or accepts an API key as a bearer token, and a separate endpoint, https://mcp.linear.app/mcp/readonly, exposes only read tools.
  • Sentry. Sentry's server at https://mcp.sentry.dev/mcp covers "searching errors, analyzing performance, triaging issues, reading documentation, and managing projects". All connections use OAuth. Adding an organization and project to the path, as in /mcp/<org>/<project>, scopes the tools to that project and hides discovery tools you don't need.

The MCP project also maintains reference servers, such as a filesystem server, that show how to build one. For a longer list sorted by team, see the best remote MCP servers, or best MCP servers for Claude Code for coding work.

How to connect an MCP server

Claude Code

Add a remote server with claude mcp add, then sign in. From Claude Code's MCP docs, using Sentry:

Shell
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp

Then run /mcp inside a Claude Code session and follow the browser sign-in. For a local server, everything after -- is the command that starts it:

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

Servers are added to your local scope by default. --scope project writes them to a .mcp.json file in the repository instead, so the team shares the same list, and --scope user makes them available in all your projects.

Cursor

Cursor reads servers from .cursor/mcp.json in a project or ~/.cursor/mcp.json for every project, per Cursor's MCP docs. A remote server needs only a URL:

JSON
{
  "mcpServers": {
    "linear": {
      "url": "https://mcp.linear.app/mcp"
    }
  }
}

A local server uses command, args and env instead of url. For remote servers that require sign-in, Cursor runs the OAuth flow itself, using PKCE and dynamic client registration.

Other apps follow the same pattern. Toolstile's client setup guides cover Claude Code, Codex, Cursor and Claude Desktop.

What can go wrong

An MCP server acts with whatever access its credentials carry, and the model decides when to call it. That combination creates risks a normal API integration doesn't have:

  • Prompt injection. Text the agent reads through one tool, such as an issue body, a web page or a support ticket, can contain instructions that steer it into calling another tool.
  • Tool poisoning. Tool descriptions go straight to the model, so a malicious or compromised server can hide instructions in them. The spec says clients must treat tool annotations as untrusted unless the server is trusted.
  • Too much access. A token with broad scopes, or a server with dozens of write tools, gives a confused agent room to do damage.
  • Credentials in config files. API keys for local servers often sit in a config file that can be committed or copied.

The spec puts some of this on each side: servers must validate inputs and enforce access controls, and clients should confirm sensitive operations and show tool inputs before sending them. MCP security risks covers each attack with the controls that address it.

How teams control access to MCP servers

One developer with two servers can manage fine with their app's own settings. Claude Code, for example, lets you allow, ask about or deny each MCP tool by name. Across a team the questions change: which servers are approved, which tools each agent may call, who signs in to the shared accounts, and where calls are recorded.

There are two places to answer them. Client-side allowlists live in each app's settings, and the MCP allowlist guide compares the options in Claude Code, Cursor, Codex and VS Code. The other place is an MCP gateway: a service that sits between your apps and the servers, holds the upstream credentials, filters tools/list per agent and checks every tools/call before forwarding it.

Toolstile is a managed MCP gateway. You connect remote servers once in a workspace, add one URL to each AI app, and set Allow, Require approval or Block per tool for each agent, with a shared activity log. It connects to remote HTTPS servers only, so local stdio servers stay configured in your app. Getting started walks through a first connection, and pricing includes a free plan.

FAQ

Who created MCP?

Anthropic. Its November 2024 announcement says MCP "was created at Anthropic by David Soria Parra and Justin Spahr-Summers". On 9 December 2025, Anthropic donated MCP to the Agentic AI Foundation, a directed fund under the Linux Foundation. The project's maintainers kept the same governance model.

Is MCP open source?

Yes. The specification repository is open source. Its license file describes a transition from MIT to Apache-2.0, with some earlier contributions keeping MIT. The project also publishes official SDKs and reference servers. Individual MCP servers are separate projects with their own licenses, and a vendor's hosted server is a service rather than code you can inspect.

What is the difference between an MCP server and an API?

An MCP server usually wraps an API. The API is built for developers who write code against specific endpoints. The MCP server describes its operations as tools with names, descriptions and schemas that a model can read and choose from at run time, in the same format every MCP app understands. GitHub's REST API and GitHub's MCP server reach the same data; the MCP server is the version an agent can use without custom integration code.

Do I need to write code to use an MCP server?

No. Using a server means adding its URL or command to your AI app's settings, as in the Claude Code and Cursor examples above. Writing code is only needed to build a new server, and the official SDKs handle the protocol details.

Are MCP servers safe to use?

An official vendor server still needs review. Check which tools it exposes and what permissions its credentials carry; malicious content can steer an agent into misusing tools it is allowed to call. Prefer official servers, give each the narrowest scopes or read-only endpoints it offers, and require approval for tools that write, send or delete.