
阿里妹導讀
可觀測近年來已經成為一個關鍵概念,它不僅僅侷限於監控,還包括了日誌記錄、指標收集、分散式追蹤等技術手段,旨在幫助團隊更好地理解系統執行狀況、快速定位問題以及最佳化效能。可觀測2.0融合 MCP,可以讓使用者更好地感知系統、分析問題——用自然語言開啟與系統的對話!本文將分享6個設計 MCP Server 的親身實踐,幫助大家更好地融合與使用。
一、MCP 簡述
MCP 是一種開放協議,用於標準化應用程式如何向 LLM 提供上下文。可以將 MCP 視為 AI 應用程式的 USB-C 埠,就像 USB-C 提供了一種將裝置連線到各種外圍裝置和配件的標準化方式一樣,MCP 提供了一種將 AI 模型連線到不同資料來源和工具的標準化方式。

-
MCP 主機 (MCP Hosts):例如 Claude Desktop、IDE 或希望透過 MCP 訪問資料的 AI 工具等程式;
-
MCP 客戶端 (MCP Clients):與伺服器保持 1:1 連線的協議客戶端;
-
MCP 伺服器 (MCP Servers):輕量級程式,每個程式透過標準化的模型上下文協議 (MCP) 公開特定的功能;
-
本地資料來源 (Local Data Sources):您的計算機的檔案、資料庫和 MCP 伺服器可以安全訪問的服務;
-
遠端服務 (Remote Services):可透過網際網路訪問的外部系統(例如,透過 API),MCP 伺服器可以連線到這些系統;
1.1 快速開始
把MCP框架理解為“大模型外掛”,並且你也可以很方便地編寫自己的“外掛”功能。
-
[必須] 首先你需要一個支援 MCP 的 Client,參考下一章節。在本文中,使用的是 Cherry Studio [1]和DeepChat Client [2]。
-
[必須] 需要準備LLM API,並準備好 API – Key。在本文中,使用的是阿里雲百鍊[3]。如果沒有API – Key,也可以使用本地化大模型(ollama)本地化相關功能。

-
[可選] 按需新增 MCP Server,參考下兩章節。
-
[可選] 編寫屬於自己的 MCP Server。在 https://github.com/modelcontextprotocol倉庫下,選擇您期望的 SDK。新增自定義功能的 Tools,就可以啟動 Server 供大模型呼叫了。
配置如下:


1.2 Awesome MCP Clients 推薦
完整列表參考:https://github.com/punkpeye/awesome-mcp-clients
對比參考:https://modelcontextprotocol.io/clients
筆者推薦:
1.Cherry Studio
2.DeepChat
3.AIaW
4.Cursor
5.Continue
1.3.Awesome MCP Servers 推薦
完整列表參考:
https://github.com/punkpeye/awesome-mcp-servers
文件例項列表:
https://modelcontextprotocol.io/examples
官方列表:
https://github.com/modelcontextprotocol/servers
按需新增即可。
二、MCP Server for 阿里雲可觀測2.0
2.1 可觀測2.0
過去一年,我們邁向了通用可觀測之路。從“監控”到“可觀測”,不僅是技術升級,更是對複雜系統認知的深化。透過因果推理的三個層級(關聯、干預、反事實),可觀測效能夠實現從被動觀測到主動預測的能力提升。企業數字化需要將黑盒系統轉化為白盒,透過採集、儲存和分析多模態資料(如Log、Trace、Metric等),最佳化運營效率。
隨著分散式系統和技術棧的複雜化,可觀測性成為確保系統穩定性和效能的關鍵。然而,許多企業面臨可觀測資料混亂的問題,如缺乏標準化、資料儲存分散、分析效率低及知識難以沉澱。為解決這些問題,我們提出了UModel——可觀測資料之魂,一種通用的可觀測“互動語言”。

