Model Context Protocol (MCP): Understanding the Fundamentals
AI generated
Claude
>_
Claude · Model Context Protocol · Anthropic · Developer Tooling
Model Context Protocol (MCP): Understanding the Fundamentals
How AI assistants connect to external tools in a structured way

The Model Context Protocol is an open standard that lets AI assistants like Claude connect to databases, ticketing systems and documentation without building a one-off integration for every tool. This article explains the client-server architecture, the difference between tools, resources and prompts, and shows with concrete examples how an MCP server is actually built.

13 min. read Client-server architecture · Tools · Resources · Prompts Claude Code · Claude Desktop · Anthropic

1. The N-times-M integration problem and how MCP solves it

Before the Model Context Protocol existed, connecting an external system to an AI assistant meant building the integration from scratch, essentially every time. A company with an internal database, a ticketing system and a documentation search needed a separate, often proprietary integration for every assistant that was supposed to access it. With N assistants and M tools, that produces N times M individual integrations in the worst case, each of which has to be maintained, tested and updated whenever the underlying API changes. This pattern is well known from classic software architecture and almost always leads to sprawl.

Anthropic released the Model Context Protocol as an open standard in November 2024 specifically to turn this N-times-M problem into an N-plus-M problem. Instead of building a separate bridge for every combination of assistant and tool, a tool provider implements one MCP server, and any MCP-capable client, such as Claude Desktop, Claude Code, or another compatible application, can use that server without additional customization. The USB-C comparison that Anthropic itself uses captures the core idea well: one uniform interface instead of a tangle of special-purpose adapters.

2. Client-server architecture: host, client, server

MCP distinguishes three roles that are conceptually cleanly separated, even though they sometimes run inside the same process in practice. The host is the application a human actually interacts with, for example Claude Desktop, Claude Code, or a custom-built chat interface. The host manages one or more clients, and each client holds its own stateful, one-to-one connection to exactly one server. The server is the part that actually provides access to an external system, such as a database, a ticketing system, or a file collection, and it is implemented completely independently of the specific host.

This separation exists for a practical reason: a server does not need to know anything about Claude or any other language model, it only describes which capabilities it offers. During connection setup, client and server exchange their capabilities in a handshake, so the client knows in advance whether a server supports tools, resources, prompts, or a combination of these. This encapsulation also acts as a security boundary: the server controls exactly which operations it permits, while the host decides which servers are trusted in the first place.

3. JSON-RPC as the foundation: handshake and capabilities

At the transport level, MCP builds on JSON-RPC 2.0, a lightweight, long-established protocol for remote procedure calls. Every message is either a request with a unique ID that expects a response, or a notification that expects none. This choice is deliberately conservative: JSON-RPC is easy to parse, language-agnostic, and implementable in essentially any programming language with minimal effort, which keeps the barrier to writing new server implementations low.

After the initial handshake, in which protocol version and capabilities are exchanged, the client calls typical methods such as tools/list, tools/call, resources/list, or prompts/get. The response to tools/list illustrates how a server describes its capabilities: every tool returns a name, a description the language model can understand, and a JSON schema for the expected parameters. Claude uses exactly this schema to decide whether and with which arguments a tool should be called to answer a given request.


{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "search_products",
        "description": "Search products by SKU prefix and return name, price and stock status",
        "inputSchema": {
          "type": "object",
          "properties": {
            "sku_prefix": { "type": "string" },
            "limit": { "type": "integer", "default": 20 }
          },
          "required": ["sku_prefix"]
        }
      },
      {
        "name": "create_ticket",
        "description": "Create a new support ticket in the tracker",
        "inputSchema": {
          "type": "object",
          "properties": {
            "title": { "type": "string" },
            "description": { "type": "string" },
            "priority": { "type": "string", "enum": ["low", "medium", "high"] }
          },
          "required": ["title", "description", "priority"]
        }
      }
    ]
  }
}

4. Tools: the functions an MCP server provides

