Skip to content

Commit c46cb27

Browse files
Merge pull request #316 from huggingface/mcp-protocol
[ENHANCEMENT] brief primer on MCP Model Context Protocol
2 parents 3e559ad + a74edb9 commit c46cb27

File tree

3 files changed

+126
-64
lines changed

3 files changed

+126
-64
lines changed

units/en/unit1/tools.mdx

+32-21
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Here are some commonly used tools in AI agents:
2424

2525
Those are only examples, as you can in fact create a tool for any use case!
2626

27-
A good tool should be something that **complements the power of an LLM**.
27+
A good tool should be something that **complements the power of an LLM**.
2828

2929
For instance, if you need to perform arithmetic, giving a **calculator tool** to your LLM will provide better results than relying on the native capabilities of the model.
3030

@@ -140,18 +140,18 @@ We create a generic `Tool` class that we can reuse whenever we need to use a too
140140
class Tool:
141141
"""
142142
A class representing a reusable piece of code (Tool).
143-
143+
144144
Attributes:
145145
name (str): Name of the tool.
146146
description (str): A textual description of what the tool does.
147147
func (callable): The function this tool wraps.
148148
arguments (list): A list of argument.
149149
outputs (str or list): The return type(s) of the wrapped function.
150150
"""
151-
def __init__(self,
152-
name: str,
153-
description: str,
154-
func: callable,
151+
def __init__(self,
152+
name: str,
153+
description: str,
154+
func: callable,
155155
arguments: list,
156156
outputs: str):
157157
self.name = name
@@ -162,13 +162,13 @@ class Tool:
162162

163163
def to_string(self) -> str:
164164
"""
165-
Return a string representation of the tool,
165+
Return a string representation of the tool,
166166
including its name, description, arguments, and outputs.
167167
"""
168168
args_str = ", ".join([
169169
f"{arg_name}: {arg_type}" for arg_name, arg_type in self.arguments
170170
])
171-
171+
172172
return (
173173
f"Tool Name: {self.name},"
174174
f" Description: {self.description},"
@@ -219,40 +219,40 @@ def tool(func):
219219
"""
220220
# Get the function signature
221221
signature = inspect.signature(func)
222-
222+
223223
# Extract (param_name, param_annotation) pairs for inputs
224224
arguments = []
225225
for param in signature.parameters.values():
226226
annotation_name = (
227-
param.annotation.__name__
228-
if hasattr(param.annotation, '__name__')
227+
param.annotation.__name__
228+
if hasattr(param.annotation, '__name__')
229229
else str(param.annotation)
230230
)
231231
arguments.append((param.name, annotation_name))
232-
232+
233233
# Determine the return annotation
234234
return_annotation = signature.return_annotation
235235
if return_annotation is inspect._empty:
236236
outputs = "No return annotation"
237237
else:
238238
outputs = (
239-
return_annotation.__name__
240-
if hasattr(return_annotation, '__name__')
239+
return_annotation.__name__
240+
if hasattr(return_annotation, '__name__')
241241
else str(return_annotation)
242242
)
243-
243+
244244
# Use the function's docstring as the description (default if None)
245245
description = func.__doc__ or "No description provided."
246-
246+
247247
# The function name becomes the Tool name
248248
name = func.__name__
249-
249+
250250
# Return a new Tool instance
251251
return Tool(
252-
name=name,
253-
description=description,
254-
func=func,
255-
arguments=arguments,
252+
name=name,
253+
description=description,
254+
func=func,
255+
arguments=arguments,
256256
outputs=outputs
257257
)
258258
```
@@ -282,6 +282,17 @@ The description is **injected** in the system prompt. Taking the example with wh
282282

283283
In the [Actions](actions) section, we will learn more about how an Agent can **Call** this tool we just created.
284284

285+
### Model Context Protocol (MCP): a unified tool interface
286+
287+
Model Context Protocol (MCP) is an **open protocol** that standardizes how applications **provide tools to LLMs**.
288+
MCP provides:
289+
290+
- A growing list of pre-built integrations that your LLM can directly plug into
291+
- The flexibility to switch between LLM providers and vendors
292+
- Best practices for securing your data within your infrastructure
293+
294+
This means that **any framework implementing MCP can leverage tools defined within the protocol**, eliminating the need to reimplement the same tool interface for each framework.
295+
285296
---
286297

287298
Tools play a crucial role in enhancing the capabilities of AI agents.

units/en/unit2/llama-index/tools.mdx

+19
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,25 @@ To get a more detailed view of the tools, we can take a look at the `metadata` o
9898
[(tool.metadata.name, tool.metadata.description) for tool in tool_spec_list]
9999
```
100100

101+
### Model Context Protocol (MCP) in LlamaIndex
102+
103+
LlamaIndex also allows using MCP tools through a [ToolSpec on the LlamaHub](https://llamahub.ai/l/tools/llama-index-tools-mcp?from=).
104+
You can simply run an MCP server and start using it through the following implementation.
105+
106+
```python
107+
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
108+
109+
# We consider there is a mcp server running on 127.0.0.1:8000, or you can use the mcp client to connect to your own mcp server.
110+
mcp_client = BasicMCPClient("http://127.0.0.1:8000/sse")
111+
mcp_tool = McpToolSpec(client=mcp_client)
112+
113+
# get the agent
114+
agent = await get_agent(mcp_tool)
115+
116+
# create the agent context
117+
agent_context = Context(agent)
118+
```
119+
101120
## Utility Tools
102121

103122
Oftentimes, directly querying an API **can return an excessive amount of data**, some of which may be irrelevant, overflow the context window of the LLM, or unnecessarily increase the number of tokens that you are using.

units/en/unit2/smolagents/tools.mdx

+75-43
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
{label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/agents-course/blob/main/notebooks/unit2/smolagents/tools.ipynb"},
55
]} />
66

7-
# Tools
7+
# Tools
88

9-
As we explored in [unit 1](https://huggingface.co/learn/agents-course/unit1/tools), agents use tools to perform various actions. In `smolagents`, tools are treated as **functions that an LLM can call within an agent system**.
9+
As we explored in [unit 1](https://huggingface.co/learn/agents-course/unit1/tools), agents use tools to perform various actions. In `smolagents`, tools are treated as **functions that an LLM can call within an agent system**.
1010

11-
To interact with a tool, the LLM needs an **interface description** with these key components:
11+
To interact with a tool, the LLM needs an **interface description** with these key components:
1212

1313
- **Name**: What the tool is called
14-
- **Tool description**: What the tool does
14+
- **Tool description**: What the tool does
1515
- **Input types and descriptions**: What arguments the tool accepts
1616
- **Output type**: What the tool returns
1717

@@ -30,19 +30,19 @@ Below, you can see an animation illustrating how a tool call is managed:
3030

3131
## Tool Creation Methods
3232

33-
In `smolagents`, tools can be defined in two ways:
33+
In `smolagents`, tools can be defined in two ways:
3434
1. **Using the `@tool` decorator** for simple function-based tools
35-
2. **Creating a subclass of `Tool`** for more complex functionality
35+
2. **Creating a subclass of `Tool`** for more complex functionality
3636

37-
### The `@tool` Decorator
37+
### The `@tool` Decorator
3838

39-
The `@tool` decorator is the **recommended way to define simple tools**. Under the hood, smolagents will parse basic information about the function from Python. So if you name your function clearly and write a good docstring, it will be easier for the LLM to use.
39+
The `@tool` decorator is the **recommended way to define simple tools**. Under the hood, smolagents will parse basic information about the function from Python. So if you name your function clearly and write a good docstring, it will be easier for the LLM to use.
4040

41-
Using this approach, we define a function with:
41+
Using this approach, we define a function with:
4242

43-
- **A clear and descriptive function name** that helps the LLM understand its purpose.
44-
- **Type hints for both inputs and outputs** to ensure proper usage.
45-
- **A detailed description**, including an `Args:` section where each argument is explicitly described. These descriptions provide valuable context for the LLM, so it's important to write them carefully.
43+
- **A clear and descriptive function name** that helps the LLM understand its purpose.
44+
- **Type hints for both inputs and outputs** to ensure proper usage.
45+
- **A detailed description**, including an `Args:` section where each argument is explicitly described. These descriptions provide valuable context for the LLM, so it's important to write them carefully.
4646

4747
#### Generating a tool that retrieves the highest-rated catering
4848

@@ -52,7 +52,7 @@ Using this approach, we define a function with:
5252
You can follow the code in <a href="https://huggingface.co/agents-course/notebooks/blob/main/unit2/smolagents/tools.ipynb" target="_blank">this notebook</a> that you can run using Google Colab.
5353
</Tip>
5454

55-
Let's imagine that Alfred has already decided on the menu for the party, but now he needs help preparing food for such a large number of guests. To do so, he would like to hire a catering service and needs to identify the highest-rated options available. Alfred can leverage a tool to search for the best catering services in his area.
55+
Let's imagine that Alfred has already decided on the menu for the party, but now he needs help preparing food for such a large number of guests. To do so, he would like to hire a catering service and needs to identify the highest-rated options available. Alfred can leverage a tool to search for the best catering services in his area.
5656

5757
Below is an example of how Alfred can use the `@tool` decorator to make this happen:
5858

@@ -64,7 +64,7 @@ from smolagents import CodeAgent, HfApiModel, tool
6464
def catering_service_tool(query: str) -> str:
6565
"""
6666
This tool returns the highest-rated catering service in Gotham City.
67-
67+
6868
Args:
6969
query: A search term for finding catering services.
7070
"""
@@ -74,10 +74,10 @@ def catering_service_tool(query: str) -> str:
7474
"Wayne Manor Catering": 4.8,
7575
"Gotham City Events": 4.7,
7676
}
77-
77+
7878
# Find the highest rated catering service (simulating search query filtering)
7979
best_service = max(services, key=services.get)
80-
80+
8181
return best_service
8282

8383

@@ -91,21 +91,21 @@ result = agent.run(
9191
print(result) # Output: Gotham Catering Co.
9292
```
9393

94-
### Defining a Tool as a Python Class
94+
### Defining a Tool as a Python Class
9595

96-
This approach involves creating a subclass of [`Tool`](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools#smolagents.Tool). For complex tools, we can implement a class instead of a Python function. The class wraps the function with metadata that helps the LLM understand how to use it effectively. In this class, we define:
96+
This approach involves creating a subclass of [`Tool`](https://huggingface.co/docs/smolagents/v1.8.1/en/reference/tools#smolagents.Tool). For complex tools, we can implement a class instead of a Python function. The class wraps the function with metadata that helps the LLM understand how to use it effectively. In this class, we define:
9797

98-
- `name`: The tool's name.
99-
- `description`: A description used to populate the agent's system prompt.
100-
- `inputs`: A dictionary with keys `type` and `description`, providing information to help the Python interpreter process inputs.
101-
- `output_type`: Specifies the expected output type.
98+
- `name`: The tool's name.
99+
- `description`: A description used to populate the agent's system prompt.
100+
- `inputs`: A dictionary with keys `type` and `description`, providing information to help the Python interpreter process inputs.
101+
- `output_type`: Specifies the expected output type.
102102
- `forward`: The method containing the inference logic to execute.
103103

104104
Below, we can see an example of a tool built using `Tool` and how to integrate it within a `CodeAgent`.
105105

106106
#### Generating a tool to generate ideas about the superhero-themed party
107107

108-
Alfred's party at the mansion is a **superhero-themed event**, but he needs some creative ideas to make it truly special. As a fantastic host, he wants to surprise the guests with a unique theme.
108+
Alfred's party at the mansion is a **superhero-themed event**, but he needs some creative ideas to make it truly special. As a fantastic host, he wants to surprise the guests with a unique theme.
109109

110110
To do this, he can use an agent that generates superhero-themed party ideas based on a given category. This way, Alfred can find the perfect party theme to wow his guests.
111111

@@ -117,14 +117,14 @@ class SuperheroPartyThemeTool(Tool):
117117
description = """
118118
This tool suggests creative superhero-themed party ideas based on a category.
119119
It returns a unique party theme idea."""
120-
120+
121121
inputs = {
122122
"category": {
123123
"type": "string",
124124
"description": "The type of superhero party (e.g., 'classic heroes', 'villain masquerade', 'futuristic Gotham').",
125125
}
126126
}
127-
127+
128128
output_type = "string"
129129

130130
def forward(self, category: str):
@@ -133,7 +133,7 @@ class SuperheroPartyThemeTool(Tool):
133133
"villain masquerade": "Gotham Rogues' Ball: A mysterious masquerade where guests dress as classic Batman villains.",
134134
"futuristic Gotham": "Neo-Gotham Night: A cyberpunk-style party inspired by Batman Beyond, with neon decorations and futuristic gadgets."
135135
}
136-
136+
137137
return themes.get(category.lower(), "Themed party idea not found. Try 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.")
138138

139139
# Instantiate the tool
@@ -150,34 +150,34 @@ print(result) # Output: "Gotham Rogues' Ball: A mysterious masquerade where gue
150150

151151
With this tool, Alfred will be the ultimate super host, impressing his guests with a superhero-themed party they won't forget! 🦸‍♂️🦸‍♀️
152152

153-
## Default Toolbox
153+
## Default Toolbox
154154

155-
`smolagents` comes with a set of pre-built tools that can be directly injected into your agent. The [default toolbox](https://huggingface.co/docs/smolagents/guided_tour?build-a-tool=Decorate+a+function+with+%40tool#default-toolbox) includes:
155+
`smolagents` comes with a set of pre-built tools that can be directly injected into your agent. The [default toolbox](https://huggingface.co/docs/smolagents/guided_tour?build-a-tool=Decorate+a+function+with+%40tool#default-toolbox) includes:
156156

157-
- **PythonInterpreterTool**
158-
- **FinalAnswerTool**
159-
- **UserInputTool**
160-
- **DuckDuckGoSearchTool**
161-
- **GoogleSearchTool**
162-
- **VisitWebpageTool**
157+
- **PythonInterpreterTool**
158+
- **FinalAnswerTool**
159+
- **UserInputTool**
160+
- **DuckDuckGoSearchTool**
161+
- **GoogleSearchTool**
162+
- **VisitWebpageTool**
163163

164164
Alfred could use various tools to ensure a flawless party at Wayne Manor:
165165

166-
- First, he could use the `DuckDuckGoSearchTool` to find creative superhero-themed party ideas.
166+
- First, he could use the `DuckDuckGoSearchTool` to find creative superhero-themed party ideas.
167167

168-
- For catering, he'd rely on the `GoogleSearchTool` to find the highest-rated services in Gotham.
168+
- For catering, he'd rely on the `GoogleSearchTool` to find the highest-rated services in Gotham.
169169

170-
- To manage seating arrangements, Alfred could run calculations with the `PythonInterpreterTool`.
170+
- To manage seating arrangements, Alfred could run calculations with the `PythonInterpreterTool`.
171171

172-
- Once everything is gathered, he'd compile the plan using the `FinalAnswerTool`.
172+
- Once everything is gathered, he'd compile the plan using the `FinalAnswerTool`.
173173

174174
With these tools, Alfred guarantees the party is both exceptional and seamless. 🦇💡
175175

176176
## Sharing and Importing Tools
177177

178-
One of the most powerful features of **smolagents** is its ability to share custom tools on the Hub and seamlessly integrate tools created by the community. This includes connecting with **HF Spaces** and **LangChain tools**, significantly enhancing Alfred's ability to orchestrate an unforgettable party at Wayne Manor. 🎭
178+
One of the most powerful features of **smolagents** is its ability to share custom tools on the Hub and seamlessly integrate tools created by the community. This includes connecting with **HF Spaces** and **LangChain tools**, significantly enhancing Alfred's ability to orchestrate an unforgettable party at Wayne Manor. 🎭
179179

180-
With these integrations, Alfred can tap into advanced event-planning tools—whether it's adjusting the lighting for the perfect ambiance, curating the ideal playlist for the party, or coordinating with Gotham's finest caterers.
180+
With these integrations, Alfred can tap into advanced event-planning tools—whether it's adjusting the lighting for the perfect ambiance, curating the ideal playlist for the party, or coordinating with Gotham's finest caterers.
181181

182182
Here are examples showcasing how these functionalities can elevate the party experience:
183183

@@ -193,7 +193,7 @@ party_theme_tool.push_to_hub("{your_username}/party_theme_tool", token="<YOUR_HU
193193

194194
### Importing a Tool from the Hub
195195

196-
You can easily import tools created by other users using the `load_tool()` function. For example, Alfred might want to generate a promotional image for the party using AI. Instead of building a tool from scratch, he can leverage a predefined one from the community:
196+
You can easily import tools created by other users using the `load_tool()` function. For example, Alfred might want to generate a promotional image for the party using AI. Instead of building a tool from scratch, he can leverage a predefined one from the community:
197197

198198
```python
199199
from smolagents import load_tool, CodeAgent, HfApiModel
@@ -213,7 +213,7 @@ agent.run("Generate an image of a luxurious superhero-themed party at Wayne Mano
213213

214214
### Importing a Hugging Face Space as a Tool
215215

216-
You can also import a HF Space as a tool using `Tool.from_space()`. This opens up possibilities for integrating with thousands of spaces from the community for tasks from image generation to data analysis.
216+
You can also import a HF Space as a tool using `Tool.from_space()`. This opens up possibilities for integrating with thousands of spaces from the community for tasks from image generation to data analysis.
217217

218218
The tool will connect with the spaces Gradio backend using the `gradio_client`, so make sure to install it via `pip` if you don't have it already.
219219

@@ -233,7 +233,7 @@ model = HfApiModel("Qwen/Qwen2.5-Coder-32B-Instruct")
233233
agent = CodeAgent(tools=[image_generation_tool], model=model)
234234

235235
agent.run(
236-
"Improve this prompt, then generate an image of it.",
236+
"Improve this prompt, then generate an image of it.",
237237
additional_args={'user_prompt': 'A grand superhero-themed party at Wayne Manor, with Alfred overseeing a luxurious gala'}
238238
)
239239
```
@@ -260,6 +260,38 @@ agent = CodeAgent(tools=[search_tool], model=model)
260260
agent.run("Search for luxury entertainment ideas for a superhero-themed event, such as live performances and interactive experiences.")
261261
```
262262

263+
### Importing a tool collection from any MCP server
264+
265+
`smolagents` also allows importing tools from the hundreds of MCP servers available on [glama.ai](https://glama.ai/mcp/servers) or [smithery.ai](https://smithery.ai).
266+
267+
<details>
268+
<summary>Install mcp client</summary>
269+
270+
We first need to install the `mcp` integration for `smolagents`.
271+
272+
```bash
273+
pip install "smolagents[mcp]"
274+
```
275+
</details>
276+
277+
The MCP servers tools can be loaded in a ToolCollection object as follow:
278+
279+
```python
280+
import os
281+
from smolagents import ToolCollection, CodeAgent
282+
from mcp import StdioServerParameters
283+
284+
server_parameters = StdioServerParameters(
285+
command="uv",
286+
args=["--quiet", "[email protected]"],
287+
env={"UV_PYTHON": "3.12", **os.environ},
288+
)
289+
290+
with ToolCollection.from_mcp(server_parameters) as tool_collection:
291+
agent = CodeAgent(tools=[*tool_collection.tools], add_base_tools=True)
292+
agent.run("Please find a remedy for hangover.")
293+
```
294+
263295
With this setup, Alfred can quickly discover luxurious entertainment options, ensuring Gotham's elite guests have an unforgettable experience. This tool helps him curate the perfect superhero-themed event for Wayne Manor! 🎉
264296

265297
## Resources

0 commit comments

Comments
 (0)