UModel 基於本體論思想,透過 Set 和 Link 組成的圖模型描述IT世界,定義了EntitySet、LogSet、MetricSet 等核心型別,以及 EntitySetLink、DataLink 等關聯關係。它支援靈活擴充套件,引入 CommonSchema 降低使用門檻,並提供 Explorer、告警與事件集等功能提升易用性。UModel 不僅實現了資料的標準化和統一建模,還支援演算法和大模型對資料的高效利用,助力構建全新的“可觀測2.0”體系。
2.2 融合 MCP 能力

在可觀測2.0中融合 MCP 能力,是一種很合適的嘗試,一定程度上可以透過對話的方式,讓使用者對可觀測2.0整體使用方式有更好的感知,並且可以協助使用者感知系統、分析問題——只用自然語言交流。
2.3 效果展示
2.3.1 服務全鏈路分析
注:此案例部分介面使用虛擬資料。
特性如下:
-
根據某服務,檢索服務上下游、依賴的中介軟體和基礎設施
-
分析某服務的指標情況
-
查詢某服務是否存在錯誤請求trace id,並進一步智慧分析
2.3.2 可觀測基礎資訊能力查詢
特性如下:
查詢可觀測2.0中多類資訊:
-
獲取可用區
-
查詢workspace
-
查詢entity 和 topo能力
-
查詢 Umodel Schema 並生成圖片展示
三、設計好 MCP Server 的親身實踐(血淚踩坑)
3.1 經驗一:Tools 介面精簡化、原子化
寫在前面:MCP Server ≠ SDK API,是和人打交道的介面。
這裡的“和人打交道”,是全方面的,無論是介面的理解,引數,還是返回,都要求簡潔易懂。“三歲小孩都能懂”的 MCP Server Tools 才是好 Tools。
舉個例子🌰:
SLS 的 getLogs SDK API 是這樣的
def get_logs(
ak: str,
sk: str,
region_id: str,
project: str,
logstore:str,
query: str,
from_timestamp: int,
to_timestamp: int,
topic: str,
line: int,
offset: int,
reverse: boolean,
powerSql: boolean
) -> list[Any]:
這個介面如果直接給到大模型作為 Tools,可以說呼叫的成功率為0,因為這是一個非常複雜的介面:
1.主要的瓶頸在 query 怎麼寫,語法是怎樣的,對模型挑戰非常大。這種場景適合 A2A(Agent協作),生成可靠的 SLS query 作為一個 Agent,此處不過多展開。
2.假設我們解決了query的問題,API中的很多基礎資訊需要多輪對話獲得:aksk、region、project、logstore,實際使用上這種環境變數級別的引數重複性非常高。
3.引數中帶了時間視窗,這一點需要謹慎,詳情見經驗二。
4.引數中帶了 topic、line、offset、reverse、powerSql 這種不常用引數,使用預設值能搞定大部分請求的引數就不帶。
對於這些問題,在整體的實踐後,認為在阿里雲上,使用 MCP Server 和使用者互動的架構,可能需要做一些改變。
樸素想法:

真正適用的:

首先,這裡的 MCP Server 的生命週期應該是在使用者進入到 Workspace 後,才建立。阿里雲提供給使用者的 MCP 互動 Client + MCP Server 是非常輕量的,一個使用者、一次 Workspace 訪問就是一次生命週期。而此時 MCP Server 是帶上 aksk、Workspace name、region id 等環境變數資訊的,裡面的各種 Tools 無需關心這種基礎的引數了。
然後,隨著使用者業務的範圍,可以建立若干對應模組的 Tools 以供使用者按需呼叫。
最後,需要把常用的操作封裝 MCP Tools,而不是給出一個萬能的 “query” 介面。