Tools are the most active category of MCP capabilities: functions with clearly defined parameters that the language model can call on its own to perform an action or retrieve information. Unlike a static knowledge base, the model decides at runtime, based on a tool's name, description, and parameter schema, whether calling it makes sense. A tool can be purely read-only, such as a product search, or trigger a side effect, such as creating a ticket, which is why host applications typically ask for user confirmation before the latter kind runs.

The example below shows a minimal MCP server in Python using the official SDK that exposes a read-only interface to a Magento product table. The function search_products is registered via the @mcp.tool() decorator; its docstring and type annotations are automatically translated into the JSON schema the client receives during the handshake. This automation is one of the practical advantages of MCP over hand-written function descriptions: the schema necessarily stays in sync with the actual implementation, because both are generated from the same code.


#!/usr/bin/env python3
"""MCP server exposing a read-only interface to a Magento product table."""
from mcp.server.fastmcp import FastMCP
import mysql.connector

mcp = FastMCP("magento-catalog")


def get_connection():
    """Open a connection using a read-only database user."""
    return mysql.connector.connect(
        host="localhost",
        user="readonly_user",
        password="change-me",
        database="magento",
    )


@mcp.tool()
def search_products(sku_prefix: str, limit: int = 20) -> list[dict]:
    """Search products by SKU prefix and return name, price and stock status."""
    conn = get_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute(
        "SELECT sku, name, price FROM catalog_product_flat_1 "
        "WHERE sku LIKE %s LIMIT %s",
        (f"{sku_prefix}%", limit),
    )
    rows = cursor.fetchall()
    cursor.close()
    conn.close()
    return rows


@mcp.resource("schema://catalog_product_flat")
def get_schema() -> str:
    """Expose the flat product table schema as read-only context."""
    return "sku VARCHAR(64), name VARCHAR(255), price DECIMAL(12,4), status INT"


if __name__ == "__main__":
    mcp.run(transport="stdio")

5. Resources and prompts: providing context and templates

Besides tools, MCP defines two more capability types that are frequently underestimated because no language model calls them like a function. Resources are addressable, mostly read-only data sources, each identified by a unique URI, such as schema://catalog_product_flat or file:///docs/deployment.md. Conceptually they behave like a GET request: no side effect, interchangeable content, repeatable retrieval. The key difference from tools lies in who makes the decision: resources are typically selected by the host application or the user and attached as context, while the language model itself does not actively search for them.

Prompts are predefined, parameterizable templates that a server provides and that the user triggers deliberately, comparable to a slash command. A documentation server might offer a prompt called summarize-release-notes, for instance, which expects a version number as an argument and assembles it into a complete, pre-formulated request to the model. This three-way split into tools, resources, and prompts ultimately reflects who is in control of an action, the model, the application, or the human, and it makes MCP servers considerably more predictable than a single, undifferentiated list of functions.

6. Transport mechanisms: stdio, HTTP and streaming

MCP deliberately separates the protocol from the transport layer, so the same JSON-RPC message structure can run over different channels. The stdio transport is the simplest case: the host launches the server as a local child process and communicates over standard input and standard output. This works well for tools that should run locally anyway, such as filesystem access or a local development database, because no network exposure is created and the server's lifetime is tied to the host's session.

For servers that should be usable independently of the host and potentially by several clients at once, for example a central ticketing server shared by an entire team, MCP defines an HTTP-based transport with streaming support for server-initiated messages. This path adds authentication requirements, usually via OAuth 2.1, because the server is now reachable over a network and is no longer implicitly protected by the local process launch. The official MCP Inspector is well suited for testing and debugging both transport types, making tool calls interactively traceable before a server is connected to a client in production.


#!/usr/bin/env bash
# Test an MCP server via stdio using the official inspector
npx @modelcontextprotocol/inspector python3 ./mcp-servers/catalog_server.py

# List the tools a running MCP server exposes over HTTP transport
curl -s -X POST https://mcp.internal.mironsoft.de/jira \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq '.result.tools[].name'

