一、背景
今年 MCP 的概念非常火,市面上也涌現出了一大批 MCP 相關工具。作為技術一線者,都會按捺不住地去實操一下,很早的時候就有個設想,如果把我們的測試工具都改造為符合 MCP 服務協議標準,然後全部接入 AI Agent,打造一個集萬千工具於一體的智能管家來幫助我們提效,是不是一個很完美的設想。很多宏偉或者天馬行空的想法想要真正的落地,必然需要不斷向下,拆解成可落地的任務模塊,這裏我們先從造數開始。
二、AI 造數設想
在實際業務需求測試中,我們依賴的測試數據需要很多前置的數據要求,這時候會涉及到分步使用不同的造數腳本。比如團長拉新做任務,需要一個 30 天內沒發過動態的賬號,加入團隊,發一篇動態,動態過一審,過二審,閲讀數滿足 300 個。
為了完成這個場景的造數,我們需要去造數工廠、接口自動化、腳本代碼等平台找對應的造數工具,分別去執行才能完成這一系列的操作。可以從下圖中看到,總計需要 6 個步驟才能完成。如果不是熟悉所有的業務,哪怕有現成的造數腳本,組合起來使用還是有一定的門檻。
那麼在 AI 風行的年代,我們想要實現的是:按照用户輸入的測試數據要求,能夠按照已有造數能力自動編排,生成對應的測試數據給用户使用。
最終實現效果案例:我需要一個團長拉新的測試數據,要求是 30 天內沒有發過動態,進入團隊 A,然後發佈一條動態,需要過一審風控審核,二審標註,最後需要獲得 300 個閲讀數。
AI 造數自動去造數池子中尋找對應的造數接口,按照提問的順序要求來依次執行造數,最後返回給用户對應的測試賬號。
這裏不再重複介紹 MCP 的概念,我們參考官方給出的 client-server 通用架構圖來畫一個 AI 造數的架構圖,便於理解在落地到 AI 造數的場景,我們可以做哪些事。本篇文章主要就講解了圖中的其中一環,落地社區造數服務的 MCP 接入。
三、社區造數服務 tools
框架介紹
社區的造數服務技術棧是基於 FastAPI 框架實現的,通過 uv工具來管理依賴庫、虛擬環境等,這個工具親測的確比傳統的 pip 或者 poetry 等工具更好用。從安裝 uv到啓動項目,只要 4 步就能無痛搞定環境,不用擔心本地其他環境的干擾。
## uv命令1. 安裝uv : `curl -LsSf https://astral.sh/uv/install.sh | sh`2. 創建環境 - 自定義環境名稱和Python版本 `uv venv tools_venv --python 3.12`3. 激活環境 `source tools_venv/bin/activate`4. 安裝依賴包 `uv pip install -r pyproject.toml`
## 本地啓動項目直接運行main.py文件中的main方法即可,debug模式自己pycharm中設置if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
中間件相關配置全部通過 ARK 來管理,項目結構如下:
## 項目結構
```bash
├── main.py # 啓動 APP 入口文件
├── README.md # 開發手冊
├── Dockerfile # Docker 鏡像文件
├── alembic # alembic 遷移 DB 自動生成的相關文件
│ ├── README
│ ├── .env.py
│ ├── script.py.mako
│ └── versions # 存放每次遷移的版本,可用於回滾 DB 版本
├── alembic.ini # alembic 配置文件
├── app
│ ├── __init__.py # 註冊 app
│ ├── api # api 開發目錄
│ ├── core # app 的全局配置
│ ├── crud # 每個 table 的增刪改查操作
│ ├── db # db 配置
│ ├── models # 存放表結構
│ ├── schemas # pydantic 模型
│ └── utils # 工具類
├── .pre-commit-config.yaml # 配置 git commit 時自動檢測工具└── pyproject.toml # 依賴庫管理```
統一部署到公司的發佈平台,通過 http://{造數服務域名}/tools/docs#/ ,地址可以訪問目前社區所有的造數接口。同時也對接了造數工廠,可以直接去造數工廠使用。
改造思路
老方案-基於 MCP Python SDK
早在出現 MCP 這個概念的時候,我就想過有天把我們的造數服務通過 MCP 工具暴露出來,這樣就可以非常方便的集成各種 Agent,打造 AI 造數。在出現這個 FastAPI-MCP 框架之前,想要把造數服務改造成支持 MCP ,就需要通過引入 MCP 依賴庫來實現。但這個方案對於已有的造數服務來説改造成本有些高,可以看老方案的案例。
從官方文檔面向服務器開發者 - MCP 中文文檔中可以找到有對應的 MCP Python SDK,主要就是安裝 MCP 這個依賴庫。這裏舉一個簡單的 demo,通過手機號查詢用户信息的方法。可以很清晰的看出來這個 SDK 的語法結構是需要 @mcp.tool() 這個裝飾器來修飾,那麼原有的造數服務暴露出來的所有接口方法是否都需要改造,這仍有一定的成本(未考慮其他複雜場景情況下)。
# server.pyfrom mcp.server.fastmcp import FastMCPfrom tools.tools_set import get_user_infoimport uvicorn# Create an MCP servermcp = FastMCP("Demo")
@mcp.tool()async def get_user_info_tool(mobile: str) -> Coroutine[Any, Any, Any]: """根據輸入的手機號獲取用户信息 Args: mobile: 手機號 """ info = get_user_info(mobile) return info
if __name__ == "__main__": """Initialize and run the server""" # mcp.run(transport="sse") """Start the FastAPI server with uvicorn""" uvicorn.run(app, host="0.0.0.0", port=8003)
基於上述代碼 demo,我們通過 uvicorn 啓動服務,當然也可以單獨啓動 MCP 服務。控制枱輸出如下,代表啓動成功,接下來我們就可以使用 MCP 客户端工具進行連接使用了,這裏使用 Cursor來做演示。
看圖標顯示綠色,無報錯説明連接成功,這裏也能看到 demo 中的 get_user_info_tool 方法作為 MCP 工具暴露了出來。演示到這裏,説明了該方案是可行的。因為本文重點講解採用的新方案,此處就不再多介紹,感興趣的可以去看官方文檔。
四、FastAPI-MCP
安裝運行
“Expose your FastAPI endpoints as Model Context Protocol (MCP) tools, with Auth! ”
這是引用官網介紹的第一句話,翻譯過來大概的意思就是:把你的 FastAPI 服務作為 MCP 工具暴露出來成為現實!
-
安裝 FastAPI-MCP 庫
uv add fastapi-mcporuv pip install fastapi-mcp - 使用 FastAPI-MCP,只需要 3 行代碼就能把 FastAPI 框架改造成一個 MCP 服務
- 通過 uvicorn 啓動服務器,使用http://localhost:8000/mcp 來訪問 MCP server
from fastapi import FastAPIimport uvicornfrom fastapi_mcp import FastApiMCP
# Create (or import) a FastAPI appapp = FastAPI()
# Create an MCP server based on this appmcp = FastApiMCP(app)
# Mount the MCP server directly to your appmcp.mount()
if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)
用法介紹
自定義配置
通過看源碼 FastApi-MCP 類,基本能清晰的看出來各個參數的用處,這裏將介紹幾個常用的。
class FastApiMCP: """ Create an MCP server from a FastAPI app. """ def __init__( self, fastapi: Annotated[ FastAPI, Doc("The FastAPI application to create an MCP server from"), ], name: Annotated[ Optional[str], Doc("Name for the MCP server (defaults to app.title)"), ] = None, description: Annotated[ Optional[str], Doc("Description for the MCP server (defaults to app.description)"), ] = None, describe_all_responses: Annotated[ bool, Doc("Whether to include all possible response schemas in tool descriptions"), ] = False, describe_full_response_schema: Annotated[ bool, Doc("Whether to include full json schema for responses in tool descriptions"), ] = False, http_client: Annotated[ Optional[httpx.AsyncClient], Doc( """ Optional custom HTTP client to use for API calls to the FastAPI app. Has to be an instance of `httpx.AsyncClient`. """ ), ] = None, include_operations: Annotated[ Optional[List[str]], Doc("List of operation IDs to include as MCP tools. Cannot be used with exclude_operations."), ] = None, exclude_operations: Annotated[ Optional[List[str]], Doc("List of operation IDs to exclude from MCP tools. Cannot be used with include_operations."), ] = None, include_tags: Annotated[ Optional[List[str]], Doc("List of tags to include as MCP tools. Cannot be used with exclude_tags."), ] = None, exclude_tags: Annotated[ Optional[List[str]], Doc("List of tags to exclude from MCP tools. Cannot be used with include_tags."), ] = None, auth_config: Annotated[ Optional[AuthConfig], Doc("Configuration for MCP authentication"), ] = None, ): ...
※ Server metadata
- name:MCP 服務名
- description:對 MCP 服務的描述
※ Tool and schema descriptions
創建 MCP 服務器時,可以通過修改 describe_all_responses ,把所有可能的響應模式包含在工具描述中,或通過更改 describe_full_response_schema 把完整的 json 包含在工具描述中。
from fastapi import FastAPIfrom fastapi_mcp import FastApiMCP
app = FastAPI()
mcp = FastApiMCP( app, name="My API MCP", description="Very cool MCP server", describe_all_responses=True, describe_full_response_schema=True)
mcp.mount()
※ Customizing Exposed Endpoints
- include_operations , 暴露 operation_id=XXX 的接口
- exclude_operations , 排除 operation_id=XXX 的接口
- include_tags , 暴露 tags=XXX 的接口
- exclude_tags ,排除 tags=XXX 的接口
組合使用:
- include_operations 和 exclude_operations 不能同時使用
- include_tags 和 exclude_tags 不能同時使用
- include_operations 和 include_tags 可以組合使用,匹配任一個條件就滿足
from fastapi import FastAPIfrom fastapi_mcp import FastApiMCP
app = FastAPI()
# 案例1:include_operationsmcp = FastApiMCP( app, include_operations=["get_user", "create_user"])
# 案例2:exclude_operationsmcp = FastApiMCP( app, exclude_operations=["delete_user"])
# 案例3:include_tagsmcp = FastApiMCP( app, include_tags=["users", "public"])
#案例4:exclude_tagsmcp = FastApiMCP( app, exclude_tags=["admin", "internal"])
# 案例5:Combinedmcp = FastApiMCP( app, include_operations=["user_login"], include_tags=["public"])
mcp.mount()
工具命名
FastAPI 中的路由通過 operation_id 參數來作 MCP 工具名稱,如果沒有顯示命名,框架會自動生成一個。此處經測試,如果不顯示命名,自動生成的名字不僅會很奇怪,還會影響 AI 造數的準確性,所以這裏最好作好規範,必須要顯示命名。
# Auto-generated operation_id (something like "read_user_users__user_id__get")@app.get("/users/{user_id}")async def read_user(user_id: int): return {"user_id": user_id}
# Explicit operation_id (tool will be named "get_user_info")@app.get("/users/{user_id}", operation_id="get_user_info")async def read_user(user_id: int): return {"user_id": user_id}
五、接入造數服務
框架升級及改造
在接入的時候,要查一下官方文檔要求的 Python,FastAPI 等版本,先進行框架升級,防止出現不兼容的問題。這項通過管理工具安裝依賴庫時能自動校驗,其他一些兼容問題在啓動服務後根據實際場景一一去解決即可。這裏推薦使用 uv 工具進行管理,親測比之前的 poetry 更好用。
列幾個核心庫的版本,都是驗證過沒有兼容問題的。在過程中也是遇到一些兼容問題花了點時間,因為 FastAPI-MCP 框架比較新,網上資料還不全,遇到沒法解決的問題大家可以去項目 issue 中找,提升解決問題效率。
python = "^3.12"fastapi = "0.115.12"fastapi-mcp ="0.3.1"mcp="1.7.0"pydantic = "^2.11.0"pydantic-settings = "^2.2.0"
步驟
第一步: 引入 fastapi-mcp
第二步: main.py 中添加 MCP 服務
第三步: 也是工作量最大的一步,將每個造數接口都做顯示命名,並且做好文檔註釋,寫的越清楚 AI 造數的準確率越高,需要對應編寫造數場景測試,共同完成
最後一步: 啓動服務 uvicorn.run('main:app', host='0.0.0.0', port=8023, reload=True, workers=2) ,無報錯基本就沒有問題了。再通過 MCP 客户端工具連接使用即可
接入 Cursor
改造完之後的造數服務成功對外暴露了 MCP 服務,現在我們可以通過 MCP 客户端去連接使用了,這裏選用了 Cursor,因為 Cursor 使用的人比較多,同時集成了市面上的主流大模型。
步驟
第一步: 創建一個 mcp.json,按照標準 json 配置即可
{ "mcpServers": { "fastapi-mcp": { "url": "http://localhost:8022/mcp", "description": "本地開發環境MCP服務配置" }, "tools-mcp": { "url": "http://localhost:8011/mcp", "description": "本地開發環境MCP服務配置" }, "demo-mcp": { "url": "http://localhost:8001/sse", "description": "本地開發環境MCP服務配置" }, "tools-mcp-prod": { "url": "http://XXXXXX/mcp", "description": "線上" }}}
第二步:點擊右上角設置 icon,進入 Cursor Settings,選擇 MCP
第三步: 這裏可以看到,在剛才 mcp.json 中配置的 MCP工具均加載過來,打開開關,運行狀態顯示為綠色,無報錯並説明了服務接入正常,接下來就可以正常使用 Cursor 中的 Agent 進行對話了
實操演練
我們現在只希望使用造數能力,因此我們可以指定剛才配置的 MCP 工具。
場景化案例
需求:給手機號為 11120210001 的用户發佈一個點評動態,並且通過風控一審。
這裏注意一下提問方式,因為我們沒有對大模型進行特別的訓練,AI 不一定知道 111 開頭的是我們測試使用的虛擬手機號,有可能會誤解為 userId,所以我們需要告訴 AI 這是一個手機號。
可以看到在這個 demo 中, Agent 自動幫我們分了三步去調用對應的 MCP tool,第一步通過我們輸入的手機號去獲取 userId,第二步通過 userId 去發佈點評動態,第三步通過點評動態 id 去通過風控一審。原本需要三步完成的造數場景,現在通過一句話描述就完成了。
調優案例
需求:隨機創建 10 個測試賬號
※ 調優之前
造數代碼,主要看文檔註釋內容。
@router.post('/create-account', operation_id="create_account",summary="創建測試賬號")async def c_create_account( env: str = Body(..., description='環境'), phonenumber: str = Body(..., description='手機號'), pwd: str = Body(..., description='密碼'), usernum: str = Body(None, description='數量'),) -> Any: """ 創建測試賬號,默認111開頭 args env: 環境,默認:t1 phonenumber: 手機號 pwd: 密碼,默認:test123 usernum: 數量 """
把這個造數需求發送給 AI,發現報錯了。我們去代碼中看下為何返回了 false,原來是因為接口返回非 200,排查下來是因為 t1 環境測試賬號造數默認填了 111,不需要再加 111,所以接口直接 500 了。
這裏 AI 犯了兩個錯誤:
- 因為默認手機號都是 11 位的,這裏 AI 不知道只需要傳 8 位就行。
- 我沒有輸入具體的手機號,所以按照代碼邏輯應該是支持自動隨機生成的,但是 AI 也不知道這個邏輯,“自作主張”給我傳入了一個手機號。
※ 調優後
通過排查我們已經明確知道 AI 犯了哪些錯誤,那麼我們針對這些錯誤去調優即可。所謂的調優主要就是修改文檔註釋,可以前後對比下注釋內容。
"""創建測試賬號,默認111開頭,不用填寫111,只需要後面8位不傳手機號phonenumber,默認隨機生成手機號
args env: 環境,默認:t1 phonenumber: 手機號,非必填,不填自動生成 pwd: 密碼,默認:test123 usernum: 數量"""
※ 最終效果
通過這個案例可以看到,準確率依賴我們對造數接口的文檔註釋,所以在實際使用過程中,前期需要我們不斷地去調優,才能達到我們想要的效果。
當然隨着後續迭代,可能可以用更優雅的方式完成這個工作,比如再引入靜態代碼分析工具,通過 AI 編程自動完成註釋。
六、總結
技術實踐成果
通過將社區造數服務改造成符合 MCP(Model Context Protocol) 標準的工具,我們成功實現了以下目標:
AI 驅動的測試數據自動化
用户通過自然語言描述需求,AI Agent 可自動編排造數接口生成複雜測試數據,將原本需手動執行 3 步的操作簡化為一步指令。
低成本框架升級
基於 fastapi-mcp 框架,僅需少量代碼改造即可將 FastAPI 服務快速接入 MCP 協議,解決了傳統 SDK 方案的高適配成本問題。
工具鏈整合
通過對接 Cursor 等 AI 工具平台,驗證了 MCP 協議在跨平台協作中的可行性,為後續構建“社區智能管家”奠定技術基礎。
核心實踐經驗
註釋即規範
AI 調用接口的準確性高度依賴代碼註釋的清晰度。通過優化接口文檔(如參數默認值、輸入格式説明),可顯著提升 Agent 的任務解析成功率。
漸進式調優
初期需通過人工干預優化 Agent 的接口調用邏輯,未來可引入代碼靜態分析工具自動生成標準化註釋。
未來優化方向
動態編排增強
當前接口調用為線性執行,後續可探索基於依賴關係的動態編排(如並行執行獨立步驟、自動重試失敗操作)。
多 Agent 協作
結合領域知識庫與測試斷言工具,實現從“造數”到“驗證”的全鏈路 AI 自治。
協議擴展性
探索 MCP 與更多協議(如 OpenAPI)的互操作性,提升工具服務的跨平台複用能力。
價值與啓示
本次實踐印證了 “AI+協議化工具” 在測試領域的巨大潛力:降低技術門檻 (非技術人員可直接描述需求)、提升執行效率 (分鐘級操作秒級完成)、釋放創新空間 (複雜場景的自動化長鏈路測試)。
隨着 MCP 生態的完善,測試工程將逐步從“工具堆砌”走向“智能協作”,為研發效能帶來質的突破。
七、感想
“我不是英雄,只是一個拿錘子的約德爾人”
站在巨人的肩膀上總是能看的更高更遠,追隨技術大牛們的步伐,把 AI 應用到工作中、生活中。回想九年前初入測試行業時捧讀的《Google 軟件測試之道》,書中“人類智慧的最後一英尺”已然越來越近。重讀了 2022 年在公司內部博客發表的《Google 軟件測試之道:結合實踐的總結》一文,發現僅僅過了3 年,如果現在再去寫,又是完全不一樣的想法了,技術的發展已發生翻天覆地的變化。
此刻回望測試領域的演進曲線,愈發感到:「拿錘者」的價值不在於揮舞工具的姿態,而在於持續校準認知座標的能力 。當 AI 重構測試鏈路的每個環節時,唯以「錘者」的務實與「巨人」的視野雙軌並行,方能在技術洪流中錨定價值支點。
加油吧!不忘初心,你我終將能抵達一個又一個“終點”!
往期回顧
1.CSS闖關指南:從手寫地獄到“類”積木之旅|得物技術
2.從零實現模塊級代碼影響面分析方案|得物技術
3.以細節詮釋專業,用成長定義價值——對話@孟同學 |得物技術
4.得物可觀測平台架構升級:基於GreptimeDB的全新監控體系實踐
5.得物自研DGraph4.0推薦核心引擎升級之路
文 / 阿凱
關注得物技術,每週更新技術乾貨
要是覺得文章對你有幫助的話,歡迎評論轉發點贊~
未經得物技術許可嚴禁轉載,否則依法追究法律責任。