KeiStory

반응형

LangChain MCP 와 Streamlit 으로 채팅창 만들기

 

지난 포스팅에 이어서 

2025.06.03 - [코딩/Python_AI] - langchain_mcp_adapters 를 이용해 Langchain 과 MCP 연동하기

 

이번 포스팅에서는 Streamlit 으로 채팅 화면을 만드는 방법을 알아봅니다.

MCP 서버를 통해 수학 계산, 날씨 조회 등의 외부 도구를 직접 호출하는 구조를 기반으로 하며 모두 외부서버로 떠 있어야합니다.

weather server (8010)

from typing import List
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Weather", port=8010)

@mcp.tool()
async def get_weather(location: str) -> str:
    """해당 지역의 날씨를 알려줍니다."""
    return "날씨는 맑음입니다."

if __name__ == "__main__":
    mcp.run(transport="streamable-http")

math server (8020)

# math_server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Math", port=8020)

@mcp.tool()
def add(a: int, b: int) -> int:
    """두 수를 더합니다."""
    return a + b

@mcp.tool()
def multiply(a: int, b: int) -> int:
    """두 수를 곱합니다."""
    return a * b

if __name__ == "__main__":
    # mcp.run(transport="stdio")
    mcp.run(transport="streamable-http")

 

streamlit 을 이용한 app 코드입니다.

mcp 도구를 체크 박스로 사용여부를 설정할 수 있습니다.

# pip install streamlit langchain-openai langchain langchain-mcp-adapters
# pip install nest_asyncio
import streamlit as st
import os
from dotenv import load_dotenv
import asyncio
import nest_asyncio

from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langchain_mcp_adapters.client import MultiServerMCPClient

nest_asyncio.apply()
load_dotenv()

# OpenAI API 키 로드
openai_key = os.getenv("OPENAI_API_KEY")
if not openai_key:
    st.error("❌ OPENAI_API_KEY 가 .env에 설정되어 있지 않습니다.")
    st.stop()

# MCP 서버 정의 (토글용)
default_mcp_servers = {
    "math": {
        "url": "http://localhost:8020/mcp",
        "transport": "streamable_http",
        "enabled": True
    },
    "weather": {
        "url": "http://localhost:8010/mcp",
        "transport": "streamable_http",
        "enabled": True
    }
}

st.title("🔧 LangChain MCP 채팅")
st.markdown("OpenAI GPT-4o + MCP 도구 연동")

# 세션 상태 초기화
if "chat_history" not in st.session_state:
    st.session_state.chat_history = []

if "mcp_config" not in st.session_state:
    st.session_state.mcp_config = default_mcp_servers.copy()

# MCP 도구 토글 UI
st.sidebar.title("🧩 MCP 도구 설정")
for name, config in st.session_state.mcp_config.items():
    config["enabled"] = st.sidebar.checkbox(name, value=config["enabled"])

# 사용자 입력
user_input = st.chat_input("질문을 입력하세요...")

# 메인 비동기 처리
async def handle_query(query):
    # 사용 중인 MCP 도구만 필터링
    active_tools = {
        name: {k: v for k, v in config.items() if k != "enabled"}
        for name, config in st.session_state.mcp_config.items() if config["enabled"]
    }

    client = MultiServerMCPClient(active_tools)
    tools = await client.get_tools()

    model = ChatOpenAI(openai_api_key=openai_key, model="gpt-4o", temperature=0)
    agent = create_react_agent(model=model, tools=tools)

    response = await agent.ainvoke({"messages": [{"role": "user", "content": query}]})

    tool_used = None
    final_answer = None

    for message in response.get("messages", []):
        if hasattr(message, "tool_calls") and message.tool_calls:
            for tool_call in message.tool_calls:
                tool_used = tool_call.get("name")
        if hasattr(message, "content") and message.content:
            final_answer = message.content

    return tool_used, final_answer

# 채팅 처리
if user_input:
    st.session_state.chat_history.append(("user", user_input))
    tool, answer = asyncio.run(handle_query(user_input))
    tool_msg = f"🔧 MCP 도구 사용됨: `{tool}`" if tool else "🧠 도구 사용 없이 응답함"
    st.session_state.chat_history.append(("assistant", f"{tool_msg}\n\n{answer}"))

# 채팅 UI 렌더링
for sender, message in st.session_state.chat_history:
    with st.chat_message(sender):
        st.markdown(message)

위 코드를 보면 알수 있듯이 도구를 사용한 경우는 어떤 도구를 사용했는지 알려주면 도구를 사용하지 않은 경우도 표시해 줍니다.

일반적인 대화도 가능하지만 mcp 도구가 필요한 경우 도구를 활용해 응답하게 됩니다.

* .env 파일에 OPEN API KEY 가 설정되어있어야 합니다.

 

결과

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band