# Register a local MCP server with Claude Code (stdio transport)
claude mcp add magento-catalog -- python3 ./mcp-servers/catalog_server.py

# Register a remote MCP server reachable over HTTP transport
claude mcp add docs-search --transport http https://mcp.internal.mironsoft.de/docs

7. Practical examples: database, ticketing and documentation servers

Three recurring examples illustrate nicely how different MCP servers can look in practice, even though they all follow the same protocol. A database server typically wraps a small number of tightly scoped queries instead of generic SQL access, for example product search by SKU or stock lookups, and usually runs locally over stdio with a read-only database user. A ticketing server for systems like Jira or GitHub Issues, by contrast, exposes typical workflow actions as tools, such as creating a ticket, changing its status, or adding a comment, and it often runs as a central HTTP server because several people on the team want to use it at the same time.

A documentation search server usually exposes a combination of a search tool that runs semantic or full-text search over internal handbooks, runbooks, or wikis, and resources for individual documents that can then be attached as context. The example below shows an excerpt from a ticketing server in Node.js using the official TypeScript SDK: the tool create_ticket validates its parameters through a Zod schema, calls the tracker's internal REST API, and returns a short confirmation message with the newly created ticket ID back to the model.


// mcp-jira-server.js: expose a ticketing system as MCP tools
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "jira-tickets", version: "1.0.0" });

