使用 FastAPI + FastMCP 進行 MCP 引導的實用指南
在當今的智能交互領域,用戶與AI系統的對話質量直接決定了服務體驗的優劣。Model Context Protocol(MCP,模型上下文協議)作為一種標準化的交互框架,為服務器與客戶端之間的動態信息獲取提供了可靠解決方案。本文將深入解析MCP協議中的誘導流程(Elicitation Process),通過基于FastAPI框架和FastMCP庫構建的投資顧問機器人實例,詳細講解如何在實際項目中高效實現這一流程。無論你是AI應用開發者還是協議集成工程師,讀完本文后都能清晰掌握MCP誘導流程的核心原理與落地方法。
什么是MCP誘導流程?
MCP誘導流程是Model Context Protocol的核心功能之一,它允許服務器在交互過程中通過客戶端向用戶請求額外信息,同時保持客戶端對用戶交互和數據共享的控制權。這種動態信息收集機制的關鍵在于:服務器通過JSON schema定義結構化數據請求,客戶端負責呈現交互界面并返回驗證后的用戶響應,從而實現靈活且標準化的上下文管理。
舉個生活化的例子:當你使用投資顧問AI時,它不會一次性拋出所有問題,而是先詢問你的投資目標,再根據你的回答(如“為退休儲蓄”)進一步詢問退休時間、風險承受能力等相關信息。這種循序漸進的對話方式正是MCP誘導流程的典型應用——通過結構化的多輪交互,逐步構建完整的用戶畫像。
MCP協議的優勢在于其標準化設計,它定義了服務器與客戶端之間的通信規范,使得不同系統可以無縫集成。在傳統的AI交互模式中,開發者往往需要為每類對話場景定制通信邏輯,而MCP通過統一的誘導流程接口,將對話管理與業務邏輯解耦,大幅提升了開發效率和系統兼容性。
MCP誘導流程的核心組件
要實現基于MCP的誘導流程,需要理解其核心組件及協作方式。在我們的投資顧問機器人案例中,系統架構分為兩個關鍵部分:
MCP客戶端(Client)
基于FastAPI框架構建,負責處理與用戶的直接交互。客戶端通過WebSocket建立實時通信通道,接收用戶輸入并展示AI消息。在代碼實現中,client.py文件包含了WebSocket端點定義、會話管理邏輯和誘導回調函數。
客戶端的核心職責包括:
- 維護用戶會話狀態
- 轉發AI消息至用戶界面
- 收集并驗證用戶輸入
- 與MCP服務器建立安全通信
MCP服務器(Server)
基于FastMCP庫實現,負責業務邏輯和對話流程管理。服務器定義了誘導步驟、AI交互邏輯和數據驗證規則,通過工具接口(Tool)與客戶端通信。mcp_server.py文件包含了步驟定義、AI代理鏈配置和工具實現。
服務器的核心功能包括:
- 定義誘導流程的步驟序列
- 生成AI對話內容
- 解析和驗證用戶輸入
- 維護對話上下文狀態
這兩個組件通過MCP協議規范進行通信,客戶端專注于用戶交互體驗,服務器專注于業務邏輯處理,兩者通過預定義的消息格式交換數據,實現了清晰的職責分離。
實戰:構建投資顧問機器人
接下來,我們將通過具體代碼解析,詳細講解如何實現一個基于MCP誘導流程的投資顧問機器人。這個機器人能夠通過多輪對話收集用戶的投資目標、時間線、風險承受能力和初始投資金額,最終生成結構化的投資建議。
項目初始化與依賴配置
首先需要安裝必要的依賴庫:
pip install fastapi uvicorn mcp fastmcp langchain-openai python-dotenv loguru項目結構設計遵循模塊化原則:
mcp-investment-bot/
├── client.py # MCP客戶端實現
├── mcp_server.py # MCP服務器實現
├── .env # 環境變量配置
└── requirements.txt # 項目依賴在.env文件中配置OpenAI API密鑰等敏感信息:
OPENAI_API_KEY=your_api_key_hereMCP客戶端實現詳解
客戶端代碼(client.py)的核心是WebSocket端點和誘導回調函數。讓我們逐步解析關鍵代碼片段:
WebSocket端點配置
@app.websocket("/investment-conversation")
async def investment_conversation(websocket: WebSocket):
async with streamablehttp_client(url=MCP_SERVER_URL) as (read_stream, write_stream, get_session_id):
async with ClientSession(
read_stream=read_stream,
write_stream=write_stream,
elicitation_callback=smart_elicitation_callback,
) as session:
await session.initialize()
try:
await websocket.accept()
session_id = get_session_id()
WEBSOCKET_MANAGER[session_id] = websocket
result = await session.call_tool(
name="elicit-investment-conversation",
arguments={"session_id": session_id},
)
await websocket.send_json(result.structuredContent)
except Exception as e:
logger.exception(e)
finally:
await websocket.close()這段代碼創建了一個WebSocket端點/investment-conversation,當用戶連接時:
- 與MCP服務器建立流通信(streamable HTTP)
- 初始化客戶端會話并注冊誘導回調函數
- 接受WebSocket連接并生成會話ID
- 調用服務器端的elicit-investment-conversation工具啟動誘導流程
- 接收最終結果并發送給用戶
誘導回調函數
回調函數是客戶端與服務器交互的關鍵橋梁:
async def smart_elicitation_callback(
context: RequestContext["ClientSession", Any],
params: types.ElicitRequestParams,
):
data = json.loads(params.message)
# 向用戶發送AI消息
await WEBSOCKET_MANAGER[data["session_id"]].send_json(
{"message": data["ai_message"], "step_name": data["step_name"]}
)
user_message = None
# 如果需要用戶輸入,則等待并接收響應
if data["retrieve_output"] is True:
user_message = await WEBSOCKET_MANAGER[data["session_id"]].receive_json()
user_message = user_message["message"]
# 將用戶輸入返回給服務器
return types.ElicitResult(
actinotallow="accept",
cnotallow={"user_message": user_message},
)回調函數的工作流程:
- 解析服務器發送的消息參數
- 通過WebSocket將AI生成的問題發送給對應會話的用戶
- 根據retrieve_output標志判斷是否需要等待用戶輸入
- 收集用戶響應并封裝成ElicitResult返回給服務器
這種設計確保了客戶端能夠靈活響應服務器的誘導請求,同時保持用戶交互的實時性和流暢性。
MCP服務器實現詳解
服務器代碼(mcp_server.py)包含了誘導流程的核心邏輯,包括步驟定義、AI交互鏈和工具實現。
誘導步驟定義
投資顧問機器人的誘導流程分為四個關鍵步驟:
STEPS = [
(
"purpose",
"Step 1, The user is defining their investment purpose. Ask them why they are investing — for example, retirement, wealth growth, education, or a major purchase. If a purpose is provided, confirm.",
),
(
"timeline",
"Step 2, The user is specifying their investment timeline. Ask how long they plan to keep the investment — short-term (1–3 years), medium-term (3–7 years), or long-term (7+ years). If a value is given, confirm and ask if they need liquidity before then.",
),
(
"risk_tolerance",
"Step 3, The user is describing their risk tolerance. Ask how comfortable they are with potential losses in exchange for potential returns. If a level (low, moderate, high) is provided, confirm and ask for past experience or examples.",
),
(
"investment_entry",
"Step 4, The user is entering how they plan to invest. Ask how much they plan to invest and whether it's a one-time or recurring investment. If they mention an amount or product (e.g., ETFs), confirm and ask about timing or strategy.",
),
]每個步驟包含兩個元素:步驟名稱(用于數據存儲)和步驟提示(指導AI生成問題)。這種結構化定義使得流程易于擴展和修改——只需調整步驟列表,即可改變對話邏輯。
AI代理鏈配置
為了讓AI能夠生成自然且符合流程的問題,我們使用LangChain構建了AI代理鏈:
async def retrieve_agent_chain():
llm = ChatOpenAI(model="o3-2025-04-16", streaming=False)
system_message = """
You are an intelligent and adaptive investment assistant designed to guide users through a step-by-step
process to define their investment profile. Your role is to gather input for the following stages:
purpose, timeline, risk tolerance, and investment entry.
...
Always respond in **this JSON structure**:
{
"ai_message": "string",
"investment_data": "string or null"
}
"""
prompt = ChatPromptTemplate.from_messages(
[
("system", system_message),
MessagesPlaceholder(variable_name="chat_history"),
("user", "{input}"),
]
)
output_parser = OutputFixingParser.from_llm(
parser=PydanticOutputParser(pydantic_object=InvestmentStepOutput),
llm=llm,
max_retries=3,
)
agent_chain = prompt | llm | output_parser
return agent_chain這個代理鏈的核心組件包括:
- 大語言模型:使用OpenAI的o3-2025-04-16模型生成自然語言
- 系統提示:定義AI的角色和行為規范,確保對話符合投資顧問的專業語境
- 輸出解析器:將AI響應解析為結構化的InvestmentStepOutput對象,包含ai_message(給用戶的問題)和investment_data(提取的結構化信息)
OutputFixingParser的使用確保了即使AI偶爾生成格式錯誤的響應,系統也能自動修正或重試,提高了流程的健壯性。
誘導工具實現
服務器通過工具(Tool)接口暴露誘導流程功能:
@mcp_server.tool(name="elicit-investment-conversation")
async def elicit_investment_conversation(
ctx: Context, session_id: str
) -> InvestmentOutput:
chat_history = []
investment_output = InvestmentOutput()
agent_chain = await retrieve_agent_chain()
for step_name, step_prompt in STEPS:
user_message = ""
step_output = None
retrieve_output = True
while step_output is None:
# 調用AI生成當前步驟的消息
ai_output = await agent_chain.ainvoke(
input={
"input": user_message,
"step_prompt": step_prompt,
"chat_history": chat_history,
}
)
# 檢查是否獲取到足夠信息
if ai_output.investment_data:
retrieve_output = False
step_output = ai_output.investment_data
# 向客戶端發送誘導請求
response = await ctx.elicit(
message=json.dumps({
"session_id": session_id,
"retrieve_output": retrieve_output,
"ai_message": ai_output.ai_message,
"step_name": step_name,
}),
schema=ElicitationResponse,
)
# 處理客戶端返回的響應
match response:
case AcceptedElicitation(data=data):
user_message = data.user_message
chat_history.append(("user", user_message))
case DeclinedElicitation():
break
case CancelledElicitation():
break
# 保存當前步驟的結果
setattr(investment_output, step_name, step_output)
return investment_output這個工具函數實現了核心的誘導邏輯:
- 初始化對話歷史和結果對象
- 遍歷預定義的誘導步驟
- 對每個步驟:
- 調用AI代理鏈生成問題
- 通過ctx.elicit()向客戶端發送誘導請求
- 等待并處理用戶響應
- 驗證是否獲取到足夠信息,否則重復當前步驟
- 收集所有步驟的結果并返回結構化數據
這種循環結構確保了每個步驟都能獲得足夠的用戶信息后再進入下一步,避免了因信息不足導致的建議質量問題。
MCP誘導流程的工作原理
理解MCP誘導流程的工作原理,需要跟蹤從用戶連接到最終結果生成的完整生命周期。
流程啟動階段
- 用戶通過WebSocket連接到客戶端的/investment-conversation端點
- 客戶端與MCP服務器建立流通信會話
- 客戶端調用服務器的elicit-investment-conversation工具,傳入會話ID
- 服務器初始化對話上下文,準備開始誘導流程
多輪交互階段
以“投資目標”步驟為例,交互流程如下:
- 服務器調用AI代理鏈,基于步驟提示生成問題(如“您投資的主要目的是什么?”)
- 服務器通過ctx.elicit()發送誘導請求,包含AI消息和會話信息
- 客戶端的smart_elicitation_callback被觸發,將AI消息通過WebSocket發送給用戶
- 用戶輸入響應(如“我在為退休儲蓄”)并發送給客戶端
- 客戶端將用戶響應封裝成ElicitResult返回給服務器
- 服務器解析響應,AI判斷信息是否足夠
- 若信息足夠,保存結果并進入下一步;否則重復當前步驟
這一過程在每個步驟中重復,直到所有必要信息收集完畢。
結果生成階段
- 服務器完成所有誘導步驟后,將收集的信息整理成InvestmentOutput對象
- 服務器將結果返回給客戶端
- 客戶端通過WebSocket將最終結果展示給用戶
- 客戶端和服務器關閉會話連接
整個流程中,MCP協議確保了服務器與客戶端之間的通信標準化,而FastAPI和FastMCP則提供了高效的實現框架,使得開發者可以專注于業務邏輯而非通信細節。
結構化輸出與應用擴展
MCP誘導流程的最終價值體現在其生成的結構化數據上。在我們的案例中,最終輸出定義為:
class InvestmentOutput(BaseModel):
purpose: Optional[str] = Field(default=None)
timeline: Optional[str] = Field(default=None)
risk_tolerance: Optional[str] = Field(default=None)
investment_entry: Optional[str] = Field(default=None)一個典型的輸出示例如下:
{
"purpose": "retirement",
"timeline": "20 years",
"risk_tolerance": "moderate",
"investment_entry": "$10,000 one-time"
}這種結構化數據可以直接用于后續處理:
- 傳入投資策略生成模型,獲取個性化建議
- 存儲到數據庫,用于用戶投資畫像分析
- 作為輸入參數,進行投資回報模擬計算
- 集成到財務規劃系統,生成完整的退休計劃
在實際應用中,你可以根據業務需求擴展輸出模型,例如增加“每月追加投資金額”“投資偏好行業”等字段,只需相應調整誘導步驟和AI提示即可。
進階優化與最佳實踐
要構建生產級別的MCP誘導系統,還需要考慮以下優化方向:
錯誤處理與重試機制
在網絡不穩定或用戶輸入異常的情況下,系統需要具備容錯能力??梢詳U展客戶端和服務器代碼,增加:
- 連接超時自動重連
- 用戶輸入驗證和錯誤提示
- AI生成內容的質量檢查
- 關鍵步驟的日志記錄和監控
會話管理與上下文持久化
對于復雜的誘導流程,可能需要支持會話中斷后恢復??梢酝ㄟ^以下方式實現:
- 將對話歷史存儲到數據庫
- 使用Redis等緩存服務保存會話狀態
- 實現會話ID與用戶身份的關聯
- 支持會話過期策略配置
用戶體驗優化
為提升用戶體驗,可以在客戶端實現:
- 步驟進度指示器
- 輸入驗證和即時反饋
- 對話歷史展示
- 響應等待狀態提示
- 深色/淺色模式適配
安全性增強
生產環境中需要加強安全措施:
- 對WebSocket通信進行加密(wss協議)
- 實現用戶身份認證和授權
- 對服務器接口進行速率限制
- 驗證客戶端請求的來源合法性
- 敏感數據加密存儲
code:https://github.com/fmelihh/mcp-elicitation-fastapi-investment-bot

































