Week 3 - Tools and MCP Connections
Connecting AI Agents to External Services
Lesson Overview
| Segment | Duration |
|---|---|
| Lecture: Tools vs MCP Connections | 10 minutes |
| Guided Activity: Canvas MCP Setup | 20 minutes |
| Hands-on Coding: Building an Agent with Tools | 30+ minutes |
Learning Objectives: By the end of this lesson, students will be able to:
- Explain the difference between Tools and MCP connections
- Set up and use the Canvas MCP connection
- Build an AI agent that uses tools to interact with external services
- Understand the flow: User → AI → MCP Client → MCP Server → Tool → Result
Colab Notebook for Today:
Week 3 - MCP Lesson
(It is recommended to download a copy of the notebook to your own google colab)
What is an MCP?
Simply put, MCP is a protocol that standardizes how agents access tools and data. MCP servers host the tools, and MCP clients connect agents to those servers.
Here are some examples:
Let’s say that you are a malicious CIA agent who is trying to overthrow a foreign government with hundreds of agentic AI’s meant to hack into a government’s datacenter, or you are consulting for LinkedIn.
In the CIA example, you could connect your agents to a MCP server so that all of your agents can have access to all the same tools and have a separate computer run the tools instead of whatever the agents are being run on.
In the LinkedIn example, LinkedIn can create a MCP server with tools they made so that they can control the flow of sensitive data being sent to your agents (this may actually be coming soon).
How are MCP’s different from tools?
A tool is some sort of logic that is executed by Python, in your file, on your computer. An MCP however exposes tools or in other words shows them to the agent.
For example, let’s say you had 3 agents running on your computer for some reason and you want them all to use a tool. You can locally host a MCP that all the agents connect to and can run. An agent can be connected to multiple MCP servers, and MCPs can be run remotely or locally.
Useful MCP Walkthrough:
Building your first MCP server with Python in 2026
TOOLS AND MCP CONNECTIONS
1. WHAT is the difference between TOOLS and MCP CONNECTIONS?
A Tool is like a button and a MCP is like a USB-C port
We use a tool to perform a specific function or task within a software application or system. Tools are typically designed to help users accomplish specific goals, such as editing text, creating graphics, or managing data.
Examples of tools:
search_google(query)get_employee(id)send_email(to, subject, body)run_sql(query)schedule_meeting(time, people)
MCP (Model Context Protocol) is the standardized way AI discovers and talks to tools.
Without an MCP connection, if an AI like ChatGPT wanted to talk to gmail, it would need custom glue code to execute its goals. So lets say we wanted our AI agent to access data in LinkedIn. The company would need to create a MCP server connecton for AI’s to talk to linkedIn. LinkedIn would then be able to control the access levels, data formats, and security protocols for AI’s accessing its data.
Examples of MCP connections:
- Canvas MCP connection
- Google Search MCP connection
- SQL Database MCP connection
- Calendar MCP connection
We will be using a Canvas MCP, which means we will need to establish a MCP connection and then use the MCP’s tool to allow our agent to talk to canvas.
2. LET’S USE THEM
User → AI → MCP Client → MCP Server → Tool → Result → AI → User
Canvas MCP Setup
First install dependencies
%pip install nest_asyncio
%pip install langchain
%pip install langchain-google-genai
%pip install langchain-mcp-adapters
%pip install nest_asyncio langchain langchain-google-genai langchain-mcp-adaptersImport required libraries
import os
import asyncio
import nest_asyncio
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClientSetup & Configure
# 1. SETUP & FIX ASYNC (Required for Notebooks)
# This fixes "RuntimeError: This event loop is already running"
nest_asyncio.apply()
from dotenv import load_dotenv
load_dotenv()
# 2. SETUP CREDENTIALS
# Set CANVAS_API_TOKEN and GOOGLE_API_KEY (or GEMINI_API_KEY) as environment variables in your shell.
# You need your Canvas URL and Token (from your school profile settings)
os.environ["CANVAS_API_URL"] = ""
os.environ["CANVAS_API_TOKEN"] = ""
os.environ["GOOGLE_API_KEY"] = ""Load your API keys securely (Best Practice for Notebooks)
Use export GOOGLE_API_KEY='your_google_api_key_here' in your terminal before running the notebook
Then use echo $GOOGLE_API_KEY to verify it’s set
Building the MCP Agent
Load MCP Agent Function
async def load_mcp_agent():
llm = ChatGoogleGenerativeAI(
model="gemini-2.5-flash",
temperature=0,
api_key=os.environ.get("GOOGLE_API_KEY") or os.environ.get("GEMINI_API_KEY")
)
mcp_client = MultiServerMCPClient({
"canvas": {
"command": "canvas-mcp-server",
"args": [],
"transport": "stdio"
}
})
mcp_tools = await mcp_client.get_tools()
all_tools = mcp_tools + [student_file_tool]
agent = create_agent(
llm,
tools=all_tools,
system_prompt="You are a helpful assistant for a student. Use the tools to assist with their requests."
)
return agent, mcp_clientCreate Custom Tool for Local Files
from langchain_core.tools import Tool
from pprint import pprint
STUDENT_DATA_DIR = "student_data"
def read_student_files(query: str) -> str:
"""
Reads all files in student_data/ and returns their contents.
The query is ignored for now (simple version).
"""
if not os.path.exists(STUDENT_DATA_DIR):
return "student_data folder not found."
all_text = []
for fname in os.listdir(STUDENT_DATA_DIR):
path = os.path.join(STUDENT_DATA_DIR, fname)
if not os.path.isfile(path):
continue
try:
with open(path, "r", encoding="utf-8", errors="ignore") as f:
content = f.read()
all_text.append(f"\n--- {fname} ---\n{content}")
except Exception as e:
all_text.append(f"\n--- {fname} ---\nERROR: {e}")
return "\n".join(all_text)
# Defining tool
student_file_tool = Tool(
name="student_data_reader",
func=read_student_files,
description="Use this to read files from the local student_data folder. Whenever the user wants to access local files, go here. User may call this folder 'my folder, the folder' or other general terms"
)Run the Agent
async def main():
agent, mcp_client = await load_mcp_agent()
user_prompt = "Go into my folder into the study guide and give me a 3 sentence summary of what I should study"
result = await agent.ainvoke({
"messages": [
{"role": "user", "content": user_prompt}
]
})
# Inspect full response to find the correct field to use
pprint(result)
# Run the async main function in the notebook
asyncio.run(main())Exploration
Now that you have a working MCP agent:
- Try modifying the system prompt to change the agent’s behavior
- Experiment with different user prompts
- Create additional custom tools for other local resources
- Explore what Canvas tools are available through the MCP connection