通过 HTTP API 形式调用飞书官方部署的 MCP 服务,实现 AI Agent 与飞书云文档、通讯录等能力的深度集成。
| 工具名称 | 功能描述 | 支持认证 | 所需权限 |
|---|---|---|---|
| --------- | --------- | --------- | --------- |
search-user | 根据关键词搜索企业内用户 | UAT | contact:user:search |
get-user | 获取用户个人信息 | UAT/TAT | contact:contact.base:readonly |
fetch-file | 获取文件内容(图片/附件) | UAT/TAT | docs:document.media:download |
| 工具名称 | 功能描述 | 支持认证 | 所需权限 |
|---|---|---|---|
| --------- | --------- | --------- | --------- |
search-doc | 搜索云文档 | UAT | search:docs:read |
create-doc | 创建云文档 | UAT/TAT | docx:document:create |
fetch-doc | 查看云文档内容 | UAT/TAT | docx:document:readonly |
update-doc | 更新云文档 | UAT/TAT | docx:document:write_only |
list-docs | 获取文档列表 | UAT/TAT | wiki:wiki:readonly |
get-comments | 查看文档评论 | UAT/TAT | docs:document.comment:read |
add-comments | 添加文档评论 | UAT/TAT | docs:document.comment:create |
import requests
import json
url = "https://mcp.feishu.cn/mcp"
headers = {
"Content-Type": "application/json",
"X-Lark-MCP-TAT": "t-gxxxxxxxxxxxxxxxxxxxxx", # 或使用 X-Lark-MCP-UAT
"X-Lark-MCP-Allowed-Tools": "create-doc,fetch-doc,update-doc"
}
payload = {
"jsonrpc": "2.0",
"id": 1,
"method": "initialize"
}
response = requests.post(url, headers=headers, json=payload)
result = response.json()
print(json.dumps(result, indent=2))
payload = {
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
response = requests.post(url, headers=headers, json=payload)
tools = response.json()["result"]["tools"]
for tool in tools:
print(f"工具名:{tool['name']}")
print(f"描述:{tool['description']}")
# 示例:创建云文档
payload = {
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "create-doc",
"arguments": {
"title": "我的测试文档",
"content": "# 你好\n这是通过 MCP 创建的文档"
}
}
}
response = requests.post(url, headers=headers, json=payload)
result = response.json()
print(json.dumps(result, indent=2))
代表用户身份,适用于需要模拟特定用户操作的场景。
获取方式:
使用示例:
headers["X-Lark-MCP-UAT"] = "u-gxxxxxxxxxxxxxxxxxxxxx"
代表应用身份,适用于服务端到服务端的调用场景。
获取方式:
def get_tenant_access_token(app_id, app_secret):
url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
payload = {
"app_id": app_id,
"app_secret": app_secret
}
response = requests.post(url, json=payload)
return response.json()["tenant_access_token"]
# 使用
tat = get_tenant_access_token("cli_xxxxx", "xxxxxxxx")
headers["X-Lark-MCP-TAT"] = tat
class FeishuMCPClient:
"""飞书 MCP 远程服务客户端"""
def __init__(self, token, token_type="TAT", allowed_tools=None):
"""
初始化 MCP 客户端
Args:
token: 访问凭证 (UAT 或 TAT)
token_type: 凭证类型,"UAT" 或 "TAT"
allowed_tools: 允许使用的工具列表
"""
self.base_url = "https://mcp.feishu.cn/mcp"
self.token = token
self.token_type = token_type
self.allowed_tools = allowed_tools or []
self.session_id = None
def _get_headers(self):
"""获取请求头"""
headers = {
"Content-Type": "application/json"
}
if self.token_type == "UAT":
headers["X-Lark-MCP-UAT"] = self.token
else:
headers["X-Lark-MCP-TAT"] = self.token
if self.allowed_tools:
headers["X-Lark-MCP-Allowed-Tools"] = ",".join(self.allowed_tools)
return headers
def _request(self, method, params=None):
"""发送 MCP 请求"""
payload = {
"jsonrpc": "2.0",
"id": 1,
"method": method
}
if params:
payload["params"] = params
response = requests.post(
self.base_url,
headers=self._get_headers(),
json=payload
)
return response.json()
def initialize(self):
"""初始化 MCP 会话"""
result = self._request("initialize")
if "result" in result:
self.session_id = result["result"].get("protocolVersion")
print(f"MCP 会话初始化成功,协议版本:{self.session_id}")
return result
def list_tools(self):
"""列出可用工具"""
result = self._request("tools/list")
if "result" in result and "tools" in result["result"]:
tools = result["result"]["tools"]
print(f"可用工具数量:{len(tools)}")
for tool in tools:
print(f" - {tool['name']}: {tool['description']}")
return result
def call_tool(self, tool_name, arguments):
"""调用工具"""
params = {
"name": tool_name,
"arguments": arguments
}
result = self._request("tools/call", params)
# 检查是否执行失败
if "result" in result and result["result"].get("isError"):
error_text = result["result"]["content"][0]["text"]
print(f"工具执行失败:{error_text}")
return result
# ========== 便捷方法 ==========
def create_doc(self, title, content="", folder_token=None):
"""创建云文档"""
arguments = {
"title": title,
"content": content
}
if folder_token:
arguments["folder_token"] = folder_token
return self.call_tool("create-doc", arguments)
def fetch_doc(self, doc_id):
"""查看云文档"""
return self.call_tool("fetch-doc", {"docID": doc_id})
def update_doc(self, doc_id, content, block_id=None):
"""更新云文档"""
arguments = {
"docID": doc_id,
"content": content
}
if block_id:
arguments["block_id"] = block_id
return self.call_tool("update-doc", arguments)
def search_doc(self, query, creator_id=None):
"""搜索云文档"""
arguments = {
"query": query
}
if creator_id:
arguments["creator_id"] = creator_id
return self.call_tool("search-doc", arguments)
def search_user(self, query):
"""搜索用户"""
return self.call_tool("search-user", {"query": query})
def list_docs(self, folder_token, page_size=20):
"""获取文档列表"""
arguments = {
"folder_token": folder_token,
"page_size": page_size
}
return self.call_tool("list-docs", arguments)
def get_comments(self, doc_id):
"""获取文档评论"""
return self.call_tool("get-comments", {"docID": doc_id})
def add_comment(self, doc_id, comment):
"""添加文档评论"""
arguments = {
"docID": doc_id,
"comment": comment
}
return self.call_tool("add-comments", arguments)
# ============ 使用示例 ============
if __name__ == "__main__":
# 初始化客户端
client = FeishuMCPClient(
token="t-gxxxxxxxxxxxxxxxxxxxxx", # 替换为你的 TAT
token_type="TAT",
allowed_tools=["create-doc", "fetch-doc", "update-doc", "search-doc"]
)
# 初始化会话
client.initialize()
# 列出可用工具
client.list_tools()
# 创建文档
result = client.create_doc(
title="测试文档",
content="# 你好\n这是通过 MCP 创建的文档"
)
print(f"创建结果:{result}")
# 假设获得了文档 ID
doc_id = result["result"]["content"][0]["text"] # 实际需要从响应中提取
# 查看文档
doc_content = client.fetch_doc(doc_id)
print(f"文档内容:{doc_content}")
# 更新文档
update_result = client.update_doc(
doc_id=doc_id,
content="\n## 更新内容\n这是追加的内容"
)
print(f"更新结果:{update_result}")
# 错误响应格式
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Method not found"
}
}
# 常见错误码
ERROR_CODES = {
"-32700": "Parse error - 检查 JSON 格式",
"-32600": "Invalid Request - JSON-RPC 结构错误",
"-32601": "Method not found - 方法不存在",
"-32602": "Invalid params - 参数错误",
"-32603": "Internal error - 服务端异常",
"-32030": "Rate Limited - 请求频率超限",
"-32011": "UAT TAT Required - 缺少认证凭证",
"-32003": "Param Validate Error - 凭证无效或过期",
"-32042": "Invalid Content Type - Content-Type 错误"
}
告诉 SuperMike:
> "用 MCP 创建一个飞书文档,标题是'项目周报',内容是'# 本周工作\n1. 完成功能开发\n2. 修复 3 个 bug'"
> "读取这个飞书文档:https://xxx.feishu.cn/docx/ABC123def"
> "搜索用户'张三',获取他的 open_id"
> "在文档 https://xxx.feishu.cn/docx/ABC123def 末尾追加内容:'\n## 更新记录\n2026-03-09 更新'"
_技能版本:v1.0_
_创建日期:2026-03-09_
_作者:SuperMike_
共 1 个版本