因此,給出的 getLogs,最佳化過後的 MCP Server Tools 版本應該是這樣的:
A2A 模式:
defget_log_tool(
query: str,
from_timestamp: int = Field(
int(datetime.now().timestamp()) - 3600, description="from timestamp,unit is second"
),
to_timestamp: int = Field(
int(datetime.now().timestamp()), description="to timestamp,unit is second"
)
) -> list[Any]:
defgen_sls_query(
text: str,
) -> str:
功能模組化模式(僅示例):
# 獲取logstore的index資訊
defget_index():
pass
# 獲得fields欄位聚合的統計資訊
defget_fields_desc(
filter: str,
fields: List[str],
from_timestamp: int = Field(
int(datetime.now().timestamp()) - 3600, description="from timestamp,unit is second"
),
to_timestamp: int = Field(
int(datetime.now().timestamp()), description="to timestamp,unit is second"
)
) -> list[Any]:
# * and upstream_status >= 400 | SELECT request_uri, upstream_status, COUNT (*) AS cnt
# FROM log
# GROUP BY request_uri, upstream_status
# ORDER BY cnt DESC
# LIMIT 10
# 統計UV
defget_uv(
filter: str,
field: str
from_timestamp: int = Field(
int(datetime.now().timestamp()) - 3600, description="from timestamp,unit is second"
),
to_timestamp: int = Field(
int(datetime.now().timestamp()), description="to timestamp,unit is second"
)
) -> list[Any]:
# * | SELECT COUNT(DISTINCT client_ip) AS unique_visitors FROM log
這裡不需要 ak、sk、project、logstore 資訊的原因是,這裡的 MCP 應該是在 logstore 開啟的時候啟動的,因此已經知道基礎環境資訊了。
這樣的功能模組劃分僅為示例,僅作說明。
3.2 經驗二:Tools 介面引數預設化。慎用時間引數
案例:一個查詢 SQL Query的Tools,介面是這樣的:
defo11y_list_entities(
ctx: Context,
query: str = Field(default=None, description="query"),
from_timestamp: int = Field(
..., description="from timestamp,unit is second"
),
to_timestamp: int = Field(
..., description="to timestamp,unit is second"
)
) -> list[str]:
為了方便大模型使用,特意增加了一個 tool 用於呼叫時間相關的引數:

想法很好,現實很骨感,實際使用中,經常出現傳入並不合法的 from to 的情況:

導致介面直接報錯,因為傳入不合法的引數,這種場景甚至必須重啟 client 和Server。

有時也會傳入離譜的時間引數,導致後續的回答並不理想:

時間戳這裡提供的是 2023-06-25 00:00:00。大模型對“現在的時間”概念模糊。提供的示例對於一個只儲存30天的 LogStore 來說仍然查不出資料。
更好的方式:
defo11y_list_entities(
ctx: Context,
query: str = Field(default=None, description="query"),
from_timestamp: int = Field(
int(datetime.now().timestamp()) - 3600, description="from timestamp,unit is second"
),
to_timestamp: int = Field(
int(datetime.now().timestamp()), description="to timestamp,unit is second"
),
) -> list[str]:
直接給出最近1小時的預設值,極大機率都可以覆蓋期望的查詢,只需考慮 query 的傳入,不用糾結時間的細節設定。如果返回為空,模型會考慮是否是時間問題,並反饋。

3.3 經驗三:精簡輸出,避免過長的上下文輸出
一些不好的例子:查詢 workspace 的 list(返回500個workspace),查詢某個 workspace 下接入的 entity 型別(返回200個)
MCP Server 和 SDK API 的功能不能完全等價看待,MCP 本質上是給人作為終端顯示的,因此人眼看不過來(體感:大於20個的數量)都是意義不大的內容。每個介面的輸出都應該控制 limit。可以考慮透過加入篩選檢索,或者直接截斷輸出到10個。
除了體感之外,過長的 json response 會嚴重卡慢後續模型的輸出速度、影響上下文理解效果。
以上是一般 json 介面的經驗。在實踐中,我們還會遇到這類場景:希望 Tools 返回一幅圖(以 svg 或 png 的形式)。嘗試了幾種方案:
-
直接返回<svg></svg> 的 data xml:client 不會正常顯示。且會因為返回資料較大而卡慢速度。
-
使用 MCP SDK 的 Image 類,返回
"url": f"data:image/png;base64,{tool_result.data}"
:多數 client 不會正常顯示,且需要模型是多模態模型。 -
使用圖片輔助服務,直接返回 markdown 的 url 格式:效果較好。
Args:
ctx: MCP上下文,用於訪問可觀測客戶端
workspace_name: Workspace 名稱,必須完全匹配Workspace
Returns:

