get-yuque-toc
Retrieve the complete table of contents structure for Yuque knowledge bases to view document hierarchies, titles, and slugs for organized navigation.
Instructions
获取语雀知识库的完整目录结构(TOC)。
可以查看知识库中所有文档的层级结构、标题和 slug。
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No | 知识库命名空间 (例如: username/repo),如果未提供则使用默认命名空间 |
Input Schema (JSON Schema)
{
"properties": {
"namespace": {
"description": "知识库命名空间 (例如: username/repo),如果未提供则使用默认命名空间",
"type": "string"
}
},
"type": "object"
}
Implementation Reference
- src/index.ts:224-304 (handler)The main execution handler for the 'get-yuque-toc' tool. It validates the namespace, fetches the book metadata and TOC using API helpers, formats the output as Markdown tree, and returns it in the MCP content format.async ({ namespace }) => { try { const finalNamespace = namespace || YUQUE_CONFIG.namespace; if (!finalNamespace) { return { content: [ { type: "text", text: `错误: 请提供知识库命名空间。\n\n示例: "username/repo"`, }, ], }; } if (!isValidNamespace(finalNamespace)) { return { content: [ { type: "text", text: `错误: 命名空间格式无效。\n\n命名空间应该是 "username/repo" 的格式。`, }, ], }; } // 获取知识库信息 const book = await fetchYuqueBook(finalNamespace, YUQUE_CONFIG); if (!book) { return { content: [ { type: "text", text: `错误: 无法获取知识库 ${finalNamespace}。\n\n请检查命名空间是否正确,以及是否有访问权限。`, }, ], }; } // 获取目录 const toc = await fetchYuqueToc(finalNamespace, YUQUE_CONFIG); if (toc.length === 0) { return { content: [ { type: "text", text: `知识库 "${book.name}" 暂无文档。`, }, ], }; } // 格式化输出 let output = `# 知识库: ${book.name}\n\n`; output += `**命名空间**: ${book.namespace}\n`; output += `**描述**: ${book.description || "无"}\n`; output += `**文档数量**: ${book.items_count}\n`; output += `**链接**: https://www.yuque.com/${book.namespace}\n\n`; output += `---\n\n`; output += formatTocTree(toc); return { content: [ { type: "text", text: output, }, ], }; } catch (error) { return { content: [ { type: "text", text: `错误: ${error instanceof Error ? error.message : "未知错误"}`, }, ], }; } }
- src/index.ts:210-305 (registration)The registration of the 'get-yuque-toc' tool using McpServer.registerTool, including title, description, input schema, and handler reference.server.registerTool( "get-yuque-toc", { title: "获取知识库目录", description: `获取语雀知识库的完整目录结构(TOC)。 可以查看知识库中所有文档的层级结构、标题和 slug。`, inputSchema: { namespace: z .string() .optional() .describe("知识库命名空间 (例如: username/repo),如果未提供则使用默认命名空间"), }, }, async ({ namespace }) => { try { const finalNamespace = namespace || YUQUE_CONFIG.namespace; if (!finalNamespace) { return { content: [ { type: "text", text: `错误: 请提供知识库命名空间。\n\n示例: "username/repo"`, }, ], }; } if (!isValidNamespace(finalNamespace)) { return { content: [ { type: "text", text: `错误: 命名空间格式无效。\n\n命名空间应该是 "username/repo" 的格式。`, }, ], }; } // 获取知识库信息 const book = await fetchYuqueBook(finalNamespace, YUQUE_CONFIG); if (!book) { return { content: [ { type: "text", text: `错误: 无法获取知识库 ${finalNamespace}。\n\n请检查命名空间是否正确,以及是否有访问权限。`, }, ], }; } // 获取目录 const toc = await fetchYuqueToc(finalNamespace, YUQUE_CONFIG); if (toc.length === 0) { return { content: [ { type: "text", text: `知识库 "${book.name}" 暂无文档。`, }, ], }; } // 格式化输出 let output = `# 知识库: ${book.name}\n\n`; output += `**命名空间**: ${book.namespace}\n`; output += `**描述**: ${book.description || "无"}\n`; output += `**文档数量**: ${book.items_count}\n`; output += `**链接**: https://www.yuque.com/${book.namespace}\n\n`; output += `---\n\n`; output += formatTocTree(toc); return { content: [ { type: "text", text: output, }, ], }; } catch (error) { return { content: [ { type: "text", text: `错误: ${error instanceof Error ? error.message : "未知错误"}`, }, ], }; } } );
- src/index.ts:217-222 (schema)Zod-based input schema for the tool, defining the optional 'namespace' parameter.inputSchema: { namespace: z .string() .optional() .describe("知识库命名空间 (例如: username/repo),如果未提供则使用默认命名空间"), },
- src/lib/api.ts:109-133 (helper)Helper function that makes the API request to retrieve the TOC (table of contents) for a Yuque knowledge base.export async function fetchYuqueToc( namespace: string, config: YuqueConfig ): Promise<YuqueTocItem[]> { try { const url = `${config.baseUrl}/api/v2/repos/${namespace}/toc`; const response = await request(url, { method: "GET", headers: buildHeaders(config), }); if (response.statusCode === 200) { const result = (await response.body.json()) as YuqueApiResponse<YuqueTocItem[]>; return result.data || []; } else { const errorData = (await response.body.json()) as YuqueError; console.error("Yuque API error:", errorData); return []; } } catch (error) { console.error("Error fetching Yuque TOC:", error); return []; } }
- src/lib/api.ts:138-162 (helper)Helper function that fetches metadata for the Yuque knowledge base (book).export async function fetchYuqueBook( namespace: string, config: YuqueConfig ): Promise<YuqueBook | null> { try { const url = `${config.baseUrl}/api/v2/repos/${namespace}`; const response = await request(url, { method: "GET", headers: buildHeaders(config), }); if (response.statusCode === 200) { const result = (await response.body.json()) as YuqueApiResponse<YuqueBook>; return result.data; } else { const errorData = (await response.body.json()) as YuqueError; console.error("Yuque API error:", errorData); return null; } } catch (error) { console.error("Error fetching Yuque book:", error); return null; } }
- src/lib/utils.ts:114-145 (helper)Helper function that formats the TOC array into a hierarchical Markdown tree structure.export function formatTocTree(toc: YuqueTocItem[]): string { let output = `# 知识库目录\n\n`; const buildTree = (items: YuqueTocItem[], parentUuid: string = "", depth: number = 0): string => { let result = ""; const children = items.filter((item) => (item.parent_uuid || "") === parentUuid); children.forEach((item) => { const indent = " ".repeat(depth); const prefix = depth === 0 ? "#".repeat(Math.min(depth + 2, 6)) + " " : "- "; if (item.type === "TITLE") { result += `${indent}${prefix}**${item.title}**\n`; } else if (item.type === "DOC") { result += `${indent}${prefix}${item.title} \`[${item.slug}]\`\n`; } else if (item.type === "LINK") { result += `${indent}${prefix}[${item.title}](${item.url})\n`; } // 递归处理子节点 if (item.uuid) { result += buildTree(items, item.uuid, depth + 1); } }); return result; }; output += buildTree(toc); return output; }