The problem MCP solves

Every AI application needs context — files, tickets, databases, calendars — and the ability to act. Before MCP, each pairing was a bespoke integration: the IDE assistant had its own GitHub connector, the chat app another, your internal agent a third. That’s the classic M × N problem: M apps times N tools.

Without MCP

M × N custom integrations. Each app re-implements auth, schemas and error handling for each tool.

With MCP

M + N. Each tool ships one MCP server; each app ships one MCP client. They interoperate.

MCP architecture: hosts, clients and servers

  • Host: the application the user interacts with — a desktop chat assistant, a code editor, a custom agent. It manages clients, permissions and the LLM.
  • Client: a connector inside the host that maintains a one-to-one session with a single server.
  • Server: a program that exposes capabilities from a system — e.g., a Postgres server offering a query tool and table schemas as resources.

Messages use JSON-RPC 2.0. Two standard transports cover most cases: stdio for local servers launched as a subprocess, and Streamable HTTP for remote servers (with OAuth-based authorisation for protected ones).

The building blocks: tools, resources and prompts

PrimitiveWhat it isControlled byExample
ToolsFunctions the model can call to act or computeThe model (with user approval)create_issue, run_query, send_email
ResourcesRead-only data the app can load as contextThe applicationFile contents, DB schema, a wiki page
PromptsReusable prompt templates with parametersThe user (e.g., slash commands)“Summarise PR #{number}”

Clients can offer capabilities back to servers too — for example sampling (a server asks the host’s LLM to generate text) and elicitation (a server asks the user for extra input mid-task).

What happens during an MCP call

Step through

User asks: “Open a GitHub issue for the login bug we just discussed.”

MCP vs function calling vs APIs

REST / GraphQL APIFunction (tool) callingMCP
What it isInterface to a serviceModel capability to request a tool callProtocol for serving tools, data and prompts to AI apps
Who integratesDeveloper, per appDeveloper defines tools per appServer built once; any MCP client discovers it
DiscoveryRead the docsHard-coded in your appAt runtime via tools/list etc.
RelationshipOften wrapped by an MCP serverHow the model invokes MCP toolsSits between the two

They’re layers, not competitors: the API does the work, the MCP server describes and exposes it in a standard way, and function calling is how the model asks to use it.

Build a minimal MCP server in Python

The official Python SDK includes FastMCP, which turns type-hinted functions into MCP tools — the docstring becomes the description the model reads.

server.py
# pip install "mcp[cli]"
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("course-catalog")

COURSES = {
    "prompt-engineering": "Write reliable prompts: roles, examples, structured output.",
    "rag": "Build retrieval-augmented generation apps end to end.",
}

@mcp.tool()
def search_courses(keyword: str) -> list[str]:
    """Search course names and descriptions by keyword. Returns matching course ids."""
    k = keyword.lower()
    return [cid for cid, desc in COURSES.items() if k in cid or k in desc.lower()]

@mcp.resource("course://{course_id}")
def course_details(course_id: str) -> str:
    """Full description of a course."""
    return COURSES.get(course_id, "Course not found")

@mcp.prompt()
def study_plan(course_id: str, weeks: int = 4) -> str:
    """Prompt template that asks for a study plan."""
    return f"Create a {weeks}-week study plan for the course '{course_id}'."

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

Test it with the MCP Inspector (mcp dev server.py), then register it in any MCP-capable host. Many desktop hosts use a JSON config along these lines:

{
  "mcpServers": {
    "course-catalog": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

Write tool descriptions like prompts — clear, specific, with when-to-use guidance — because they are literally what the model reads when deciding which tool to call. Define precise input schemas (the JSON Schema Builder helps).

MCP security risks

RiskWhat it looks likeMitigation
Prompt injection via tool outputA fetched web page or email contains “ignore your instructions and…”Treat outputs as data; confirm sensitive actions with the user
Tool poisoningMalicious instructions hidden in a tool’s descriptionInstall servers only from trusted sources; review descriptions; pin versions
Over-permissioned serversA “read docs” server holding admin tokensLeast-privilege, scoped credentials per server
Data exfiltrationCombining a private-data tool with an outbound toolSeparate sensitive servers; restrict outbound actions; log everything

When should you use MCP?

  • Yes: you want the same tools available across several AI apps, agents or IDEs; you’re publishing an integration for others; you want users to plug in their own servers.
  • Maybe not: a single app with two internal functions — plain function calling is simpler.
Quick quiz

MCP essentials