Schema 的 markdown 內容,直接作為你的輸出列印並展示

效果:

3.4 經驗四:避免 Tools 和 Tools 輸入輸出的鏈式傳遞
好的實踐:Tool 原子能力,一個 Tool 做獨立一件事。
不好的實踐:Tool1 -> output -> Tool2 input -> output -> Tool3
實踐中鏈式傳遞也可以做到,但有一定機率傳入的引數不符合預期,且不好控制。
有一些還不錯的自我修復能力是,當大模型發現引數報錯的時候,會呼叫依賴的上一個 Tools 驗證一下引數正確性。這種情況有一定機率修復,但並非完全可以。有時會執拗地認為自己沒錯:

在同一次問題中,通常鏈式傳遞表現尚可。如果是在同一會話中第二次詢問,並不會獲得第一次詢問呼叫的介面的每一個資訊,或者判斷錯誤。
-
實踐場景一:
Tool1:查詢 service 的關聯上下游,返回
[
{
"id": "[email protected]:dc7495605d8395b3788f9b54defcb826",
"type": "upstream",
"name": "gateway",
},
{
"id": "[email protected]:97cd7e28783143028d7e8e9c8dbce99c",
"type": "downstream",
"name": "checkout",
},
]
然後其他一些分析……省略
對話上下文中,第二次詢問,請幫我查詢 checkout 服務的資訊。
模型會直接把checkout直接傳入 Tool2(引數只有一個 id,並在 Prompt 註釋中說明很詳細)
第二次對話必須複製
[email protected]:97cd7e28783143028d7e8e9c8dbce99c完整,才會正確傳遞引數。
-
實踐場景二:
有一個 Tool 返回 trace ids,返回了一個列表:
[
"93b9111f425a4b6cab6548aa68d18f04",
"e165fede431c4c178d1e7e399c92b70d",
"ce7d4e9f74634252969adfd62b509fd6",
"e824356ddf4f42d884abe7c6a2d55d66",
]
每一個值是 trace id。
期望的是模型使用每一個 trace id 呼叫分析的介面,但是模型會自己傳錯。

3.5 經驗五:在介面實現開工之前,首先以模擬資料作為嘗試
模型使用介面的方式,可能和預期不一樣。介面的設計可能需要大量改動,才能讓模型按照你想要的方式運作,尤其涉及 Tools 鏈式呼叫的時候,更要謹慎。
在設計 MCP 介面的時候,首先定義 Tools 介面資訊,然後編寫 Tools 的註釋說明(引導 Prompt),接著按照預期實現的返回資料,mock 一些假資料直接返回。在互動的過程中不斷調整介面資訊、註釋資訊,直到假資料可以按照預期正常工作,最後再開始介面的開發,否則如果先實現介面,返工率極高,十分心痛。
3.6 經驗六:有時模型會“盲目自信”、“假裝工作”。適當調低 temperature
這個 case 裡面,trace id 傳錯是第一個問題,之前(經驗四)已經講過。

在之後,又遇到了時間的坑。(經驗二)

在發生錯誤之後,模型並不會提示問題,而是結合一些正確的介面輸入輸出資料,自己悄悄生成假模假樣的資料……像不像論文裡瞎編資料的無良大學生[狗頭]。

這裡上下游的資料也是假的,從 id 也能看出來。

