Model Context Protocol (MCP) and Tool Calling
Model Context Protocol (MCP) and Tool Calling
Learn how the Model Context Protocol standardizes connections between AI applications and external capabilities through hosts, clients, servers, tools, resources, prompts, structured schemas, capability negotiation, secure transports, user approval, observability, and controlled tool execution.
Introduction
Large Language Models generate text from the information available in their context. They do not automatically have access to current databases, organizational documents, calculators, business applications, or external APIs.
Application developers can connect models to these systems through custom integrations. However, building a different connector for every combination of AI application and external system creates duplicated implementation, inconsistent interfaces, and additional security and maintenance responsibilities.
The Model Context Protocol, abbreviated as MCP, provides a standardized protocol through which compatible AI applications can connect to servers that expose context and capabilities.
Tool calling allows a model to request a structured operation such as a calculation, search, database lookup, or API call. The application remains responsible for validating, authorizing, executing, and auditing the requested operation.
Learning Objectives
By the End of This Lesson
- Define the Model Context Protocol
- Explain why standardized AI integrations are useful
- Identify MCP hosts, clients, and servers
- Distinguish tools, resources, and prompts
- Understand JSON-RPC communication
- Understand initialization and capability negotiation
- Explain tool discovery and invocation
- Create explicit tool input schemas
- Return structured tool results
- Build a basic Python MCP server
- Create read-only and action-oriented tools
- Understand MCP client responsibilities
- Distinguish MCP from ordinary model tool calling
- Validate model-generated tool arguments
- Apply least-privilege authorization
- Require approval for consequential actions
- Handle tool errors, timeouts, and retries
- Test MCP servers and tool contracts
- Monitor MCP operations
- Create an MCP production-readiness checklist
Prerequisites
Recommended Knowledge
- Python programming
- Functions, exceptions, and type annotations
- Large Language Model fundamentals
- Prompt engineering
- JSON and JSON Schema
- REST and remote API fundamentals
- Authentication and authorization
- Tool-calling agents
- LangChain and LangGraph orchestration
- Observability and structured logging
- Application security fundamentals
Example Packages
- Official MCP Python SDK
- Pydantic
- HTTPX for approved HTTP integrations
- python-dotenv for local development
- pytest for testing
python -m pip install \
mcp \
pydantic \
httpx \
python-dotenv \
pytest
What Is MCP?
MCP is an open protocol that defines a standard way for an AI application to obtain contextual information and interact with external capabilities exposed by compatible servers.
| MCP Provides | Purpose |
|---|---|
| Standard Messages | Define compatible requests, responses, and notifications |
| Capability Negotiation | Allows participants to declare supported features |
| Tool Discovery | Allows clients to obtain available tool definitions |
| Resource Access | Allows servers to expose contextual information |
| Prompt Discovery | Allows servers to expose reusable prompt templates |
| Structured Errors | Communicates protocol and operation failures |
| Progress and Cancellation | Supports controlled handling of longer operations |
MCP Architecture
| Component | Responsibility |
|---|---|
| Host | Runs the user-facing AI application and manages connected clients |
| Client | Maintains protocol communication with one MCP server |
| Server | Exposes approved tools, resources, or prompts |
| Local Data Source | Provides files, databases, or local application data |
| Remote Service | Provides external data or operations through approved APIs |
| Language Model | May select or request tools based on user intent and context |
MCP Host
The host is the AI application that coordinates user interaction, model access, MCP clients, permissions, consent, and result presentation.
Host Responsibilities
- Authenticate the user
- Manage MCP server connections
- Control which capabilities enter model context
- Present exposed tools clearly
- Request confirmation where required
- Validate model-generated tool requests
- Protect credentials and private context
- Display results safely
- Record audit and observability evidence
- Terminate unsafe or unauthorized operations
MCP Client
An MCP client is a protocol connector managed by the host. It establishes communication with an MCP server and exchanges protocol messages.
Client Responsibilities
- Establish the server connection
- Initialize the protocol session
- Negotiate capabilities
- Discover tools, resources, and prompts
- Send structured requests
- Receive responses and notifications
- Handle pagination where required
- Handle cancellation and errors
- Close connections safely
MCP Server
An MCP server exposes a focused set of approved capabilities. It translates protocol operations into interactions with local or remote systems.
Server Responsibilities
- Declare supported capabilities
- Publish accurate tool and resource definitions
- Validate every request
- Authenticate and authorize the caller
- Enforce least privilege
- Protect downstream credentials
- Apply timeouts and rate limits
- Return structured results and errors
- Record audit evidence
- Prevent unauthorized side effects
Core MCP Primitives
| Primitive | Purpose | Typical Control |
|---|---|---|
| Tools | Expose functions or operations | Model-controlled request with application authorization |
| Resources | Expose contextual data identified by a URI | Application-controlled discovery and reading |
| Prompts | Expose reusable prompt templates or workflows | User or application selection |
| Sampling | Allows an eligible server to request language-model generation through the client | Client-controlled model access and policy |
MCP Tools
An MCP tool is a named capability with a description and structured input schema. The description helps the model or application understand when the tool is appropriate.
{
"name": "calculate_order_total",
"description": "Calculate the total of non-negative item prices.",
"inputSchema": {
"type": "object",
"properties": {
"item_prices": {
"type": "array",
"items": {
"type": "number",
"minimum": 0
},
"minItems": 1
}
},
"required": [
"item_prices"
],
"additionalProperties": false
}
}
Good Tool Definition
- Uses a stable and descriptive name
- Explains when the tool should be used
- Explains important limitations
- Defines required arguments
- Uses strict data types and constraints
- Rejects unexpected arguments
- Documents side effects
- Returns a predictable structure
MCP Resources
Resources expose contextual information that an application can discover or read. A resource is commonly identified through a URI.
{
"uri": "knowledge://policies/password-reset",
"name": "Password Reset Policy",
"description": "Approved password-reset policy content.",
"mimeType": "text/plain"
}
| Resource Type | Example |
|---|---|
| Static Resource | One approved configuration or policy document |
| Dynamic Resource | Current state returned from a source system |
| Resource Template | A parameterized URI for a family of records |
| Text Resource | Plain text, Markdown, JSON, or code |
| Binary Resource | Binary content represented according to the protocol |
MCP Prompts
MCP prompts are reusable prompt templates exposed by a server. They can standardize interactions with a capability or domain.
{
"name": "summarize_policy",
"description": "Create a concise summary of an approved policy resource.",
"arguments": [
{
"name": "policy_uri",
"description": "URI of the authorized policy resource.",
"required": true
},
{
"name": "audience",
"description": "Intended audience for the summary.",
"required": true
}
]
}
JSON-RPC Communication
MCP uses JSON-RPC messages. A request includes a method and may include parameters. A response contains either a result or an error associated with the request identifier.
| Message Type | Purpose |
|---|---|
| Request | Asks the receiving party to perform an operation |
| Response | Returns a result for a request |
| Error Response | Returns structured failure information |
| Notification | Communicates an event without requiring a response |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": []
}
}
Initialization and Capability Negotiation
Before ordinary operations begin, the client and server establish protocol compatibility and exchange information about supported capabilities.
Initialization Establishes
- Protocol version compatibility
- Client identity and capabilities
- Server identity and capabilities
- Supported primitives
- Applicable optional features
- Session readiness
Tool Discovery
The host can make authorized tool definitions available to the model. The model may then request one of those tools using arguments that should conform to the tool's schema.
Tool Invocation Lifecycle
Discover Tools
The client obtains the tools available under the caller's authorized scope.
Make Tools Available to the Model
The host supplies selected tool definitions to the language model.
Receive a Tool Request
The model returns a structured tool name and proposed arguments.
Validate and Authorize
The application validates schema, semantics, caller permission, target scope, and action risk.
Request Approval
The host obtains human confirmation when the operation requires approval.
Invoke the Tool
The client sends the approved tool request to the MCP server.
Return the Result
The server returns structured content or a controlled error.
Generate the Final Response
The model uses the result while the application validates and presents the final response.
Build a Basic MCP Server
from mcp.server.fastmcp import FastMCP
mcp_server = FastMCP(
"Course Utility Server"
)
@mcp_server.tool()
def calculate_order_total(
item_prices: list[
float
]
) -> dict:
"""Calculate the total of non-negative item prices."""
if not item_prices:
raise ValueError(
"At least one item price is required."
)
if any(
item_price < 0
for item_price in item_prices
):
raise ValueError(
"Item prices cannot be negative."
)
total = sum(
item_prices
)
return {
"item_count": len(
item_prices
),
"total": round(
total,
2
)
}
if __name__ == "__main__":
mcp_server.run()
Expose a Resource
from mcp.server.fastmcp import FastMCP
mcp_server = FastMCP(
"Knowledge Server"
)
APPROVED_POLICY_TEXT = (
"Password resets must use the "
"approved identity-verification workflow."
)
@mcp_server.resource(
"knowledge://policies/password-reset"
)
def read_password_reset_policy() -> str:
"""Return the approved password-reset policy."""
return APPROVED_POLICY_TEXT
Expose a Prompt
@mcp_server.prompt()
def summarize_policy(
policy_text: str,
audience: str
) -> str:
"""Create a controlled policy-summary prompt."""
return (
"Summarize the supplied policy for "
f"the following audience: {audience}.\n\n"
"Use only the supplied policy. "
"Do not add requirements.\n\n"
f"Policy:\n{policy_text}"
)
Build a Tool that Calls an External API
import os
import httpx
from mcp.server.fastmcp import FastMCP
mcp_server = FastMCP(
"Approved Service Connector"
)
@mcp_server.tool()
async def get_record_status(
record_id: str
) -> dict:
"""Get the status of an authorized record."""
normalized_record_id = (
record_id.strip()
)
if not normalized_record_id:
raise ValueError(
"record_id is required."
)
if len(
normalized_record_id
) > 100:
raise ValueError(
"record_id exceeds the "
"approved length."
)
service_base_url = os.environ[
"APPROVED_SERVICE_BASE_URL"
]
access_token = os.environ[
"APPROVED_SERVICE_ACCESS_TOKEN"
]
request_url = (
f"{service_base_url}/records/"
f"{normalized_record_id}"
)
timeout = httpx.Timeout(
10.0
)
async with httpx.AsyncClient(
timeout=timeout,
verify=True
) as client:
response = await client.get(
request_url,
headers={
"Authorization": (
f"Bearer {access_token}"
)
}
)
response.raise_for_status()
response_data = response.json()
return {
"record_id": normalized_record_id,
"status": response_data.get(
"status"
)
}
Create a Read-Only Database Tool
import os
import sqlite3
from mcp.server.fastmcp import FastMCP
mcp_server = FastMCP(
"Inventory Lookup Server"
)
@mcp_server.tool()
def get_inventory_summary(
item_id: str
) -> dict:
"""Get an inventory summary for one item."""
normalized_item_id = (
item_id.strip()
)
if not normalized_item_id:
raise ValueError(
"item_id is required."
)
database_path = os.environ[
"APPROVED_INVENTORY_DATABASE"
]
query = (
"SELECT item_id, available_quantity "
"FROM inventory_summary "
"WHERE item_id = ?"
)
with sqlite3.connect(
database_path
) as connection:
connection.row_factory = (
sqlite3.Row
)
result = connection.execute(
query,
(
normalized_item_id,
)
).fetchone()
if result is None:
return {
"found": False,
"item_id": normalized_item_id
}
return {
"found": True,
"item_id": result[
"item_id"
],
"available_quantity": result[
"available_quantity"
]
}
Direct Tool Calling vs MCP
| Area | Direct Tool Calling | MCP |
|---|---|---|
| Tool Definition | Defined directly in the application or provider API | Discovered from a compatible MCP server |
| Integration Contract | Application-specific | Standardized protocol contract |
| Discovery | Usually configured by application code | Supported through protocol operations |
| Transport | Depends on application implementation | Uses supported MCP transport patterns |
| Resources and Prompts | Require separate application design | Defined as MCP primitives |
| Authorization | Application responsibility | Still an application and server responsibility |
Generic Model Tool-Calling Loop
def run_tool_calling_loop(
model_client,
messages,
available_tools,
execute_tool,
maximum_tool_calls=5
):
tool_call_count = 0
while True:
model_response = model_client.generate(
messages=messages,
tools=available_tools
)
tool_requests = (
model_response.get(
"tool_calls",
[]
)
)
if not tool_requests:
return model_response[
"content"
]
for tool_request in tool_requests:
tool_call_count += 1
if (
tool_call_count
>
maximum_tool_calls
):
raise RuntimeError(
"Maximum tool-call limit reached."
)
tool_name = tool_request[
"name"
]
tool_arguments = tool_request[
"arguments"
]
tool_result = execute_tool(
tool_name=tool_name,
arguments=tool_arguments
)
messages.append(
{
"role": "tool",
"name": tool_name,
"content": tool_result
}
)
Validate Tool Arguments
from pydantic import BaseModel
from pydantic import Field
from pydantic import ValidationError
class OrderTotalInput(
BaseModel
):
item_prices: list[
float
] = Field(
min_length=1,
max_length=100
)
def validate_order_total_arguments(
proposed_arguments
):
try:
validated_arguments = (
OrderTotalInput.model_validate(
proposed_arguments
)
)
if any(
item_price < 0
for item_price
in validated_arguments.item_prices
):
raise ValueError(
"Negative item prices "
"are not permitted."
)
return {
"valid": True,
"arguments": (
validated_arguments.model_dump()
),
"error": None
}
except (
ValidationError,
ValueError
) as error:
return {
"valid": False,
"arguments": None,
"error": str(
error
)
}
Authentication vs Authorization
| Control | Question |
|---|---|
| Authentication | Who is making the request? |
| Authorization | May this identity perform this operation? |
| Scope Validation | Is the requested target inside the permitted boundary? |
| Consent | Has an informed user approved this operation where required? |
| Audit | Can the decision and execution be reconstructed? |
Human Approval
Consequential tools should require clear user confirmation before execution.
Approval Interface Should Display
- The tool name and purpose
- The proposed action
- The target system and record
- The validated arguments
- The expected effect
- Whether the operation is reversible
- Relevant warnings
- The requesting application
- Approve, reject, or edit options
Read Tools vs Action Tools
| Tool Type | Example | Primary Risk |
|---|---|---|
| Read Tool | Retrieve the status of one authorized record | Data disclosure |
| Calculation Tool | Calculate a deterministic total | Incorrect inputs or interpretation |
| Create Tool | Create a new business record | Unauthorized side effect |
| Update Tool | Modify an existing record | Incorrect or destructive change |
| Delete Tool | Remove a record | Potentially irreversible loss |
| Communication Tool | Send an approved message | External disclosure or unintended commitment |
| Execution Tool | Run an approved automation | Code execution and downstream effects |
Idempotency
An idempotent operation can be repeated with the same idempotency identity without producing an additional unintended effect.
from pydantic import BaseModel
from pydantic import Field
class CreateRequest(
BaseModel
):
idempotency_key: str = Field(
min_length=16,
max_length=128
)
requested_value: str = Field(
min_length=1,
max_length=500
)
def create_record_safely(
request: CreateRequest,
repository
):
previous_result = (
repository.find_by_idempotency_key(
request.idempotency_key
)
)
if previous_result is not None:
return previous_result
return repository.create(
idempotency_key=(
request.idempotency_key
),
requested_value=(
request.requested_value
)
)
Tool Error Handling
| Error | Controlled Response |
|---|---|
| Invalid Arguments | Reject and provide a bounded validation message |
| Authentication Failure | Reject and require a valid identity |
| Authorization Failure | Reject without allowing model override |
| Record Not Found | Return an explicit not-found result without fabrication |
| Temporary Dependency Failure | Use bounded retry where safe or return controlled failure |
| Timeout | Cancel where possible and avoid claiming success |
| Partial Side Effect | Stop, preserve evidence, and initiate recovery procedures |
| Rate Limit | Apply approved backoff or return an actionable error |
Timeouts and Bounded Retries
import asyncio
async def run_with_timeout(
operation,
timeout_seconds
):
if timeout_seconds <= 0:
raise ValueError(
"timeout_seconds must be positive."
)
try:
return await asyncio.wait_for(
operation,
timeout=timeout_seconds
)
except asyncio.TimeoutError as error:
raise TimeoutError(
"Tool execution exceeded "
"the approved timeout."
) from error
Bound
- Total tool calls per request
- Retries per tool
- Execution duration
- Input and output size
- Database rows returned
- Network response size
- Total model tokens
- Total request cost
Prompt Injection and Tool Poisoning
Untrusted content may attempt to influence a model into calling tools, disclosing data, or ignoring application policy. Tool names, descriptions, results, resources, and prompts can also become attack surfaces if their source or integrity is not controlled.
Required Defenses
- Trust only approved MCP servers
- Review tool descriptions and schemas
- Pin or verify server packages and configurations
- Treat resources and tool results as untrusted data
- Keep credentials outside model context
- Do not let content change authorization policy
- Validate tool selection and arguments outside the model
- Require confirmation for consequential actions
- Restrict network, file, and process access
- Monitor unexpected capability changes
- Test direct and indirect prompt injection
- Disable servers that fail integrity checks
Supply-Chain Security
Server Supply-Chain Controls
- Use approved server repositories
- Pin dependency and server versions
- Verify package integrity
- Review source code or publisher trust
- Scan dependencies and container images
- Restrict server permissions
- Run servers in isolated environments where appropriate
- Monitor tool-list and schema changes
- Maintain an inventory of connected servers
- Remove unused or abandoned servers
Test MCP Tools Directly
def test_calculate_order_total():
result = calculate_order_total(
item_prices=[
12.50,
7.25,
3.00
]
)
assert result[
"item_count"
] == 3
assert result[
"total"
] == 22.75
def test_calculate_order_total_rejects_negative():
try:
calculate_order_total(
item_prices=[
10.00,
-2.00
]
)
assert False
except ValueError as error:
assert (
"negative"
in str(
error
).lower()
)
MCP Testing Layers
| Test Layer | Purpose |
|---|---|
| Function Unit Test | Validates core business logic |
| Schema Test | Validates accepted and rejected arguments |
| Authorization Test | Verifies permitted and denied identities |
| Tool Discovery Test | Verifies the correct authorized tool set |
| Protocol Test | Validates initialization and request-response behavior |
| Transport Test | Validates connection, cancellation, and shutdown |
| Failure Test | Validates timeouts, dependency failures, and partial results |
| Consent Test | Verifies required approval before execution |
| Model Selection Test | Verifies correct and unnecessary tool-call behavior |
| Security Test | Tests injection, privilege escalation, and data exposure |
MCP Observability
Record for Every Tool Operation
- Request and trace identifiers
- Host, client, and server versions
- Authenticated identity reference
- Tool name and schema version
- Validated argument metadata
- Authorization decision
- Approval decision where applicable
- Execution status
- Duration and timeout status
- Result type and response size
- Error category
- Downstream dependency status
MCP Metrics
| Metric | Purpose |
|---|---|
| Server Availability | Tracks successful client-server communication |
| Tool Discovery Failures | Tracks capability-listing problems |
| Tool Invocation Count | Tracks usage by tool and version |
| Tool Success Rate | Tracks completed operations |
| Tool Latency | Tracks operation-duration distributions |
| Validation Failure Rate | Tracks invalid model-generated arguments |
| Authorization Denial Rate | Tracks rejected operations |
| Approval Rejection Rate | Tracks user rejection of proposed actions |
| Timeout and Retry Rate | Tracks dependency and reliability issues |
| Unexpected Tool-List Change | Tracks capability drift |
| Cost per Completed Task | Tracks model and tool operating efficiency |
Version the Complete MCP Integration
| Asset | Versioning Requirement |
|---|---|
| Protocol | Supported MCP specification version |
| Host Application | Application and orchestration version |
| MCP Client | SDK and client-configuration version |
| MCP Server | Server code, package, and deployment version |
| Tool | Name, description, input schema, output contract, and implementation |
| Resource | URI, content source, schema, and version |
| Prompt | Template, arguments, and approval version |
| Authorization Policy | Scope, role, resource, and action policy version |
| Model | Provider, model, and immutable revision |
| Evaluation | Test suite, dataset, metrics, and release policy |
Responsible Tool Calling
Responsible-Use Requirements
- Define intended and prohibited tools
- Separate information retrieval from consequential actions
- Use the minimum data required for each tool
- Preserve human oversight where needed
- Explain proposed actions before confirmation
- Provide cancellation and correction options
- Test behavior with ambiguous requests
- Test unauthorized and adversarial requests
- Prevent the model from claiming unexecuted actions succeeded
- Record limitations and known failure modes
- Monitor complaints and unexpected outcomes
- Disable tools that no longer satisfy approved requirements
Common MCP and Tool-Calling Mistakes
Troubleshooting
| Symptom | Investigation |
|---|---|
| Initialization Fails | Protocol versions, SDK compatibility, transport, and server startup |
| Tool Is Missing | Server capability, authorization scope, tool registration, and discovery cache |
| Model Selects Wrong Tool | Tool name, description, overlap, prompt, and model capability |
| Arguments Fail Validation | Input schema, descriptions, model output, and application mapping |
| Authorization Is Inconsistent | Caller identity, token audience, scopes, resource policy, and caching |
| Tool Executes Twice | Retries, idempotency, client reconnects, and duplicated requests |
| Tool Times Out | Dependency latency, timeout policy, payload size, and cancellation |
| Result Is Truncated | Response limits, pagination, serialization, and client handling |
| Server Leaks Data | Authorization, filtering, resource discovery, logs, and error messages |
| Works Locally but Not Remotely | Transport, authentication, certificates, network policy, and environment configuration |
Recommended MCP Workflow
Define the Capability
Identify the user need, source system, allowed operation, expected output, risks, and ownership.
Select the Correct Primitive
Use a resource for context, a prompt for a reusable template, or a tool for an operation.
Design the Contract
Define stable names, descriptions, strict schemas, bounded results, and explicit failure behavior.
Implement Security
Add authentication, authorization, least privilege, isolation, secret protection, and scoped data access.
Add Consent and Idempotency
Require meaningful approval for consequential actions and protect repeated side effects.
Implement the Server
Register focused tools, resources, and prompts using a compatible SDK.
Integrate the Client
Initialize the connection, negotiate capabilities, discover permitted features, and invoke them safely.
Test Every Layer
Test functions, schemas, permissions, consent, protocol, transport, errors, injection, and model behavior.
Deploy with Observability
Record versions, decisions, latency, errors, tool results, approvals, and downstream effects safely.
Govern and Improve
Review usage, security, schemas, unexpected behavior, cost, complaints, server inventory, and retirement needs.
Hands-On Practice
Create a Calculation Tool
Build a deterministic tool with typed arguments, validation, structured output, and unit tests.
Create a Resource
Expose one synthetic, read-only knowledge resource through a stable URI.
Create a Prompt
Expose a reusable prompt with defined arguments and evidence boundaries.
Add External API Access
Call an approved development API using secure credentials, validation, transport protection, and timeouts.
Test Tool Discovery
Verify that different authorized identities receive only their permitted tool definitions.
Test Tool Calling
Verify correct selection, invalid arguments, unnecessary calls, and tool-result interpretation.
Add Human Approval
Create one synthetic side-effecting operation that cannot run without explicit confirmation.
Run Security Tests
Test unauthorized access, malicious tool arguments, prompt injection, duplicate execution, timeouts, and data leakage.
Knowledge Check
What is MCP?
Explain how it standardizes communication between AI applications and external context or capabilities.
What is an MCP host?
Explain the user-facing AI application that manages clients, model context, consent, and presentation.
What is an MCP client?
Explain the connector that communicates with one MCP server.
What is an MCP server?
Explain how it exposes approved tools, resources, or prompts.
How does a resource differ from a tool?
Explain contextual data access compared with requesting an operation.
What is capability negotiation?
Explain how protocol participants declare their supported features during initialization.
Why is valid JSON insufficient for tool execution?
Explain the need for semantic, authorization, target, policy, and business validation.
Why is idempotency important?
Explain how it prevents repeated requests from creating duplicate unintended side effects.
Why should tool results be treated as untrusted?
Explain how external data can contain errors, malicious instructions, oversized content, or unauthorized information.
Why does MCP not replace authorization?
Explain that protocol compatibility does not determine whether a specific caller may perform a specific operation.
MCP Readiness Checklist
Confirm Before Production Use
- The MCP use case is documented
- The host, client, server, and data owners are identified
- The supported protocol version is recorded
- The server source and publisher are approved
- Server and dependency versions are pinned
- Tools, resources, and prompts are inventoried
- Each tool has a stable name and clear description
- Each tool has a strict input schema
- Unexpected arguments are rejected
- Tool results use a documented structure
- Resources use stable URIs
- Resource access is permission-aware
- Prompt templates are reviewed and versioned
- Authentication occurs at the correct boundary
- Authorization is checked for every operation
- Only permitted tools are discoverable
- Least-privilege permissions are enforced
- Credentials remain outside model context
- External destinations are allowlisted
- Secure transport is configured
- Tool arguments receive semantic validation
- Consequential operations require approval
- Approval displays the exact action and target
- Side-effecting operations implement idempotency
- Timeouts and cancellation are configured
- Retries are bounded and operation-aware
- Input, output, row, token, and cost limits exist
- Tool results are treated as untrusted data
- Prompt-injection tests pass
- Privilege-escalation tests pass
- Tool-discovery tests pass
- Protocol and transport tests pass
- Error handling does not fabricate success
- Tool calls have trace and request identifiers
- Sensitive telemetry is minimized
- Unexpected capability changes generate alerts
- Fallback and recovery are tested
- Server revocation and retirement are documented
- The complete integration is versioned and auditable
Lesson Summary
| Concept | Main Outcome |
|---|---|
| MCP | Standardizes connections between AI applications and external capabilities |
| Host | Runs the AI application and manages clients and user interaction |
| Client | Maintains protocol communication with one server |
| Server | Exposes approved tools, resources, and prompts |
| Tool | Provides a structured callable operation |
| Resource | Provides contextual data through a URI |
| Prompt | Provides a reusable prompt template |
| JSON-RPC | Provides the protocol message format |
| Capability Negotiation | Establishes supported protocol features |
| Tool Discovery | Provides the permitted tool definitions to a client |
| Tool Calling | Allows a model to request a structured operation |
| Schema Validation | Checks argument structure and data types |
| Authorization | Determines whether the caller may perform the operation |
| Human Approval | Preserves control over consequential actions |
| Observability | Provides traceability for discovery, decisions, execution, and results |
Key Takeaway
The Model Context Protocol provides a standardized way for AI applications to connect with external context and capabilities. An MCP host manages the user-facing application, MCP clients maintain protocol connections, and MCP servers expose tools, resources, and prompts. Tools allow models to request structured operations, while resources provide contextual data and prompts provide reusable interaction templates. MCP improves integration consistency, but it does not make model-generated actions inherently safe. Production systems must still authenticate users, authorize every operation, expose only permitted capabilities, validate tool arguments, protect credentials, isolate servers, treat external content as untrusted, require meaningful approval, implement idempotency, bound retries, and audit every consequential action. The objective is not to give an AI model unrestricted access. The objective is to provide carefully scoped, discoverable, interoperable, and governed capabilities.
Get Machine Learning updates by email
Short, practical lessons and course updates from Rumman Ansari. No spam.