WEBVTT

00:00.210 --> 00:01.920
Instructor: So let's go back to the code

00:01.920 --> 00:04.050
and let's go to main.py file,

00:04.050 --> 00:08.580
and we'll start by creating the Stdio client

00:08.580 --> 00:11.550
'cause that's going to be the proxy for our MCP host,

00:11.550 --> 00:13.590
which is going to be our LangGraph agent.

00:13.590 --> 00:15.420
And the client needs to know two things.

00:15.420 --> 00:17.910
It needs to know how to run the MCP Server,

00:17.910 --> 00:19.680
so which commands to execute

00:19.680 --> 00:21.330
in order for the server to work.

00:21.330 --> 00:24.690
And second, it needs to know how it'll communicate with it.

00:24.690 --> 00:27.270
And those two pieces of information, we're going

00:27.270 --> 00:31.860
to supply the Stdio client with the Stdio server parameters.

00:31.860 --> 00:34.680
So when we initialize this variable here,

00:34.680 --> 00:38.250
we give it the information of how to run the MCP Server

00:38.250 --> 00:42.750
and the object itself, the Stdio server parameters,

00:42.750 --> 00:44.610
it has the information that it's going

00:44.610 --> 00:48.090
to communicate via the transport of Stdio.

00:48.090 --> 00:50.580
So it has all of that information.

00:50.580 --> 00:52.440
Anthropic handles this for us,

00:52.440 --> 00:55.500
and this is what's convenient about MCP SDK.

00:55.500 --> 01:00.030
Wonderful so let's go and use the Stdio client

01:00.030 --> 01:03.540
context manager and let's define it

01:03.540 --> 01:06.930
and supply it with the Stdio server params.

01:06.930 --> 01:11.190
So to do that I'm going to write async with

01:11.190 --> 01:13.950
as the context manager, stdio_client,

01:13.950 --> 01:16.060
and I'm going to give it the argument

01:16.978 --> 01:18.330
of the Stdio server params,

01:18.330 --> 01:21.030
and what we're going to get back from this, we're going

01:21.030 --> 01:23.010
to get back two objects here.

01:23.010 --> 01:25.110
One object is going to be the read

01:25.110 --> 01:27.810
and the other is going to be the write transport.

01:27.810 --> 01:29.460
All right, so after we did that,

01:29.460 --> 01:32.460
we want to create the client session

01:32.460 --> 01:35.910
because every client connects to a server via session,

01:35.910 --> 01:38.490
and we're going to feed that session with the write

01:38.490 --> 01:40.110
and read we just got here.

01:40.110 --> 01:42.630
So let's go and use async context manager

01:42.630 --> 01:44.490
with client session.

01:44.490 --> 01:47.340
And here we're going to give it the read stream

01:47.340 --> 01:49.590
of read we got from before,

01:49.590 --> 01:52.650
and the write stream of write we got from before as well.

01:52.650 --> 01:55.650
So now we have a client session ready.

01:55.650 --> 01:59.160
And this MCP client session, this object is what's going

01:59.160 --> 02:01.380
to do the heavy lifting of communicating

02:01.380 --> 02:03.237
between the client and the server.

02:03.237 --> 02:05.310
And to be honest, we don't really need

02:05.310 --> 02:06.780
to understand this in depth

02:06.780 --> 02:10.890
how this communication is working as the users of this SDK.

02:10.890 --> 02:12.120
If you want, please let me know.

02:12.120 --> 02:14.400
I'd be happy to make a deep dive into it,

02:14.400 --> 02:16.620
but we should use it as a black box.

02:16.620 --> 02:19.170
And this is the convenient thing about using frameworks

02:19.170 --> 02:21.660
with abstract information for us, which is not

02:21.660 --> 02:25.320
that relevant because as the developers of the agent,

02:25.320 --> 02:27.420
we don't really care about the ins and outs

02:27.420 --> 02:30.270
about the communication between the client and the server.

02:30.270 --> 02:31.980
We just assume that it's working

02:31.980 --> 02:35.550
and that the Anthropic software engineers did a decent job

02:35.550 --> 02:38.700
implementing this and abstract away this for us.

02:38.700 --> 02:41.880
Cool, so now the client knows exactly how to run