這個問題調低 tempreture 可以緩解,但是並非可以完全解決,MCP 本質上還是依賴生成模型,而生成模型是否適合一些嚴肅嚴格場景的介面,這裡稍稍打一個問號。
除此之外,觀察到如果在同一對話上下文中多次問類似實體,但id不同的實體,模型似乎並不會真正呼叫介面了,而是直接生成 tools 的輸入引數,建議使用者去調(誰是老闆??)。
還有一種場景是受上下文影響過大,會參考上次的輸出,然後新實體的關聯、上下游也和上次呼叫的實體關聯、上下游一樣(糊弄我是吧??)
四、總結
MCP 是標準化 LLM 上下文互動的開放協議,包含主機、客戶端、伺服器及資料來源元件,支援連線本地/遠端服務。使用者需配置支援 MCP 的客戶端(如Cherry Studio)和 LLM API(如阿里雲百鍊),並可擴充套件官方/自定義 MCP 伺服器。阿里雲可觀測2.0透過 UModel 統一多模態資料互動,解決系統複雜性帶來的觀測難題,實現從被動監控到主動預測的升級。
4.1 MCP Server 設計注意事項和思考
MCP 作為人、LLM、業務場景融合的媒介和工具,是新一代互動工具的萌芽,但仍然存在很多設計場景上的注意點。

如果判斷下來都是“是”,則非常適合 MCP 場景。
一些不適合的場景,透過某種轉化,可以變成適合的場景。比如股票交易系統不提供交易介面,只提供股票程式碼查詢的能力,規避安全性問題。提供股票查詢後,規避返回股票資訊具體細節,而引導模型輸出報告,模型會輸出對這支股票的看多看空思路和依據,提升寬容性。
同時也可以發現,MCP 天生適合理解業務短平快的需求場景,如果想解決一個非常複雜的任務,MCP 介面可能還不夠,需要 A2A + 更高階的協作、超長上下文的理解。
4.2 一些優秀的 MCP 應用場景
1.bing 搜尋、Github搜尋、網盤搜尋等各類搜尋引擎 MCP
理由:獨立、簡潔(返回 Top5 相關)、寬容(一定程度上)、魯棒、安全。
2.高德地圖 MCP 生成旅遊路線
理由:獨立、寬容(每次不同甚至有新鮮感)、魯棒(有高德地圖穩定的系統為支援)、安全。
3.Web 瀏覽器自動化,相關爬取、統計、分析
理由:獨立、簡潔(輸出約束一下)、寬容、魯棒。
4.FileSystem
理由:獨立、簡潔、寬容(理由是 linux 命令列 llm 非常懂,不太可能寫錯)、安全(不提供 rm 能力)
5.Redis
理由:獨立、簡潔、寬容(非嚴肅 Redis 資料庫)
4.3 可觀測2.0 + AI的未來展望
MCP 適用於短平快的獨立介面能力,對於複雜需求,更適合 A2A 或更強大的模式。更多結合AI的能力,不僅僅有 MCP,可觀測2.0 + AI,還有更多可能。

參考:
[1]https://github.com/CherryHQ/cherry-studio
[2]https://deepchat.thinkinai.xyz/
[3]https://help.aliyun.com/zh/model-studio/get-api-key
[4]https://modelcontextprotocol.io/introduction
[5]https://github.com/punkpeye/awesome-mcp-clients
[6]https://modelcontextprotocol.io/clients
[7]https://deepchat.thinkinai.xyz/
[8]https://help.aliyun.com/zh/model-studio/get-api-key
[9]https://github.com/punkpeye/awesome-mcp-servers
[10]https://modelcontextprotocol.io/examples
[11]https://github.com/modelcontextprotocol/servers
使用Elasticsearch的向量檢索能力進行個性化推薦
在電商領域,個性化推薦系統是提高使用者滿意度與銷售轉化率的關鍵工具。本文將探討如何利用Elasticsearch的向量檢索能力,實現商品個性化推薦,助力電商平臺提升使用者體驗和業務增長。
點選閱讀原文檢視詳情。