server.tool(
  "create_ticket",
  "Create a new support ticket in the tracker",
  {
    title: z.string(),
    description: z.string(),
    priority: z.enum(["low", "medium", "high"]),
  },
  async ({ title, description, priority }) => {
    const response = await fetch("https://jira.internal/api/issues", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ title, description, priority }),
    });
    const ticket = await response.json();
    return {
      content: [{ type: "text", text: `Created ticket ${ticket.key}` }],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

8. Security and trust: what MCP does not automatically solve

MCP standardizes how an assistant accesses external systems, but it makes no statement about whether that access is safe. A server gets exactly the rights that its underlying code and the credentials it uses bring with it; a database server whose user has write access to the entire database can, in theory, do far more than search products, even if only a single read-only tool is exposed. Likewise, content read through a resource, such as a manipulated wiki page, can attempt to steer the model toward unwanted tool calls through prompt injection.

The practical countermeasures barely differ from those for any other external dependency: create database users with the least privilege necessary, review a third-party server's source code before installing it, and use host applications like Claude Code that require confirmation before potentially consequential tool calls instead of executing every call blindly. For HTTP servers, network segmentation is an additional layer, so a compromised server does not automatically gain access to further internal systems. MCP servers should be treated organizationally like any other software dependency, including versioning, updates, and occasional security review.

9. Setting up MCP in Claude Code and Claude Desktop

Claude Code and Claude Desktop read MCP server definitions from an .mcp.json file or from the configuration managed via claude mcp add. Each entry describes how a server is started, either as a local process with a command and arguments for stdio, or as a URL for a remote HTTP server. Claude Code distinguishes three visibility scopes: local for servers visible only on your own machine, project-wide for servers that are versioned in the repository and shared with the team, and user-wide for servers that should be available across all projects.


{
  "mcpServers": {
    "magento-catalog": {
      "command": "python3",
      "args": ["./mcp-servers/catalog_server.py"],
      "env": { "DB_HOST": "localhost" }
    },
    "docs-search": {
      "command": "npx",
      "args": ["-y", "@mironsoft/mcp-docs-search"]
    },
    "jira-tickets": {
      "url": "https://mcp.internal.mironsoft.de/jira",
      "transport": "http"
    }
  }
}

The following overview weighs the effort of MCP against a classic custom integration built per tool.

Aspect Without MCP (custom integration) With an MCP server Benefit
Connecting a new tool A dedicated API client per assistant and tool One server, usable by any MCP client No N-times-M integration overhead
Describing a tool Hardcoded in the prompt, manually maintained Schema is reported by the server at runtime Self-describing, less prompt maintenance
Data access Direct DB access from the assistant's code Encapsulated behind defined tools/resources Controlled, auditable interface
Reusability Tied to a single chatbot/client Server runs independently of the client Reusable across multiple AI applications
Permissions Often an implicit API key with full access Server scopes tools/resources granularly Smaller blast radius when things go wrong

In practice, many setups combine both approaches: fast, local MCP servers for development tools such as database or filesystem access, and continued direct API calls for one-off special cases that no second client will ever reuse.

Mironsoft

Magento and Hyva development with AI-assisted workflows

Want an MCP server built for your Magento store?

We build MCP servers that connect Claude to your product data, ticketing systems and internal documentation in a structured way, including a permission model and setup in Claude Code.

MCP server development

Database, ticketing and documentation access as a dedicated server

Security design

Least privilege, network segmentation and confirmation rules

Team rollout

Project-wide .mcp.json configuration for the whole team

10. Summary

The Model Context Protocol solves a structural problem in AI-assisted development: without a common standard, every combination of assistant and external tool would need to be integrated separately. MCP reduces that effort by letting servers describe their capabilities once via tools, resources and prompts, and any MCP-capable client, including Claude Code and Claude Desktop, can use them without further customization. The split into host, client and server keeps responsibilities clear: the server knows nothing about a language model, the client knows no business-logic detail, and the host decides which servers are trusted at all.

It remains important that MCP is a communication protocol, not a security guarantee. Access rights, prompt injection risks, and the trustworthiness of third-party servers still need to be addressed deliberately, with the same tools used for any other external dependency. For teams that want to connect several internal systems, such as databases, ticketing, and documentation, to Claude, MCP is by now the most practical standard route, because the work invested in a server stays reusable across projects and even across different AI applications.

Model Context Protocol (MCP): the essentials at a glance

Problem solved

N times M custom integrations between assistants and tools become N plus M reusable MCP servers.

Architecture

A host manages clients, each client holds a one-to-one connection to a server, capabilities are exchanged in a handshake.

Capabilities

Tools (model-controlled), resources (application-controlled) and prompts (user-controlled) clearly separate who triggers an action.

Security

MCP standardizes the access path, not its safety. Least privilege and server review remain necessary.

11. FAQ: Model Context Protocol (MCP)

1What is the Model Context Protocol (MCP)?
An open standard released by Anthropic in November 2024 that describes how AI assistants connect to external tools and data sources in a structured way, without a proprietary integration per assistant and tool.
2What problem does MCP actually solve?
Reduces the N-times-M integration problem between assistants and tools to N plus M, because each server is implemented once and can be used by any number of clients.
3What is the difference between host, client and server?
The host is the application, the client maintains a one-to-one connection to exactly one server, the server provides the actual access to an external system.
4What are tools in MCP?
Functions with a defined parameter schema that the language model can call on its own at runtime. Host applications usually ask for confirmation before tools with side effects run.
5What are resources and how do they differ from tools?
Addressable, mostly read-only data sources with a unique URI, comparable to a GET request. Usually the application or the user selects them, not the model.
6What are prompts in MCP?
Predefined, parameterizable templates that the user triggers deliberately, similar to a slash command, producing a complete request to the model.
7Which transport mechanisms does MCP support?
stdio for local processes without network exposure, HTTP with streaming support for central, shared servers with OAuth authentication.
8Is MCP only usable with Claude or is it an open standard?
An open standard with a public specification. Besides Claude, several other clients now support the protocol, and server implementations are client-independent.
9What security risks does MCP bring with it?
A server gets the rights of its credentials, and resource content can attempt prompt injection. Least privilege and server review remain necessary.
10How do I set up an MCP server in Claude Code?
Via claude mcp add with a command/arguments for stdio, or a URL for HTTP. Configuration can be stored locally, project-wide via .mcp.json, or user-wide.