
MCP RAG Server
โ 40from kyopark2014
A lightweight Python server for Retrieval-Augmented Generation (RAG) using AWS Lambda. It retrieves knowledge from external data sources like arXiv and PubMed.
MCP Application ๊ตฌํํ๊ธฐ
MCP(Model Context Protocol)์ ์์ฑํ AI application์ด ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋ ์ฃผ์ํ ์ธํฐํ์ด์ค๋ก ๋น ๋ฅด๊ฒ ํ์ฐ๋๊ณ ์์ต๋๋ค. 2024๋ 11์์ Anthropic์ ์คํ์์ค ํ๋ก์ ํธ๋ก ์์๋์๊ณ , ํ์ฌ Cursor๋ฟ ์๋๋ผ OpenAI์์๋ ์ง์ํ๊ณ ์์ต๋๋ค. ์ฌ๊ธฐ์์๋ MCP with LangChain์ ์ด์ฉํ์ฌ LangGraph๋ก ๋ง๋ application์ด MCP๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช ํฉ๋๋ค. ์ฌ๊ธฐ์ ๊ตฌํํ RAG๋ Amazon์ ์์ ๊ด๋ฆฌํ RAG ์๋น์ค์ธ Knowledge base๋ก ๊ตฌํ๋์์ผ๋ฏ๋ก, ๋ฌธ์์ ํ ์คํธ ์ถ์ถ, ๋๊ธฐํ, chunking๊ณผ ๊ฐ์ ์์ ์ ์์ฝ๊ฒ ์ํํ ์ ์์ผ๋ฉฐ, ๋ฉํฐ๋ชจ๋ฌ์ ์ด์ฉํด ์ด๋ฏธ์ง/ํ๋ฅผ ๋ถ์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์์๋ MCP server์์ RAG์ ์์ฝ๊ฒ ์ ๊ทผํ ์ ์๋๋ก AWS Lambda๋ฅผ ์ด์ฉํด API๋ฅผ ๊ตฌ์ฑํ์์ต๋๋ค.
์๋ architecture๋ AWS ํ๊ฒฝ์์ MCP๋ฅผ ํฌํจํ Agent๋ฅผ ๊ตฌ์ฑํ๋๊ฒ์ ๋ณด์ฌ์ค๋๋ค. Agent๋ MCP server/client ๊ตฌ์กฐ๋ฅผ ํ์ฉํ์ฌ ์ธ๋ถ์ ๋ฐ์ดํฐ ์์ค๋ฅผ ํ์ฉํ ์ ์์ต๋๋ค. MCP client๋ MCP server์ JSON-RPC ํ๋กํ ์ฝ์ ๊ธฐ๋ฐํ์ฌ stdio/SSE๋ก ํต์ ์ ์ํํฉ๋๋ค. Stdio ์ฌ์ฉ์ MCP Server๋ python, java์ ๊ฐ์ ์ฝ๋๋ก ๊ตฌ์ฑ์ด ๋๊ณ , client์์ ์์ฒญ์ด ์ค๋ฉด RAG๋ ์ธํฐ๋ท๋ฑ์ ์ด์ฉํด ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ฑฐ๋ ์ ๋ฌํ๋ ์ญํ ์ ์ํํฉ๋๋ค. SSE๋ก ํ ๊ฒฝ์ฐ์ MCP client์ server๋ IP๋ก ํต์ ์ ํ๊ฒ ๋ฉ๋๋ค. ์ฌ๊ธฐ์๋ Streamlit์ ์ด์ฉํด application์ UI๋ฅผ ๊ตฌ์ฑํ๊ณ , ์ฌ์ฉ์๋ ALB - CloudFront๋ฅผ ์ด์ฉํด HTTPS ๋ฐฉ์์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด application์ ์ด์ฉํฉ๋๋ค. ๋ํ, ์ฌ๊ธฐ์์๋ ์ปค์คํฐ๋ง์ด์ง์ด ์ ๋ฆฌํ LangGraph๋ฅผ ์ด์ฉํด MCP ๊ธฐ๋ฐ์ application์ ๊ฐ๋ฐํ๋๊ฒ์ ์ค๋ช ํฉ๋๋ค.
MCP ํ์ฉ
MCP Basic
์ฌ์ฉ์๋ ์์ ์ Computer์ ์ค์น๋ Claude Desktop, Cursor์ ๊ฐ์ AI ๋๊ตฌ๋ฟ ์๋๋ผ ์ฃผ๋ก Agentํํ๋ก ๊ฐ๋ฐ๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ํตํด MCP ์๋ฒ์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. MCP server๋ MCP client์ ์์ฒญ์ ์์ ์ด ํ ์ ์๋ ๊ธฐ๋ฅ์ capability๋ก ์ ๊ณตํ๊ณ client์ ์์ฒญ์ ์ํํฉ๋๋ค. MCP server๋ local computer์ ํ์ผ์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์กฐํํ ์ ์์๋ฟ ์๋๋ผ ์ธํฐ๋ท์ ์๋ ์ธ๋ถ ์๋ฒ์ API๋ฅผ ์ด์ฉํด ํ์ํ ์ ๋ณด๋ฅผ ์กฐํํ ์ ์์ต๋๋ค. MCP Client๋ Server์ JSON-RPC 2.0 ํ๋กํ ์ฝ์ ์ด์ฉํด ์ฐ๊ฒฐ๋๋๋ฐ, stdio๋ SSE (Server-Sent Events)์ ์ ํํ์ฌ, Host์ ์์ฒญ์ MCP์ ์ ๋ฌํ ์ ์๊ณ , ์๋ต์ ๋ฐ์์ ํ์ฉํ ์ ์์ต๋๋ค.
MCP์ ์ฃผ์ ์์์ ์ ์์ ๋์์ ์๋์ ๊ฐ์ต๋๋ค.
- MCP Hosts: MCP ํ๋กํ ์ฝ์ ํตํด ๋ฐ์ดํฐ์ ์ ๊ทผํ๋ ํ๋ก๊ทธ๋จ/AI ๋๊ตฌ๋ก์ Claude Desktop, Cursor, User Agent Application์ด ํด๋น๋ฉ๋๋ค.
- MCP Clients: MCP Server์ 1:1๋ก ์ฐ๊ฒฐ์ ์ํํ๋ Client๋ก์ MCP Server์ stdio ๋๋ SSE ๋ฐฉ์์ผ๋ก ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
- MCP Servers: ํ์คํ๋ MCP๋ฅผ ํตํด Client์ Tool์ Capability๋ฅผ ์๋ ค์ฃผ๋ ๊ฒฝ๋ ํ๋ก๊ทธ๋จ์ผ๋ก Local Computer์ ํ์ผ์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์กฐํํ ์ ์๊ณ , ์ธ๋ถ API๋ฅผ ์ด์ฉํด ์ ๋ณด๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.
- Local data sources: MCP ์๋ฒ๊ฐ ์ ๊ทผํ ์ ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ก์ปฌ ๋ฐ์ดํฐ
- Remote services: API๋ฅผ ํตํด ์ ๊ทผ ๊ฐ๋ฅํ ์ธ๋ถ ์์คํ
MCP๋ฅผ ์ฌ์ฉํ๋ฉด ์๋์ ๊ฐ์ ์ฅ์ ์ด ์์ต๋๋ค.
- ํ์คํ๋ ๋ฐฉ์์ผ๋ก ๋ค์ํ ๋ฐ์ดํฐ ์์ค์ ์ ๊ทผ ๊ฐ๋ฅํฉ๋๋ค.
- ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋ ๋ณ๊ฒฝ ์์ด MCP ์๋ฒ ์ ๋ฐ์ดํธ๋ฅผ ํตํ ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐํ ์ ์์ต๋๋ค.
- ์กฐ์ง ์ ๋ฐ์ ๊ฑธ์ณ AI ์ง์ ๋ฐ ํ์ฅ์ด ์ฉ์ดํฉ๋๋ค.
MCP Server Components์๋ ์๋์ ๊ฐ์ ํญ๋ชฉ์ด ์์ต๋๋ค.
- Tools (Model-controlled): LLM์ด ํน์ ์์ ์ ์ํํ๊ธฐ ์ํด ํธ์ถํ ์ ์๋ ๊ธฐ๋ฅ(๋๊ตฌ)์ผ๋ก์, API์ ๊ฐ์ด ํน์ ํ action์ ์ํํฉ๋๋ค.
tools = await session.list_tools()- Resources (Application-controlled): ์์ฑํ AI ์ดํ๋ฆฌ์ผ์ด์ ์ด ์ ๊ทผ ํ ์ ์๋ ๋ฐ์ดํฐ ์์ค์ ๋๋ค. ๋ณต์กํ ๊ณ์ฐ(significant computation)์ด๋ ๋ถ์์ฉ(side effect)์์ด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
resources = await session.list_resources()- Prompts (User-controlled): tool๋ resource๋ฅผ ์ฌ์ฉํ ๋์ ์ด์ฉํ๋ ์ฌ์ ์ ์๋ ํ ํ๋ ์ผ๋ก์ ์ถ๋ก (inference)์ ์ ์ ํํ ์ ์์ต๋๋ค.
prompts = await session.list_prompts()Operation Architecture
Streamlit UI(app.py)์์ ๋ํ ํํยทAgent ํ์
ยทMCP ์๋ฒ๋ฅผ ์ ํํ๋ฉด chat.py๊ฐ ๋ชจ๋๋ณ๋ก ๋ผ์ฐํ
ํฉ๋๋ค. Agent ๋ชจ๋๋ LangGraph, Strands, Claude Agent SDK ์ธ ๊ฐ์ง ๊ตฌํ์ ์ง์ํ๋ฉฐ, MCP ์๋ฒ ์ค์ ์ mcp_config.py์์ stdio / streamable HTTP transport๋ก ๋ก๋๋ฉ๋๋ค.
flowchart TB
subgraph UI["Streamlit (app.py)"]
MODE["๋ํ ํํ / Agent ํ์
"]
MCPUI["MCP ์๋ฒ ์ ํ"]
end
subgraph Router["chat.py"]
RAG[run_rag_with_knowledge_base]
LG[run_langgraph_agent]
ST[run_strands_agent]
CA[run_claude_agent]
end
subgraph LLM["Amazon Bedrock"]
BR[Bedrock Runtime]
KB[Knowledge Base]
end
subgraph Agents["Agent ๊ตฌํ"]
LGA["LangGraph\nMultiServerMCPClient + built-in tools"]
STA["Strands\nMCPClientManager + strands_tools"]
CLA["Claude SDK\nClaudeSDKClient + MCP"]
end
subgraph MCPServers["MCP Servers (mcp_config.py)"]
MCP["knowledge base ยท tavily ยท aws document ยท korea_weather ยท ..."]
end
subgraph Storage["Artifacts / S3"]
ART[artifacts/]
S3[(S3)]
end
MODE --> RAG
MODE --> LG
MODE --> ST
MODE --> CA
MCPUI --> MCPServers
RAG --> KB --> BR
LG --> LGA --> BR
ST --> STA --> BR
CA --> CLA --> BR
LGA --> MCPServers
STA --> MCPServers
CLA --> MCPServers
LGA --> ART
STA --> ART
LGA --> S3
STA --> S3| ๋ชจ๋ | ๋ชจ๋ | ์ค๋ช |
|---|---|---|
| ์ผ์์ ์ธ ๋ํ | chat.general_conversation | ๋ํ ์ด๋ ฅ + Bedrock Runtime invoke_model_with_response_stream ์คํธ๋ฆฌ๋ฐ |
| RAG | chat.run_rag_with_knowledge_base | Bedrock Knowledge Base ๊ฒ์(retrieve) ํ Bedrock Runtime์ผ๋ก ๋ต๋ณ ์์ฑ |
| Agent / Agent (Chat) โ langgraph | chat.run_langgraph_agent | LangGraph StateGraph + LangChain MultiServerMCPClient + built-in tools |
| Agent / Agent (Chat) โ strands | chat.run_strands_agent | Strands SDK + strands_tools + MCPClientManager + built-in tools |
| Agent / Agent (Chat) โ claude | claude_agent.run_claude_agent | Claude Agent SDK(ClaudeSDKClient) + MCP (Bedrock ๋ฐฑ์๋) |
| ์ด๋ฏธ์ง ๋ถ์ | chat.summarize_image / chat.get_image_summarization | ChatBedrock ๋ฉํฐ๋ชจ๋ฌ (์ด๋ฏธ์ง + ํ ์คํธ) ๋ถ์ |
| ๋ฒ์ญํ๊ธฐ | chat.translate_text | ํโ์ ๋ฒ์ญ |
| ๋ฌธ๋ฒ ๊ฒํ ํ๊ธฐ | chat.check_grammer | ํ๊ตญ์ดยท์์ด ๋ฌธ๋ฒ ๊ฒํ ๋ฐ ์์ ์ ์ |
Agent (Chat) ๋ชจ๋๋ Agent ๋ชจ๋์ ๋์ผํ Agent ๊ตฌํ์ ์ฌ์ฉํ๋, history_mode=Enable๋ก ๋ํ ์ด๋ ฅ์ ์ ์งํฉ๋๋ค. MCP ์๋ฒ๋ ์ฌ์ด๋๋ฐ์์ ๋ค์ค ์ ํ ๊ฐ๋ฅํ๋ฉฐ, mcp_config.load_selected_config()๋ก stdio ๋๋ streamable HTTP ์ค์ ์ด ๋ณํฉ๋ฉ๋๋ค.
LangChain MCP Adapter
LangChain MCP Adapter๋ MCP๋ฅผ LangGraph agent์ ํจ๊ป ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฒฝ๋์ ๋ฉํผ(lightweight wrapper)๋ก์ MIT ๊ธฐ๋ฐ์ ์คํ์์ค์ ๋๋ค. MCP Adapter์ ์ฃผ๋ ์ญํ ์ MCP server๋ฅผ ์ํ tool๋ค์ ์ ์ํ๊ณ , MCP client์์ tools์ ์ ๋ณด๋ฅผ ์กฐํํ๊ณ LangGraph์ tool node๋ก ์ ์ํ์ฌ ํ์ฉํ ์ ์๋๋ก ๋์์ค๋๋ค.
์ฌ์ ์ค๋น
MCP์ LangChain MCP Adapter๋ฅผ ์๋์ ๊ฐ์ด ์ค์นํฉ๋๋ค.
pip install mcp langchain-mcp-adaptersMCP Server
RAG ๊ฒ์์ ์ํ MCP server๋ ์๋์ ๊ฐ์ด ์ ์ํ ์ ์์ต๋๋ค. Server์ transport๋ฅผ "stdio"๋ก ์ง์ ํ๋ฉด server๋ฅผ ์ง์ ์คํ์ํค์ง ์๋๋ผ๋, client๊ฐ server์ python code๋ฅผ ์ง์ ์คํํ ์ ์์ด์ ํธ๋ฆฌํฉ๋๋ค.
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(
name = "retrieve"
)
@mcp.tool()
def rag_search(keyword: str) -> str:
"search keyword"
return retrieve(keyword)
if __name__ =="__main__":
mcp.run(transport="stdio")Server๋ ์์ฒญ์ด ๋ค์ด์ค๋ฉด, retrieve_knowledge_base()๋ก RAG ๊ฒ์์ ์ํํฉ๋๋ค.
bedrock_agent_runtime_client = boto3.client("bedrock-agent-runtime", region_name=bedrock_region)
def retrieve(query):
response = bedrock_agent_runtime_client.retrieve(
retrievalQuery={"text": query},
knowledgeBaseId=knowledge_base_id,
retrievalConfiguration={
"vectorSearchConfiguration": {"numberOfResults": number_of_results},
},
)
payload = json.load(output['Payload'])
return payload['response'], []Drug discovery์ ๊ด๋ จํ์ฌ, arXiv, ChEMBL, ClinicalTrials.gov, PubMed์ ์ง์ํ๊ณ ์์ต๋๋ค.
MCP Client
MCP client์ด ํ๋์ MCP server๋ง ๋ณผ ๊ฒฝ์ฐ์๋ ์๋์ ๊ฐ์ด stdio_client์ StdioServerParameters๋ฅผ ์ด์ฉํด ๊ตฌํํ ์ ์์ต๋๋ค. MCP server์ ๋ํ ์ ๋ณด๋ config.json์์ ์ฝ์ด์ค๊ฑฐ๋ streamlit์์ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ์ ๋ณด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. load_mcp_server_parameters()์์๋ mcp_json์ ์ฝ์ด์์ StdioServerParameters์ ๊ตฌ์ฑํฉ๋๋ค.
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
)์๋์ ๊ฐ์ด MCP server์ ๋ํ ์ ๋ณด๋ก stdio_client๋ฅผ ๊ตฌ์ฑํฉ๋๋ค. ์ด๋ tools์ ๋ํ ์ ๋ณด๋ฅผ load_mcp_tools๋ก ๊ฐ์ ธ์ต๋๋ค. Agent์์๋ tool ์ ๋ณด๋ฅผ bindํ๊ณ ainvoke๋ฅผ ์ด์ฉํด ์์ฒญ๋ ๋์์ ์ํํฉ๋๋ค.
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
server_params = load_mcp_server_parameters()
client = MultiServerMCPClient(server_params)
tools = await client.get_tools()
app = buildAgent(tools)
config = {
"recursion_limit": 50,
"configurable": {"thread_id": user_id},
"tools": tools,
"system_prompt": None
}
inputs = {
"messages": [HumanMessage(content=query)]
}
async for output in app.astream(inputs, config):
for key, value in output.items():
if isinstance(value, dict) and "messages" in value:
final_output = value
if final_output and "messages" in final_output and len(final_output["messages"]) > 0:
result = final_output["messages"][-1].content
else:
result = "๋ต๋ณ์ ์ฐพ์ง ๋ชปํ์์ต๋๋ค."์ฌ๊ธฐ์์๋ ์๋์ ๊ฐ์ด ReAct ๋ฐฉ์์ LangGraph agent๋ฅผ ์ด์ฉํฉ๋๋ค.
def call_model(state: State, config):
system = (
"๋น์ ์ ์ด๋ฆ์ ์์ฐ์ด๊ณ , ์ง๋ฌธ์ ์น๊ทผํ ๋ฐฉ์์ผ๋ก ๋๋ตํ๋๋ก ์ค๊ณ๋ ๋ํํ AI์
๋๋ค."
"์ํฉ์ ๋ง๋ ๊ตฌ์ฒด์ ์ธ ์ธ๋ถ ์ ๋ณด๋ฅผ ์ถฉ๋ถํ ์ ๊ณตํฉ๋๋ค."
"๋ชจ๋ฅด๋ ์ง๋ฌธ์ ๋ฐ์ผ๋ฉด ์์งํ ๋ชจ๋ฅธ๋ค๊ณ ๋งํฉ๋๋ค."
"ํ๊ตญ์ด๋ก ๋ต๋ณํ์ธ์."
)
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 buildAgent(tools):
tool_node = ToolNode(tools)
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()MCP client๋ ์๋์ ๊ฐ์ด ์คํํฉ๋๋ค. ๋น๋๊ธฐ์ ์ผ๋ก ์คํํ๊ธฐ ์ํด์ asyncio๋ฅผ ์ด์ฉํ์์ต๋๋ค.
asyncio.run(mcp_agent(query, st))์ฌ๊ธฐ์๋ customize๊ฐ ์ฉ์ดํ๋๋ก agent๋ฅผ ์ ์ํ์์ต๋๋ค.
MCP Servers์ ํ์ฉ
Model Context Protocol servers์์๋ ์๋์ ๊ฐ์ ์๋ฒ๋ค์ ๋ํ ์ ๋ณด๋ฅผ ์ ๊ณตํ๊ณ ์์ต๋๋ค.
Smithery์์ MCP server๋ฅผ ์ฐพ์๋ณด๊ณ ํ์ํ ์๋ฒ๋ฅผ ์ฐพ์ผ๋ฉด ์ ์ํ ์ ์๋ MCP ์๋ฒ ์ ๋ณด๋ฅผ JSON ํํ๋ก ์กฐํํ ์ ์์ต๋๋ค.
Smithery - Google Search Server์์ ํ์ธํ ๊ตฌ๊ธ ๊ฒ์์ฉ MCP ์๋ฒ ์ ๋ณด๋ ์๋์ ๊ฐ์ต๋๋ค. ๊ฒ์์์ง ID์ API Key๋ฅผ ํ์๋ก ํฉ๋๋ค.
{
"mcpServers": {
"google-search-mcp-server": {
"command": "npx",
"args": [
"-y",
"@smithery/cli@latest",
"run",
"@gradusnikov/google-search-mcp-server",
"--config",
"{\"googleCseId\":\"b5cd8c527fbd64b72\",\"googleApiKey\":\"AIzbSyDQlYpck8-9TbBSuxoew1luOGVB6unRPNk\"}"
]
}
}
}์๋์ ๊ฐ์ด json ํ์์ ์๋ฒ์ ๋ณด๋ฅผ ์ ๋ฐ์ดํธ ํ ์ ์์ต๋๋ค. ์๋์์๋ mcp-server.py์์ ์ ์ํ search๋ฅผ ์ด์ฉํ๊ณ ์์ต๋๋ค.
{
"mcpServers": {
"search": {
"command": "python",
"args": [
"application/mcp-server.py"
]
}
}
}AWS Cost Analysis
MCP tool๋ก์ ์๋์ ๊ฐ์ด AWS cost ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ ๋ถ์ํ ์ ์์ต๋๋ค.
from datetime import datetime, timedelta
import pandas as pd
def get_cost_analysis(days: str=30):
end_date = datetime.now()
start_date = end_date - timedelta(days=days)
ce = boto3.client('ce')
service_response = ce.get_cost_and_usage(
TimePeriod={
'Start': start_date.strftime('%Y-%m-%d'),
'End': end_date.strftime('%Y-%m-%d')
},
Granularity='MONTHLY',
Metrics=['UnblendedCost'],
GroupBy=[{'Type': 'DIMENSION', 'Key': 'SERVICE'}]
)
service_costs = pd.DataFrame([
{
'SERVICE': group['Keys'][0],
'cost': float(group['Metrics']['UnblendedCost']['Amount'])
}
for group in service_response['ResultsByTime'][0]['Groups']
])
# region cost
region_response = ce.get_cost_and_usage(
TimePeriod={
'Start': start_date.strftime('%Y-%m-%d'),
'End': end_date.strftime('%Y-%m-%d')
},
Granularity='MONTHLY',
Metrics=['UnblendedCost'],
GroupBy=[{'Type': 'DIMENSION', 'Key': 'REGION'}]
)
region_costs = pd.DataFrame([
{
'REGION': group['Keys'][0],
'cost': float(group['Metrics']['UnblendedCost']['Amount'])
}
for group in region_response['ResultsByTime'][0]['Groups']
])
# Daily Cost
daily_response = ce.get_cost_and_usage(
TimePeriod={
'Start': start_date.strftime('%Y-%m-%d'),
'End': end_date.strftime('%Y-%m-%d')
},
Granularity='DAILY',
Metrics=['UnblendedCost'],
GroupBy=[{'Type': 'DIMENSION', 'Key': 'SERVICE'}]
)
daily_costs = []
for time_period in daily_response['ResultsByTime']:
date = time_period['TimePeriod']['Start']
for group in time_period['Groups']:
daily_costs.append({
'date': date,
'SERVICE': group['Keys'][0],
'cost': float(group['Metrics']['UnblendedCost']['Amount'])
})
daily_costs_df = pd.DataFrame(daily_costs)
return {
'service_costs': service_costs,
'region_costs': region_costs,
'daily_costs': daily_costs_df
}cost์ ์๊ธฐ 3๊ฐ์ง ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋ํ๋ก ์ฌ์ฉํ๊ธฐ ์ํด์๋ ์๋ ํจํค์ง ์ค์น๊ฐ ํ์ํฉ๋๋ค.
pip install -U kaleidoMCP Image Generation
mcp_server_image_generation.py๊ณผ ๊ฐ์ด ์ด๋ฏธ์ง ์์ฑํ๋ tool์ ๋ฑ๋กํฉ๋๋ค.
MCP config๋ ์๋์ ๊ฐ์ด ์ค์ ํฉ๋๋ค. mcp_config.py์ ์ฐธ์กฐํฉ๋๋ค.
{
"mcpServers": {
"imageGeneration": {
"command": "python",
"args": [
"application/mcp_server_image_generation.py"
]
}
}
}์ดํ mcp_nova_canvas.py์ ๊ฐ์ด ์ด๋ฏธ์ง๋ฅผ ์์ฑํฉ๋๋ค.
async def mcp_generate_image(ctx, prompt, negative_prompt, filename, width, height, quality, cfg_scale, seed, number_of_images):
"""Generate an image using Amazon Nova Canvas with text prompt."""
response = await generate_image_with_text(
prompt=prompt,
negative_prompt=negative_prompt,
filename=filename,
width=width,
height=height,
quality=quality,
cfg_scale=cfg_scale,
seed=seed,
number_of_images=number_of_images
)
return {
"url": [f'{path}' for path in response.paths]
} MCP์ image_generation๋ก ๋ถํฐ ์ป์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ด ํ์ํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ chat.py์ ์ฐธ๊ณ ํ์ธ์.
def show_status_message(response, st):
image_url = []
for i, re in enumerate(response):
logger.info(f"message[{i}]: {re}")
if i==len(response)-1:
break
if isinstance(re, ToolMessage):
tool_result = json.loads(re.content)
logger.info(f"tool_result: {tool_result}")
if "url" in tool_result:
st.info(f"URL: {tool_result['url']}")
urls = tool_result['url']
for url in urls:
image_url.append(url)
st.image(url)
return image_urlMCP AWS Diagram
AWS Diagram MCP Server์ ์ด์ฉํ๋ฉด AWS Diagram์ ๊ทธ๋ฆด ์ ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ mcp_config.py์ ์ฐธ์กฐํฉ๋๋ค.
์ด๋ ์ฌ์ฉํ๋ MCP Config๋ ์๋์ ๊ฐ์ต๋๋ค.
{
"mcpServers": {
"awslabs.aws-diagram-mcp-server": {
"command": "uvx",
"args": ["awslabs.aws-diagram-mcp-server"],
"env": {
"FASTMCP_LOG_LEVEL": "ERROR"
},
}
}
}Diagram์ ๊ทธ๋ฆฌ๊ธฐ ์ํด์๋ Graphviz๋ฅผ ๋ฐ๋ผ์ graphviz๋ฅผ ์ค์นํฉ๋๋ค. Mac์์๋ ์๋ ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํฉ๋๋ค.
brew install graphvizMCP AWS Documentation
AWS Documentation MCP Server์ ์ด์ฉํ์ฌ AWS ๋ฌธ์๋ค์ ์กฐํํ ์ ์์ต๋๋ค. ์ด๋ ์ฌ์ฉํ๋ MCP config๋ ์๋์ ๊ฐ์ต๋๋ค. ์์ธํ ๋ด์ฉ์ mcp_config.py์ ์ฐธ์กฐํฉ๋๋ค.
{
"mcpServers": {
"awslabs.aws-documentation-mcp-server": {
"command": "uvx",
"args": ["awslabs.aws-documentation-mcp-server@latest"],
"env": {
"FASTMCP_LOG_LEVEL": "ERROR"
}
}
}
}๋ฆฌ์ ๋ณ ์ฌ์ฉํ ์ ์๋ ๋ชจ๋ธ์ ํ์ธ ๋ฐฉ๋ฒ
์ฌ์ฉํ ์ ์๋ ๋ชจ๋ธ์ ํ์ธ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ์ต๋๋ค.
aws bedrock list-foundation-models --region=us-west-2 --by-provider anthropic --query "modelSummaries[*].modelId"Message Trim
LangGraph ์์ด์ ํธ(application/langgraph_agent.py์ call_model)๋ LLM ํธ์ถ ์ง์ ์ HumanMessage ๊ธฐ์ค ์ต๊ทผ Nํด๋ง ๋จ๊น๋๋ค. LangGraph state์ messages๋ checkpointer์ ๊ทธ๋๋ก ๋๊ณ , ๋ชจ๋ธ์ ๋๊ธฐ๋ ๋ฉ์์ง๋ง trimํฉ๋๋ค. history_mode=Enable/Disable ๋ชจ๋ ๋์ผํ๊ฒ ์ ์ฉ๋ฉ๋๋ค.
๊ธฐ๋ณธ๊ฐ: MAX_CONTEXT_TURNS = 5 (์ผ๋ฐ ์ฑํ
์ SimpleMemory(k=5)์ ๋์ผํ โ์ต๊ทผ 5ํดโ ์๋)
์ค์ ๋ณ๊ฒฝ:
- application/langgraph_agent.py์
MAX_CONTEXT_TURNS์์ ์์ - ๋๋ application/chat.py์
create_agent()์์ config์max_turns/configurable.max_turns์ง์ max_turns=0์ด๋ฉด trim ๋นํ์ฑํ
์์์ trim ํจ์๋ langgraph_agent.py์ ์ ์ํฉ๋๋ค.
# application/langgraph_agent.py
MAX_CONTEXT_TURNS = 5
def trim_messages_by_human_turns(messages: list, max_turns: int) -> list:
"""Keep messages from the last N HumanMessage turns (inclusive)."""
if max_turns <= 0 or not messages:
return messages
human_indices = [i for i, msg in enumerate(messages) if isinstance(msg, HumanMessage)]
if len(human_indices) <= max_turns:
return messages
return messages[human_indices[-max_turns]:]call_model์์๋ ToolMessage content ์ ๊ทํ ํ trim์ ์ ์ฉํฉ๋๋ค.
# application/langgraph_agent.py โ call_model() ๋ด๋ถ
max_turns = (
config.get("configurable", {}).get("max_turns")
or config.get("max_turns")
or MAX_CONTEXT_TURNS
)
trimmed = trim_messages_by_human_turns(messages, max_turns)
if len(trimmed) < len(messages):
logger.info(
f"trimmed messages from {len(messages)} to {len(trimmed)} "
f"(max_turns={max_turns})"
)
messages = trimmed
prompt = ChatPromptTemplate.from_messages(
[
("system", system),
MessagesPlaceholder(variable_name="messages"),
]
)
chain = prompt | model
async for chunk in chain.astream({"messages": messages}):
...์์ด์ ํธ config๋ chat.py์ create_agent()์์ ์์ฑํ๋ฉฐ, history_mode์ ๊ด๊ณ์์ด max_turns๋ฅผ ์ ๋ฌํฉ๋๋ค.
# application/chat.py โ create_agent()
if history_mode == "Enable":
app = langgraph_agent.buildChatAgentWithHistory(tools)
config = {
"recursion_limit": 50,
"configurable": {
"thread_id": user_id,
"tools": tools,
"system_prompt": None,
},
"max_turns": langgraph_agent.MAX_CONTEXT_TURNS,
}
else:
app = langgraph_agent.buildChatAgent(tools)
config = {
"recursion_limit": 50,
"configurable": {
"thread_id": user_id,
"tools": tools,
"system_prompt": None,
},
"max_turns": langgraph_agent.MAX_CONTEXT_TURNS,
}max_turns=5์ ์๋ฏธ
- ์ฌ์ฉ์ HumanMessage 5๊ฐ์, ๊ฐ ํด์ ์ด์ด์ง ๋ชจ๋ ํ์ ๋ฉ์์ง๋ฅผ ์ ์ง
- 1ํด =
HumanMessage1๊ฐ + ๊ทธ ๋ค์AIMessage,ToolMessage, ๋๊ตฌ feedback loop ์ ์ฒด - ๋๊ตฌ๋ฅผ ์ฌ๋ฌ ๋ฒ ํธ์ถํด๋ ๊ฐ์ ์ฌ์ฉ์ ์ง๋ฌธ์ด๋ฉด 1ํด์ผ๋ก ์นด์ดํธ
์ (๋๊ตฌ ์ฌ์ฉ ํฌํจ)
Human(Q1) โ AI(tool_calls) โ ToolMessage โ AI(A1)
Human(Q2) โ AI(A2)
Human(Q3) โ AI(tool_calls) โ ToolMessage โ AI(A3)max_turns=2์ด๋ฉด Q2๋ถํฐ ์ ์ง:
Human(Q2) โ AI(A2) โ Human(Q3) โ AI(tool_calls) โ ToolMessage โ AI(A3)๋ฉ์์ง ๊ฐ์ trim๊ณผ์ ์ฐจ์ด
| ๋ฐฉ์ | N=5์ผ ๋ |
|---|---|
| ์ด์ (๋ฉ์์ง ๊ฐ์) | ๋ฉ์์ง ๊ฐ์ฒด 5๊ฐ๋ง ์ ์ง โ ๋๊ตฌ ๋ฃจํ ๋๋ฌธ์ ์ฌ์ฉ์ ํด ์๊ฐ ๋ถ๊ท์น |
| ํ์ฌ (HumanMessage ํด) | ์ฌ์ฉ์ ์ง๋ฌธ 5๊ฐ + ๊ฐ ํด์ AI/Tool ์๋ต ์ ์ฒด ์ ์ง |
Checkpointer์์ ๊ด๊ณ
history_mode=Enable์ผ ๋MemorySavercheckpointer์๋ ์ ์ฒด ๋ํ ์ด๋ ฅ์ด ์ ์ฅ๋ฉ๋๋ค.- trim์ LLM ์ปจํ ์คํธ ์๋์ฐ ๊ด๋ฆฌ์ฉ์ด๋ฉฐ, ์ ์ฅ๋ history๋ฅผ ์ญ์ ํ์ง ์์ต๋๋ค.
- CloudWatch(
/ecs/...) ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ก๊ทธ์์trimmed messages from X to Y (max_turns=5)๋ก trim ์ฌ๋ถ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
๋ฐฐํฌํ๊ธฐ
EC2๋ก ๋ฐฐํฌํ๊ธฐ
AWS console์ EC2๋ก ์ ์ํ์ฌ Launch an instance๋ฅผ ์ ํํฉ๋๋ค. [Launch instance]๋ฅผ ์ ํํ ํ์ ์ ๋นํ Name์ ์ ๋ ฅํฉ๋๋ค. (์: es) key pair์ "Proceed without key pair"์ ์ ํํ๊ณ ๋์ด๊ฐ๋๋ค.
Instance๊ฐ ์ค๋น๋๋ฉด [Connet] - [EC2 Instance Connect]๋ฅผ ์ ํํ์ฌ ์๋์ฒ๋ผ ์ ์ํฉ๋๋ค.
์ดํ ์๋์ ๊ฐ์ด python, pip, git, boto3๋ฅผ ์ค์นํฉ๋๋ค.
sudo yum install python3 python3-pip git docker -y
pip install boto3Workshop์ ๊ฒฝ์ฐ์ ์๋ ํํ๋ก ๋ Credential์ ๋ณต์ฌํ์ฌ EC2 ํฐ๋ฏธ๋์ ์ ๋ ฅํฉ๋๋ค.
์๋์ ๊ฐ์ด git source๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
git clone https://github.com/kyopark2014/es-us-project์๋์ ๊ฐ์ด installer.py๋ฅผ ์ด์ฉํด ์ค์น๋ฅผ ์์ํฉ๋๋ค.
cd es-us-project && python3 installer.pyAPI ๊ตฌํ์ ํ์ํ credential์ secret์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค. ๋ฐ๋ผ์ ์ค์น์ ํ์ํ credential ์ ๋ ฅ์ด ํ์ํ๋ฐ ์๋์ ๊ฐ์ ๋ฐฉ์์ ํ์ฉํ์ฌ ๋ฏธ๋ฆฌ credential์ ์ค๋นํฉ๋๋ค.
- ์ผ๋ฐ ์ธํฐ๋ท ๊ฒ์: Tavily Search์ ์ ์ํ์ฌ ๊ฐ์ ํ API Key๋ฅผ ๋ฐ๊ธํฉ๋๋ค. ์ด๊ฒ์ tvly-๋ก ์์ํฉ๋๋ค.
- ๋ ์จ ๊ฒ์: openweathermap์ ์ ์ํ์ฌ API Key๋ฅผ ๋ฐ๊ธํฉ๋๋ค. ์ด๋ price plan์ "Free"๋ฅผ ์ ํํฉ๋๋ค.
์ค์น๊ฐ ์๋ฃ๋๋ฉด ์๋์ ๊ฐ์ CloudFront๋ก ์ ์ํ์ฌ ๋์์ ํ์ธํฉ๋๋ค.
์ธํ๋ผ๊ฐ ๋์ด์ ํ์์์ ๋์๋ uninstaller.py๋ฅผ ์ด์ฉํด ์ ๊ฑฐํฉ๋๋ค.
python uninstaller.py๋ฐฐํฌ๋ Application ์ ๋ฐ์ดํธ ํ๊ธฐ
AWS console์ EC2๋ก ์ ์ํ์ฌ Launch an instance๋ฅผ ์ ํํ์ฌ ์๋์ ๊ฐ์ด ์๋์ ๊ฐ์ด "app-for-es-us"๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง๋ instance id๋ฅผ ์ ํํฉ๋๋ค.
[connect]๋ฅผ ์ ํํ ํ์ Session Manager๋ฅผ ์ ํํ์ฌ ์ ์ํฉ๋๋ค.
์ดํ ์๋์ ๊ฐ์ด ์ ๋ฐ์ดํธํ ํ์ ๋ค์ ๋ธ๋ผ์ฐ์ ์์ ํ์ธํฉ๋๋ค.
cd ~/es-us-project/ && sudo ./update.sh์คํ ๋ก๊ทธ ํ์ธ
EC2 console์์ "app-for-es-us"๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง๋ instance id๋ฅผ ์ ํ ํ ํ์, EC2์ Session Manager๋ฅผ ์ด์ฉํด ์ ์ํฉ๋๋ค.
๋จผ์ ์๋์ ๊ฐ์ด ํ์ฌ docker container ID๋ฅผ ํ์ธํฉ๋๋ค.
sudo docker ps์ดํ ์๋์ ๊ฐ์ด container ID๋ฅผ ์ด์ฉํด ๋ก๊ทธ๋ฅผ ํ์ธํฉ๋๋ค.
sudo docker logs [container ID]์ค์ ์คํ์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ต๋๋ค.
Local์์ ์คํํ๊ธฐ
AWS ํ๊ฒฝ์ ์ ํ์ฉํ๊ธฐ ์ํด์๋ AWS CLI๋ฅผ ์ค์นํ์ฌ์ผ ํฉ๋๋ค. EC2์์ ๋ฐฐํฌํ๋ ๊ฒฝ์ฐ์๋ ๋ณ๋๋ก ์ค์น๊ฐ ํ์ํ์ง ์์ต๋๋ค. Local์ ์ค์น์๋ ์๋ ๋ช ๋ น์ด๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/installAWS credential์ ์๋์ ๊ฐ์ด AWS CLI๋ฅผ ์ด์ฉํด ๋ฑ๋กํฉ๋๋ค.
aws configure์ค์นํ๋ค๊ฐ ๋ฐ์ํ๋ ๊ฐ์ข ๋ฌธ์ ๋ Kiro-cli๋ฅผ ์ด์ฉํด ๋น ๋ฅด๊ฒ ์์ ํฉ๋๋ค. ์๋์ ๊ฐ์ด ์ค์นํ ์ ์์ง๋ง, Windows์์๋ Kiro ์ค์น์์ ๋ค์ด๋ก๋ ์ค์นํฉ๋๋ค. ์คํ์๋ ์ ์์ "kiro-cli"๋ผ๊ณ ์ ๋ ฅํฉ๋๋ค.
curl -fsSL https://cli.kiro.dev/install | bashvenv๋ก ํ๊ฒฝ์ ๊ตฌ์ฑํ๋ฉด ํธ๋ฆฌํ๊ฒ ํจํค์ง๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ์๋์ ๊ฐ์ด ํ๊ฒฝ์ ์ค์ ํฉ๋๋ค.
python -m venv .venv
source .venv/bin/activate์ดํ ๋ค์ด๋ก๋ ๋ฐ์ github ํด๋๋ก ์ด๋ํ ํ์ ์๋์ ๊ฐ์ด ํ์ํ ํจํค์ง๋ฅผ ์ถ๊ฐ๋ก ์ค์น ํฉ๋๋ค.
pip install -r requirements.txt์ดํ ์๋์ ๊ฐ์ ๋ช ๋ น์ด๋ก streamlit์ ์คํํฉ๋๋ค.
streamlit run application/app.pyMCP Inspector
Development Mode์์ mcp server๋ฅผ ํ ์คํธ ํ๊ธฐ ์ํด MCP inspector๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค. ์๋์ ๊ฐ์ด cli๋ฅผ ์ค์นํฉ๋๋ค.
pip install 'mcp[cli]'์ดํ ์๋์ ๊ฐ์ด ์คํํ๋ฉด ์ฝ๊ฒ mcp-server.py์ ๋์์ ํ ์คํธ ํ ์ ์์ต๋๋ค. ์คํ์ http://localhost:5173 ์ ๊ฐ์ URL์ ์ ๊ณตํฉ๋๋ค.
mcp dev mcp-server.py์คํ ๊ฒฐ๊ณผ
MCP๋ก RAG๋ฅผ ์กฐํํ์ฌ ํ์ฉํ๊ธฐ
error_code.pdf์ ๋ค์ด๋ก๋ ํ ํ์ ํ์ผ์ ์ ๋ก๋ํฉ๋๋ค. ์ดํ ์๋์ ๊ฐ์ด "๋ณด์ผ๋ฌ ์๋ฌ์ค ์์๊ณผ ๊ด๋ จ๋ ์๋ฌ ์ฝ๋๋ฅผ ๊ฒ์ํด์ฃผ์ธ์."์ ๊ฐ์ด ์ ๋ ฅํ๋ฉด mcp๋ฅผ ์ด์ฉํด tool์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ณ , search tool๋ก ์ป์ด์ง ์ ๋ณด๋ฅผ ์ด์ฉํด ์๋์ ๊ฐ์ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ค ์ ์์ต๋๋ค. ์ด๋ search tool์ lambda๋ฅผ ์คํํ๋๋ฐ lambda์์๋ ์์ ๊ด๋ฆฌํ RAG ์๋น์ค์ธ knowledge base๋ฅผ ์ด์ฉํ์ฌ ๊ฒ์์ด๋ฅผ ์กฐํํ๊ณ ๊ด๋ จ์ฑ์ ํ๊ฐํ ํ์ ๊ด๋ จ๋ ๋ฌธ์๋ง์ ์ ๋ฌํฉ๋๋ค. Agent๋ RAG๋ฅผ ์กฐํํ์ฌ ์ป์ด์ง ์ ๋ณด๋ก ๋ต๋ณ์ ์๋์ ๊ฐ์ด ๊ตฌํฉ๋๋ค.
MCP๋ก ์ธํฐ๋ท ๊ฒ์์ ํ์ฌ ํ์ฉํ๊ธฐ
smithery-Tavily์ ์ ์ํ์ฌ ํ๊ฒฝ์ ๋ง๋ ์ค์ ๊ฐ์ ์ป์ด์ต๋๋ค. ์๋๋ Mac/Linux์ JSON format์ ์ ์ ์ ๋ณด์ ๋๋ค.
{
"mcpServers": {
"mcp-tavily": {
"command": "npx",
"args": [
"-y",
"@smithery/cli@latest",
"run",
"mcp-tavily",
"--key",
"132c5abd-6f2e-4e42-89a1-d0b1fcb75613"
]
}
}
}์๋๋ ๊ธฐ๋ณธ ์ค์ ๋ RAG๋ฅผ ์ํ ์ ๋ณด์ ๋๋ค.
{
"mcpServers": {
"search": {
"command": "python",
"args": [
"application/mcp-server.py"
]
}
}
}์๋๋ multiple mcp server๋ฅผ ์ค์ ์ config ์ ๋๋ค.
{
"mcpServers":{
"RAG":{
"command":"python",
"args":[
"application/mcp-server.py"
]
},
"mcp-tavily":{
"command":"npx",
"args":[
"-y",
"@smithery/cli@latest",
"run",
"mcp-tavily",
"--key",
"132c5abd-6f2e-4e42-89a1-d0b1fcb75613"
]
}
}
}์ด ์ ๋ณด๋ฅผ ์๋์ ๊ฐ์ด ์ผ์ชฝ ๋ฉ๋ด์ MCP Config์ ๋ณต์ฌํฉ๋๋ค.
์ดํ ๋ฉ๋ด์์ "Agent"๋ฅผ ์ ํํ์ ์๋์ ๊ฐ์ด "๊ฐ๋จ์ญ ๋ง์ง์?"๋ผ๊ณ ์ ๋ ฅํ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํฉ๋๋ค.
AWS Cost Analysis
"์ง๋ ํ๋ฌ๊ฐ์ AWS ๋น์ฉ์ ์์ฝํด์ฃผ์ธ์." ์ ๋ ฅํ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํฉ๋๋ค.
์ด๋ฏธ์ง ์์ฑ
์ผ์ชฝ ๋ฉ๋ด์์ Agent๋ฅผ ์ ํํ๊ณ , MCP config๋ก "image generation"์ ์ ํํ ํ์ "๋ ธ์์ด ์ง๋ ์๋ฆ๋ค์ด ๊ฐ๋ณ์ ๋ฌ๋ฆฌ๊ธฐํ๋ ์ฌ๋์ ๊ทธ๋ ค์ฃผ์ธ์."๋ผ๊ณ ์ ๋ ฅ ํ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํฉ๋๋ค.
AWS Architecture ๊ทธ๋ฆฌ๊ธฐ
๋ฉ๋ด์์ "Agent(Chat)"๋ฅผ ์ ํํ๊ณ MCP๋ก "aws diagram"๋ฅผ ๊ณ ๋ฅธ ํ, "Amazon S3๋ก web hosting์ ํ๊ธฐ ์ํ architecture๋ฅผ ์ถ์ฒํด์ฃผ์ธ์."์ "Cognito๋ฅผ ์ด์ฉํด ์ธ์ฆํ ์ ์๋๋ก ํด์ฃผ์ธ์."์ผ๋ก ์์ฐจ์ ์ผ๋ก ๋ช ๋ น์ ํ๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
Code Interpreter์ ํ์ฉ
"strawberry์ r์ ๊ฐฏ์๋?"๋ก ์ง๋ฌธํ๋ฉด ์๋์ ๊ฐ์ด Tools ๋ฆฌ์คํธ์์ "repl_coder"๊ฐ ์ ํ๋์ด ํ์ฉ๋ฉ๋๋ค.
Storage
Tool์์ "aws storage"๋ฅผ ์ ํํ๊ณ , "๋ด s3 ์ ์ฒด ์ฌ์ฉ๋์?"์ด๋ผ๊ณ ์ง๋ฌธํฉ๋๋ค. ์ด๋์ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ์ต๋๋ค.
"๋ด aws strorage ์ฌ์ฉ๋์?"์ด๋ผ๊ณ ์ง๋ฌธํ๋ฉด, S3, EFS, EBS์ ์ฉ๋์ ํ์ธํ์ฌ ์๋์ ๊ฐ์ด ๋ต๋ณํ ์ ์์ต๋๋ค.
Reference
Using MCP with LangGraph agents
Understanding MCP From Scratch
"Vibe Coding" LangGraph apps with llms.txt and MCP
MCP LLMS-TXT Documentation Server
Model Context Protocol (MCP) and Amazon Bedrock
Model Context Protocol servers
Using LangChain With Model Context Protocol (MCP)
Cursor AI ๋ง๊ณ , ๋๋ง์ #MCP ์์ด์ ํธ ์ฑ ๋ง๋ค์ด ๋ณด๊ธฐ!
The Top 7 MCP-Supported AI Frameworks
Drug Discovery Agent based on Amazon Bedrock
pip install mcp langchain-mcp-adaptersBefore it works, you'll need: FASTMCP_LOG_LEVEL
No common issues documented yet. If you hit a problem, the repository's GitHub Issues page is the best place to look.
Licensed under Apache-2.0โ you can use, modify, and redistribute it under that license's terms.
View the full license file on GitHub โ