MCP
Contents
Model Context Prortocol
Install and configure MCPs on your computer.
Requirements
To follow along you need:
- Claude.ai account (MCP support is available for all account types)
- The Claude Desktop app, available for macOS and Windows
- uv - a Rust-based Python package manager (full installation instructions):
macOS via Homebrew:
brew install uv
Windows via WinGet:
winget install --id=astral-sh.uv -e
Adding the fetch MCP server to Claude Desktop
The Model Context Protocol GitHub repository provides a long list of reference MCP servers you can install and experiment with. One of these is fetch, which visits a provided URL, processes its content, and converts it to Markdown for easier access.
MCPs are added to Claude Desktop through the claude_desktop_config.json file. The file location is OS-dependent:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Windows:
%APPDATA%\Claude\claude_desktop_config.json
If you have not used MCPs with Claude Desktop before, the file has not been created. To generate the file or get to its location, perform the following steps:
- Open Claude Desktop
- Go to the application menu and select "Settings"
- In the Settings panel, select "Developer" in the sidebar
- Click the "Edit Config" button
This will open a file browser with the claude_desktop_config.json file highlighted.
To add the fetch MCP:
- Open claude_desktop_config.json in your preferred code editor
- Add the following code:
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
}
}
}
- Save the file
- Reboot Claude
- If there are no errors, the MCP Server has been successfully installed
Common error: uvx ENOENT
If you get a series of errors, one of them saying "uvx ENOENT" it means either uv is not installed on your system or uvx is not in the path. To fix the problem, reinstall uv following the instructions above, or alter the command property in the fetch object to show the full path to uv on your computer.
To find the path to uv on your computer, enter the following command in a terminal:
macOS:
which uv
Windows:
where uv
The resulting code in claude_desktop_config.json will look similar to this:
{
"mcpServers": {
"fetch": {
"command": "/Users/your-username/.local/bin/uvx",
"args": ["mcp-server-fetch"]
}
}
}
Using an MCP server in Claude Desktop
If there are no errors, prompt Claude to retrieve a URL for you, for example: "Fetch https://modelcontextprotocol.io/quickstart/user and give me the highlights."
Claude Desktop will recognize this as a task for the fetch MCP and a popup appears asking you to approve the use of the MCP. Click "Allow for this chat" or "Allow once" and the MCP server is activated.
Adding more MCP servers to Claude Desktop claude_desktop_config.json controls what MCP servers are available to Claude Desktop. To add new MCP servers, add a new object to the mcpServers object, separating each server with a comma like this:
{
"mcpServers": {
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
},
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/your-username/Desktop",
"/Users/your-username/folder/of/your/choice"
]
}
}
}
MCP server arguments
The example above adds the filesystem MCP server to Claude. While fetch is written in Python, filesystem is written in TypeScript which is why its command is npx. This is an example of the universality of the MCP protocol: MCP is language agnostic and its configuration is universal. The JSON structure and mcpServers object is the standardized way of loading MCP servers into any MCP client, and the config can therefore be transferred without modification between clients.
For a broad range of examples of how to implement and run MCP servers using Python and TypeScript, explore the reference servers provided in the modelcontextprotocol/servers GitHub repository!
MCP Features
Resources
Expose data and content from your servers to LLMs
Use a resource when you want to passively expose data or content to an MCP client and let the client choose when to access it.
Prompts
Create reusable prompt templates and workflows
Use a prompt when you want the client to surface prompts and workflows to the user, for example to streamline interaction with a resource or tool.
Tools
Enable LLMs to perform actions through your server
Use a tool when you want the client to perform an action, for example to request content from an API, transform data, or send an email.
Capabilities
- Sampling : Let your servers request completions from LLMs
- Roots : Clients inform servers about resources and their locations
Exploring available MCP servers and clients
Link : https://modelcontextprotocol.io/introduction
Example Servers : https://modelcontextprotocol.io/examples
Sources Codes of Example Servers https://github.com/modelcontextprotocol/servers
Other servers
Building your own MCP servers
Links
- Open Meteo API : https://open-meteo.com/en/docs
- Course Sources : https://github.com/LinkedInLearning/model-context-protocol-mcp-hands-on-with-agentic-ai-2034200/
- Course : https://www.linkedin.com/learning/model-context-protocol-mcp-hands-on-with-agentic-ai/
Setting Up the Project
Create a new folder called mcp-server-weather using the editor tools or terminal:
mkdir mcp-server-weather
Navigate to the folder in terminal:
cd mcp-server-weather
Initiate a new uv project:
uv init
Create a virtual environment using uv:
uv venv
Start the virtual environment:
source .venv/bin/activate
Note: To stop the virtual environment, run deactivate in terminal.
Install the Python MCP SDK with the CLI extension and additional Python dependencies in the virtual environment:
uv add "mcp[cli]" httpx
Building the weather MCP server
Scaffolding
Start by adding scaffolding for the MCP server:
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# Initialize FastMCP server
mcp = FastMCP("weather")
### The rest of your code goes between here...
### ... and here.
if __name__ == "__main__":
# Initialize and run the server
mcp.run(transport='stdio')
This adds strong typing, the httpx client for accessing the web, the FastMCP class for building MCP servers, and runs the MCP server using stdio (standard input/output) as the transport mechanism, which is what Claude Desktop and other MCP clients expect.
Constants and helper functions
Next, add constants and a helper function to interact with the Open-Meteo API:
# Constants
OPENMETEO_API_BASE = "https://api.open-meteo.com/v1"
USER_AGENT = "weather-app/1.0"
# Helper function to make a request to the Open-Meteo API
async def make_openmeteo_request(url: str) -> dict[str, Any] | None:
"""Make a request to the Open-Meteo API with proper error handling."""
headers = {
"User-Agent": USER_AGENT,
"Accept": "application/json"
}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
Create a get_forecast tool
The Open-Weather API has a /forecast endpoint that can provide current weather and hourly forecast for any location defined by latitude and longitude with optional parameters for the data you need. For the full specification, visit the API documentation.
Since we want the LLM to be able to automatically request data from the API, and may also want the MCP server to perform actions on that data, each API interaction in this MCP server is best exposed as a tool.
Here's how to build a tool requesting the current weather using the Python SDK:
@mcp.tool()
async def get_current_weather(latitude: float, longitude: float) -> str:
"""Get current weather for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
url = f"{OPENMETEO_API_BASE}/forecast?latitude={latitude}&longitude={longitude}¤t=temperature_2m,is_day,showers,cloud_cover,wind_speed_10m,wind_direction_10m,pressure_msl,snowfall,precipitation,relative_humidity_2m,apparent_temperature,rain,weather_code,surface_pressure,wind_gusts_10m"
data = await make_openmeteo_request(url)
if not data:
return "Unable to fetch current weather data for this location."
return data
(See the official documentation for instructions on how to define tools without the SDK.)
- Tools are defined using @mcp.tool()
- The LLM uses the initial comment as its prompt for when and how to use the tool, so this is where you define the tool operation
- Tools are written as regular Python function with your specified arguments
- Tools should always return data
- The LLM receives the returned data for further processing
Testing and running the MCP server
The MCP server is now fully functional and ready to test using the MCP Inspector. You'll learn more about the inspector in the next video, but here's a preview:
- In terminal, start your MCP server in developer mode by running:
mcp dev server.py
- The MCP Inspector is now available at http://localhost:5173; open the URL in your browser
- Select the "Connect" button
- Select the "Tools" tab
- Select the "List Tools" button
- Select the get_current_weather tool
- In the get_current_weather panel, enter a latitude and longitude, eg 63.4463991, 10.8127596
- Under "Tool Result" you'll see a JSON object with weather data
Press Ctrl+C in terminal to crash out of the MCP Inspector.
Extend the MCP server with more features
Now that you've built a tool, take what you've learned to add more tools and resources to the MCP server. Here are two ideas to get you started:
- get_forecast - Retrieves the forecast for the specified location, with an optional argument for the range of the forecast
- get_location - Uses the Open-Meteo Geocoding API for more accurate location searches (without this you are relying on the LLM to generate the latitude and longitude, which can result in errors)
Running Local MCP Servers in Claude Desktop
Claude Desktop serves as a good testing ground for your custom MCP servers. Installing local MCP servers in Claude Desktop is done the same way published MCP servers are installed. The main difference is in the args property.
Add a new weather object to the mcpServers object in claude_desktop_config.json like this:
{
"mcpServers": {
"weather": {
"command": "/Users/your-username/.local/bin/uv",
"args": [
"run",
"--with",
"mcp[cli]",
"mcp",
"run",
"/Users/your-username/path/to/open-meteo-weather/server.py"
]
}
}
}
Different ways of spinning up MCP servers
Note the args property in the open-meteo-weather server is far more complex than the ones you added for fetch and filesystem earlier. This is because Claude Desktop needs to know how to spin up the local server in its virtual environment. args holds an array of commands to run the open-meteo-weather MCP server in a virtual environment:
uv run --with mcp[cli] mcp run /Users/your-username/path/to/open-meteo-weather/server.py
Here's a breakdown of this command:
- uv run starts up uv
- --with mcp[cli] adds the mcp[cli] dependency to uv
- mcp run <path-to-file> uses the mcp cli to run the specified file
This allows Claude Desktop to spin up the server in its own virtual environment without your involvement. And yes, that means the LLM is running software inside itself!