Content
# Using MCP Agent
MCP (Model Context Protocol) is rapidly becoming a key interface for generative AI applications to leverage external data. Here, we will configure MCP and an agent in a local environment to easily try out MCP. For more detailed information such as cloud deployment, please refer to [kyopark/mcp](https://github.com/kyopark2014/mcp).
## Using MCP
### MCP Basic
Users can connect to the MCP server not only through AI tools installed on their computers, such as Claude Desktop and Cursor, but also through applications primarily developed in the form of agents. The MCP server provides its capabilities as a service to MCP client requests and performs the client's requests. The MCP server can query files or databases on the local computer, as well as use APIs from external servers on the internet to retrieve necessary information. The MCP Client connects to the Server using the JSON-RPC 2.0 protocol, and can select stdio or SSE (Server-Sent Events) to transmit Host requests to MCP and receive and utilize responses.
<img src="https://github.com/user-attachments/assets/31065469-69f0-4ce8-a241-747fc3504e6f" width="750">
The definitions and operations of the main elements of MCP are as follows:
- MCP Hosts: Programs/AI tools that access data through the MCP protocol, such as Claude Desktop, Cursor, and User Agent Applications.
- MCP Clients: Clients that perform 1:1 connections with the MCP Server and can connect to the MCP Server via stdio or Streamable HTTP.
- MCP Servers: Lightweight programs that inform Clients of the capabilities of Tools through standardized MCP, can query files or databases on the Local Computer, and can retrieve information using external APIs.
- Local data sources: Databases and local data that the MCP server can access.
- Remote services: External systems accessible via API.
Using MCP has the following advantages:
- Access to various data sources is possible in a standardized way.
- New features can be added through MCP server updates without changing application code.
- AI support and expansion are facilitated throughout the organization.
[MCP Server Components](https://www.philschmid.de/mcp-introduction) include the following items:
- Tools (Model-controlled): Functions (tools) that the LLM can call to perform specific tasks, such as performing specific actions like APIs.
```python
tools = await session.list_tools()
```
- Resources (Application-controlled): Data sources that generative AI applications can access. Data can be retrieved without significant computation or side effects.
```python
resources = await session.list_resources()
```
- Prompts (User-controlled): Predefined templates used when using tools or resources, which can be selected before inference.
```python
prompts = await session.list_prompts()
```
### LangChain MCP Adapter
[LangChain MCP Adapter](https://github.com/langchain-ai/langchain-mcp-adapters) is a lightweight wrapper that allows MCP to be used with LangGraph agents and is MIT-based open source. The main role of the MCP Adapter is to define tools for the MCP server, retrieve tool information from the MCP client, and define and utilize them as tool nodes in LangGraph.
#### MCP Server
The MCP server for RAG search can be defined as follows. Specifying the server's transport as "stdio" is convenient because the client can directly execute the server's Python code without having to continuously run the server.
```python
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(
name = "Search",
instructions=(
"You are a helpful assistant. "
"You can search the documentation for the user's question and provide the answer."
),
)
@mcp.tool()
def search(keyword: str) -> str:
"search keyword"
return retrieve_knowledge_base(keyword)
if __name__ =="__main__":
print(f"###### main ######")
mcp.run(transport="stdio")
```
When a request comes in, the server performs a RAG search with retrieve_knowledge_base(). Since the server's Python code should be lightweight, it was configured to trigger a lambda as shown below. The Lambda performs retrieve, grade, and generation operations. You can specify "model_name" as shown below, and you can optionally use "grading" if needed. Also, if you want to speed up processing with parallel processing, set "multi_region" to "Enable". See [lambda-rag](./lambda-rag/lambda_function.py) for detailed code.
```python
def retrieve_knowledge_base(query):
lambda_client = boto3.client(
service_name='lambda',
region_name=bedrock_region
)
functionName = f"lambda-rag-for-{projectName}"
payload = {
'function': 'search_rag',
'knowledge_base_name': knowledge_base_name,
'keyword': query,
'top_k': numberOfDocs,
'grading': "Enable",
'model_name': model_name,
'multi_region': multi_region
}
output = lambda_client.invoke(
FunctionName=functionName,
Payload=json.dumps(payload),
)
payload = json.load(output['Payload'])
return payload['response'], []
```
#### MCP Client
You can implement the MCP client using `stdio_client` and `StdioServerParameters` as shown below if the MCP client only sees one MCP server. Information about the MCP server can be read from `config.json` or you can use information entered by the user in streamlit. `load_mcp_server_parameters()` reads `mcp_json` and configures [StdioServerParameters](https://github.com/langchain-ai/langchain-mcp-adapters). The MCP server information in `config.json` is obtained from the output generated after deployment with AWS CDK.
```python
from mcp import ClientSession, StdioServerParameters
def load_mcp_server_parameters():
mcp_json = json.loads(mcp_config)
mcpServers = mcp_json.get("mcpServers")
command = ""
args = []
if mcpServers is not None:
for server in mcpServers:
config = mcpServers.get(server)
if "command" in config:
command = config["command"]
if "args" in config:
args = config["args"]
break
return StdioServerParameters(
command=command,
args=args
)
```
Configure the `stdio_client` with the MCP server information as shown below. At this time, the tool information is obtained with `load_mcp_tools`. The Agent binds the tool information and performs the requested action using `ainvoke`.
```python
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
async def mcp_rag_agent_single(query, st):
server_params = load_mcp_server_parameters()
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await load_mcp_tools(session)
with st.status("thinking...", expanded=True, state="running") as status:
agent = create_agent(tools)
agent_response = await agent.ainvoke({"messages": query})
result = agent_response["messages"][-1].content
st.markdown(result)
st.session_state.messages.append({
"role": "assistant",
"content": result
})
return result
```
The MCP client is executed as follows. `asyncio` was used to run it asynchronously. You can then update the information when the user updates the MCP Config in the UI.
```python
asyncio.run(mcp_rag_agent_single(query, st))
```
If there are multiple server information, use the `MultiServerMCPClient` provided by [langchain-mcp-adapters](https://github.com/langchain-ai/langchain-mcp-adapters). First, get the server information as shown below.
```python
def load_multiple_mcp_server_parameters():
mcp_json = json.loads(mcp_config)
mcpServers = mcp_json.get("mcpServers")
server_info = {}
if mcpServers is not None:
command = ""
args = []
for server in mcpServers:
config = mcpServers.get(server)
if "command" in config:
command = config["command"]
if "args" in config:
args = config["args"]
server_info[server] = {
"command": command,
"args": args,
"transport": "stdio"
}
return server_info
```
After that, define the client with the MCP server information and `MultiServerMCPClient` as shown below. The tool information obtained from the MCP server is obtained with `client.get_tools()` and used when creating the agent. As with the Single MCP server, you can run it with `ainvoke` to get the result.
```python
from langchain_mcp_adapters.client import MultiServerMCPClient
asyncio.run(mcp_rag_agent_multiple(query, st))
async def mcp_rag_agent_multiple(query, st):
server_params = load_multiple_mcp_server_parameters()
async with MultiServerMCPClient(server_params) as client:
with st.status("thinking...", expanded=True, state="running") as status:
tools = client.get_tools()
agent = create_agent(tools)
response = await agent.ainvoke({"messages": query})
result = response["messages"][-1].content
st.markdown(result)
st.session_state.messages.append({
"role": "assistant",
"content": result
})
return result
```
Here, the agent is defined to facilitate customization.
```python
def create_agent(tools):
tool_node = ToolNode(tools)
chatModel = get_chat(extended_thinking="Disable")
model = chatModel.bind_tools(tools)
class State(TypedDict):
messages: Annotated[list, add_messages]
def call_model(state: State, config):
system = (
"Your name is Seo-yeon, and you are an interactive AI designed to answer questions in a friendly manner."
"Provide enough specific details in context."
"If you get a question you don't know, honestly say you don't know."
"Answer in Korean."
)
try:
prompt = ChatPromptTemplate.from_messages(
[
("system", system),
MessagesPlaceholder(variable_name="messages"),
]
)
chain = prompt | model
response = chain.invoke(state["messages"])
return {"messages": [response]}
def should_continue(state: State) -> Literal["continue", "end"]:
messages = state["messages"]
last_message = messages[-1]
if isinstance(last_message, AIMessage) and last_message.tool_calls:
return "continue"
else:
return "end"
def buildChatAgent():
workflow = StateGraph(State)
workflow.add_node("agent", call_model)
workflow.add_node("action", tool_node)
workflow.add_edge(START, "agent")
workflow.add_conditional_edges(
"agent",
should_continue,
{
"continue": "action",
"end": END,
},
)
workflow.add_edge("action", "agent")
return workflow.compile()
return buildChatAgent()
```
## Using MCP Servers
[Model Context Protocol servers](https://github.com/modelcontextprotocol/servers) also provide information on the following servers.
- [Perplexity Ask MCP Server](https://github.com/ppl-ai/modelcontextprotocol)
- [Riza MCP Server](https://github.com/riza-io/riza-mcp)
- [Tavily MCP Server](https://github.com/tavily-ai/tavily-mcp)
You can search for MCP servers at [Smithery](https://smithery.ai/) and retrieve the MCP server information to connect to the servers you need in JSON format.
<img src="https://github.com/user-attachments/assets/62e534ee-88bd-4f9f-a4ff-129522fd834f" width="500">
The MCP server information for Google Search confirmed at [Smithery - Google Search Server](https://smithery.ai/server/@gradusnikov/google-search-mcp-server) is as follows. Requires a search engine ID and API Key.
```java
{
"mcpServers": {
"google-search-mcp-server": {
"command": "npx",
"args": [
"-y",
"@smithery/cli@latest",
"run",
"@gradusnikov/google-search-mcp-server",
"--config",
"{\"googleCseId\":\"b5cd8c527fbd64b72\",\"googleApiKey\":\"AIzbSyDQlYpck8-9TbBSuxoew1luOGVB6unRPNk\"}"
]
}
}
}
```
You can update the server information in json format as shown below. The following uses the search defined in [mcp-server.py](./application/mcp-server.py).
```java
{
"mcpServers": {
"search": {
"command": "python",
"args": [
"application/mcp-server.py"
]
}
}
}
```
### Run Locally (MAC)
1) AWS CLI is required for normal progress, but it is not required. Install according to [Install or update the latest version of AWS CLI](https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html) and register AWS credentials with the "aws configure" command.
2) It is convenient to configure the environment with venv. Create an appropriate folder and set the environment as follows.
```text
python -m venv venv
source venv/bin/activate
```
3) Download the source.
```python
git clone https://github.com/kyopark2014/mcp-agent
```
4) After moving to the downloaded github folder, install the necessary packages as follows.
```text
cd mcp-agent && python -m pip install -r requirements.txt
```
5) Set the keys for the Internet and weather lookup APIs according to [Key settings required for practice](https://github.com/kyopark2014/mcp-agent/blob/main/mcp.md#%EC%8B%A4%EC%8A%B5%EC%97%90-%ED%95%84%EC%9A%94%ED%95%9C-key-%EC%84%A4%EC%A0%95). Once set, the following json file is created in `application/config.json`.
```java
{
"WEATHER_API_KEY": "fbd00245cabcedefghijkd3e94905f7049",
"TAVILY_API_KEY": "tvly-1234567890U3imZFs4LNO2g0Qv1LoE"
}
```
6) Now that you are ready, run streamlit with the following command. Perform a behavior test by referring to [How to use MCP Tool](https://github.com/kyopark2014/mcp-agent/blob/main/mcp.md#mcp-tool-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95).
```text
streamlit run application/app.py
```
### Run with Docker Locally
Install and run docker as follows.
```text
brew install --cask docker
```
Now build using the script as shown below. [build.sh](./build.sh) retrieves aws credentials and includes them when building.
```text
./build.sh
```
Now run as follows. For convenience, the docker port is set to 8502 below, but you can set it according to your environment.
```text
docker run -p 8502:8501 mcp-agent
```
Access the following URL in your browser.
```text
http://0.0.0.0:8502
```
### Preparation for Execution
To draw a diagram, install graphviz according to [Graphviz](https://www.graphviz.org/download/). Use the following command on Mac.
```text
brew install graphviz
```
## Execution Result
When performing complex questions such as "I want to go to Jeju from Seoul via Busan. What is the weather and restaurants like during the trip?", information is collected using various tools as shown below.

As a result, it is possible to answer complex questions as shown below.

## Reference
[MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
[LangChain MCP Adapters](https://github.com/langchain-ai/langchain-mcp-adapters)
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.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers