mcp-feishu 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+ .Python
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ .venv/
10
+ env/
11
+ venv/
12
+ .pytest_cache/
13
+ .coverage
14
+ htmlcov/
15
+ .DS_Store
16
+ *.swp
17
+ *.swo
@@ -0,0 +1,30 @@
1
+ # mcp-feishu — AI 指南
2
+
3
+ ## Purpose
4
+
5
+ 标准 Model Context Protocol (MCP) Server,为 LLM / Agent 客户端提供 `send_to_feishu` 工具,将文本以 Markdown 格式推送到飞书自定义机器人群聊。
6
+
7
+ 纯环境变量驱动,零配置中心依赖,可独立打包分发至 PyPI 并迁移到任何主机。
8
+
9
+ ## Architecture Map
10
+
11
+ | 路径 | 语义 |
12
+ |---|---|
13
+ | `src/mcp_feishu/__init__.py` | 包版本与入口暴露 |
14
+ | `src/mcp_feishu/__main__.py` | MCP Server 实现、飞书签名与 Webhook 投递 |
15
+ | `pyproject.toml` | 打包构建元数据与 CLI entry-point |
16
+ | `README.md` | 使用指南与环境变量说明 |
17
+
18
+ ## Environment Variables
19
+
20
+ | 变量 | 必填 | 默认值 | 说明 |
21
+ |---|---|---|---|
22
+ | `FEISHU_WEBHOOK` | 是 | 无 | 机器人 Webhook URL |
23
+ | `FEISHU_SECRET` | 否 | 空 | 机器人安全签名 Secret |
24
+ | `FEISHU_TITLE` | 否 | `📋 来自 AI 的消息` | 默认卡片标题 |
25
+
26
+ ## Verification
27
+
28
+ ```bash
29
+ uv run --project OWNED/mcp-feishu python -m mcp_feishu --help
30
+ ```
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.5
2
+ Name: mcp-feishu
3
+ Version: 0.1.0
4
+ Summary: 把消息发到飞书自定义机器人的标准 MCP Server (Model Context Protocol)
5
+ License-Expression: MIT
6
+ Keywords: feishu,lark,llm,mcp,model-context-protocol,notification
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Communications :: Chat
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: httpx>=0.27.0
19
+ Requires-Dist: mcp>=2.1.0
20
+ Description-Content-Type: text/markdown
21
+
22
+ # mcp-feishu
23
+
24
+ 面向大语言模型与智能 Agent 的标准 **Model Context Protocol (MCP)** Server。
25
+
26
+ 它的作用是为 AI 提供 `send_to_feishu` 工具,将长文本、运维命令、配置片段等内容以富文本卡片的形式推送到飞书自定义机器人群组中。用户在飞书客户端可以直接一键整段复制命令,无需在终端手动抄写。
27
+
28
+ ---
29
+
30
+ ## 特性
31
+
32
+ - **标准协议支持**:基于 Model Context Protocol Python SDK 实现,遵循 MCP 标准规范。
33
+ - **零配置中心依赖**:纯粹通过环境变量读取参数,不强绑定任何特定主机或配置中心(如 Nacos)。可跨机器无缝迁移部署。
34
+ - **即装即用**:支持直接通过 `uvx mcp-feishu` 或 `pip install mcp-feishu` 启动。
35
+ - **安全与防泄露**:内置敏感请求日志脱敏机制,确保 Webhook 凭据不打印至终端或日志。
36
+ - **富文本排版**:飞书交互式卡片渲染,支持 Markdown 与等宽代码块整段复制。
37
+
38
+ ---
39
+
40
+ ## 环境变量配置
41
+
42
+ 本服务完全由环境变量控制,无需修改任何代码文件:
43
+
44
+ | 环境变量 | 必填 | 默认值 | 说明 |
45
+ |---|---|---|---|
46
+ | `FEISHU_WEBHOOK` | **是** | 无 | 飞书群自定义机器人的 Webhook 地址(形如 `https://open.feishu.cn/open-apis/bot/v2/hook/...`) |
47
+ | `FEISHU_SECRET` | 否 | 空 | 机器人开启「签名校验」时的校验 Secret |
48
+ | `FEISHU_TITLE` | 否 | `📋 来自 AI 的消息` | 发送卡片的默认标题 |
49
+
50
+ ---
51
+
52
+ ## 快速使用
53
+
54
+ ### 1. Claude Desktop / Codex 配置 (推荐使用 uvx)
55
+
56
+ 在你的客户端配置文件(如 `claude_desktop_config.json` 或 `~/.codex/config.toml`)中加入配置:
57
+
58
+ #### JSON 格式 (Claude Desktop / Cursor 等)
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "feishu": {
63
+ "command": "uvx",
64
+ "args": ["mcp-feishu"],
65
+ "env": {
66
+ "FEISHU_WEBHOOK": "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_ROBOT_WEBHOOK_KEY",
67
+ "FEISHU_SECRET": "YOUR_SECRET_IF_ENABLED"
68
+ }
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ #### TOML 格式 (Codex 等)
75
+ ```toml
76
+ [mcp_servers.feishu]
77
+ type = "stdio"
78
+ command = "uvx"
79
+ args = ["mcp-feishu"]
80
+
81
+ [mcp_servers.feishu.env]
82
+ FEISHU_WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_ROBOT_WEBHOOK_KEY"
83
+ FEISHU_SECRET = "YOUR_SECRET_IF_ENABLED"
84
+ ```
85
+
86
+ ### 2. 通过 pip 安装运行
87
+
88
+ ```bash
89
+ pip install mcp-feishu
90
+ export FEISHU_WEBHOOK="https://open.feishu.cn/open-apis/bot/v2/hook/xxx"
91
+ mcp-feishu
92
+ ```
93
+
94
+ ---
95
+
96
+ ## 提供的工具 (Tools)
97
+
98
+ ### `send_to_feishu`
99
+
100
+ 向指定的飞书群机器人发送通知卡片。
101
+
102
+ - **参数**:
103
+ - `text` (string, required): 消息正文。支持 Markdown;长命令或代码建议使用 ```` ``` ```` 包裹,以便在客户端整段复制。
104
+ - `title` (string, optional): 卡片头部标题。留空时使用 `FEISHU_TITLE` 默认标题。
105
+ - **返回**:发送状态结果描述(例如 `"已送达"` 或失败原因)。
106
+
107
+ ---
108
+
109
+ ## 开源协议
110
+
111
+ MIT License
@@ -0,0 +1,90 @@
1
+ # mcp-feishu
2
+
3
+ 面向大语言模型与智能 Agent 的标准 **Model Context Protocol (MCP)** Server。
4
+
5
+ 它的作用是为 AI 提供 `send_to_feishu` 工具,将长文本、运维命令、配置片段等内容以富文本卡片的形式推送到飞书自定义机器人群组中。用户在飞书客户端可以直接一键整段复制命令,无需在终端手动抄写。
6
+
7
+ ---
8
+
9
+ ## 特性
10
+
11
+ - **标准协议支持**:基于 Model Context Protocol Python SDK 实现,遵循 MCP 标准规范。
12
+ - **零配置中心依赖**:纯粹通过环境变量读取参数,不强绑定任何特定主机或配置中心(如 Nacos)。可跨机器无缝迁移部署。
13
+ - **即装即用**:支持直接通过 `uvx mcp-feishu` 或 `pip install mcp-feishu` 启动。
14
+ - **安全与防泄露**:内置敏感请求日志脱敏机制,确保 Webhook 凭据不打印至终端或日志。
15
+ - **富文本排版**:飞书交互式卡片渲染,支持 Markdown 与等宽代码块整段复制。
16
+
17
+ ---
18
+
19
+ ## 环境变量配置
20
+
21
+ 本服务完全由环境变量控制,无需修改任何代码文件:
22
+
23
+ | 环境变量 | 必填 | 默认值 | 说明 |
24
+ |---|---|---|---|
25
+ | `FEISHU_WEBHOOK` | **是** | 无 | 飞书群自定义机器人的 Webhook 地址(形如 `https://open.feishu.cn/open-apis/bot/v2/hook/...`) |
26
+ | `FEISHU_SECRET` | 否 | 空 | 机器人开启「签名校验」时的校验 Secret |
27
+ | `FEISHU_TITLE` | 否 | `📋 来自 AI 的消息` | 发送卡片的默认标题 |
28
+
29
+ ---
30
+
31
+ ## 快速使用
32
+
33
+ ### 1. Claude Desktop / Codex 配置 (推荐使用 uvx)
34
+
35
+ 在你的客户端配置文件(如 `claude_desktop_config.json` 或 `~/.codex/config.toml`)中加入配置:
36
+
37
+ #### JSON 格式 (Claude Desktop / Cursor 等)
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "feishu": {
42
+ "command": "uvx",
43
+ "args": ["mcp-feishu"],
44
+ "env": {
45
+ "FEISHU_WEBHOOK": "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_ROBOT_WEBHOOK_KEY",
46
+ "FEISHU_SECRET": "YOUR_SECRET_IF_ENABLED"
47
+ }
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ #### TOML 格式 (Codex 等)
54
+ ```toml
55
+ [mcp_servers.feishu]
56
+ type = "stdio"
57
+ command = "uvx"
58
+ args = ["mcp-feishu"]
59
+
60
+ [mcp_servers.feishu.env]
61
+ FEISHU_WEBHOOK = "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_ROBOT_WEBHOOK_KEY"
62
+ FEISHU_SECRET = "YOUR_SECRET_IF_ENABLED"
63
+ ```
64
+
65
+ ### 2. 通过 pip 安装运行
66
+
67
+ ```bash
68
+ pip install mcp-feishu
69
+ export FEISHU_WEBHOOK="https://open.feishu.cn/open-apis/bot/v2/hook/xxx"
70
+ mcp-feishu
71
+ ```
72
+
73
+ ---
74
+
75
+ ## 提供的工具 (Tools)
76
+
77
+ ### `send_to_feishu`
78
+
79
+ 向指定的飞书群机器人发送通知卡片。
80
+
81
+ - **参数**:
82
+ - `text` (string, required): 消息正文。支持 Markdown;长命令或代码建议使用 ```` ``` ```` 包裹,以便在客户端整段复制。
83
+ - `title` (string, optional): 卡片头部标题。留空时使用 `FEISHU_TITLE` 默认标题。
84
+ - **返回**:发送状态结果描述(例如 `"已送达"` 或失败原因)。
85
+
86
+ ---
87
+
88
+ ## 开源协议
89
+
90
+ MIT License
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "mcp-feishu"
3
+ version = "0.1.0"
4
+ description = "把消息发到飞书自定义机器人的标准 MCP Server (Model Context Protocol)"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = "MIT"
8
+ keywords = ["mcp", "model-context-protocol", "feishu", "lark", "llm", "notification"]
9
+ classifiers = [
10
+ "Development Status :: 4 - Beta",
11
+ "Intended Audience :: Developers",
12
+ "License :: OSI Approved :: MIT License",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Topic :: Communications :: Chat",
19
+ "Topic :: Software Development :: Libraries :: Python Modules",
20
+ ]
21
+ dependencies = [
22
+ "mcp>=2.1.0",
23
+ "httpx>=0.27.0",
24
+ ]
25
+
26
+ [project.scripts]
27
+ mcp-feishu = "mcp_feishu.__main__:main"
28
+
29
+ [build-system]
30
+ requires = ["hatchling"]
31
+ build-backend = "hatchling.build"
32
+
33
+ [tool.hatch.build.targets.wheel]
34
+ packages = ["src/mcp_feishu"]
@@ -0,0 +1 @@
1
+ """把消息发到飞书自定义机器人的 MCP server。"""
@@ -0,0 +1,105 @@
1
+ # -*- coding: utf-8 -*-
2
+ """飞书通知 MCP server。
3
+
4
+ 只做一件事:把一段文本发到飞书自定义机器人,方便人在手机或客户端里直接复制。
5
+
6
+ 配置全部来自环境变量,**不读取任何本机配置中心**——这样整个目录拷到别的机器上、
7
+ 或者换一个机器人,改环境变量即可,不需要改代码:
8
+
9
+ FEISHU_WEBHOOK 必填,自定义机器人的 webhook 地址
10
+ FEISHU_SECRET 选填,机器人开启「签名校验」时才需要
11
+ FEISHU_TITLE 选填,默认卡片标题
12
+
13
+ 为什么不复用本仓库的 runtime.notify:那个库从 r-nacos 读配置,绑死在这台主机上,
14
+ 与本 server「可迁移」的目标冲突。飞书签名逻辑本身只有几行,独立实现换来的是零外部依赖。
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import base64
20
+ import hashlib
21
+ import hmac
22
+ import logging
23
+ import os
24
+ import sys
25
+ import time
26
+
27
+ import httpx
28
+ from mcp.server.mcpserver import MCPServer
29
+
30
+ # httpx 默认在 INFO 级别打印完整请求 URL。webhook 地址本身就是凭据,
31
+ # 打出来等于把它写进日志——密钥契约明确禁止。这里直接压到 WARNING。
32
+ logging.getLogger("httpx").setLevel(logging.WARNING)
33
+ logging.getLogger("httpcore").setLevel(logging.WARNING)
34
+
35
+ SEND_TIMEOUT_SECONDS = 10
36
+ DEFAULT_TITLE = os.environ.get("FEISHU_TITLE", "📋 来自 AI 的消息")
37
+
38
+ mcp = MCPServer("feishu-notify")
39
+
40
+
41
+ def _sign(timestamp: int, secret: str) -> str:
42
+ """飞书签名:待签名串是 "{timestamp}\\n{secret}",消息体为空。"""
43
+ string_to_sign = f"{timestamp}\n{secret}"
44
+ digest = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
45
+ return base64.b64encode(digest).decode("utf-8")
46
+
47
+
48
+ def _post(title: str, text: str) -> str:
49
+ webhook = os.environ.get("FEISHU_WEBHOOK", "").strip()
50
+ if not webhook:
51
+ return "未配置 FEISHU_WEBHOOK,无法发送"
52
+ secret = os.environ.get("FEISHU_SECRET", "").strip()
53
+
54
+ payload: dict = {
55
+ "msg_type": "interactive",
56
+ "card": {
57
+ "header": {"title": {"tag": "plain_text", "content": title},
58
+ "template": "blue"},
59
+ # lark_md 里的 ``` 代码块在客户端是等宽显示,长按/右键可整段复制,
60
+ # 这正是这个 server 存在的理由——让人不用从终端里手抄命令。
61
+ "elements": [{"tag": "div",
62
+ "text": {"tag": "lark_md", "content": text}}],
63
+ },
64
+ }
65
+ if secret:
66
+ timestamp = int(time.time())
67
+ payload["timestamp"] = str(timestamp)
68
+ payload["sign"] = _sign(timestamp, secret)
69
+
70
+ try:
71
+ response = httpx.post(webhook, json=payload, timeout=SEND_TIMEOUT_SECONDS)
72
+ data = response.json()
73
+ except Exception as error: # noqa: BLE001
74
+ # 异常正文可能带上完整 URL,只回类型不回原文。
75
+ return f"发送异常: {type(error).__name__}"
76
+ if data.get("code", -1) == 0:
77
+ return "已送达"
78
+ return f"发送失败: {data.get('msg', '未知错误')}"
79
+
80
+
81
+ @mcp.tool()
82
+ def send_to_feishu(text: str, title: str = "") -> str:
83
+ """把一段文本发到飞书,方便用户直接复制。
84
+
85
+ 适合发:要用户手工执行的命令、需要保存的配置片段、过长不便在终端复制的内容。
86
+
87
+ Args:
88
+ text: 正文,支持 Markdown。命令请用 ``` 代码块包起来,客户端里可整段复制。
89
+ title: 卡片标题,留空则用默认标题。
90
+ """
91
+ if not text.strip():
92
+ return "正文为空,未发送"
93
+ return _post(title.strip() or DEFAULT_TITLE, text)
94
+
95
+
96
+ def main() -> int:
97
+ if not os.environ.get("FEISHU_WEBHOOK"):
98
+ print("警告:未设置 FEISHU_WEBHOOK,send_to_feishu 会直接返回失败",
99
+ file=sys.stderr)
100
+ mcp.run()
101
+ return 0
102
+
103
+
104
+ if __name__ == "__main__":
105
+ raise SystemExit(main())