Content
# MCP Series: Start Your First MCP Server and Interact with It
## 1. Background
### 1.1 Why MCP Emerged
MCP stands for Model Context Protocol (MCP), an open-source project initiated by Anthropic. Its aim is to define a standardized interface for large models and third-party tool calls, making it easier for more developers to write tool code that is compatible and universal.
MCP serves as a complement to the Tool use aspect of large language models (LLM). Code written according to the MCP standard can be integrated into one's own code and tools as quickly as Plug-in plugins. Currently, there are hundreds to thousands of tools popular in the community, which can be categorized into several major types: calls to remote APIs (e.g., search engines, information retrieval, code submission), calls to local computer shell, file systems, processes, screenshots, GUI interaction events, and calls to other third-party systems including more open-source components.
MCP is divided into Client and Server sides, with communication between them occurring via local STDIO or HTTP-SSE, using the JSON-RPC 2.0 transport protocol. STDIO uses the local standard Standard IN and Out for input and output, suitable for inter-process communication on the local machine; HTTP-SSE refers to the client transmitting data to the Server via HTTP Post, while the Server sends data back to the client using Server-Sent Events (SSE).
### 1.2 Differences Between MCP and Large Model Tool Use
MCP is essentially an abstraction and enhancement of Tool use. The process of interacting with a large model must currently support Tool use for the corresponding Tool parameters to be passed in the Prompt. The tasks completed by the original Tool use tools are encapsulated within the MCP Server, triggered by the MCP Client. The information generated from the execution results of Tool use tools is returned in a format agreed upon by the MCP Server and Client.
MCP Client and Server can be developed and maintained by different programming languages and development teams. Originally, Tool use tools for large models were written in arbitrary forms, making the code non-reusable by other projects and users. However, code that complies with the MCP Client/Server specification can be called as a Tool by other application systems.
### 1.3 MCP Architecture Diagram
When discussing the architecture diagram, most tutorials reference the one from the MCP official website. This article also includes that diagram.

The main parts of the Demo to be built later in this article are constructed according to this architecture diagram.
### 1.4 Frequently Asked Questions (FAQ)
Q: Does MCP depend on a specific programming language?
A: No, it does not. It is generally based on Python and NodeJS.
Q: Does MCP depend on a specific large model?
A: No, it does not. However, different models have different functionalities. For example, not all models support compute use, or some models do not support multimodal inputs, such as images.
Q: Does MCP need to run alongside the program of the large model, or can it be deployed independently?
A: There are no restrictions. If running on the local machine, using STDIO is more efficient; if running on another machine, HTTP communication is used.
Q: What tools are used for debugging MCP?
A: MCP Inspector, a tool based on Python or NodeJS, listens on the local port `http://localhost:5173`, which can then be accessed via a browser.
Q: What common tools are available for MCP?
A: Various SDKs in different programming languages can be used for MCP development, including Python, Java, TypeScript, etc. The Python package manager `uv` is a primary tool that effectively manages the Python runtime environment and resolves multi-version Python library dependency issues. Additionally, NodeJS's npm can directly start the MCP Inspector, and many MCP Servers are developed using Node.
Based on the above information, this article presents a Demo to understand the concepts of MCP and Tool use.
## 2. Using the MCP Debugging Tool
Install the package manager Homebrew on MacOS and install the NodeJS package to obtain the `npx` package manager.
```shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install node
npm install -g npm@latest
pip3 install mcp
```
Start the debugging tool; there is no need to download the source code from GitHub, you can directly start the MCP Inspector. Execute the following command.
```shell
npx @modelcontextprotocol/inspector
```
You should see the following output:
```
Starting MCP inspector...
Proxy server listening on port 3000
🔍 MCP Inspector is up and running at http://localhost:5173 🚀
```
Now, access `http://localhost:5173` in your browser to see the GUI interface of the MCP Inspector. The screenshot is as follows.

