Name | hljy-lark-doc-helper JSON |
Version |
0.1.9
JSON |
| download |
home_page | None |
Summary | MCP server for uploading markdown files to Lark documents with automatic image processing |
upload_time | 2025-07-18 09:00:36 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.12 |
license | MIT |
keywords |
document
feishu
lark
markdown
mcp
upload
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# 飞书文档助手 (Lark Doc Helper)
一个 MCP (Model Context Protocol) 服务器,用于将本地 Markdown 文件上传到飞书文档,并自动处理本地图片引用。
## 功能特性
- 📄 上传 Markdown 文件到飞书文档
- 🖼️ 自动检测并上传本地图片引用
- 🔗 自动替换图片链接为公共访问URL
- ⚙️ 可配置的API endpoints和认证信息
- 📊 支持多种图片格式 (jpg, jpeg, png, gif, bmp, webp, svg)
## 安装
确保您的系统已安装 Python 3.12+,然后运行:
```bash
# 使用 uv 安装依赖
uv sync
# 或者使用 pip
pip install -e .
```
## 配置
### 环境变量配置
创建一个 `.env` 文件或设置以下环境变量:
```bash
# API Endpoints配置
UPLOAD_CREDENTIALS_ENDPOINT=http://0.0.0.0:19106/api/v1/obs/post-signature/md-image-upload
OBS_UPLOAD_ENDPOINT=https://hljydc-common.obs.cn-east-3.myhuaweicloud.com
LARK_DOC_UPLOAD_ENDPOINT=http://0.0.0.0:19106/api/v1/lark-doc/helper/markdown-to-docx
# 认证配置
API_KEY=your-api-key
API_SECRET=your-api-secret
# 飞书应用配置
LARK_APP_ID=your-lark-app-id
LARK_APP_SECRET=your-lark-app-secret
LARK_TENANT_TOKEN=your-lark-tenant-token
# 默认挂载密钥(可选,也可以在调用时传入)
DEFAULT_MOUNT_KEY=
# 其他配置
MAX_FILE_SIZE=10485760 # 10MB
REQUEST_TIMEOUT=30 # 30秒
```
### 必需的API接口
您需要提供以下三个API接口:
1. **获取上传凭证接口**
- 端点:`UPLOAD_CREDENTIALS_ENDPOINT`
- 方法:POST
- 请求体:`{"filename": "image.jpg"}`
- 返回:包含OBS访问凭证的JSON
2. **OBS图片上传接口**
- 端点:`OBS_UPLOAD_ENDPOINT`
- 方法:POST
- 请求:表单数据(multipart/form-data)
- 返回:204状态码表示成功
3. **飞书文档上传接口**
- 端点:`LARK_DOC_UPLOAD_ENDPOINT`
- 方法:POST
- 请求体:`{"markdown": "...", "doc_name": "...", "mount_key": "..."}`
- 返回:包含文档URL的JSON
## 使用方法
### 作为 MCP 服务器运行
```bash
python main.py
```
### 在 Cursor 中使用
详细的Cursor配置指南请参考 [cursor-mcp-config.md](cursor-mcp-config.md)
简要配置:
1. 在Cursor设置中添加MCP服务器配置
2. 配置命令:`python /path/to/main.py`
3. 设置环境变量(API endpoints等)
4. 在聊天中直接使用工具
### 在其他 MCP 客户端中使用
服务器提供一个工具:`upload_markdown_to_lark_doc`
参数:
- `markdown_file_path`: 要上传的 Markdown 文件的绝对路径
- `doc_title`: 飞书文档的标题
- `mount_key`: 飞书文档的挂载密钥
示例:
```json
{
"tool": "upload_markdown_to_lark_doc",
"arguments": {
"markdown_file_path": "/path/to/your/document.md",
"doc_title": "我的文档标题",
"mount_key": "change-this"
}
}
```
## 工作流程
1. **读取 Markdown 文件**:从指定路径读取 Markdown 内容
2. **检测本地图片**:使用正则表达式找到所有本地图片引用
3. **上传图片**:
- 调用接口1获取上传凭证
- 调用接口2上传每张图片到OBS
- 获取图片的公共访问URL
4. **替换图片链接**:将 Markdown 中的本地图片路径替换为公共URL
5. **上传文档**:调用接口3将最终的 Markdown 内容上传到飞书文档
## 支持的图片格式
- `.jpg`, `.jpeg`
- `.png`
- `.gif`
- `.bmp`
- `.webp`
- `.svg`
## 错误处理
- 文件不存在时会返回错误
- 图片文件大小超过限制时会返回错误
- API调用失败时会返回详细的错误信息
- 配置验证失败时会返回配置错误信息
## 日志
服务器会记录以下信息:
- 发现的本地图片数量
- 图片上传进度和结果
- API调用错误和异常
## 开发
### 项目结构
```
lark-doc-helper/
├── main.py # 主程序文件
├── config.py # 配置管理
├── pyproject.toml # 项目配置
├── README.md # 说明文档
└── uv.lock # 依赖锁定文件
```
### 自定义API接口
您需要实现以下接口格式:
1. **上传凭证接口响应**:
```json
{
"status": "success",
"code": 200,
"message": null,
"data": {
"policy": "base64-encoded-policy",
"signature": "signature-string",
"accessKeyId": "access-key-id",
"key": "temp/md-image/20250717/uuid/filename.jpg",
"originPolicy": "original-policy-json"
}
}
```
2. **OBS上传接口响应**:
- 状态码:200 或 204 表示成功
- 上传成功后,图片可通过 `{obs_endpoint}/{key}` 访问
3. **飞书文档上传接口响应**:
```json
{
"status": "success",
"code": 200,
"message": null,
"data": {
"url": "https://hailiang.feishu.cn/docx/XgWDdPwRCoK7QkxcaztcOMjFnCd"
}
}
```
## 许可证
本项目使用 MIT 许可证。
## 贡献
欢迎提交 Issue 和 Pull Request!
Raw data
{
"_id": null,
"home_page": null,
"name": "hljy-lark-doc-helper",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "document, feishu, lark, markdown, mcp, upload",
"author": null,
"author_email": "HLJY <your-email@example.com>",
"download_url": "https://files.pythonhosted.org/packages/28/08/da39a7b463ab193b1f9e6dc4a6ba53a28829189b194bc46c478a2564fdb1/hljy_lark_doc_helper-0.1.9.tar.gz",
"platform": null,
"description": "# \u98de\u4e66\u6587\u6863\u52a9\u624b (Lark Doc Helper)\n\n\u4e00\u4e2a MCP (Model Context Protocol) \u670d\u52a1\u5668\uff0c\u7528\u4e8e\u5c06\u672c\u5730 Markdown \u6587\u4ef6\u4e0a\u4f20\u5230\u98de\u4e66\u6587\u6863\uff0c\u5e76\u81ea\u52a8\u5904\u7406\u672c\u5730\u56fe\u7247\u5f15\u7528\u3002\n\n## \u529f\u80fd\u7279\u6027\n\n- \ud83d\udcc4 \u4e0a\u4f20 Markdown \u6587\u4ef6\u5230\u98de\u4e66\u6587\u6863\n- \ud83d\uddbc\ufe0f \u81ea\u52a8\u68c0\u6d4b\u5e76\u4e0a\u4f20\u672c\u5730\u56fe\u7247\u5f15\u7528\n- \ud83d\udd17 \u81ea\u52a8\u66ff\u6362\u56fe\u7247\u94fe\u63a5\u4e3a\u516c\u5171\u8bbf\u95eeURL\n- \u2699\ufe0f \u53ef\u914d\u7f6e\u7684API endpoints\u548c\u8ba4\u8bc1\u4fe1\u606f\n- \ud83d\udcca \u652f\u6301\u591a\u79cd\u56fe\u7247\u683c\u5f0f (jpg, jpeg, png, gif, bmp, webp, svg)\n\n## \u5b89\u88c5\n\n\u786e\u4fdd\u60a8\u7684\u7cfb\u7edf\u5df2\u5b89\u88c5 Python 3.12+\uff0c\u7136\u540e\u8fd0\u884c\uff1a\n\n```bash\n# \u4f7f\u7528 uv \u5b89\u88c5\u4f9d\u8d56\nuv sync\n\n# \u6216\u8005\u4f7f\u7528 pip\npip install -e .\n```\n\n## \u914d\u7f6e\n\n### \u73af\u5883\u53d8\u91cf\u914d\u7f6e\n\n\u521b\u5efa\u4e00\u4e2a `.env` \u6587\u4ef6\u6216\u8bbe\u7f6e\u4ee5\u4e0b\u73af\u5883\u53d8\u91cf\uff1a\n\n```bash\n# API Endpoints\u914d\u7f6e\nUPLOAD_CREDENTIALS_ENDPOINT=http://0.0.0.0:19106/api/v1/obs/post-signature/md-image-upload\nOBS_UPLOAD_ENDPOINT=https://hljydc-common.obs.cn-east-3.myhuaweicloud.com\nLARK_DOC_UPLOAD_ENDPOINT=http://0.0.0.0:19106/api/v1/lark-doc/helper/markdown-to-docx\n\n# \u8ba4\u8bc1\u914d\u7f6e\nAPI_KEY=your-api-key\nAPI_SECRET=your-api-secret\n\n# \u98de\u4e66\u5e94\u7528\u914d\u7f6e\nLARK_APP_ID=your-lark-app-id\nLARK_APP_SECRET=your-lark-app-secret\nLARK_TENANT_TOKEN=your-lark-tenant-token\n\n# \u9ed8\u8ba4\u6302\u8f7d\u5bc6\u94a5\uff08\u53ef\u9009\uff0c\u4e5f\u53ef\u4ee5\u5728\u8c03\u7528\u65f6\u4f20\u5165\uff09\nDEFAULT_MOUNT_KEY=\n\n# \u5176\u4ed6\u914d\u7f6e\nMAX_FILE_SIZE=10485760 # 10MB\nREQUEST_TIMEOUT=30 # 30\u79d2\n```\n\n### \u5fc5\u9700\u7684API\u63a5\u53e3\n\n\u60a8\u9700\u8981\u63d0\u4f9b\u4ee5\u4e0b\u4e09\u4e2aAPI\u63a5\u53e3\uff1a\n\n1. **\u83b7\u53d6\u4e0a\u4f20\u51ed\u8bc1\u63a5\u53e3**\n - \u7aef\u70b9\uff1a`UPLOAD_CREDENTIALS_ENDPOINT`\n - \u65b9\u6cd5\uff1aPOST\n - \u8bf7\u6c42\u4f53\uff1a`{\"filename\": \"image.jpg\"}`\n - \u8fd4\u56de\uff1a\u5305\u542bOBS\u8bbf\u95ee\u51ed\u8bc1\u7684JSON\n\n2. **OBS\u56fe\u7247\u4e0a\u4f20\u63a5\u53e3**\n - \u7aef\u70b9\uff1a`OBS_UPLOAD_ENDPOINT`\n - \u65b9\u6cd5\uff1aPOST\n - \u8bf7\u6c42\uff1a\u8868\u5355\u6570\u636e\uff08multipart/form-data\uff09\n - \u8fd4\u56de\uff1a204\u72b6\u6001\u7801\u8868\u793a\u6210\u529f\n\n3. **\u98de\u4e66\u6587\u6863\u4e0a\u4f20\u63a5\u53e3**\n - \u7aef\u70b9\uff1a`LARK_DOC_UPLOAD_ENDPOINT`\n - \u65b9\u6cd5\uff1aPOST\n - \u8bf7\u6c42\u4f53\uff1a`{\"markdown\": \"...\", \"doc_name\": \"...\", \"mount_key\": \"...\"}`\n - \u8fd4\u56de\uff1a\u5305\u542b\u6587\u6863URL\u7684JSON\n\n## \u4f7f\u7528\u65b9\u6cd5\n\n### \u4f5c\u4e3a MCP \u670d\u52a1\u5668\u8fd0\u884c\n\n```bash\npython main.py\n```\n\n### \u5728 Cursor \u4e2d\u4f7f\u7528\n\n\u8be6\u7ec6\u7684Cursor\u914d\u7f6e\u6307\u5357\u8bf7\u53c2\u8003 [cursor-mcp-config.md](cursor-mcp-config.md)\n\n\u7b80\u8981\u914d\u7f6e\uff1a\n1. \u5728Cursor\u8bbe\u7f6e\u4e2d\u6dfb\u52a0MCP\u670d\u52a1\u5668\u914d\u7f6e\n2. \u914d\u7f6e\u547d\u4ee4\uff1a`python /path/to/main.py`\n3. \u8bbe\u7f6e\u73af\u5883\u53d8\u91cf\uff08API endpoints\u7b49\uff09\n4. \u5728\u804a\u5929\u4e2d\u76f4\u63a5\u4f7f\u7528\u5de5\u5177\n\n### \u5728\u5176\u4ed6 MCP \u5ba2\u6237\u7aef\u4e2d\u4f7f\u7528\n\n\u670d\u52a1\u5668\u63d0\u4f9b\u4e00\u4e2a\u5de5\u5177\uff1a`upload_markdown_to_lark_doc`\n\n\u53c2\u6570\uff1a\n- `markdown_file_path`: \u8981\u4e0a\u4f20\u7684 Markdown \u6587\u4ef6\u7684\u7edd\u5bf9\u8def\u5f84\n- `doc_title`: \u98de\u4e66\u6587\u6863\u7684\u6807\u9898\n- `mount_key`: \u98de\u4e66\u6587\u6863\u7684\u6302\u8f7d\u5bc6\u94a5\n\n\u793a\u4f8b\uff1a\n```json\n{\n \"tool\": \"upload_markdown_to_lark_doc\",\n \"arguments\": {\n \"markdown_file_path\": \"/path/to/your/document.md\",\n \"doc_title\": \"\u6211\u7684\u6587\u6863\u6807\u9898\",\n \"mount_key\": \"change-this\"\n }\n}\n```\n\n## \u5de5\u4f5c\u6d41\u7a0b\n\n1. **\u8bfb\u53d6 Markdown \u6587\u4ef6**\uff1a\u4ece\u6307\u5b9a\u8def\u5f84\u8bfb\u53d6 Markdown \u5185\u5bb9\n2. **\u68c0\u6d4b\u672c\u5730\u56fe\u7247**\uff1a\u4f7f\u7528\u6b63\u5219\u8868\u8fbe\u5f0f\u627e\u5230\u6240\u6709\u672c\u5730\u56fe\u7247\u5f15\u7528\n3. **\u4e0a\u4f20\u56fe\u7247**\uff1a\n - \u8c03\u7528\u63a5\u53e31\u83b7\u53d6\u4e0a\u4f20\u51ed\u8bc1\n - \u8c03\u7528\u63a5\u53e32\u4e0a\u4f20\u6bcf\u5f20\u56fe\u7247\u5230OBS\n - \u83b7\u53d6\u56fe\u7247\u7684\u516c\u5171\u8bbf\u95eeURL\n4. **\u66ff\u6362\u56fe\u7247\u94fe\u63a5**\uff1a\u5c06 Markdown \u4e2d\u7684\u672c\u5730\u56fe\u7247\u8def\u5f84\u66ff\u6362\u4e3a\u516c\u5171URL\n5. **\u4e0a\u4f20\u6587\u6863**\uff1a\u8c03\u7528\u63a5\u53e33\u5c06\u6700\u7ec8\u7684 Markdown \u5185\u5bb9\u4e0a\u4f20\u5230\u98de\u4e66\u6587\u6863\n\n## \u652f\u6301\u7684\u56fe\u7247\u683c\u5f0f\n\n- `.jpg`, `.jpeg`\n- `.png`\n- `.gif`\n- `.bmp`\n- `.webp`\n- `.svg`\n\n## \u9519\u8bef\u5904\u7406\n\n- \u6587\u4ef6\u4e0d\u5b58\u5728\u65f6\u4f1a\u8fd4\u56de\u9519\u8bef\n- \u56fe\u7247\u6587\u4ef6\u5927\u5c0f\u8d85\u8fc7\u9650\u5236\u65f6\u4f1a\u8fd4\u56de\u9519\u8bef\n- API\u8c03\u7528\u5931\u8d25\u65f6\u4f1a\u8fd4\u56de\u8be6\u7ec6\u7684\u9519\u8bef\u4fe1\u606f\n- \u914d\u7f6e\u9a8c\u8bc1\u5931\u8d25\u65f6\u4f1a\u8fd4\u56de\u914d\u7f6e\u9519\u8bef\u4fe1\u606f\n\n## \u65e5\u5fd7\n\n\u670d\u52a1\u5668\u4f1a\u8bb0\u5f55\u4ee5\u4e0b\u4fe1\u606f\uff1a\n- \u53d1\u73b0\u7684\u672c\u5730\u56fe\u7247\u6570\u91cf\n- \u56fe\u7247\u4e0a\u4f20\u8fdb\u5ea6\u548c\u7ed3\u679c\n- API\u8c03\u7528\u9519\u8bef\u548c\u5f02\u5e38\n\n## \u5f00\u53d1\n\n### \u9879\u76ee\u7ed3\u6784\n\n```\nlark-doc-helper/\n\u251c\u2500\u2500 main.py # \u4e3b\u7a0b\u5e8f\u6587\u4ef6\n\u251c\u2500\u2500 config.py # \u914d\u7f6e\u7ba1\u7406\n\u251c\u2500\u2500 pyproject.toml # \u9879\u76ee\u914d\u7f6e\n\u251c\u2500\u2500 README.md # \u8bf4\u660e\u6587\u6863\n\u2514\u2500\u2500 uv.lock # \u4f9d\u8d56\u9501\u5b9a\u6587\u4ef6\n```\n\n### \u81ea\u5b9a\u4e49API\u63a5\u53e3\n\n\u60a8\u9700\u8981\u5b9e\u73b0\u4ee5\u4e0b\u63a5\u53e3\u683c\u5f0f\uff1a\n\n1. **\u4e0a\u4f20\u51ed\u8bc1\u63a5\u53e3\u54cd\u5e94**:\n```json\n{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": null,\n \"data\": {\n \"policy\": \"base64-encoded-policy\",\n \"signature\": \"signature-string\",\n \"accessKeyId\": \"access-key-id\",\n \"key\": \"temp/md-image/20250717/uuid/filename.jpg\",\n \"originPolicy\": \"original-policy-json\"\n }\n}\n```\n\n2. **OBS\u4e0a\u4f20\u63a5\u53e3\u54cd\u5e94**:\n- \u72b6\u6001\u7801\uff1a200 \u6216 204 \u8868\u793a\u6210\u529f\n- \u4e0a\u4f20\u6210\u529f\u540e\uff0c\u56fe\u7247\u53ef\u901a\u8fc7 `{obs_endpoint}/{key}` \u8bbf\u95ee\n\n3. **\u98de\u4e66\u6587\u6863\u4e0a\u4f20\u63a5\u53e3\u54cd\u5e94**:\n```json\n{\n \"status\": \"success\",\n \"code\": 200,\n \"message\": null,\n \"data\": {\n \"url\": \"https://hailiang.feishu.cn/docx/XgWDdPwRCoK7QkxcaztcOMjFnCd\"\n }\n}\n```\n\n## \u8bb8\u53ef\u8bc1\n\n\u672c\u9879\u76ee\u4f7f\u7528 MIT \u8bb8\u53ef\u8bc1\u3002\n\n## \u8d21\u732e\n\n\u6b22\u8fce\u63d0\u4ea4 Issue \u548c Pull Request\uff01\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "MCP server for uploading markdown files to Lark documents with automatic image processing",
"version": "0.1.9",
"project_urls": {
"Homepage": "https://github.com/your-username/hljy-lark-doc-helper",
"Issues": "https://github.com/your-username/hljy-lark-doc-helper/issues",
"Repository": "https://github.com/your-username/hljy-lark-doc-helper"
},
"split_keywords": [
"document",
" feishu",
" lark",
" markdown",
" mcp",
" upload"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "e44cd229cd3146af030666068c6356d93c5313734e83fd6d6b2fcb9ff23d816c",
"md5": "0c4d384166b22e52e0ae71cd7d5a9164",
"sha256": "7c3f3924db4d8635631cf7d2f63fa32c48452f37c7ae85905b7eea116eef887f"
},
"downloads": -1,
"filename": "hljy_lark_doc_helper-0.1.9-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0c4d384166b22e52e0ae71cd7d5a9164",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 13926,
"upload_time": "2025-07-18T09:00:34",
"upload_time_iso_8601": "2025-07-18T09:00:34.756159Z",
"url": "https://files.pythonhosted.org/packages/e4/4c/d229cd3146af030666068c6356d93c5313734e83fd6d6b2fcb9ff23d816c/hljy_lark_doc_helper-0.1.9-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "2808da39a7b463ab193b1f9e6dc4a6ba53a28829189b194bc46c478a2564fdb1",
"md5": "0cf2c316a9b0660e29323fd366737f61",
"sha256": "4e466a15db64aa88c16ab680e5baa7775f28c877b2750079078f82b4cc4dacec"
},
"downloads": -1,
"filename": "hljy_lark_doc_helper-0.1.9.tar.gz",
"has_sig": false,
"md5_digest": "0cf2c316a9b0660e29323fd366737f61",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 11424,
"upload_time": "2025-07-18T09:00:36",
"upload_time_iso_8601": "2025-07-18T09:00:36.479203Z",
"url": "https://files.pythonhosted.org/packages/28/08/da39a7b463ab193b1f9e6dc4a6ba53a28829189b194bc46c478a2564fdb1/hljy_lark_doc_helper-0.1.9.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-18 09:00:36",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "your-username",
"github_project": "hljy-lark-doc-helper",
"github_not_found": true,
"lcname": "hljy-lark-doc-helper"
}