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
Copy file name to clipboardExpand all lines: asciidoc/courses/genai-mcp-build-custom-tools-python/modules/1-getting-started/lessons/1-mcp-python-sdk/lesson.adoc
+20-10Lines changed: 20 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,7 +29,7 @@ The SDK includes two main approaches for building servers:
29
29
* **FastMCP**: A high-level, decorator-based approach that makes it simple to create servers quickly
30
30
* **Low-level server**: A more flexible approach that gives you full control over the MCP protocol
31
31
32
-
In this course, we will focus on the FastMCP approach.
32
+
In this course, you will focus on the FastMCP approach.
33
33
34
34
35
35
== Installing the MCP Python SDK
@@ -48,16 +48,16 @@ This package includes both the core MCP functionality and the FastMCP high-level
48
48
49
49
== Introducing FastMCP
50
50
51
-
FastMCP is the high-level interface in the MCP Python SDK designed to make server development as simple as possible. FastMCP is built on top of the FastAPI framework, and uses a decorator approach to defining MCP features.
51
+
link:https://gofastmcp.com/[FastMCP^] is the high-level interface in the MCP Python SDK designed to make server development as simple as possible. It is built on top of the FastAPI framework, and uses a decorator approach to defining MCP features.
52
52
53
53
54
54
== Core MCP Features
55
55
56
-
MCP servers expose three types of features to clients. Let's take a look at each one and when to use them.
56
+
MCP servers expose three types of features to clients.
57
57
58
58
=== 1. Tools
59
59
60
-
**Tools** are functions that LLMs can call to perform actions or retrieve data. They are perfect for tasks that LLMs struggle with, like counting or complex calculations.
60
+
**Tools** are functions that LLMs can call to perform actions or retrieve data. Tools are perfect for tasks that LLMs struggle with, like counting or complex calculations.
61
61
62
62
**Characteristics:**
63
63
@@ -204,7 +204,7 @@ Reflection is then used to infer metadata about the tool.
204
204
2. The output of the tool is an `int`
205
205
3. The string in the opening line is used to describe what the tool does and and when it should be used.
206
206
207
-
The `@mcp.tool()` decorator accepts a number of optional arguments, which we will cover later in the course.
207
+
The `@mcp.tool()` decorator accepts a number of optional arguments, which you will learn about later in the course.
208
208
209
209
210
210
== Running the server
@@ -240,13 +240,16 @@ link:https://github.com/jlowin/fastmcp[Learn more about `fastmcp`].
240
240
241
241
=== Transport methods
242
242
243
-
In the previous course, we also covered the different transport methods that can be used to connect to an MCP server; Standard Input/Output (`stdio`), and Streamable HTTP (`http`).
244
-
As we will develop a local MCP server in this course, we will focus on the `stdio` transport method. You can change the transport method by passing the `transport` parameter to the `run` method.
243
+
In the link:https://graphacademy.neo4j.com/courses/genai-mcp-neo4j-tools/[Developing with Neo4j MCP Tools course^], we also covered the different transport methods that can be used to connect to an MCP server; Standard Input/Output (`stdio`), and Streamable HTTP (`http`).
244
+
245
+
This course will focus on the **Streamable HTTP** transport method.
246
+
The Streamable HTTP transport method exposes the tools through a HTTP server, with results streamed back to the client using link:https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events[Server-Sent Events (SSE)^].
247
+
245
248
246
249
[source,python]
247
250
----
248
251
mcp.run(
249
-
transport="http",
252
+
transport="streamable-http",
250
253
host="127.0.0.1",
251
254
port=8000,
252
255
path="/mcp"
@@ -258,13 +261,20 @@ Streaming HTTP is recommended for web deployments.
258
261
[TIP]
259
262
.The `fastmcp` command line tool
260
263
====
261
-
You can also provide the `--transport`, `--host`, `--port`, and `--path` flags to the `fastmcp` command.
264
+
You can change the transport method by providing the `--transport`, `--host`, `--port`, and `--path` flags to the `fastmcp` command.
265
+
The command doesn't execute the `__main__` block of the server, instead preferring the parameters passed to the command.
266
+
267
+
[source,bash]
268
+
----
269
+
fastmcp run server.py --transport http --host 127.0.0.1 --port 8000
270
+
----
271
+
272
+
link:https://gofastmcp.com/patterns/cli/[Learn more about the `fastmcp` command line tool^].
Copy file name to clipboardExpand all lines: asciidoc/courses/genai-mcp-build-custom-tools-python/modules/1-getting-started/lessons/3c-create-first-server/code/solution.py
Copy file name to clipboardExpand all lines: asciidoc/courses/genai-mcp-build-custom-tools-python/modules/2-database-features/lessons/10c-paginated-tool/lesson.adoc
The function takes a required `genre` parameter and optional `cursor` and `page_size` parameters. The cursor defaults to "0" (start of the list), and page_size defaults to 10 items per page.
46
+
The function takes a required `genre` parameter and optional `cursor` and `page_size` parameters. The cursor defaults to `0` (start of the list), and page_size defaults to 10 items per page.
This section converts the cursor string to a number and calculates the current page number. If the cursor is invalid, it defaults to the start (skip = 0).
55
+
This section uses the cursor number to calculate the skip value.
90
56
91
-
The query execution uses Neo4j's SKIP and LIMIT for pagination:
57
+
Next, using the driver instance from the lifespan context, execute the query to fetch the movies using the SKIP and LIMIT clauses, and coerce the results into a list of dictionaries.
The response includes the movies list and pagination metadata. The `next_cursor` is only set if a full page was returned, indicating more results are available.
71
+
The structured output consists of a dictionary with the following keys:
72
+
73
+
* `genre` - The genre passed to the tool by the client
74
+
* `movies` - A list of movies returned from the query
75
+
* `next_cursor` - The cursor for the next page
76
+
* `page` - The current page number
77
+
* `page_size` - The number of movies per page
78
+
* `has_more` - A boolean indicating if more pages are available
149
79
150
80
151
81
== Step 2: Test with the Interactive Client
@@ -177,21 +107,41 @@ genre (required)
177
107
Type: string
178
108
Enter value: Action
179
109
180
-
cursor (optional, default: 0)
110
+
page_size (optional)
111
+
Type: integer
112
+
Enter value: 2
113
+
114
+
cursor (optional)
181
115
Type: string
182
-
Enter value: 0
116
+
Enter value: 1=9
183
117
184
-
page_size (optional, default: 10)
185
-
Type: integer
186
-
Enter value: 10
187
118
----
188
119
189
-
The response should contain:
120
+
You should receive a structured response similar to the following, with information about the current page and the next cursor.
190
121
191
-
* 10 Action movies
192
-
* A `next_cursor` value (e.g., `"10"`)
193
-
* `page: 1`
194
-
* `has_more: true`
122
+
[source,json]
123
+
.Structured Response
124
+
----
125
+
{
126
+
"genre": "Action",
127
+
"movies": [
128
+
{
129
+
"title": "'Hellboy': The Seeds of Creation",
130
+
"released": "2004-07-27",
131
+
"rating": 6.9
132
+
},
133
+
{
134
+
"title": "13 Assassins (Jûsan-nin no shikaku)",
135
+
"released": "2010-09-25",
136
+
"rating": 7.6
137
+
}
138
+
],
139
+
"next_cursor": 2,
140
+
"page": 1,
141
+
"page_size": 2,
142
+
"has_more": true
143
+
}
144
+
----
195
145
196
146
197
147
=== Fetch the Second Page
@@ -204,45 +154,49 @@ genre (required)
204
154
Type: string
205
155
Enter value: Action
206
156
207
-
cursor (optional, default: 0)
208
-
Type: string
209
-
Enter value: 10
210
-
211
157
page_size (optional, default: 10)
212
158
Type: integer
213
-
Enter value: 10
214
-
----
215
-
216
-
The response should contain:
217
-
218
-
* The next 10 Action movies
219
-
* A new `next_cursor` value (e.g., `"20"`)
220
-
* `page: 2`
221
-
* `has_more: true` (if more pages exist)
222
-
223
-
224
-
=== Continue to the Last Page
159
+
Enter value: 2
225
160
226
-
Keep using the `next_cursor` until you reach a response where:
227
-
228
-
* `next_cursor` is `null` or not present
229
-
* `has_more` is `false`
230
-
* Fewer than `page_size` movies are returned
161
+
cursor (optional, default: 0)
162
+
Type: string
163
+
Enter value: 2
231
164
165
+
----
232
166
233
-
== Step 3: Test with Different Genres
167
+
The response should contain a different page number, next cursor and list of movies.
234
168
235
-
Try different genres to see how pagination behaves:
169
+
[source,json]
170
+
.Paginated Response
171
+
----
172
+
{
173
+
"genre": "Action",
174
+
"movies": [
175
+
{
176
+
"title": "2 Fast 2 Furious (Fast and the Furious 2, The)",
177
+
"released": "2003-06-06",
178
+
"rating": 5.8
179
+
},
180
+
{
181
+
"title": "2 Guns",
182
+
"released": "2013-08-02",
183
+
"rating": 6.7
184
+
}
185
+
],
186
+
"next_cursor": 6,
187
+
"page": 3,
188
+
"page_size": 2,
189
+
"has_more": true
190
+
}
191
+
----
236
192
237
-
* `"Comedy"` - Might have many pages
238
-
* `"Sci-Fi"` - Moderate number of pages
239
-
* `"Documentary"` - Might fit in a single page
240
193
241
-
Notice how some genres have more movies than others!
194
+
Experiment with different genres, for example [copy]#Comedy#, [copy]#Sci-Fi#, or [copy]#Documentary#, and change the [copy]#page_size# to see how it affects the results.
242
195
243
196
244
197
read::I have pagination![]
245
198
199
+
// TODO: Update this to add a COUNT {} subquery for the total? Nice use of degree counts...
Copy file name to clipboardExpand all lines: asciidoc/courses/genai-mcp-build-custom-tools-python/modules/2-database-features/lessons/2c-add-neo4j-connection/lesson.adoc
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -120,7 +120,7 @@ Create a `graph_statistics` tool function that uses `ctx.request_context.lifespa
0 commit comments