Skip to content

Commit 48ff2d5

Browse files
committed
add module 11 files
1 parent a8c0f41 commit 48ff2d5

200 files changed

Lines changed: 28119 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

module-11-mcp/demos/.env.example

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# demo_01.ipynb and demo_02.ipynb call an LLM to drive the agent.
2+
# LLM provider: "vocareum" (Udacity workspace default) or "openai".
3+
LLM_PROVIDER=vocareum
4+
5+
# Vocareum key, used when LLM_PROVIDER=vocareum. Udacity provides this in the workspace.
6+
VOCAREUM_API_KEY=voc-...
7+
8+
# OpenAI key, used when LLM_PROVIDER=openai (run against OpenAI directly).
9+
OPENAI_API_KEY=sk-...
10+
11+
# Optional — to see MCP tool calls as spans in Langfuse (see LANGFUSE.md):
12+
# LANGFUSE_PUBLIC_KEY=pk-lf-...
13+
# LANGFUSE_SECRET_KEY=sk-lf-...
14+
# LANGFUSE_HOST=http://localhost:3000

module-11-mcp/demos/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.env
2+
.venv/
3+
__pycache__/
4+
*.pyc
5+
.ipynb_checkpoints/
6+
uv.lock
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.12

module-11-mcp/demos/LANGFUSE.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Seeing MCP tool calls in Langfuse (optional)
2+
3+
The demos work without Langfuse. To *see* the MCP tool calls as spans — proving the protocol
4+
boundary is transparent to tracing — run a local Langfuse and attach the callback.
5+
6+
## Local Langfuse
7+
8+
```sh
9+
git clone --branch v3.130.0 https://github.com/langfuse/langfuse.git
10+
cd langfuse && docker compose up -d # UI on http://localhost:3000 after ~2-3 min
11+
```
12+
13+
Create a project, copy its public/secret keys into `.env`:
14+
15+
```
16+
LANGFUSE_PUBLIC_KEY=pk-lf-...
17+
LANGFUSE_SECRET_KEY=sk-lf-...
18+
LANGFUSE_HOST=http://localhost:3000
19+
```
20+
21+
## In the notebook
22+
23+
```python
24+
from langfuse.langchain import CallbackHandler
25+
handler = CallbackHandler()
26+
result = await agent.ainvoke({"messages": [...]}, config={"callbacks": [handler]})
27+
28+
from langfuse import get_client
29+
get_client().flush() # short-lived process: flush before it exits
30+
```
31+
32+
Open Langfuse → the run appears with the MCP tool calls as **spans** (args in, result out), just
33+
like an in-process tool. Tear down with `docker compose down -v` in the `langfuse/` checkout.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
region,property_type,bedrooms,demand_score,search_volume
2+
west,apartment,2,0.91,1240
3+
north,apartment,2,0.74,880
4+
east,studio,1,0.65,510

