6.2 KiB
name, description, version, author, metadata
| name | description | version | author | metadata | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| feishu-docs | Create and edit Feishu/Lark documents programmatically via the Docx Open API — create docs, add content blocks, read raw text, and manage permissions. Use when the user asks to create a Feishu doc from scratch or add structured content. | 1.0.0 | agent |
|
Feishu Docs — Document Creation & Editing
When to Use
- User asks you to create a Feishu document (docx) with structured content
- User wants a report, summary, or reference saved as a Feishu doc
- User says "帮我创建一份飞书文档" or similar
- Supplement to lark-mcp MCP tools (which cover search, import, bitable, IM but not block-level editing)
Trigger Conditions
- Keywords: 飞书文档, 创建文档, 写个文档, Feishu doc, Lark docx
- NOT: 飞书表格 (use lark-mcp bitable tools), 发送消息 (use
send_messageor lark-mcp IM tools)
Architecture
Two complementary systems:
| System | Strengths | Gaps |
|---|---|---|
| lark-mcp (MCP server) | Bitable CRUD, IM/groups, document search, markdown→doc import | No block-level editing, no doc creation |
| Feishu Docx API (this skill) | Create docs, add/edit/delete blocks, read raw content | Requires manual API calls via Python |
Use lark-mcp for everything it covers. Fall back to direct API for document creation and block editing.
Prerequisites
The Feishu app must have these permissions in the developer console:
docx:document— create and manage documentsdrive:drive— access cloud documents (for import API)
Without these, the API returns 404. User must add them at https://open.feishu.cn/app.
Credentials are in ~/.hermes/.env:
FEISHU_APP_ID=cli_xxx
FEISHU_APP_SECRET=xxx
Workflow: Create a Document from Scratch
Step 1: Get tenant access token
import requests
r = requests.post(
"https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
json={"app_id": aid, "app_secret": sec}, timeout=10
)
token = r.json()["tenant_access_token"]
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
Step 2: Create empty document
r = requests.post(
"https://open.feishu.cn/open-apis/docx/v1/documents",
headers=headers,
json={"title": "文档标题"},
timeout=10
)
doc_id = r.json()["data"]["document"]["document_id"]
# URL: https://xiteng.feishu.cn/docx/{doc_id}
Step 3: Add content blocks
The document root is also the root block. Add children to it:
blocks = [
{"block_type": 3, "heading1": {"elements": [
{"text_run": {"content": "大标题"}}
]}},
{"block_type": 2, "text": {"elements": [
{"text_run": {"content": "正文段落"}}
]}},
{"block_type": 12, "bullet": {"elements": [
{"text_run": {"content": "列表项"}}
]}},
]
# Batch up to 50 blocks per request
r = requests.post(
f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_id}/blocks/{doc_id}/children",
headers=headers,
json={"children": blocks},
timeout=15
)
Block type reference
| block_type | Name | Structure |
|---|---|---|
| 2 | Text paragraph | {"text": {"elements": [{"text_run": {"content": "..."}}]}} |
| 3 | Heading 1 | {"heading1": {"elements": ...}} |
| 4 | Heading 2 | {"heading2": {"elements": ...}} |
| 5 | Heading 3 | {"heading3": {"elements": ...}} |
| 6 | Heading 4 | {"heading4": {"elements": ...}} |
| 12 | Bullet list | {"bullet": {"elements": ...}} |
| 13 | Ordered list | {"ordered": {"elements": ...}} |
| 14 | Code block | {"code": {"elements": ..., "style": {"language": 1}}} |
| 17 | Callout/hint | {"callout": {"elements": ...}} |
| 22 | Divider | {"divider": {}} |
| 27 | Table | Complex — see API docs |
Step 4: Read back and verify
r = requests.get(
f"https://open.feishu.cn/open-apis/docx/v1/documents/{doc_id}/raw_content",
headers={"Authorization": f"Bearer {token}"},
timeout=10
)
content = r.json()["data"]["content"]
Common Pitfalls
1. 404 on import API — missing permissions
The drive/v1/files/import API requires drive:drive permission. Without it, returns 404.
Fix: User must add the permission in Feishu Developer Console → App → Permissions.
2. ENV var redaction in scripts
When writing Python scripts that read ~/.hermes/.env, do NOT write lines like:
# ❌ Redaction will eat the string
elif line.startswith("FEISHU_APP_SECRET=*** ...
Instead construct the key name dynamically:
# ✅ Safe from redaction
if k == "FEISHU_APP_SECRET": ...
# or
prefix = "FEISHU_APP"
if k == prefix + "_SECRET": ...
3. Block batch limit
The children API accepts at most 50 blocks per request. Split large documents into batches.
4. Document ID = Root block ID
The document_id returned from create is also the root block ID. Use it for both:
GET /docx/v1/documents/{doc_id}— get document metadataPOST /docx/v1/documents/{doc_id}/blocks/{doc_id}/children— add blocks
Integration with lark-mcp
When lark-mcp is connected (see references/lark-mcp-setup.md), use it for:
docx_builtin_search— search existing documentsdocx_v1_document_rawContent— read document plain textdocx_builtin_import— quick markdown→doc conversion (creates new doc)bitable_*— multi-dimensional table operationsim_*— messages and groups
Use direct API (this skill) when you need:
- Create a blank document with a specific title
- Add/edit/delete individual blocks
- Modify existing document structure
Verification Checklist
FEISHU_APP_IDandFEISHU_APP_SECRETare set in.env- App has
docx:documentpermission - Document created:
GET /docx/v1/documents/{id}returns 200 - Content added:
GET /docx/v1/documents/{id}/blocksreturns blocks - User can open the URL in Feishu
Related Files
scripts/create_doc.py— reusable script: create doc + add content from markdownreferences/lark-mcp-setup.md— MCP server installation and credential managementreferences/docx-block-types.md— full block type reference with examples