當我們在開發模型或使用模型的過程中,常常會遇到一個問題是我們的Demo成果要怎麼可以快速展示在他人面前?我們可能會先想到把結果輸出成表單,或是寫一個前端來當做互動的介面,但這往往需要額外的技能與時間。這時候 Streamlit 就像是一個神隊友,只要使用簡單的 Python 程式碼,就能在短短幾分鐘內把資料分析或機器學習成果轉換成網頁應用,讓同學或朋友只要打開瀏覽器就能操作。
昨天,我們挑戰改用 LangGraph 來搭建 Agent,把 MCP Server 以 stdio 的方式接上,讓 Agent 能在推論流程中呼叫 sayHello 工具。
今天,我們要再更進一步嘗試使用 Streamlit 來串接這個 Agent,讓整個互動過程可以即時的展示在網頁上。
我們前幾天寫的 mcp_server.py 長這樣:
mcp = FastMCP("My MCP Server")
@mcp.tool
def sayHello(text: str) -> str:
"""回傳一段打招呼的訊息。"""
return f"Hello, {text}!"
if __name__ == "__main__":
mcp.run()
這個 Server 透過 mcp.run(),會使用 stdio 來跟外部溝通。
我們昨天寫的 Agent.py 長這樣:
load_dotenv()
MODEL = os.getenv("OPENAI_API_MODEL", "gpt-4.1")
SYSTEM_HINT = (
"你是一個只會打招呼的助手。"
"當使用者請你打招呼時,請呼叫 MCP 提供的 sayHello(text: str) 工具來產生訊息;"
"若使用者需求與打招呼無關,直接回覆「我只能打招呼。」;"
"所有回覆一律使用繁體中文。"
)
def _extract_text_from_result(result) -> str:
try:
if isinstance(result, dict) and "messages" in result and result["messages"]:
last = result["messages"][-1]
content = getattr(last, "content", None) or ""
if isinstance(content, list):
# 內容有可能是多段結構,取出文字段
texts = []
for part in content:
if isinstance(part, dict) and "text" in part:
texts.append(part["text"])
elif isinstance(part, str):
texts.append(part)
return "\n".join([t for t in texts if t])
if isinstance(content, str):
return content
return str(result)
except Exception:
return str(result)
async def run_agent(user_query: str):
params = StdioServerParameters(
command="python",
args=["mcp_server.py"],
env=os.environ.copy(),
)
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await load_mcp_tools(session)
llm = ChatOpenAI(model=MODEL)
agent = create_react_agent(llm, tools)
messages = [
{"role": "system", "content": SYSTEM_HINT},
{"role": "user", "content": user_query},
]
result = await agent.ainvoke({"messages": messages})
return _extract_text_from_result(result)
if __name__ == "__main__":
out = asyncio.run(run_agent("幫我跟小明打招呼"))
print(out)
python -m venv venv
source ./venv/bin/activate
pip install streamlit
st.set_page_config(page_title="MCP 測試")
st.title("MCP 測試")
if "history" not in st.session_state:
st.session_state.history = []
for role, msg in st.session_state.history:
with st.chat_message(role):
st.write(msg)
if prompt := st.chat_input("輸入訊息(例如:幫我跟小明打招呼)"):
st.session_state.history.append(("user", prompt))
with st.chat_message("user"):
st.write(prompt)
with st.chat_message("assistant"):
with st.spinner("思考中..."):
try:
reply = asyncio.run(run_agent(prompt))
except Exception as e:
reply = f"執行出錯:{e}"
st.write(reply)
st.session_state.history.append(("assistant", reply))
使用以下指令運行:
streamlit run app.py --server.address localhost --server.port 8501
結果如下圖:
從昨天透過 LangGraph 串接 MCP Server 工具,到今天再把 Agent 包進 Streamlit,我們完成從後端推論到前端展示的循環。透過這樣的組合,讓我們可以在有限的時間裡完成一個可互動的應用,不需要額外的前端開發,也不需處理複雜的部署,就能把成果即時展示給同學或團隊成員。