module-11-mcp/demos/demo_01.ipynb

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "9a277590",
6+
"metadata": {},
7+
"source": [
8+
"# Demo 1 — Consume open MCP servers\n",
9+
"\n",
10+
"Point one client at two independent, public MCP servers — the **LangChain Docs** MCP and the **AWS Knowledge** MCP — and hand their tools to an agent. The agent answers using tools it never wrote, from two unrelated providers, unified by one protocol.\n",
11+
"\n",
12+
"*Needs network to both hosted (no-auth) servers and an `OPENAI_API_KEY` in `.env`.*"
13+
]
14+
},
15+
{
16+
"cell_type": "code",
17+
"execution_count": 1,
18+
"id": "e9826e5f",
19+
"metadata": {
20+
"execution": {
21+
"iopub.execute_input": "2026-07-09T02:41:51.461839Z",
22+
"iopub.status.busy": "2026-07-09T02:41:51.461759Z",
23+
"iopub.status.idle": "2026-07-09T02:41:52.307530Z",
24+
"shell.execute_reply": "2026-07-09T02:41:52.307059Z"
25+
}
26+
},
27+
"outputs": [],
28+
"source": [
29+
"import os\n",
30+
"from dotenv import load_dotenv\n",
31+
"from langchain.agents import create_agent\n",
32+
"from langchain_openai import ChatOpenAI\n",
33+
"from langchain_mcp_adapters.client import MultiServerMCPClient"
34+
]
35+
},
36+
{
37+
"cell_type": "code",
38+
"execution_count": 2,
39+
"id": "aa6624a0",
40+
"metadata": {
41+
"execution": {
42+
"iopub.execute_input": "2026-07-09T02:41:52.309122Z",
43+
"iopub.status.busy": "2026-07-09T02:41:52.309023Z",
44+
"iopub.status.idle": "2026-07-09T02:41:52.312593Z",
45+
"shell.execute_reply": "2026-07-09T02:41:52.312085Z"
46+
}
47+
},
48+
"outputs": [
49+
{
50+
"data": {
51+
"text/plain": [
52+
"True"
53+
]
54+
},
55+
"execution_count": 2,
56+
"metadata": {},
57+
"output_type": "execute_result"
58+
}
59+
],
60+
"source": [
61+
"load_dotenv()"
62+
]
63+
},
64+
{
65+
"cell_type": "markdown",
66+
"id": "e60251a6",
67+
"metadata": {},
68+
"source": [
69+
"## One client, two open servers\n",
70+
"`get_tools()` connects to both and returns their tools as LangChain tools — discovered at runtime, no bespoke client code per provider."
71+
]
72+
},
73+
{
74+
"cell_type": "code",
75+
"execution_count": 3,
76+
"id": "972cc039",
77+
"metadata": {
78+
"execution": {
79+
"iopub.execute_input": "2026-07-09T02:41:52.313777Z",
80+
"iopub.status.busy": "2026-07-09T02:41:52.313710Z",
81+
"iopub.status.idle": "2026-07-09T02:41:54.588577Z",
82+
"shell.execute_reply": "2026-07-09T02:41:54.588035Z"
83+
}
84+
},
85+
"outputs": [
86+
{
87+
"name": "stdout",
88+
"output_type": "stream",
89+
"text": [
90+
"8 tools discovered from 2 servers:\n",
91+
" - search_docs_by_lang_chain\n",
92+
" - query_docs_filesystem_docs_by_lang_chain\n",
93+
" - submit_feedback\n",
94+
" - aws___read_documentation\n",
95+
" - aws___search_documentation\n",
96+
" - aws___list_regions\n",
97+
" - aws___get_regional_availability\n",
98+
" - aws___retrieve_skill\n"
99+
]
100+
}
101+
],
102+
"source": [
103+
"client = MultiServerMCPClient(\n",
104+
" {\n",
105+
" \"langchain-docs\": {\n",
106+
" \"transport\": \"streamable_http\",\n",
107+
" \"url\": \"https://docs.langchain.com/mcp\",\n",
108+
" },\n",
109+
" \"aws-knowledge\": {\n",
110+
" \"transport\": \"streamable_http\",\n",
111+
" \"url\": \"https://knowledge-mcp.global.api.aws\",\n",
112+
" },\n",
113+
" }\n",
114+
")\n",
115+
"tools = await client.get_tools()\n",
116+
"print(f\"{len(tools)} tools discovered from 2 servers:\")\n",
117+
"for t in tools:\n",
118+
" print(\" -\", t.name)"
119+
]
120+
},
121+
{
122+
"cell_type": "markdown",
123+
"id": "c9e156ce",
124+
"metadata": {},
125+
"source": [
126+
"## Build an agent on the discovered tools\n",
127+
"We wrote none of these tools. The agent just gets a tool list."
128+
]
129+
},
130+
{
131+
"cell_type": "code",
132+
"execution_count": 4,
133+
"id": "58c79fb8",
134+
"metadata": {
135+
"execution": {
136+
"iopub.execute_input": "2026-07-09T02:41:54.590082Z",
137+
"iopub.status.busy": "2026-07-09T02:41:54.589980Z",
138+
"iopub.status.idle": "2026-07-09T02:41:54.860143Z",
139+
"shell.execute_reply": "2026-07-09T02:41:54.859710Z"
140+
}
141+
},
142+
"outputs": [],
143+
"source": [
144+
"provider = os.getenv(\"LLM_PROVIDER\", \"openai\")\n",
145+
"model_kwargs = {\"model\": \"gpt-4o-mini\", \"temperature\": 0}\n",
146+
"if provider == \"vocareum\":\n",
147+
" model_kwargs |= {\"base_url\": \"https://openai.vocareum.com/v1\", \"api_key\": os.getenv(\"VOCAREUM_API_KEY\")}\n",
148+
"agent = create_agent(ChatOpenAI(**model_kwargs), tools)"
149+
]
150+
},
151+
{
152+
"cell_type": "markdown",
153+
"id": "78a90bc8",
154+
"metadata": {},
155+
"source": [
156+
"## Ask a LangChain question → routes to the LangChain-docs tool"
157+
]
158+
},
159+
{
160+
"cell_type": "code",
161+
"execution_count": 7,
162+
"id": "bd1ffe0f",
163+
"metadata": {
164+
"execution": {
165+
"iopub.execute_input": "2026-07-09T02:41:54.861548Z",
166+
"iopub.status.busy": "2026-07-09T02:41:54.861486Z",
167+
"iopub.status.idle": "2026-07-09T02:42:01.682038Z",
168+
"shell.execute_reply": "2026-07-09T02:42:01.681730Z"
169+
}
170+
},
171+
"outputs": [
172+
{
173+
"name": "stdout",
174+
"output_type": "stream",
175+
"text": [
176+
"The `create_agent()` function in LangChain is used to create an agent that can perform tasks based on the tools and models provided. It allows you to define a system prompt and specify the tools the agent can use to fulfill user requests.\n",
177+
"\n",
178+
"### Python Example\n",
179+
"\n",
180+
"Here’s a Python example of how to use `create_agent()`:\n",
181+
"\n",
182+
"```python\n",
183+
"from langchain.agents import create_agent\n",
184+
"from langchain.chat_models import init_chat_model\n",
185+
"\n",
186+
"# Define low-level API tools (stubbed)\n",
187+
"@tool\n",
188+
"def create_calendar_event(title: str, start_time: str, end_time: str, attendees: list[str], location: str = \"\") -> str:\n",
189+
" \"\"\"Create a calendar event.\"\"\"\n",
190+
" return f\"Event created: {title} from {start_time} to {end_time} with {len(attendees)} attendees\"\n",
191+
"\n",
192+
"@tool\n",
193+
"def send_email(to: list[str], subject: str, body: str, cc: list[str] = []) -> str:\n",
194+
" \"\"\"Send an email via email API.\"\"\"\n",
195+
" return f\"Email sent to {', '.join(to)} - Subject: {subject}\"\n",
196+
"\n",
197+
"# Initialize the chat model\n",
198+
"model = init_chat_model(\"gpt-5.5\")\n",
199+
"\n",
200+
"# Create the agent\n",
201+
"calendar_agent = create_agent(\n",
202+
" model,\n",
203+
" tools=[create_calendar_event, send_email],\n",
204+
" system_prompt=(\n",
205+
" \"You are a calendar scheduling assistant. \"\n",
206+
" \"Parse natural language scheduling requests into proper ISO datetime formats. \"\n",
207+
" \"Use create_calendar_event to schedule events.\"\n",
208+
" )\n",
209+
")\n",
210+
"\n",
211+
"# Example usage\n",
212+
"user_request = \"Schedule a meeting with the design team next Tuesday at 2pm.\"\n",
213+
"result = calendar_agent.invoke({\"messages\": [{\"role\": \"user\", \"content\": user_request}]})\n",
214+
"print(result[\"messages\"][-1].text)\n",
215+
"```\n",
216+
"\n",
217+
"In this example, the agent is designed to handle calendar scheduling requests and can create events or send emails based on user input.\n",
218+
"\n",
219+
"For more details, you can refer to the [LangChain documentation on creating agents](https://docs.langchain.com/oss/python/langchain/agents#execution-environment).\n"
220+
]
221+
}
222+
],
223+
"source": [
224+
"res = await agent.ainvoke(\n",
225+
" {\n",
226+
" \"messages\": [\n",
227+
" {\"role\": \"system\", \"content\": \"You are a helpful assistant that answers questions about LangChain concisely.\"},\n",
228+
" {\"role\": \"system\", \"content\": \"Filter the results to only include Python examples (include Python in the query text)\"},\n",
229+
" {\"role\": \"system\", \"content\": \"Make sure to include the correct references to the LangChain documentation.\"},\n",
230+
" {\"role\": \"user\", \"content\": \"In LangChain, what does create_agent() do? Search the docs and provide a Python example.\"},\n",
231+
" ]\n",
232+
" }\n",
233+
")\n",
234+
"print(res[\"messages\"][-1].content)"
235+
]
236+
},
237+
{
238+
"cell_type": "markdown",
239+
"id": "ff368528",
240+
"metadata": {},
241+
"source": [
242+
"## Ask an AWS question → routes to the AWS-knowledge tool"
243+
]
244+
},
245+
{
246+
"cell_type": "code",
247+
"execution_count": 8,
248+
"id": "fad295e7",
249+
"metadata": {
250+
"execution": {
251+
"iopub.execute_input": "2026-07-09T02:42:01.683299Z",
252+
"iopub.status.busy": "2026-07-09T02:42:01.683229Z",
253+
"iopub.status.idle": "2026-07-09T02:42:05.791892Z",
254+
"shell.execute_reply": "2026-07-09T02:42:05.791462Z"
255+
}
256+
},
257+
"outputs": [
258+
{
259+
"name": "stdout",
260+
"output_type": "stream",
261+
"text": [
262+
"Here are a few AWS regions:\n",
263+
"\n",
264+
"1. **Africa (Cape Town)** - af-south-1\n",
265+
"2. **Asia Pacific (Tokyo)** - ap-northeast-1\n",
266+
"3. **Europe (Frankfurt)** - eu-central-1\n",
267+
"4. **US East (N. Virginia)** - us-east-1\n",
268+
"5. **South America (Sao Paulo)** - sa-east-1\n",
269+
"\n",
270+
"If you need more information or additional regions, feel free to ask!\n"
271+
]
272+
}
273+
],
274+
"source": [
275+
"res = await agent.ainvoke(\n",
276+
" {\"messages\": [{\"role\": \"user\", \"content\": \"List a few AWS regions using the AWS knowledge tools.\"}]}\n",
277+
")\n",
278+
"print(res[\"messages\"][-1].content)"
279+
]
280+
},
281+
{
282+
"cell_type": "markdown",
283+
"id": "a78bda24",
284+
"metadata": {},
285+
"source": [
286+
"Two providers, zero tool code, one protocol."
287+
]
288+
},
289+
{
290+
"cell_type": "markdown",
291+
"id": "79c6ad9e",
292+
"metadata": {},
293+
"source": []
294+
}
295+
],
296+
"metadata": {
297+
"kernelspec": {
298+
"display_name": "mcp-demos (3.12.11)",
299+
"language": "python",
300+
"name": "python3"
301+
},
302+
"language_info": {
303+
"codemirror_mode": {
304+
"name": "ipython",
305+
"version": 3
306+
},
307+
"file_extension": ".py",
308+
"mimetype": "text/x-python",
309+
"name": "python",
310+
"nbconvert_exporter": "python",
311+
"pygments_lexer": "ipython3",
312+
"version": "3.12.11"
313+
}
314+
},
315+
"nbformat": 4,
316+
"nbformat_minor": 5
317+
}

0 commit comments

Comments
 (0)