/**
* Feishu MCP Server - Zod Schemas
*
* Input validation schemas for MCP tools with detailed descriptions.
*/
import { z } from 'zod'
// ============================================================================
// Document Schemas
// ============================================================================
/**
* Schema for reading a document
*/
export const ReadDocumentSchema = z.object({
document_id: z
.string()
.min(1)
.describe(
'飞书文档 ID 或完整 URL。支持格式:文档ID、https://xxx.feishu.cn/docx/xxx、https://xxx.feishu.cn/wiki/xxx'
),
format: z
.enum(['markdown', 'json'])
.default('markdown')
.describe('输出格式:markdown(默认,易读)或 json(结构化数据)'),
})
export type ReadDocumentInput = z.infer<typeof ReadDocumentSchema>
/**
* Schema for creating a document
*/
export const CreateDocumentSchema = z.object({
title: z.string().min(1).max(800).describe('文档标题,最长 800 字符'),
content: z
.string()
.optional()
.describe('文档内容,支持 Markdown 格式。包括标题、列表、代码块、引用等'),
folder_token: z
.string()
.optional()
.describe('目标文件夹 Token。不指定则创建在根目录'),
})
export type CreateDocumentInput = z.infer<typeof CreateDocumentSchema>
/**
* Schema for appending content to a document
*/
export const AppendContentSchema = z.object({
document_id: z.string().min(1).describe('飞书文档 ID 或 URL'),
content: z.string().min(1).describe('要追加的内容,支持 Markdown 格式'),
})
export type AppendContentInput = z.infer<typeof AppendContentSchema>
/**
* Schema for updating document content (replace)
*/
export const UpdateContentSchema = z.object({
document_id: z.string().min(1).describe('飞书文档 ID 或 URL'),
content: z.string().min(1).describe('新的文档内容,将替换除标题外的所有内容'),
})
export type UpdateContentInput = z.infer<typeof UpdateContentSchema>
// ============================================================================
// Block Schemas
// ============================================================================
/**
* Schema for inserting a Mermaid diagram
*/
export const InsertDiagramSchema = z.object({
document_id: z.string().min(1).describe('飞书文档 ID 或 URL'),
mermaid_code: z
.string()
.min(1)
.describe(
'Mermaid 图表代码,支持 flowchart、sequenceDiagram、classDiagram、graph 等类型'
),
block_id: z
.string()
.optional()
.describe('插入位置的 Block ID。不指定则追加到文档末尾'),
})
export type InsertDiagramInput = z.infer<typeof InsertDiagramSchema>
/**
* Schema for listing document blocks
*/
export const ListBlocksSchema = z.object({
document_id: z.string().min(1).describe('飞书文档 ID 或 URL'),
})
export type ListBlocksInput = z.infer<typeof ListBlocksSchema>
/**
* Schema for deleting a block
* SAFETY: Requires explicit user confirmation to prevent accidental deletion
*/
export const DeleteBlockSchema = z.object({
document_id: z.string().min(1).describe('飞书文档 ID 或 URL'),
block_id: z.string().min(1).describe('要删除的 Block ID'),
confirm: z
.boolean()
.optional()
.describe(
'【安全确认】必须设置为 true 才能执行删除。删除操作不可恢复,请确保用户已明确同意删除。'
),
})
export type DeleteBlockInput = z.infer<typeof DeleteBlockSchema>
// ============================================================================
// Search/Query Schemas
// ============================================================================
/**
* Schema for getting document info
*/
export const GetDocumentInfoSchema = z.object({
document_id: z.string().min(1).describe('飞书文档 ID 或 URL'),
})
export type GetDocumentInfoInput = z.infer<typeof GetDocumentInfoSchema>
// ============================================================================
// Table Schemas
// ============================================================================
/**
* Schema for inserting a table into a document
*/
export const InsertTableSchema = z.object({
document_id: z.string().min(1).describe('飞书文档 ID 或 URL'),
markdown_table: z
.string()
.optional()
.describe(
'Markdown 格式的表格。例如:| 列1 | 列2 |\\n|---|---|\\n| 值1 | 值2 |'
),
headers: z
.array(z.string())
.optional()
.describe('表头数组。与 rows 配合使用,二选一:markdown_table 或 headers+rows'),
rows: z
.array(z.array(z.string()))
.optional()
.describe('数据行数组。每行是一个字符串数组'),
header_row: z
.boolean()
.optional()
.default(true)
.describe('第一行是否为表头样式(默认 true)'),
column_width: z
.array(z.number())
.optional()
.describe('列宽数组(像素),不指定则自动分配'),
block_id: z
.string()
.optional()
.describe('插入位置的 Block ID。不指定则追加到文档末尾'),
})
export type InsertTableInput = z.infer<typeof InsertTableSchema>
// ============================================================================
// Export all schemas
// ============================================================================
export const schemas = {
ReadDocumentSchema,
CreateDocumentSchema,
AppendContentSchema,
UpdateContentSchema,
InsertDiagramSchema,
InsertTableSchema,
ListBlocksSchema,
DeleteBlockSchema,
GetDocumentInfoSchema,
}