Lesson 3: Give Your Agent Tools Using MCP
Code for this lesson: samples/03-mcp-tools
Where Tools Come From
Section titled “Where Tools Come From”Tools give agents the ability to take actions and access information beyond what’s in the model’s training data. There isn’t one way to define a tool. Tools can come from different places, and they all sit side by side in the same agent’s tools list:
- Custom tools you write yourself with the
@tooldecorator (you saw this in lesson 1) - Vended tools that ship with the SDK in
strands.vended_tools: file editing, shell, web fetch - MCP servers that expose tools over a standard protocol, whether you run them or someone else does
- Other agents, which you’ll see in lesson 10 when we cover agents as tools
MCP is particularly powerful because it lets you connect agents to externally managed tool servers. The agent discovers available tools dynamically at runtime rather than having them hardcoded.
MCP (Model Context Protocol)
Section titled “MCP (Model Context Protocol)”MCP is an open standard that gives agents a consistent way to discover and interact with external capabilities (GitHub, AWS, databases, browser tools) through a standard protocol. Servers can run locally as a subprocess (stdio) or remotely over HTTP.
from mcp import stdio_client, StdioServerParametersfrom strands import Agentfrom strands.tools.mcp import MCPClient
# Remote MCP server (Streamable HTTP): pass the URL and Strands builds the transportaws_knowledge = MCPClient( url="https://knowledge-mcp.global.api.aws", prefix="knowledge",)
# Local MCP server (stdio)aws_pricing = MCPClient( lambda: stdio_client(StdioServerParameters( command="uvx", args=["awslabs.aws-pricing-mcp-server@latest"], env={"AWS_REGION": "us-east-1"} )), prefix="pricing")
agent = Agent(tools=[aws_knowledge, aws_pricing], system_prompt="You are an AWS architect.")agent("What AWS services should I use for a serverless FastAPI backend?")The prefix argument namespaces tool names from each server so two servers exposing a tool with the same name don’t collide.
Mixing MCP Tools with Vended Tools
Section titled “Mixing MCP Tools with Vended Tools”An MCP client sits in the tools list alongside any other tool. Here a coding assistant gets AWS documentation through MCP plus local file and shell access through vended tools:
from strands import Agentfrom strands.tools.mcp import MCPClientfrom strands.vended_tools import file_editor, shell
# Connect to the AWS MCP server (streamable HTTP)aws_mcp = MCPClient(url="https://aws-mcp.us-east-1.api.aws/mcp")
SYSTEM_PROMPT = """You are a coding assistant with AWS expertise.Use the AWS MCP tools to look up documentation, architecture patterns,and service details when answering questions about building on AWS.Be concise and actionable in your recommendations."""
agent = Agent( tools=[aws_mcp, file_editor, shell], system_prompt=SYSTEM_PROMPT,)
agent("I need to build a serverless FastAPI backend with authentication " "and file uploads. What AWS services should I use and how should " "I architect this?")Tool Filtering
Section titled “Tool Filtering”Too many tools leads to worse tool selection, hallucinated tool names, and wasted context. In production, restrict which tools an agent can access using tool_filters and only expose what the agent actually needs:
from strands import Agentfrom strands.tools.mcp import MCPClient
# Filter to only documentation toolsfiltered_mcp = MCPClient( url="https://aws-mcp.us-east-1.api.aws/mcp", tool_filters={ "allowed": ["aws___search_documentation", "aws___read_documentation"] },)
agent = Agent( tools=[filtered_mcp], system_prompt="You are an AWS documentation assistant.",)Controlling Tool Execution
Section titled “Controlling Tool Execution”By default Strands runs multiple tool calls from a single model turn concurrently. When tools have side effects that depend on each other, switch to a sequential executor:
from strands import Agent, toolfrom strands.tools.executors import SequentialToolExecutor
@tooldef step_one() -> str: """Perform the first step of the workflow.""" return "Step one complete - file created."
@tooldef step_two() -> str: """Perform the second step that depends on step one.""" return "Step two complete - file processed."
agent = Agent( tools=[step_one, step_two], tool_executor=SequentialToolExecutor(),)agent("Run step one and then step two.")The Security Boundary
Section titled “The Security Boundary”Tools execute with the permissions of the host process. If you give an agent the shell tool, you’ve given it access to your machine. With MCP, you’re handing your agent tools that someone else controls. Be thoughtful about what you connect.
For sandboxed execution, look at Strands Shell, which gives agents isolated filesystem and network access.
Resources
Section titled “Resources”- 📖 Tools Overview
- 📖 MCP Tools
- 📖 Custom Tools
- 🛠️ Strands Shell