feishu-mcp 0.1.7 → 0.1.8
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/LICENSE +21 -21
- package/README.md +261 -251
- package/dist/mcp/feishuMcp.js +1 -1
- package/dist/mcp/tools/feishuBlockTools.js +37 -30
- package/dist/mcp/tools/feishuFolderTools.js +95 -30
- package/dist/mcp/tools/feishuTools.js +84 -30
- package/dist/services/feishuApiService.js +470 -67
- package/dist/types/feishuSchema.js +30 -4
- package/dist/utils/document.js +114 -114
- package/package.json +75 -75
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
//
|
|
2
|
+
// 文档类型枚举(用于 get_feishu_document_info)
|
|
3
|
+
export const DocumentTypeSchema = z.enum(['document', 'wiki']).optional().describe('Document type (optional). "document" for regular document, "wiki" for Wiki document.');
|
|
4
|
+
// 文档ID或URL参数定义(仅支持普通文档)
|
|
3
5
|
export const DocumentIdSchema = z.string().describe('Document ID or URL (required). Supports the following formats:\n' +
|
|
4
6
|
'1. Standard document URL: https://xxx.feishu.cn/docs/xxx or https://xxx.feishu.cn/docx/xxx\n' +
|
|
5
|
-
'2. Direct document ID: e.g., JcKbdlokYoPIe0xDzJ1cduRXnRf
|
|
6
|
-
|
|
7
|
+
'2. Direct document ID: e.g., JcKbdlokYoPIe0xDzJ1cduRXnRf');
|
|
8
|
+
// 文档ID或Wiki ID参数定义(用于 get_feishu_document_info,支持普通文档和Wiki文档)
|
|
9
|
+
export const DocumentIdOrWikiIdSchema = z.string().describe('Document ID, URL, or Wiki ID/URL (required). Supports regular document formats (https://xxx.feishu.cn/docx/xxx or direct ID) and Wiki formats (https://xxx.feishu.cn/wiki/xxxxx or Wiki token).');
|
|
7
10
|
// 父块ID参数定义
|
|
8
11
|
export const ParentBlockIdSchema = z.string().describe('Parent block ID (required). Target block ID where content will be added, without any URL prefix. ' +
|
|
9
12
|
'For page-level (root level) insertion, extract and use only the document ID portion (not the full URL) as parentBlockId. ' +
|
|
@@ -179,13 +182,36 @@ export const MediaIdSchema = z.string().describe('Media ID (required). The uniqu
|
|
|
179
182
|
// 额外参数定义 - 用于媒体资源下载
|
|
180
183
|
export const MediaExtraSchema = z.string().optional().describe('Extra parameters for media download (optional). ' +
|
|
181
184
|
'These parameters are passed directly to the Feishu API and can modify how the media is returned.');
|
|
182
|
-
// 文件夹Token
|
|
185
|
+
// 文件夹Token参数定义(必传)
|
|
183
186
|
export const FolderTokenSchema = z.string().describe('Folder token (required). The unique identifier for a folder in Feishu. ' +
|
|
184
187
|
'Format is an alphanumeric string like "FWK2fMleClICfodlHHWc4Mygnhb".');
|
|
188
|
+
// 文件夹Token参数定义(可选,用于文档创建、获取文件列表等场景)
|
|
189
|
+
export const FolderTokenOptionalSchema = z.string().optional().describe('Folder token (optional, for Feishu Drive folder mode). The unique identifier for a folder in Feishu Drive. ' +
|
|
190
|
+
'Format is an alphanumeric string like "FWK2fMleClICfodlHHWc4Mygnhb". ');
|
|
185
191
|
// 文件夹名称参数定义
|
|
186
192
|
export const FolderNameSchema = z.string().describe('Folder name (required). The name for the new folder to be created.');
|
|
193
|
+
// 知识空间ID参数定义
|
|
194
|
+
export const SpaceIdSchema = z.string().describe('Space ID (optional, required for wiki space mode). The unique identifier for a wiki space in Feishu. ' +
|
|
195
|
+
'Can be obtained from get_feishu_root_folder_info (wiki_spaces array or my_library.space_id). ' +
|
|
196
|
+
'Format is typically like "74812***88644".');
|
|
197
|
+
// 父节点Token参数定义
|
|
198
|
+
export const ParentNodeTokenSchema = z.string().optional().describe('Parent node token (optional, used with spaceId). The token of the parent node in a wiki space. ' +
|
|
199
|
+
'If not provided or empty, will retrieve nodes from the root of the wiki space. ' +
|
|
200
|
+
'Format is typically like "PdDWwIHD6****MhcIOY7npg".');
|
|
201
|
+
// 知识库节点上下文参数定义(包装 spaceId 和 parentNodeToken)
|
|
202
|
+
export const WikiSpaceNodeContextSchema = z.object({
|
|
203
|
+
spaceId: SpaceIdSchema.optional(),
|
|
204
|
+
parentNodeToken: ParentNodeTokenSchema,
|
|
205
|
+
}).optional().describe('Wiki space node context object. Contains spaceId (required when using this object) and optional parentNodeToken. ' +
|
|
206
|
+
'Used for wiki space operations instead of folderToken.');
|
|
187
207
|
// 搜索关键字参数定义
|
|
188
208
|
export const SearchKeySchema = z.string().describe('Search keyword (required). The keyword to search for in documents.');
|
|
209
|
+
// 搜索类型枚举
|
|
210
|
+
export const SearchTypeSchema = z.enum(['document', 'wiki', 'both']).optional().default('both').describe('Search type (optional, default: "both"). "document": only documents, "wiki": only wiki nodes, "both": both (default)');
|
|
211
|
+
// 知识库分页token参数定义
|
|
212
|
+
export const PageTokenSchema = z.string().optional().describe('Wiki page token (optional). Token from previous wiki search result for pagination. Only needed when fetching next page of wiki results.');
|
|
213
|
+
// 文档分页偏移量参数定义
|
|
214
|
+
export const OffsetSchema = z.number().optional().describe('Document offset (optional). Offset for document search pagination. Only needed when fetching next page of document results.');
|
|
189
215
|
// 图片路径或URL参数定义
|
|
190
216
|
export const ImagePathOrUrlSchema = z.string().describe('Image path or URL (required). Supports the following formats:\n' +
|
|
191
217
|
'1. Local file absolute path: e.g., "C:\\path\\to\\image.jpg"\n' +
|
package/dist/utils/document.js
CHANGED
|
@@ -136,127 +136,127 @@ export function renderFeishuAuthResultHtml(data) {
|
|
|
136
136
|
expiresIn = expiresIn - now;
|
|
137
137
|
if (refreshExpiresIn && refreshExpiresIn > 1000000000)
|
|
138
138
|
refreshExpiresIn = refreshExpiresIn - now;
|
|
139
|
-
const tokenBlock = data && !isError ? `
|
|
140
|
-
<div class="card">
|
|
141
|
-
<h3>Token 信息</h3>
|
|
142
|
-
<ul class="kv-list">
|
|
143
|
-
<li><b>token_type:</b> <span>${data.token_type || ''}</span></li>
|
|
144
|
-
<li><b>access_token:</b> <span class="foldable" onclick="toggleFold(this)">点击展开/收起</span><pre class="fold scrollable">${data.access_token || ''}</pre></li>
|
|
145
|
-
<li><b>expires_in:</b> <span>${formatExpire(expiresIn)}</span></li>
|
|
146
|
-
<li><b>refresh_token:</b> <span class="foldable" onclick="toggleFold(this)">点击展开/收起</span><pre class="fold scrollable">${data.refresh_token || ''}</pre></li>
|
|
147
|
-
<li><b>refresh_token_expires_in:</b> <span>${formatExpire(refreshExpiresIn)}</span></li>
|
|
148
|
-
<li><b>scope:</b> <pre class="scope">${(data.scope || '').replace(/ /g, '\n')}</pre></li>
|
|
149
|
-
</ul>
|
|
150
|
-
<div class="success-action">
|
|
151
|
-
<span class="success-msg">授权成功,继续完成任务</span>
|
|
152
|
-
<button class="copy-btn" onclick="copySuccessMsg(this)">点击复制到粘贴板</button>
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
139
|
+
const tokenBlock = data && !isError ? `
|
|
140
|
+
<div class="card">
|
|
141
|
+
<h3>Token 信息</h3>
|
|
142
|
+
<ul class="kv-list">
|
|
143
|
+
<li><b>token_type:</b> <span>${data.token_type || ''}</span></li>
|
|
144
|
+
<li><b>access_token:</b> <span class="foldable" onclick="toggleFold(this)">点击展开/收起</span><pre class="fold scrollable">${data.access_token || ''}</pre></li>
|
|
145
|
+
<li><b>expires_in:</b> <span>${formatExpire(expiresIn)}</span></li>
|
|
146
|
+
<li><b>refresh_token:</b> <span class="foldable" onclick="toggleFold(this)">点击展开/收起</span><pre class="fold scrollable">${data.refresh_token || ''}</pre></li>
|
|
147
|
+
<li><b>refresh_token_expires_in:</b> <span>${formatExpire(refreshExpiresIn)}</span></li>
|
|
148
|
+
<li><b>scope:</b> <pre class="scope">${(data.scope || '').replace(/ /g, '\n')}</pre></li>
|
|
149
|
+
</ul>
|
|
150
|
+
<div class="success-action">
|
|
151
|
+
<span class="success-msg">授权成功,继续完成任务</span>
|
|
152
|
+
<button class="copy-btn" onclick="copySuccessMsg(this)">点击复制到粘贴板</button>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
155
|
` : '';
|
|
156
156
|
let userBlock = '';
|
|
157
157
|
const userInfo = data && data.userInfo && data.userInfo.data;
|
|
158
158
|
if (userInfo) {
|
|
159
|
-
userBlock = `
|
|
160
|
-
<div class="card user-card">
|
|
161
|
-
<div class="avatar-wrap">
|
|
162
|
-
<img src="${userInfo.avatar_big || userInfo.avatar_thumb || userInfo.avatar_url || ''}" class="avatar" />
|
|
163
|
-
</div>
|
|
164
|
-
<div class="user-info">
|
|
165
|
-
<div class="user-name">${userInfo.name || ''}</div>
|
|
166
|
-
<div class="user-en">${userInfo.en_name || ''}</div>
|
|
167
|
-
</div>
|
|
168
|
-
</div>
|
|
159
|
+
userBlock = `
|
|
160
|
+
<div class="card user-card">
|
|
161
|
+
<div class="avatar-wrap">
|
|
162
|
+
<img src="${userInfo.avatar_big || userInfo.avatar_thumb || userInfo.avatar_url || ''}" class="avatar" />
|
|
163
|
+
</div>
|
|
164
|
+
<div class="user-info">
|
|
165
|
+
<div class="user-name">${userInfo.name || ''}</div>
|
|
166
|
+
<div class="user-en">${userInfo.en_name || ''}</div>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
169
|
`;
|
|
170
170
|
}
|
|
171
|
-
const errorBlock = isError ? `
|
|
172
|
-
<div class="card error-card">
|
|
173
|
-
<h3>授权失败</h3>
|
|
174
|
-
<div class="error-msg">${escapeHtml(data.error || '')}</div>
|
|
175
|
-
<div class="error-code">错误码: ${data.code || ''}</div>
|
|
176
|
-
</div>
|
|
171
|
+
const errorBlock = isError ? `
|
|
172
|
+
<div class="card error-card">
|
|
173
|
+
<h3>授权失败</h3>
|
|
174
|
+
<div class="error-msg">${escapeHtml(data.error || '')}</div>
|
|
175
|
+
<div class="error-code">错误码: ${data.code || ''}</div>
|
|
176
|
+
</div>
|
|
177
177
|
` : '';
|
|
178
|
-
return `
|
|
179
|
-
<html>
|
|
180
|
-
<head>
|
|
181
|
-
<title>飞书授权结果</title>
|
|
182
|
-
<meta charset="utf-8"/>
|
|
183
|
-
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
184
|
-
<style>
|
|
185
|
-
body { background: #f7f8fa; font-family: 'Segoe UI', Arial, sans-serif; margin:0; padding:0; }
|
|
186
|
-
.container { max-width: 600px; margin: 40px auto; padding: 16px; }
|
|
187
|
-
.card { background: #fff; border-radius: 12px; box-shadow: 0 2px 12px #0001; margin-bottom: 24px; padding: 24px 20px; }
|
|
188
|
-
.user-card { display: flex; align-items: center; gap: 24px; }
|
|
189
|
-
.avatar-wrap { flex-shrink: 0; }
|
|
190
|
-
.avatar { width: 96px; height: 96px; border-radius: 50%; box-shadow: 0 2px 8px #0002; display: block; margin: 0 auto; }
|
|
191
|
-
.user-info { flex: 1; }
|
|
192
|
-
.user-name { font-size: 1.5em; font-weight: bold; margin-bottom: 4px; }
|
|
193
|
-
.user-en { color: #888; margin-bottom: 10px; }
|
|
194
|
-
.kv-list { list-style: none; padding: 0; margin: 0; }
|
|
195
|
-
.kv-list li { margin-bottom: 6px; word-break: break-all; }
|
|
196
|
-
.kv-list b { color: #1976d2; }
|
|
197
|
-
.scope { background: #f0f4f8; border-radius: 4px; padding: 6px; font-size: 0.95em; white-space: pre-line; }
|
|
198
|
-
.foldable { color: #1976d2; cursor: pointer; text-decoration: underline; margin-left: 8px; }
|
|
199
|
-
.fold { display: none; background: #f6f6f6; border-radius: 4px; padding: 6px; margin: 4px 0; font-size: 0.92em; max-width: 100%; overflow-x: auto; word-break: break-all; }
|
|
200
|
-
.scrollable { max-width: 100%; overflow-x: auto; font-family: 'Fira Mono', 'Consolas', 'Menlo', monospace; font-size: 0.93em; }
|
|
201
|
-
.success-action { margin-top: 18px; display: flex; align-items: center; gap: 16px; }
|
|
202
|
-
.success-msg { color: #388e3c; font-weight: bold; }
|
|
203
|
-
.copy-btn { background: #1976d2; color: #fff; border: none; border-radius: 4px; padding: 6px 16px; font-size: 1em; cursor: pointer; transition: background 0.2s; }
|
|
204
|
-
.copy-btn:hover { background: #125ea2; }
|
|
205
|
-
.error-card { border-left: 6px solid #e53935; background: #fff0f0; color: #b71c1c; }
|
|
206
|
-
.error-msg { font-size: 1.1em; margin-bottom: 8px; }
|
|
207
|
-
.error-code { color: #b71c1c; font-size: 0.95em; }
|
|
208
|
-
.raw-block { margin-top: 24px; }
|
|
209
|
-
.raw-toggle { color: #1976d2; cursor: pointer; text-decoration: underline; margin-bottom: 8px; display: inline-block; }
|
|
210
|
-
.raw-pre { display: none; background: #23272e; color: #fff; border-radius: 6px; padding: 12px; font-size: 0.95em; overflow-x: auto; max-width: 100%; }
|
|
211
|
-
@media (max-width: 700px) {
|
|
212
|
-
.container { max-width: 98vw; padding: 4vw; }
|
|
213
|
-
.card { padding: 4vw 3vw; }
|
|
214
|
-
.avatar { width: 64px; height: 64px; }
|
|
215
|
-
}
|
|
216
|
-
</style>
|
|
217
|
-
<script>
|
|
218
|
-
function toggleFold(el) {
|
|
219
|
-
var pre = el.nextElementSibling;
|
|
220
|
-
if (pre.style.display === 'block') {
|
|
221
|
-
pre.style.display = 'none';
|
|
222
|
-
} else {
|
|
223
|
-
pre.style.display = 'block';
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
function toggleRaw() {
|
|
227
|
-
var pre = document.getElementById('raw-pre');
|
|
228
|
-
if (pre.style.display === 'block') {
|
|
229
|
-
pre.style.display = 'none';
|
|
230
|
-
} else {
|
|
231
|
-
pre.style.display = 'block';
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
function copySuccessMsg(btn) {
|
|
235
|
-
var text = '授权成功,继续完成任务';
|
|
236
|
-
navigator.clipboard.writeText(text).then(function() {
|
|
237
|
-
btn.innerText = '已复制';
|
|
238
|
-
btn.disabled = true;
|
|
239
|
-
setTimeout(function() {
|
|
240
|
-
btn.innerText = '点击复制到粘贴板';
|
|
241
|
-
btn.disabled = false;
|
|
242
|
-
}, 2000);
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
</script>
|
|
246
|
-
</head>
|
|
247
|
-
<body>
|
|
248
|
-
<div class="container">
|
|
249
|
-
<h2 style="margin-bottom:24px;">飞书授权结果</h2>
|
|
250
|
-
${errorBlock}
|
|
251
|
-
${tokenBlock}
|
|
252
|
-
${userBlock}
|
|
253
|
-
<div class="card raw-block">
|
|
254
|
-
<span class="raw-toggle" onclick="toggleRaw()">点击展开/收起原始数据</span>
|
|
255
|
-
<pre id="raw-pre" class="raw-pre">${escapeHtml(JSON.stringify(data, null, 2))}</pre>
|
|
256
|
-
</div>
|
|
257
|
-
</div>
|
|
258
|
-
</body>
|
|
259
|
-
</html>
|
|
178
|
+
return `
|
|
179
|
+
<html>
|
|
180
|
+
<head>
|
|
181
|
+
<title>飞书授权结果</title>
|
|
182
|
+
<meta charset="utf-8"/>
|
|
183
|
+
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
184
|
+
<style>
|
|
185
|
+
body { background: #f7f8fa; font-family: 'Segoe UI', Arial, sans-serif; margin:0; padding:0; }
|
|
186
|
+
.container { max-width: 600px; margin: 40px auto; padding: 16px; }
|
|
187
|
+
.card { background: #fff; border-radius: 12px; box-shadow: 0 2px 12px #0001; margin-bottom: 24px; padding: 24px 20px; }
|
|
188
|
+
.user-card { display: flex; align-items: center; gap: 24px; }
|
|
189
|
+
.avatar-wrap { flex-shrink: 0; }
|
|
190
|
+
.avatar { width: 96px; height: 96px; border-radius: 50%; box-shadow: 0 2px 8px #0002; display: block; margin: 0 auto; }
|
|
191
|
+
.user-info { flex: 1; }
|
|
192
|
+
.user-name { font-size: 1.5em; font-weight: bold; margin-bottom: 4px; }
|
|
193
|
+
.user-en { color: #888; margin-bottom: 10px; }
|
|
194
|
+
.kv-list { list-style: none; padding: 0; margin: 0; }
|
|
195
|
+
.kv-list li { margin-bottom: 6px; word-break: break-all; }
|
|
196
|
+
.kv-list b { color: #1976d2; }
|
|
197
|
+
.scope { background: #f0f4f8; border-radius: 4px; padding: 6px; font-size: 0.95em; white-space: pre-line; }
|
|
198
|
+
.foldable { color: #1976d2; cursor: pointer; text-decoration: underline; margin-left: 8px; }
|
|
199
|
+
.fold { display: none; background: #f6f6f6; border-radius: 4px; padding: 6px; margin: 4px 0; font-size: 0.92em; max-width: 100%; overflow-x: auto; word-break: break-all; }
|
|
200
|
+
.scrollable { max-width: 100%; overflow-x: auto; font-family: 'Fira Mono', 'Consolas', 'Menlo', monospace; font-size: 0.93em; }
|
|
201
|
+
.success-action { margin-top: 18px; display: flex; align-items: center; gap: 16px; }
|
|
202
|
+
.success-msg { color: #388e3c; font-weight: bold; }
|
|
203
|
+
.copy-btn { background: #1976d2; color: #fff; border: none; border-radius: 4px; padding: 6px 16px; font-size: 1em; cursor: pointer; transition: background 0.2s; }
|
|
204
|
+
.copy-btn:hover { background: #125ea2; }
|
|
205
|
+
.error-card { border-left: 6px solid #e53935; background: #fff0f0; color: #b71c1c; }
|
|
206
|
+
.error-msg { font-size: 1.1em; margin-bottom: 8px; }
|
|
207
|
+
.error-code { color: #b71c1c; font-size: 0.95em; }
|
|
208
|
+
.raw-block { margin-top: 24px; }
|
|
209
|
+
.raw-toggle { color: #1976d2; cursor: pointer; text-decoration: underline; margin-bottom: 8px; display: inline-block; }
|
|
210
|
+
.raw-pre { display: none; background: #23272e; color: #fff; border-radius: 6px; padding: 12px; font-size: 0.95em; overflow-x: auto; max-width: 100%; }
|
|
211
|
+
@media (max-width: 700px) {
|
|
212
|
+
.container { max-width: 98vw; padding: 4vw; }
|
|
213
|
+
.card { padding: 4vw 3vw; }
|
|
214
|
+
.avatar { width: 64px; height: 64px; }
|
|
215
|
+
}
|
|
216
|
+
</style>
|
|
217
|
+
<script>
|
|
218
|
+
function toggleFold(el) {
|
|
219
|
+
var pre = el.nextElementSibling;
|
|
220
|
+
if (pre.style.display === 'block') {
|
|
221
|
+
pre.style.display = 'none';
|
|
222
|
+
} else {
|
|
223
|
+
pre.style.display = 'block';
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function toggleRaw() {
|
|
227
|
+
var pre = document.getElementById('raw-pre');
|
|
228
|
+
if (pre.style.display === 'block') {
|
|
229
|
+
pre.style.display = 'none';
|
|
230
|
+
} else {
|
|
231
|
+
pre.style.display = 'block';
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function copySuccessMsg(btn) {
|
|
235
|
+
var text = '授权成功,继续完成任务';
|
|
236
|
+
navigator.clipboard.writeText(text).then(function() {
|
|
237
|
+
btn.innerText = '已复制';
|
|
238
|
+
btn.disabled = true;
|
|
239
|
+
setTimeout(function() {
|
|
240
|
+
btn.innerText = '点击复制到粘贴板';
|
|
241
|
+
btn.disabled = false;
|
|
242
|
+
}, 2000);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
</script>
|
|
246
|
+
</head>
|
|
247
|
+
<body>
|
|
248
|
+
<div class="container">
|
|
249
|
+
<h2 style="margin-bottom:24px;">飞书授权结果</h2>
|
|
250
|
+
${errorBlock}
|
|
251
|
+
${tokenBlock}
|
|
252
|
+
${userBlock}
|
|
253
|
+
<div class="card raw-block">
|
|
254
|
+
<span class="raw-toggle" onclick="toggleRaw()">点击展开/收起原始数据</span>
|
|
255
|
+
<pre id="raw-pre" class="raw-pre">${escapeHtml(JSON.stringify(data, null, 2))}</pre>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
</body>
|
|
259
|
+
</html>
|
|
260
260
|
`;
|
|
261
261
|
}
|
|
262
262
|
function escapeHtml(str) {
|
package/package.json
CHANGED
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "feishu-mcp",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Model Context Protocol server for Feishu integration",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"feishu-mcp": "./dist/cli.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"dist",
|
|
12
|
-
"README.md"
|
|
13
|
-
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "tsc && tsc-alias",
|
|
16
|
-
"type-check": "tsc --noEmit",
|
|
17
|
-
"start": "node dist/index.js",
|
|
18
|
-
"start:cli": "cross-env NODE_ENV=cli node dist/index.js",
|
|
19
|
-
"start:http": "node dist/index.js",
|
|
20
|
-
"dev": "cross-env NODE_ENV=development tsx watch src/index.ts",
|
|
21
|
-
"dev:cli": "cross-env NODE_ENV=development tsx watch src/index.ts --stdio",
|
|
22
|
-
"lint": "eslint . --ext .ts",
|
|
23
|
-
"format": "prettier --write \"src/**/*.ts\"",
|
|
24
|
-
"inspect": "pnpx @modelcontextprotocol/inspector",
|
|
25
|
-
"prepare": "pnpm run build",
|
|
26
|
-
"pub:release": "pnpm build && npm publish"
|
|
27
|
-
},
|
|
28
|
-
"engines": {
|
|
29
|
-
"node": "^20.17.0"
|
|
30
|
-
},
|
|
31
|
-
"repository": {
|
|
32
|
-
"type": "git",
|
|
33
|
-
"url": "https://github.com/cso1z/Feishu-MCP.git"
|
|
34
|
-
},
|
|
35
|
-
"keywords": [
|
|
36
|
-
"feishu",
|
|
37
|
-
"lark",
|
|
38
|
-
"mcp",
|
|
39
|
-
"typescript"
|
|
40
|
-
],
|
|
41
|
-
"author": "cso1z",
|
|
42
|
-
"license": "MIT",
|
|
43
|
-
"dependencies": {
|
|
44
|
-
"@modelcontextprotocol/sdk": "^1.17.5",
|
|
45
|
-
"@types/yargs": "^17.0.33",
|
|
46
|
-
"axios": "^1.7.9",
|
|
47
|
-
"cross-env": "^7.0.3",
|
|
48
|
-
"dotenv": "^16.4.7",
|
|
49
|
-
"express": "^4.21.2",
|
|
50
|
-
"form-data": "^4.0.3",
|
|
51
|
-
"remeda": "^2.20.1",
|
|
52
|
-
"yargs": "^17.7.2",
|
|
53
|
-
"zod": "^3.24.2"
|
|
54
|
-
},
|
|
55
|
-
"devDependencies": {
|
|
56
|
-
"@types/express": "^5.0.0",
|
|
57
|
-
"@types/jest": "^29.5.11",
|
|
58
|
-
"@types/node": "^20.17.0",
|
|
59
|
-
"@typescript-eslint/eslint-plugin": "^8.24.0",
|
|
60
|
-
"@typescript-eslint/parser": "^8.24.0",
|
|
61
|
-
"eslint": "^9.20.1",
|
|
62
|
-
"eslint-config-prettier": "^10.0.1",
|
|
63
|
-
"jest": "^29.7.0",
|
|
64
|
-
"prettier": "^3.5.0",
|
|
65
|
-
"ts-jest": "^29.2.5",
|
|
66
|
-
"tsc-alias": "^1.8.10",
|
|
67
|
-
"tsx": "^4.19.2",
|
|
68
|
-
"typescript": "^5.7.3"
|
|
69
|
-
},
|
|
70
|
-
"pnpm": {
|
|
71
|
-
"overrides": {
|
|
72
|
-
"feishu-mcp": "link:"
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "feishu-mcp",
|
|
3
|
+
"version": "0.1.8",
|
|
4
|
+
"description": "Model Context Protocol server for Feishu integration",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"feishu-mcp": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc && tsc-alias",
|
|
16
|
+
"type-check": "tsc --noEmit",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"start:cli": "cross-env NODE_ENV=cli node dist/index.js",
|
|
19
|
+
"start:http": "node dist/index.js",
|
|
20
|
+
"dev": "cross-env NODE_ENV=development tsx watch src/index.ts",
|
|
21
|
+
"dev:cli": "cross-env NODE_ENV=development tsx watch src/index.ts --stdio",
|
|
22
|
+
"lint": "eslint . --ext .ts",
|
|
23
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
24
|
+
"inspect": "pnpx @modelcontextprotocol/inspector",
|
|
25
|
+
"prepare": "pnpm run build",
|
|
26
|
+
"pub:release": "pnpm build && npm publish"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": "^20.17.0"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/cso1z/Feishu-MCP.git"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"feishu",
|
|
37
|
+
"lark",
|
|
38
|
+
"mcp",
|
|
39
|
+
"typescript"
|
|
40
|
+
],
|
|
41
|
+
"author": "cso1z",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@modelcontextprotocol/sdk": "^1.17.5",
|
|
45
|
+
"@types/yargs": "^17.0.33",
|
|
46
|
+
"axios": "^1.7.9",
|
|
47
|
+
"cross-env": "^7.0.3",
|
|
48
|
+
"dotenv": "^16.4.7",
|
|
49
|
+
"express": "^4.21.2",
|
|
50
|
+
"form-data": "^4.0.3",
|
|
51
|
+
"remeda": "^2.20.1",
|
|
52
|
+
"yargs": "^17.7.2",
|
|
53
|
+
"zod": "^3.24.2"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/express": "^5.0.0",
|
|
57
|
+
"@types/jest": "^29.5.11",
|
|
58
|
+
"@types/node": "^20.17.0",
|
|
59
|
+
"@typescript-eslint/eslint-plugin": "^8.24.0",
|
|
60
|
+
"@typescript-eslint/parser": "^8.24.0",
|
|
61
|
+
"eslint": "^9.20.1",
|
|
62
|
+
"eslint-config-prettier": "^10.0.1",
|
|
63
|
+
"jest": "^29.7.0",
|
|
64
|
+
"prettier": "^3.5.0",
|
|
65
|
+
"ts-jest": "^29.2.5",
|
|
66
|
+
"tsc-alias": "^1.8.10",
|
|
67
|
+
"tsx": "^4.19.2",
|
|
68
|
+
"typescript": "^5.7.3"
|
|
69
|
+
},
|
|
70
|
+
"pnpm": {
|
|
71
|
+
"overrides": {
|
|
72
|
+
"feishu-mcp": "link:"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|