yuque-mcp 0.1.0
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.
- package/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +215 -0
- package/README.zh-CN.md +231 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +12 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +37 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +72 -0
- package/dist/server.js.map +1 -0
- package/dist/services/types.d.ts +138 -0
- package/dist/services/types.d.ts.map +1 -0
- package/dist/services/types.js +3 -0
- package/dist/services/types.js.map +1 -0
- package/dist/services/yuque-client.d.ts +65 -0
- package/dist/services/yuque-client.d.ts.map +1 -0
- package/dist/services/yuque-client.js +269 -0
- package/dist/services/yuque-client.js.map +1 -0
- package/dist/tools/doc.d.ts +143 -0
- package/dist/tools/doc.d.ts.map +1 -0
- package/dist/tools/doc.js +131 -0
- package/dist/tools/doc.js.map +1 -0
- package/dist/tools/group.d.ts +71 -0
- package/dist/tools/group.d.ts.map +1 -0
- package/dist/tools/group.js +59 -0
- package/dist/tools/group.js.map +1 -0
- package/dist/tools/repo.d.ts +139 -0
- package/dist/tools/repo.d.ts.map +1 -0
- package/dist/tools/repo.js +124 -0
- package/dist/tools/repo.js.map +1 -0
- package/dist/tools/search.d.ts +27 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +22 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/stats.d.ts +77 -0
- package/dist/tools/stats.d.ts.map +1 -0
- package/dist/tools/stats.js +72 -0
- package/dist/tools/stats.js.map +1 -0
- package/dist/tools/toc.d.ts +45 -0
- package/dist/tools/toc.d.ts.map +1 -0
- package/dist/tools/toc.js +44 -0
- package/dist/tools/toc.js.map +1 -0
- package/dist/tools/user.d.ts +33 -0
- package/dist/tools/user.d.ts.map +1 -0
- package/dist/tools/user.js +37 -0
- package/dist/tools/user.js.map +1 -0
- package/dist/tools/version.d.ts +51 -0
- package/dist/tools/version.d.ts.map +1 -0
- package/dist/tools/version.js +54 -0
- package/dist/tools/version.js.map +1 -0
- package/dist/utils/error.d.ts +7 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +28 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/format.d.ts +78 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +87 -0
- package/dist/utils/format.js.map +1 -0
- package/package.json +68 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2025-02-15
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Initial release of Yuque MCP Server
|
|
14
|
+
- 25 tools covering Yuque API (user, repo, doc, toc, search, group, stats, version)
|
|
15
|
+
- Stdio transport for local MCP clients (Claude Desktop, Cursor, Claude Code)
|
|
16
|
+
- TypeScript implementation with strict mode
|
|
17
|
+
- Zod-based parameter validation for all tools
|
|
18
|
+
- AI-optimized response formatting (minimal token usage)
|
|
19
|
+
- Authentication via `YUQUE_TOKEN` environment variable or `--token` CLI argument
|
|
20
|
+
- Comprehensive test suite with vitest
|
|
21
|
+
- ESLint + Prettier code quality tooling
|
|
22
|
+
- CI pipeline (Node 18/20/22)
|
|
23
|
+
- Docker support
|
|
24
|
+
- Documentation in English and Chinese
|
|
25
|
+
|
|
26
|
+
[Unreleased]: https://github.com/chen201724/yuque-mcp-server/compare/v0.1.0...HEAD
|
|
27
|
+
[0.1.0]: https://github.com/chen201724/yuque-mcp-server/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 cwg
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# Yuque MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://github.com/chen201724/yuque-mcp-server/actions/workflows/ci.yml)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](https://modelcontextprotocol.io/)
|
|
7
|
+
|
|
8
|
+
MCP server for [Yuque (语雀)](https://www.yuque.com/) — expose your Yuque knowledge base to AI assistants through the [Model Context Protocol](https://modelcontextprotocol.io/).
|
|
9
|
+
|
|
10
|
+
[中文文档](./README.zh-CN.md)
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **25 Tools** — Complete coverage of Yuque API (docs, repos, search, groups, stats, TOC, versions)
|
|
15
|
+
- **Stdio Transport** — Works with Claude Desktop, Cursor, Claude Code, Windsurf, and any MCP-compatible client
|
|
16
|
+
- **Type-Safe** — Full TypeScript with strict mode + Zod parameter validation
|
|
17
|
+
- **AI-Optimized** — Response formatting designed to minimize token usage
|
|
18
|
+
- **Well-Tested** — Unit tests with vitest, CI on Node 18/20/22
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### 1. Get Your Yuque API Token
|
|
23
|
+
|
|
24
|
+
Visit [Yuque Developer Settings](https://www.yuque.com/settings/tokens) to generate a personal API token.
|
|
25
|
+
|
|
26
|
+
### 2. Configure Your MCP Client
|
|
27
|
+
|
|
28
|
+
#### Claude Code
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
claude mcp add yuque -- npx -y yuque-mcp --token=YOUR_TOKEN
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or add to `~/.claude/claude_desktop_config.json`:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"mcpServers": {
|
|
39
|
+
"yuque": {
|
|
40
|
+
"command": "npx",
|
|
41
|
+
"args": ["-y", "yuque-mcp"],
|
|
42
|
+
"env": {
|
|
43
|
+
"YUQUE_TOKEN": "YOUR_TOKEN"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### Claude Desktop
|
|
51
|
+
|
|
52
|
+
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"yuque": {
|
|
58
|
+
"command": "npx",
|
|
59
|
+
"args": ["-y", "yuque-mcp"],
|
|
60
|
+
"env": {
|
|
61
|
+
"YUQUE_TOKEN": "YOUR_TOKEN"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### Cursor
|
|
69
|
+
|
|
70
|
+
Add to `.cursor/mcp.json` in your project root:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"yuque": {
|
|
76
|
+
"command": "npx",
|
|
77
|
+
"args": ["-y", "yuque-mcp"],
|
|
78
|
+
"env": {
|
|
79
|
+
"YUQUE_TOKEN": "YOUR_TOKEN"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### Global Install (alternative)
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
npm install -g yuque-mcp
|
|
90
|
+
export YUQUE_TOKEN=your_token_here
|
|
91
|
+
yuque-mcp
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Available Tools
|
|
95
|
+
|
|
96
|
+
| Category | Tool | Description |
|
|
97
|
+
|----------|------|-------------|
|
|
98
|
+
| **User** | `yuque_get_user` | Get current user info |
|
|
99
|
+
| **User** | `yuque_list_groups` | List user's groups/teams |
|
|
100
|
+
| **Search** | `yuque_search` | Search docs, repos, or users |
|
|
101
|
+
| **Repos** | `yuque_list_repos` | List repos for user or group |
|
|
102
|
+
| **Repos** | `yuque_get_repo` | Get repo details |
|
|
103
|
+
| **Repos** | `yuque_create_repo` | Create new repo |
|
|
104
|
+
| **Repos** | `yuque_update_repo` | Update repo settings |
|
|
105
|
+
| **Repos** | `yuque_delete_repo` | Delete repo |
|
|
106
|
+
| **Docs** | `yuque_list_docs` | List documents in repo |
|
|
107
|
+
| **Docs** | `yuque_get_doc` | Get document with full content |
|
|
108
|
+
| **Docs** | `yuque_create_doc` | Create new document |
|
|
109
|
+
| **Docs** | `yuque_update_doc` | Update document |
|
|
110
|
+
| **Docs** | `yuque_delete_doc` | Delete document |
|
|
111
|
+
| **TOC** | `yuque_get_toc` | Get repo table of contents |
|
|
112
|
+
| **TOC** | `yuque_update_toc` | Update repo TOC |
|
|
113
|
+
| **Versions** | `yuque_list_doc_versions` | List document versions |
|
|
114
|
+
| **Versions** | `yuque_get_doc_version` | Get specific version |
|
|
115
|
+
| **Groups** | `yuque_list_group_members` | List group members |
|
|
116
|
+
| **Groups** | `yuque_update_group_member` | Update member role |
|
|
117
|
+
| **Groups** | `yuque_remove_group_member` | Remove member |
|
|
118
|
+
| **Stats** | `yuque_group_stats` | Group statistics |
|
|
119
|
+
| **Stats** | `yuque_group_member_stats` | Member statistics |
|
|
120
|
+
| **Stats** | `yuque_group_book_stats` | Book statistics |
|
|
121
|
+
| **Stats** | `yuque_group_doc_stats` | Document statistics |
|
|
122
|
+
| **Utility** | `yuque_hello` | Test API connectivity |
|
|
123
|
+
|
|
124
|
+
## Docker
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
docker build -t yuque-mcp .
|
|
128
|
+
docker run --rm -i -e YUQUE_TOKEN=your_token yuque-mcp
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
MCP client config with Docker:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"mcpServers": {
|
|
136
|
+
"yuque": {
|
|
137
|
+
"command": "docker",
|
|
138
|
+
"args": ["run", "--rm", "-i", "-e", "YUQUE_TOKEN", "yuque-mcp"],
|
|
139
|
+
"env": {
|
|
140
|
+
"YUQUE_TOKEN": "your_token_here"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Development
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
git clone https://github.com/chen201724/yuque-mcp-server.git
|
|
151
|
+
cd yuque-mcp-server
|
|
152
|
+
npm install
|
|
153
|
+
npm test # run tests
|
|
154
|
+
npm run test:coverage # with coverage
|
|
155
|
+
npm run build # compile TypeScript
|
|
156
|
+
npm run dev # dev mode with hot reload
|
|
157
|
+
npm run lint # lint
|
|
158
|
+
npm run format # format
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Architecture
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
src/
|
|
165
|
+
├── cli.ts — CLI entry (stdio transport)
|
|
166
|
+
├── index.ts — HTTP entry (self-hosted, optional)
|
|
167
|
+
├── server.ts — MCP server core
|
|
168
|
+
├── tools/ — Tool implementations (25 tools)
|
|
169
|
+
│ ├── user.ts — User & group listing
|
|
170
|
+
│ ├── repo.ts — Repository CRUD
|
|
171
|
+
│ ├── doc.ts — Document CRUD
|
|
172
|
+
│ ├── toc.ts — Table of contents
|
|
173
|
+
│ ├── search.ts — Full-text search
|
|
174
|
+
│ ├── group.ts — Group member management
|
|
175
|
+
│ ├── stats.ts — Analytics & statistics
|
|
176
|
+
│ └── version.ts — Document version history
|
|
177
|
+
├── services/
|
|
178
|
+
│ ├── yuque-client.ts — Yuque API HTTP client
|
|
179
|
+
│ └── types.ts — Type definitions
|
|
180
|
+
└── utils/
|
|
181
|
+
├── format.ts — AI-optimized response formatting
|
|
182
|
+
└── error.ts — Error handling & user-friendly messages
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Troubleshooting
|
|
186
|
+
|
|
187
|
+
**"YUQUE_TOKEN is required"**
|
|
188
|
+
Set the token via environment variable or `--token` argument. Get yours at [Yuque Settings](https://www.yuque.com/settings/tokens).
|
|
189
|
+
|
|
190
|
+
**"Request failed with status 401"**
|
|
191
|
+
Your token is invalid or expired. Generate a new one from Yuque settings.
|
|
192
|
+
|
|
193
|
+
**"Request failed with status 429"**
|
|
194
|
+
Rate limited by Yuque API. Wait a moment and retry.
|
|
195
|
+
|
|
196
|
+
**Tool not found**
|
|
197
|
+
Make sure you're using the latest version: `npx -y yuque-mcp@latest`
|
|
198
|
+
|
|
199
|
+
## Contributing
|
|
200
|
+
|
|
201
|
+
Contributions welcome! Please see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
202
|
+
|
|
203
|
+
## Security
|
|
204
|
+
|
|
205
|
+
For security issues, see [SECURITY.md](./SECURITY.md).
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
[MIT](./LICENSE)
|
|
210
|
+
|
|
211
|
+
## Links
|
|
212
|
+
|
|
213
|
+
- [Yuque API Documentation](https://www.yuque.com/yuque/developer/api)
|
|
214
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/)
|
|
215
|
+
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# 语雀 MCP 服务器
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.typescriptlang.org/)
|
|
5
|
+
[](https://modelcontextprotocol.io/)
|
|
6
|
+
|
|
7
|
+
语雀 API 的官方品质 MCP (Model Context Protocol) 服务器。该服务器通过标准化的 MCP 接口向 AI 助手暴露语雀的知识库能力。
|
|
8
|
+
|
|
9
|
+
[English Documentation](./README.md)
|
|
10
|
+
|
|
11
|
+
## 特性
|
|
12
|
+
|
|
13
|
+
- **完整 API 覆盖**:实现了全部 25 个语雀 API 端点
|
|
14
|
+
- **双传输模式**:支持 stdio 和 streamable-http 两种传输方式
|
|
15
|
+
- **类型安全**:完整的 TypeScript 实现,启用严格模式
|
|
16
|
+
- **AI 优化**:响应格式设计旨在最小化 token 使用
|
|
17
|
+
- **灵活认证**:支持环境变量或 CLI 参数认证
|
|
18
|
+
- **完善测试**:使用 vitest 进行全面测试覆盖
|
|
19
|
+
- **生产就绪**:遵循 Ant Design 开源标准
|
|
20
|
+
|
|
21
|
+
## 安装
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g yuque-mcp
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
或直接使用 npx:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx yuque-mcp --token=YOUR_TOKEN
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 快速开始
|
|
34
|
+
|
|
35
|
+
### 1. 获取语雀 API Token
|
|
36
|
+
|
|
37
|
+
访问 [语雀设置](https://www.yuque.com/settings/tokens) 生成你的 API token。
|
|
38
|
+
|
|
39
|
+
### 2. 运行服务器
|
|
40
|
+
|
|
41
|
+
**Stdio 模式(用于 MCP 客户端):**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
export YUQUE_TOKEN=your_token_here
|
|
45
|
+
yuque-mcp
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
或使用 CLI 参数:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
yuque-mcp --token=your_token_here
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**HTTP 模式(用于测试):**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
export YUQUE_TOKEN=your_token_here
|
|
58
|
+
npm start
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
服务器默认运行在 `http://localhost:3000`。
|
|
62
|
+
|
|
63
|
+
## 可用工具
|
|
64
|
+
|
|
65
|
+
### 用户与团队 (2 个工具)
|
|
66
|
+
- `yuque_get_user` - 获取当前用户信息
|
|
67
|
+
- `yuque_list_groups` - 列出用户的团队
|
|
68
|
+
|
|
69
|
+
### 搜索 (1 个工具)
|
|
70
|
+
- `yuque_search` - 搜索文档、知识库或用户
|
|
71
|
+
|
|
72
|
+
### 知识库 (5 个工具)
|
|
73
|
+
- `yuque_list_repos` - 列出用户或团队的知识库
|
|
74
|
+
- `yuque_get_repo` - 获取知识库详情
|
|
75
|
+
- `yuque_create_repo` - 创建新知识库
|
|
76
|
+
- `yuque_update_repo` - 更新知识库
|
|
77
|
+
- `yuque_delete_repo` - 删除知识库
|
|
78
|
+
|
|
79
|
+
### 文档 (5 个工具)
|
|
80
|
+
- `yuque_list_docs` - 列出知识库中的文档
|
|
81
|
+
- `yuque_get_doc` - 获取文档完整内容
|
|
82
|
+
- `yuque_create_doc` - 创建新文档
|
|
83
|
+
- `yuque_update_doc` - 更新文档
|
|
84
|
+
- `yuque_delete_doc` - 删除文档
|
|
85
|
+
|
|
86
|
+
### 目录 (2 个工具)
|
|
87
|
+
- `yuque_get_toc` - 获取知识库目录
|
|
88
|
+
- `yuque_update_toc` - 更新知识库目录
|
|
89
|
+
|
|
90
|
+
### 文档版本 (2 个工具)
|
|
91
|
+
- `yuque_list_doc_versions` - 列出文档版本
|
|
92
|
+
- `yuque_get_doc_version` - 获取特定版本
|
|
93
|
+
|
|
94
|
+
### 团队管理 (3 个工具)
|
|
95
|
+
- `yuque_list_group_members` - 列出团队成员
|
|
96
|
+
- `yuque_update_group_member` - 更新成员角色
|
|
97
|
+
- `yuque_remove_group_member` - 移除成员
|
|
98
|
+
|
|
99
|
+
### 统计 (4 个工具)
|
|
100
|
+
- `yuque_group_stats` - 团队统计
|
|
101
|
+
- `yuque_group_member_stats` - 成员统计
|
|
102
|
+
- `yuque_group_book_stats` - 知识库统计
|
|
103
|
+
- `yuque_group_doc_stats` - 文档统计
|
|
104
|
+
|
|
105
|
+
### 工具 (1 个工具)
|
|
106
|
+
- `yuque_hello` - 测试 API 连接
|
|
107
|
+
|
|
108
|
+
## Docker
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# 构建镜像
|
|
112
|
+
docker build -t yuque-mcp .
|
|
113
|
+
|
|
114
|
+
# 运行(stdio 模式)
|
|
115
|
+
docker run --rm -i -e YUQUE_TOKEN=your_token yuque-mcp
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Docker 方式的 MCP 客户端配置:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"mcpServers": {
|
|
123
|
+
"yuque": {
|
|
124
|
+
"command": "docker",
|
|
125
|
+
"args": ["run", "--rm", "-i", "-e", "YUQUE_TOKEN", "yuque-mcp"],
|
|
126
|
+
"env": {
|
|
127
|
+
"YUQUE_TOKEN": "your_token_here"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 配置
|
|
135
|
+
|
|
136
|
+
### 环境变量
|
|
137
|
+
|
|
138
|
+
- `YUQUE_TOKEN` - 你的语雀 API token(必需)
|
|
139
|
+
- `PORT` - HTTP 服务器端口(默认:3000,仅 HTTP 模式)
|
|
140
|
+
|
|
141
|
+
### MCP 客户端配置
|
|
142
|
+
|
|
143
|
+
添加到你的 MCP 客户端配置(例如 Claude Desktop):
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"mcpServers": {
|
|
148
|
+
"yuque": {
|
|
149
|
+
"command": "yuque-mcp",
|
|
150
|
+
"env": {
|
|
151
|
+
"YUQUE_TOKEN": "your_token_here"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## 开发
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# 克隆仓库
|
|
162
|
+
git clone https://github.com/chen201724/yuque-mcp-server.git
|
|
163
|
+
cd yuque-mcp-server
|
|
164
|
+
|
|
165
|
+
# 安装依赖
|
|
166
|
+
npm install
|
|
167
|
+
|
|
168
|
+
# 运行测试
|
|
169
|
+
npm test
|
|
170
|
+
|
|
171
|
+
# 运行测试覆盖率
|
|
172
|
+
npm run test:coverage
|
|
173
|
+
|
|
174
|
+
# 构建
|
|
175
|
+
npm run build
|
|
176
|
+
|
|
177
|
+
# 开发模式(热重载)
|
|
178
|
+
npm run dev
|
|
179
|
+
|
|
180
|
+
# 代码检查
|
|
181
|
+
npm run lint
|
|
182
|
+
|
|
183
|
+
# 代码格式化
|
|
184
|
+
npm run format
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## 架构
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
src/
|
|
191
|
+
├── index.ts — HTTP 服务器入口
|
|
192
|
+
├── cli.ts — CLI 入口(stdio)
|
|
193
|
+
├── server.ts — MCP 服务器核心
|
|
194
|
+
├── tools/ — 工具实现(按领域划分)
|
|
195
|
+
│ ├── user.ts
|
|
196
|
+
│ ├── repo.ts
|
|
197
|
+
│ ├── doc.ts
|
|
198
|
+
│ ├── toc.ts
|
|
199
|
+
│ ├── search.ts
|
|
200
|
+
│ ├── group.ts
|
|
201
|
+
│ ├── stats.ts
|
|
202
|
+
│ └── version.ts
|
|
203
|
+
├── services/
|
|
204
|
+
│ ├── yuque-client.ts — 语雀 API 客户端
|
|
205
|
+
│ └── types.ts — 类型定义
|
|
206
|
+
└── utils/
|
|
207
|
+
├── format.ts — 响应格式化
|
|
208
|
+
└── error.ts — 错误处理
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## 贡献
|
|
212
|
+
|
|
213
|
+
我们欢迎贡献!详情请参阅 [CONTRIBUTING.md](./CONTRIBUTING.md)。
|
|
214
|
+
|
|
215
|
+
## 安全
|
|
216
|
+
|
|
217
|
+
安全问题请参阅 [SECURITY.md](./SECURITY.md)。
|
|
218
|
+
|
|
219
|
+
## 许可证
|
|
220
|
+
|
|
221
|
+
[MIT](./LICENSE)
|
|
222
|
+
|
|
223
|
+
## 链接
|
|
224
|
+
|
|
225
|
+
- [语雀 API 文档](https://www.yuque.com/yuque/developer/api)
|
|
226
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/)
|
|
227
|
+
- [语雀官网](https://www.yuque.com/)
|
|
228
|
+
|
|
229
|
+
## 致谢
|
|
230
|
+
|
|
231
|
+
本项目受 [Notion MCP Server](https://github.com/makenotion/notion-mcp-server) 启发,遵循 Ant Design 开源标准。
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runStdioServer } from './server.js';
|
|
3
|
+
const token = process.env.YUQUE_TOKEN || process.argv.find((arg) => arg.startsWith('--token='))?.split('=')[1];
|
|
4
|
+
if (!token) {
|
|
5
|
+
console.error('Error: YUQUE_TOKEN environment variable or --token argument is required');
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
runStdioServer(token).catch((error) => {
|
|
9
|
+
console.error('Fatal error:', error);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/G,IAAI,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;IACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,cAAc,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACpC,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createServer as createMCPServer } from './server.js';
|
|
2
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
3
|
+
import { createServer } from 'node:http';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
const token = process.env.YUQUE_TOKEN;
|
|
6
|
+
if (!token) {
|
|
7
|
+
console.error('Error: YUQUE_TOKEN environment variable is required');
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const mcpServer = createMCPServer(token);
|
|
11
|
+
const transport = new StreamableHTTPServerTransport({
|
|
12
|
+
sessionIdGenerator: () => randomUUID(),
|
|
13
|
+
});
|
|
14
|
+
mcpServer.connect(transport).then(() => {
|
|
15
|
+
const port = Number(process.env.PORT) || 3000;
|
|
16
|
+
const httpServer = createServer((req, res) => {
|
|
17
|
+
transport.handleRequest(req, res).catch((error) => {
|
|
18
|
+
console.error('Request handling error:', error);
|
|
19
|
+
res.statusCode = 500;
|
|
20
|
+
res.end('Internal Server Error');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
httpServer.listen(port, () => {
|
|
24
|
+
console.log(`Yuque MCP Server running on http://localhost:${port}`);
|
|
25
|
+
});
|
|
26
|
+
}).catch((error) => {
|
|
27
|
+
console.error('Failed to start server:', error);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;AAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,SAAS,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;AACzC,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;IAClD,kBAAkB,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;CACvC,CAAC,CAAC;AAEH,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAC9C,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC3C,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YAChD,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QAC3B,OAAO,CAAC,GAAG,CAAC,gDAAgD,IAAI,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
export declare function createServer(token: string): Server<{
|
|
3
|
+
method: string;
|
|
4
|
+
params?: {
|
|
5
|
+
[x: string]: unknown;
|
|
6
|
+
_meta?: {
|
|
7
|
+
[x: string]: unknown;
|
|
8
|
+
progressToken?: string | number | undefined;
|
|
9
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
10
|
+
taskId: string;
|
|
11
|
+
} | undefined;
|
|
12
|
+
} | undefined;
|
|
13
|
+
} | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
method: string;
|
|
16
|
+
params?: {
|
|
17
|
+
[x: string]: unknown;
|
|
18
|
+
_meta?: {
|
|
19
|
+
[x: string]: unknown;
|
|
20
|
+
progressToken?: string | number | undefined;
|
|
21
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
22
|
+
taskId: string;
|
|
23
|
+
} | undefined;
|
|
24
|
+
} | undefined;
|
|
25
|
+
} | undefined;
|
|
26
|
+
}, {
|
|
27
|
+
[x: string]: unknown;
|
|
28
|
+
_meta?: {
|
|
29
|
+
[x: string]: unknown;
|
|
30
|
+
progressToken?: string | number | undefined;
|
|
31
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
32
|
+
taskId: string;
|
|
33
|
+
} | undefined;
|
|
34
|
+
} | undefined;
|
|
35
|
+
}>;
|
|
36
|
+
export declare function runStdioServer(token: string): Promise<void>;
|
|
37
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAgBnE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DzC;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,iBAKjD"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { YuqueClient } from './services/yuque-client.js';
|
|
5
|
+
import { userTools } from './tools/user.js';
|
|
6
|
+
import { repoTools } from './tools/repo.js';
|
|
7
|
+
import { docTools } from './tools/doc.js';
|
|
8
|
+
import { tocTools } from './tools/toc.js';
|
|
9
|
+
import { searchTools } from './tools/search.js';
|
|
10
|
+
import { groupTools } from './tools/group.js';
|
|
11
|
+
import { statsTools } from './tools/stats.js';
|
|
12
|
+
import { versionTools } from './tools/version.js';
|
|
13
|
+
export function createServer(token) {
|
|
14
|
+
const client = new YuqueClient(token);
|
|
15
|
+
const server = new Server({
|
|
16
|
+
name: 'yuque-mcp',
|
|
17
|
+
version: '0.1.0',
|
|
18
|
+
}, {
|
|
19
|
+
capabilities: {
|
|
20
|
+
tools: {},
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
// Combine all tools
|
|
24
|
+
const allTools = {
|
|
25
|
+
...userTools,
|
|
26
|
+
...repoTools,
|
|
27
|
+
...docTools,
|
|
28
|
+
...tocTools,
|
|
29
|
+
...searchTools,
|
|
30
|
+
...groupTools,
|
|
31
|
+
...statsTools,
|
|
32
|
+
...versionTools,
|
|
33
|
+
};
|
|
34
|
+
// Register list_tools handler
|
|
35
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
36
|
+
return {
|
|
37
|
+
tools: Object.entries(allTools).map(([name, tool]) => ({
|
|
38
|
+
name,
|
|
39
|
+
description: tool.description,
|
|
40
|
+
inputSchema: tool.inputSchema,
|
|
41
|
+
})),
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
// Register call_tool handler
|
|
45
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
46
|
+
const toolName = request.params.name;
|
|
47
|
+
const tool = allTools[toolName];
|
|
48
|
+
if (!tool) {
|
|
49
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
// Validate arguments with zod
|
|
53
|
+
const args = tool.inputSchema.parse(request.params.arguments);
|
|
54
|
+
// Call the tool handler
|
|
55
|
+
return await tool.handler(client, args);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error instanceof Error) {
|
|
59
|
+
throw new Error(`Tool execution failed: ${error.message}`);
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return server;
|
|
65
|
+
}
|
|
66
|
+
export async function runStdioServer(token) {
|
|
67
|
+
const server = createServer(token);
|
|
68
|
+
const transport = new StdioServerTransport();
|
|
69
|
+
await server.connect(transport);
|
|
70
|
+
console.error('Yuque MCP Server running on stdio');
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|