02:41.880 --> 02:44.550
and how to communicate with the MCP Server.

02:44.550 --> 02:48.060
So let's now see the flow in action, the MCP flow.

02:48.060 --> 02:50.910
We first want to initialize this connection here.

02:50.910 --> 02:53.520
So right now we have all the details in order

02:53.520 --> 02:55.410
to make this initialization.

02:55.410 --> 02:59.730
To do that, let's go and await session.initialize.

02:59.730 --> 03:03.403
And let's also print that the session was initialized.

03:05.220 --> 03:09.240
So after the client initializes the connection,

03:09.240 --> 03:13.320
the MCP Server is going to respond with its available tools.

03:13.320 --> 03:16.320
So after we done this initialization,

03:16.320 --> 03:19.590
then the client is going to have the tools

03:19.590 --> 03:21.810
that the MCP Server exposes.

03:21.810 --> 03:23.700
And I'll be more accurate here.

03:23.700 --> 03:26.370
It's not only the tools, it's also the resources

03:26.370 --> 03:28.950
and the prompts which the server exposes.

03:28.950 --> 03:33.630
So if we were to ask the MCP client here, what are the tools

03:33.630 --> 03:36.930
that the MCP Server exposes, it'll have this information

03:36.930 --> 03:39.450
and this is exactly what we're going to do now.

03:39.450 --> 03:42.870
So let's define a variable which is called tools,

03:42.870 --> 03:46.440
and it's going to be equal to the awaiting

03:46.440 --> 03:50.220
of the code routine of sessions.list_tools.

03:50.220 --> 03:52.680
So this is going to list all the available tools

03:52.680 --> 03:56.130
that the client has and let's go and print it.

03:56.130 --> 03:58.770
So now let's go and run this program.

03:58.770 --> 04:01.110
I'll run uvrun main.py

04:01.110 --> 04:04.050
and we can see that session was initialized

04:04.050 --> 04:08.100
And we can see processing request of type ListToolsRequest.

04:08.100 --> 04:09.953
So this log that we see right over here,

04:09.953 --> 04:13.050
this is from the MCP client itself.

04:13.050 --> 04:16.410
And this is from the MCP SDK implementation.

04:16.410 --> 04:18.480
So we didn't write this log.

04:18.480 --> 04:20.340
After we printed the tools,

04:20.340 --> 04:22.740
we can see here we have a list of tools

04:22.740 --> 04:26.040
and we have here with the add tool, the name is going

04:26.040 --> 04:30.000
to be add, we can see all the metadata, all the information,

04:30.000 --> 04:32.820
the description, the input schema, which arguments,

04:32.820 --> 04:36.270
which does it receive, which output does it output,

04:36.270 --> 04:37.950
and all the information relevant

04:37.950 --> 04:41.280
to help the LLM decide whether to call this tool or not.

04:41.280 --> 04:44.130
So we have this information about the adds tool

04:44.130 --> 04:46.950
and we have it about the multiply tool.

04:46.950 --> 04:51.300
So those are the tools that are math MCP Server exposes.

04:51.300 --> 04:54.930
So at this point, we have an MCP Server which is running

04:54.930 --> 04:57.480
because the MCP client ran it.

04:57.480 --> 05:00.960
It then created the connection in order to communicate

05:00.960 --> 05:02.970
with it via Stdio.

05:02.970 --> 05:06.180
The client now knows the tools which can be invoked.

05:06.180 --> 05:08.880
So those are the tools that the MCP Server exposes.

05:08.880 --> 05:13.140
And now we want to create the host application,

05:13.140 --> 05:16.710
which is going to contain this client information.

05:16.710 --> 05:18.870
And in this case, in this example,

05:18.870 --> 05:20.190
the host application is going

05:20.190 --> 05:22.710
to be a LangGraph react agent.

05:22.710 --> 05:25.443
So the user is going to communicate with that.

05:26.580 --> 05:29.910
All righty, so let's go and create our agent.

05:29.910 --> 05:32.910
And we're going to do this by using the LangGraph

05:32.910 --> 05:36.180
pre-built create react agent function.

05:36.180 --> 05:40.110
And this function returns us a LangGraph react agent.

05:40.110 --> 05:44.280
Now I am assuming that you know what's a react agent?

