You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Add `strict` parameter to Tool class to support OpenAI's strict mode
- Set strict=False for MCP tools to preserve optional params (MCP uses
standard JSON Schema conventions where optional params aren't in required)
- Add `sanitize_schema()` function that strips `format` field (e.g., "uri")
which OpenAI rejects, in addition to existing `title` removal
- Restructure MCP tools guide with practical Quick Start example using
MCP Fetch server
- Update MCP server link to glama.ai/mcp/servers
- Add section headers for Registering tools vs Authoring tools
- Rename "Motivating example" to "Advanced example: Code execution"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/misc/mcp-tools.qmd
+74-48Lines changed: 74 additions & 48 deletions
Original file line number
Diff line number
Diff line change
@@ -3,67 +3,101 @@ title: MCP tools
3
3
callout-appearance: simple
4
4
---
5
5
6
-
[Model Context Protocol (MCP)](https://modelcontextprotocol.io) provides a standard
6
+
[Model Context Protocol (MCP)](https://modelcontextprotocol.io) provides a standard
7
7
way to build services that LLMs can use to gain context.
8
-
Most significantly, MCP provides a standard way to serve [tools](../get-started/tools.qmd) (i.e., functions) for an LLM to call from another program or machine.
9
-
As a result, there are now [many useful MCP server implementations available](https://github.com/punkpeye/awesome-mcp-servers?tab=readme-ov-file#server-implementations) to help extend the capabilities of your chat application.
10
-
In this article, you'll learn the basics of implementing and using MCP tools in chatlas.
8
+
This includes a standard way to provide [tools](../get-started/tools.qmd) (i.e., functions) for an LLM to call from another program or machine.
9
+
There are now [many useful MCP server implementations available](https://glama.ai/mcp/servers) to help extend the capabilities of your chat application with minimal effort.
11
10
11
+
In this article, you'll learn how to both register existing MCP tools with chatlas as well as author your own custom MCP tools.
12
12
13
13
::: callout-note
14
14
## Prerequisites
15
15
16
-
To leverage MCP tools from chatlas, you'll need to install the `mcp`library.
16
+
To leverage MCP tools from chatlas, you'll want to install the `mcp`extra.
17
17
18
18
```bash
19
19
pip install 'chatlas[mcp]'
20
20
```
21
21
:::
22
22
23
23
24
-
## Basic usage
24
+
## Registering tools
25
25
26
-
Chatlas provides two ways to register MCP tools: [`.register_mcp_tools_http_stream_async()`](../reference/Chat.qmd#register_mcp_tools_http_stream_async) and [`.register_mcp_tools_stdio_async()`](../reference/Chat.qmd#register_mcp_tools_stdio_async).
26
+
### Quick start {#quick-start}
27
27
28
+
Let's start with a practical example: using the [MCP Fetch server](https://github.com/modelcontextprotocol/servers/tree/main/src/fetch) to give an LLM the ability to fetch and read web pages.
29
+
This server is maintained by Anthropic and can be run via `uvx` (which comes with [uv](https://docs.astral.sh/uv/)).
28
30
29
-
The main difference is how they interact with the MCP server: the former connects to an already running HTTP server, while the latter executes a system command to run the server locally.
30
-
Roughly speaking, usage looks something like this:
31
-
32
-
::: panel-tabset
33
-
34
-
### Streaming HTTP
31
+
For simplicity and convenience, we'll use the [`.register_mcp_tools_stdio_async()`](../reference/Chat.qmd#register_mcp_tools_stdio_async) method to both run the MCP Fetch server locally and register its tools with our `ChatOpenAI` instance:
35
32
36
33
```python
34
+
import asyncio
37
35
from chatlas import ChatOpenAI
38
36
39
-
chat = ChatOpenAI()
37
+
asyncdefmain():
38
+
chat = ChatOpenAI()
39
+
await chat.register_mcp_tools_stdio_async(
40
+
command="uvx",
41
+
args=["mcp-server-fetch"],
42
+
)
43
+
await chat.chat_async(
44
+
"Summarize the first paragraph of https://en.wikipedia.org/wiki/Python_(programming_language)"
45
+
)
46
+
await chat.cleanup_mcp_tools()
40
47
41
-
# Assuming you have an MCP server running at the specified URL
Python is a high-level, general-purpose programming language known for its emphasis on code readability through significant indentation. It supports multiple programming paradigms including structured, object-oriented, and functional programming, and is dynamically typed with garbage collection.
58
+
:::
59
+
60
+
::: callout-tip
61
+
### Built-in fetch/search tools
62
+
63
+
For providers with native web fetch support (Claude, Google), consider using [`tool_web_fetch()`](../reference/tool_web_fetch.qmd) instead -- it's simpler and doesn't require MCP setup.
64
+
Similarly, [`tool_web_search()`](../reference/tool_web_search.qmd) provides native web search for OpenAI, Claude, and Google.
65
+
:::
51
66
52
-
chat = ChatOpenAI()
53
67
54
-
# Assuming my_mcp_server.py is a valid MCP server script
The main difference is how they communicate with the MCP server: the former (Stdio) executes a system command to run the server locally, while the latter (HTTP) connects to an already running HTTP server.
76
+
77
+
This makes the Stdio method more ergonomic for local development and testing. For instance, recall the example above, which runs `uvx mcp-server-fetch` locally to provide web fetching capabilities to the chat instance:
78
+
79
+
```python
80
+
# Run a server via uvx, npx, or any other command
55
81
await chat.register_mcp_tools_stdio_async(
56
-
command="mcp",
57
-
args=["run", "my_mcp_server.py"],
82
+
command="uvx",
83
+
args=["mcp-server-fetch"],
58
84
)
59
85
```
60
86
61
-
:::
87
+
On the other hand, the HTTP method is better for production environments where the server is hosted remotely or in a longer-running process.
88
+
For example, if you have an MCP server already running at `http://localhost:8000/mcp`, you can connect to it as follows:
89
+
90
+
```python
91
+
# Connect to a server already running at the specified URL
92
+
await chat.register_mcp_tools_http_stream_async(
93
+
url="http://localhost:8000/mcp",
94
+
)
95
+
```
62
96
63
97
::: callout-warning
64
98
### Async methods
65
99
66
-
For performance reasons, the methods for registering MCP tools are asynchronous, so you'll need to use `await` when calling them.
100
+
For performance, the methods for registering MCP tools are asynchronous, so you'll need to use `await` when calling them.
67
101
In some environments, such as Jupyter notebooks and the [Positron IDE](https://positron.posit.co/) console, you can simply use `await` directly (as is done above).
68
102
However, in other environments, you may need to wrap your code in an `async` function and use `asyncio.run()` to execute it.
69
103
The examples below use `asyncio.run()` to run the asynchronous code, but you can adapt them to your environment as needed.
@@ -75,23 +109,14 @@ Note that these methods work by:
75
109
2. Requesting the available tools and making them available to the chat instance
76
110
3. Keeping the connection open for tool calls during the chat session
77
111
112
+
This means, when you no longer need the MCP tools, it's good practice to clean up the connection to the MCP server, as well `Chat`'s tool state.
113
+
This is done by calling [`.cleanup_mcp_tools()`](../reference/Chat.qmd#cleanup_mcp_tools) at the end of your chat session (the examples demonstrate how to do this).
78
114
79
-
::: callout-warning
80
-
### Cleanup
81
-
82
-
When you no longer need the MCP tools, it's important to clean up the connection to the MCP server, as well `Chat`'s tool state.
83
-
This is done by calling [`.cleanup_mcp_tools()`](../reference/Chat.qmd#cleanup_mcp_tools) at the end of your chat session (the examples demonstrate how to do this).
84
-
:::
85
-
86
-
87
-
## Basic example
88
-
89
-
Let's walk through a full-fledged example of using MCP tools in chatlas, including implementing our own MCP server.
115
+
## Authoring tools
90
116
91
-
### Basic server {#basic-server}
117
+
If existing MCP servers don't meet your needs, you can implement your own without much effort thanks to the [mcp](https://pypi.org/project/mcp/) Python library (you can also [work in other languages](https://modelcontextprotocol.io/docs/sdk), if you like).
92
118
93
119
Below is a basic MCP server with a simple `add` tool to add two numbers together.
94
-
This particular server is implemented in Python (via [mcp](https://pypi.org/project/mcp/)), but remember that MCP servers can be implemented in any programming language.
That's it! You can now run this server through the streaming HTTP or Stdio protocols and connect its tools to chatlas.
106
132
107
133
### HTTP Stream
108
134
109
135
The `mcp` library provides a CLI tool to run the MCP server over HTTP transport.
110
136
As long as you have `mcp` installed, and the [server above](#basic-server) saved as `my_mcp_server.py`, this can be done as follows:
111
137
112
138
```bash
113
-
$ mcp run -t sse my_mcp_server.py
139
+
$ mcp run -t sse my_mcp_server.py
114
140
INFO: Started server process [19144]
115
141
INFO: Waiting for application startup.
116
142
INFO: Application startup complete.
@@ -141,12 +167,12 @@ asyncio.run(do_chat("What is 5 - 3?"))
141
167
::: chatlas-response-container
142
168
143
169
```python
144
-
# 🔧 tool request
170
+
# 🔧 tool request
145
171
add(x=5, y=-3)
146
172
```
147
173
148
174
```python
149
-
# ✅ tool result
175
+
# ✅ tool result
150
176
2
151
177
```
152
178
@@ -186,27 +212,27 @@ asyncio.run(do_chat("What is 5 - 3?"))
186
212
::: chatlas-response-container
187
213
188
214
```python
189
-
# 🔧 tool request
215
+
# 🔧 tool request
190
216
add(x=5, y=-3)
191
217
```
192
218
193
219
```python
194
-
# ✅ tool result
220
+
# ✅ tool result
195
221
2
196
222
```
197
223
198
224
5 - 3 equals 2.
199
225
:::
200
226
201
227
202
-
## Motivating example
228
+
## Advanced example: Code execution
203
229
204
230
Let's look at a more compelling use case for MCP tools: code execution.
205
231
A tool that can execute code and return the results is a powerful way to extend the capabilities of an LLM.
206
232
This way, LLMs can generate code based on natural language prompts (which they are quite good at!) and then execute that code to get precise and reliable results from data (which LLMs are not so good at!).
207
233
However, allowing an LLM to execute arbitrary code is risky, as the generated code could potentially be destructive, harmful, or even malicious.
208
234
209
-
To mitigate these risks, it's important to implement safeguards around code execution.
235
+
To mitigate these risks, it's important to implement safeguards around code execution.
210
236
This can include running code in isolated environments, restricting access to sensitive resources, and carefully validating and sanitizing inputs to the code execution tool.
211
237
One such implementation is Pydantic's [Run Python MCP server](https://github.com/pydantic/pydantic-ai/tree/main/mcp-run-python), which provides a sandboxed environment for executing Python code safely via [Pyodide](https://pyodide.org/en/stable/) and [Deno](https://deno.com/).
212
238
@@ -242,4 +268,4 @@ async def _(user_input: str):
242
268
await chat.append_message_stream(stream)
243
269
```
244
270
245
-
{class="shadow rounded"}
271
+
{class="shadow rounded"}
0 commit comments