With the debugging tool ready, let's start developing the MCP Server.
## 3. Building an MCP Server to Query Weather Using the MCP Official Documentation Example
Here, we take the weather query MCP Server example provided in the Quickstart - For Server Developers section of the MCP official website.
### 3.1 Environment Setup
Install the `uv` tool.
```shell
curl -LsSf https://astral.sh/uv/install.sh | sh
```
Create a project and deploy the dependency environment.
```shell
uv init mcp-server-weather
cd mcp-server-weather
uv venv
source .venv/bin/activate
uv add "mcp[cli]" httpx
```
### 3.2 Deploying Code
Write the following code and save it in the `mcp-server-weather` directory with the filename `weather.py`.
This MCP Server runs in STDIO mode and does not need to listen on a port. When it receives a request from the MCP Client via STDIO, it initiates a request to `https://api.weather.gov`.
Due to the length of the code, it will not be pasted in full here. The code is available on GitHub [here](https://github.com/aobao32/mcp-weather-sample/blob/main/mcp-server-weather/weather.py). Click the link to view the code.
### 3.3 Starting Debugging
Since this MCP Server operates in STDIO mode and does not listen on a port, it cannot be debugged directly over the network; you must use the MCP Inspector for debugging.
In the previous section, we introduced how to start the MCP Inspector via Node. Additionally, it can also be started using Python with the following command.
```shell
uv run mcp dev weather.py
```
The output will be as follows:
```shell
Starting MCP inspector...
Proxy server listening on port 3000
🔍 MCP Inspector is up and running at http://localhost:5173 🚀
```
Now open your browser and visit the previously returned address `http://localhost:5173/`. You will see the MCP Inspector interface.
On the left side, select the protocol location, choose `STDIO` from the `Transport Type` dropdown, enter `uv` in the `Command` field, and input `run --with mcp mcp run weather.py` in the `Arguments` field. Then click the `Connect` button.
Click the `Tools` tab at the top center of the page, and then click the `List Tools` button to see the two tools available in this MCP Server, named `get_alerts` and `get_forecast`. The screenshot is as follows.

You can see that querying the available tools in this MCP Server was successful.
At this point, the Server debugging is complete. You can stop the debugging started by the `uv` tool by pressing `CTRL+C` in the terminal.
## 4. Building a Command-Line Based MCP Client and Connecting to the Server
### 4.1 How to Build an MCP Client
The MCP official documentation [here](https://modelcontextprotocol.io/quickstart/client) provides a sample example, but it calls the official Anthropic Claude API instead of the AWS Bedrock large model. Therefore, this article mainly rewrites it as follows:
- 1. Change the call from the official Anthropic API to the AWS Bedrock Converse API, allowing for profile modification to switch models (optional models like Claude 3.5/3.7 that support Tool use);
- 2. Add a system prompt;
- 3. Add a loop to support multiple Tool calls and adjust the output content after multiple Tool use calls (deduplication);
- 4. Add debug output at key points, printing key variables to the console for better understanding of the Tool use process and API parameter composition;
- 5. Change the startup method to use `uv`.
### 4.2 Environment Setup
Exit the `mcp-server-weather` directory, create a new directory, and initialize the environment.
```shell
uv init mcp-client
cd mcp-client
uv venv
source .venv/bin/activate
uv add mcp anthropic python-dotenv boto3 loguru
touch client.py
```
### 4.3 Deploying Code
Edit the following code and save it in the `mcp-client` directory with the filename `client.py`.
Due to the length of the code, it will not be pasted in full here. The code is available on GitHub [here](https://github.com/aobao32/mcp-weather-sample/blob/main/mcp-client/client.py). Click the link to view the code.
### 4.4 Accessing the MCP Server
Ensure that your local machine has configured the AKSK through AWSCLI, and that the AKSK has permission to access Bedrock and the large model.
In the current `mcp-client` directory, execute the following command to start. Be sure to replace the corresponding MCP Server file path.
```shell
uv run client.py ../mcp-server-weather/weather.py
```
In the terminal window, you can try asking questions. After asking, you will see that the large model confirms the need to call the tool. The screenshot is as follows.

Upon confirming the need to call the Tool, the MCP Client connects to the MCP Server, executes, and retrieves the result. Note that the Tool use ID is generated by the LLM during the previous run. The screenshot is as follows.

If multiple tools need to be called, the large model will run multiple rounds. The screenshot shows the second tool being called.

Thus, after completing the Tool use, the LLM will summarize and rewrite to generate the final output result. The screenshot is as follows.

At this point, we can see that a weather query MCP Server is functioning correctly, and this MCP Server uses the local STDIO calling method, requiring no port listening, saving resources and being efficient.
## 5. Analysis of the Above Demo
### 5.1 Main Interaction Process
Combining the debug information printed to the console in the above code, we can see the data interaction of the Tool use method, following the timeline as below:
- 1) The business code calls the MCP Client to query available tools and retrieves the Tool names and descriptions.
- 2) The descriptions of the available Tools are formatted in a specific JSON format, combined with the business User input to form the System prompt, which is ultimately sent to the LLM for interaction.
- 3) The LLM returns a result, determining that a specific Tool needs to be executed. At this point, the Tool name and Tool use execution ID (a randomly generated string as ID) can be obtained from the assistant label in the returned result.
- 4) The business code calls the MCP Client again to interact with the MCP Server and obtain the execution result of the Tool use.
- 5) The execution result of the Tool use is merged with the previously generated Tool use execution ID, along with the user input label as the input for the next round of dialogue, and submitted to the LLM again.
- 6) The LLM checks the Tool use execution ID to confirm the execution result, then rewrites again to output the final business result, or determines that other Tools are still needed, returning to step 2 for a loop until completion.
In the above process, the main interactions with the MCP Server are:
- Querying the names and descriptions (i.e., functionalities) of available Tools.
- Executing Tools.
In the above process, the main interactions with the LLM are:
- Determining whether a Tool is needed; if so, the LLM assigns a Tool use execution ID.
- Sending the Tool use execution result along with the Tool use execution ID back to the LLM to determine whether the execution was successful and whether other Tools are still needed.
- If no other Tools are needed, the LLM will rewrite the output result in full to generate the final return result. If it determines that other Tools are still needed, it will continue to assign new Tool names and Tool use execution IDs.
- Looping through the above process.
Thus, we can satisfy scenarios with multi-turn dialogue capabilities.
### 5.2 MCP Server List Tool Response Message
The MCP Server will declare its interface functionalities when listing tools and specify the required parameters. For example, in this case, we can see the information received by the interface.
```JSON
meta=None nextCursor=None tools=[
Tool(
name='get_alerts',
description='Get weather alerts for a US state. 提供美国州的天气预警\n\nArgs:\n state: Two-letter US state code (e.g. CA, NY)\n',
inputSchema={
'properties': {
'state': {
'title': 'State',
'type': 'string'
}
},
'required': ['state'],
'title': 'get_alertsArguments',
'type': 'object'
}
),
Tool(
name='get_forecast',
description='Get weather forecast for a location. 提供特定地理坐标的天气预报\n\nArgs:\n latitude: Latitude of the location\n longitude:Longitude of the location\n',
inputSchema={
'properties': {
'latitude': {
'title': 'Latitude',
'type': 'number'
},
'longitude': {
'title': 'Longitude',
'type': 'number'
}
},
'required': ['latitude', 'longitude'],
'title': 'get_forecastArguments',
'type': 'object'
}
)
]
```
The above parameters are the ones that the MCP Server requires to be passed in, after which the MCP Server can initiate the corresponding query.
### 5.3 Some Considerations When Using MCP and Tool Use
#### 1) Using STDIO Mode for MCP Server on Local Machine Offers Better Performance
In the earlier MCP architecture diagram, the MCP Client can call the MCP Server in two ways: STDIO and HTTP SSE. For the vast majority of local interactions, such as local Shell, local file systems, and local processes, using STDIO is simpler and more convenient. Since it does not require listening on a network port, performance is better. For independent Servers running in third-party environments, HTTP SSE can be used, but it should be noted that some HTTP servers may not fully support SSE.
Therefore, in practical use, it is recommended to use STDIO mode for all local scenarios, rather than overly relying on HTTP SSE.
#### 2) Ensure the Model on Bedrock Supports Tool Use
The previous section described the steps for LLM to interact with the MCP Server, where the key first step is for the LLM to determine the need to introduce Tool use. At this point, the LLM must support Tool use. Most models, such as Anthropic Claude and Amazon Nova Pro, support Tool use, but some specific versions do not. For example, as of March 2025, the DeepSeek R1 model provided on AWS Bedrock does not support Tool use.
If the LLM model used on Bedrock does not support Tool use, you will receive an error message as follows:
```
Error: An error occurred (ValidationException) when calling the Converse operation: This model doesn't support tool use.
```
#### 3) Pay Attention to the LLM's Returned Stop Reason
In multiple rounds of interaction with the LLM, each time the model returns a result, the JSON will contain a field called `STOP REASON`, which includes information about the current step of the model's execution. If the `STOP REASON` indicates `Tooluse`, it means that the MCP Server should be called, and the result processed by the MCP Server should be returned to the LLM. If the `STOP REASON` is `Endturn`, it indicates that this is the final output from the LLM, or that Tool use is completely unnecessary, or that the multi-turn Tool use interaction has ended and no further Tool use is needed.
Additionally, `STOP REASON` may also include other reasons such as `max_tokens`. Please refer to the Bedrock documentation [here](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_MessageStopEvent.html).
#### 4) Ensure Correctness of Tool Use IDs During Multiple Tool Uses
When the LLM determines that Tool use needs to be executed, the information returned by the LLM will provide the Tool name and Tool use ID in addition to the aforementioned `STOP REASON`. This Tool use ID is a random string representing a specific execution sequence. After calling the MCP Server to complete the request, the result generated by the MCP Server must match the Tool use ID assigned by the LLM. If these two do not match, the Bedrock API will return an error message indicating an expected Tool ID mismatch.
If multiple Tools are provided to the LLM, there may be a scenario where the LLM determines that a task requires multiple calls to different Tools, and these Tools can be executed in a random order rather than a direct sequence. In this case, the LLM will generate Tool use IDs for all execution tasks at once, and the order may vary each time. When the execution results are returned, the order of the Tool use IDs that the LLM can accept is required. This potential order issue may lead to program errors. A simple handling method is to limit the model in the System Prompt to provide only one Tool use ID at a time, calling one Tool at a time. If multiple tools are needed, the model can arrange the order for sequential execution. This way, when writing code, a relatively simple logic can be adopted, processing only one Tool use ID at a time and returning only one Tool use result to the LLM each time, which is beneficial for all. Multiple Tool use calls can be executed in several loops, and the LLM will arrange the subsequent Tool use calls and assign new Tool use IDs.
#### 5) Handling the Composition of Historical Messages Returned to the LLM (The Last Must Be User, ID Must Correspond)
When returning the execution result of the MCP Server to the LLM, it is also necessary to follow the alternating format of historical dialogue roles `assistant` and `user`. For user-initiated questions, it is undoubtedly of the `user` type. For the information provided by the model indicating the need to introduce Tool use, it is provided under the `assistant` role label. At this point, the MCP must be called. The execution result returned by the MCP Server must also be wrapped with the `user` label and included in the dialogue information and request records returned to the model. At this point, there is no need to add additional user input; simply send the Tool use ID and the Tool use execution result wrapped with the `user` label back to the LLM. The LLM will check the Tool use ID for a match and determine if the execution was successful. If subsequent execution of the next Tool use is needed, the model will handle it itself.
#### 6) Debugging Potential Errors When Running MCP Without Using UV to Manage the Environment
If you do not use `uv` to set up the environment but directly download the relevant Python files, you can install the dependency packages as follows:
```shell
pip3 install mcp anthropic python-dotenv boto3 loguru
```
Then ensure the correctness of the Python executable file on your local machine; otherwise, you may encounter issues finding the Python executable file.
```shell
sudo ln -s /usr/local/bin/python3 /usr/local/bin/python
```
Then you can run:
```shell
python3 client.py weather.py
```
## 6. Reference Documents
Quickstart - For Server Developers
[https://modelcontextprotocol.io/quickstart/server]()
Quickstart - For Client Developers
[https://modelcontextprotocol.io/quickstart/client]()
Bedrock Converse API Tool Use - Examples
[https://docs.aws.amazon.com/bedrock/latest/userguide/tool-use-examples.html]()
Numerous Third-Party MCP Servers
[https://github.com/modelcontextprotocol/servers]()
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
firecrawl
Firecrawl MCP Server enables web scraping, crawling, and content extraction.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Time
A Model Context Protocol server for time and timezone conversions.