05:44.280 --> 05:46.530
What's LangGraph? Cool.

05:46.530 --> 05:50.850
So the react agent is going to receive the LLM,

05:50.850 --> 05:54.300
which is going to be the default LLM from Chat OpenAI

05:54.300 --> 05:57.060
I think it's GPT-4o mini.

05:57.060 --> 06:00.180
And it's going to receive the tools that we want

06:00.180 --> 06:02.010
to supply our agent with.

06:02.010 --> 06:06.690
And notice in line 27, I gave it the argument of tools,

06:06.690 --> 06:09.720
which is an MCP tool object.

06:09.720 --> 06:12.270
It's not a LangChain tool object.

06:12.270 --> 06:16.230
So by running this right now, we are going to get an error,

06:16.230 --> 06:17.340
and I want to show you this.

06:17.340 --> 06:21.000
So to show you the value of the LangChain MCP adapter

06:21.000 --> 06:22.620
and what it should provide us.

06:22.620 --> 06:25.950
So let me go and run this code over here,

06:25.950 --> 06:28.080
and let me show you that we get an error

06:28.080 --> 06:29.280
and you can see that we get here

06:29.280 --> 06:31.170
that the first argument must be a string

06:31.170 --> 06:33.750
or a callable for tool decorator.

06:33.750 --> 06:35.157
Instead it got a tuple.

06:35.157 --> 06:38.280
And the TLDR for this is the mismatch.

06:38.280 --> 06:41.250
The create react agent of LangChain expect

06:41.250 --> 06:45.300
to get in the arguments, a list of LangChain tools

06:45.300 --> 06:49.890
and instead we gave it a list of or tuple of MCP tools.

06:49.890 --> 06:51.390
So they both are going

06:51.390 --> 06:54.630
to contain the same information about which tools to invoke

06:54.630 --> 06:56.580
and how to invoke them, which arguments,

06:56.580 --> 06:58.230
what's the return values?

06:58.230 --> 07:00.870
But the format is going to be a bit different.

07:00.870 --> 07:02.490
And to mitigate over this,

07:02.490 --> 07:05.730
to translate the MCP tool object into a LangChain tool

07:05.730 --> 07:08.700
object, we're going to use the load mcptools

07:08.700 --> 07:10.410
function of LangChain.

07:10.410 --> 07:14.880
And all this function needs to receive is the MCP session,

07:14.880 --> 07:17.940
which holds the information on the tools

07:17.940 --> 07:20.520
that the MCP Server exposes.

07:20.520 --> 07:24.300
So if we'll now run it, we can see

07:24.300 --> 07:27.420
that we get here coreturn is not returnable.

07:27.420 --> 07:28.680
I forgot to await it.

07:28.680 --> 07:30.213
So let's run it again,

07:32.730 --> 07:34.770
and everything is running right now.

07:34.770 --> 07:39.120
So our agent is ready to work. So now we can even test it.

07:39.120 --> 07:43.110
So let me go now even and print the tools here.

07:43.110 --> 07:45.150
Let me go and print the tools,

07:45.150 --> 07:47.280
and we're going to see that now you're going

07:47.280 --> 07:48.900
to get the LangChain tools

07:48.900 --> 07:51.960
because the structured tool class is a class

07:51.960 --> 07:53.703
from the LangChain library.

07:54.570 --> 07:59.570
Wonderful. So let's go and test our LangGraph react agent.

07:59.910 --> 08:04.910
So here we are going to run the agent.ainvoked

08:05.130 --> 08:08.190
because we are in asynchronous context

08:08.190 --> 08:10.620
and the argument that we're going to give it is going

08:10.620 --> 08:12.480
to be a dictionary, which is going

08:12.480 --> 08:13.950
to hold the key of messages.

08:13.950 --> 08:17.190
So, and here we're going to give a list of messages,

08:17.190 --> 08:20.490
and we're going to put here the human message object.

08:20.490 --> 08:22.980
Again, this is a LangChain construct,

08:22.980 --> 08:26.130
and here the content is going to be what is two plus two.

08:26.130 --> 08:30.360
And don't forget to import it because we did not import it.

08:30.360 --> 08:34.773
So let's go and simply add this import, let's say over here.
