@dhcckb/mcp-server-douban 1.0.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/README.md +107 -0
- package/dist/citations/apa.d.ts +8 -0
- package/dist/citations/apa.d.ts.map +1 -0
- package/dist/citations/apa.js +78 -0
- package/dist/citations/apa.js.map +1 -0
- package/dist/citations/bibtex.d.ts +15 -0
- package/dist/citations/bibtex.d.ts.map +1 -0
- package/dist/citations/bibtex.js +82 -0
- package/dist/citations/bibtex.js.map +1 -0
- package/dist/citations/chicago.d.ts +8 -0
- package/dist/citations/chicago.d.ts.map +1 -0
- package/dist/citations/chicago.js +66 -0
- package/dist/citations/chicago.js.map +1 -0
- package/dist/citations/gb7714.d.ts +9 -0
- package/dist/citations/gb7714.d.ts.map +1 -0
- package/dist/citations/gb7714.js +39 -0
- package/dist/citations/gb7714.js.map +1 -0
- package/dist/citations/harvard.d.ts +8 -0
- package/dist/citations/harvard.d.ts.map +1 -0
- package/dist/citations/harvard.js +50 -0
- package/dist/citations/harvard.js.map +1 -0
- package/dist/citations/mla.d.ts +8 -0
- package/dist/citations/mla.d.ts.map +1 -0
- package/dist/citations/mla.js +62 -0
- package/dist/citations/mla.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/douban_cite.d.ts +3 -0
- package/dist/tools/douban_cite.d.ts.map +1 -0
- package/dist/tools/douban_cite.js +67 -0
- package/dist/tools/douban_cite.js.map +1 -0
- package/dist/tools/douban_detail.d.ts +24 -0
- package/dist/tools/douban_detail.d.ts.map +1 -0
- package/dist/tools/douban_detail.js +188 -0
- package/dist/tools/douban_detail.js.map +1 -0
- package/dist/tools/douban_search.d.ts +21 -0
- package/dist/tools/douban_search.d.ts.map +1 -0
- package/dist/tools/douban_search.js +163 -0
- package/dist/tools/douban_search.js.map +1 -0
- package/package.json +111 -0
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @dhcckb/mcp-server-douban
|
|
2
|
+
|
|
3
|
+
通过豆瓣数据自动补全书籍元数据并按多规范生成参考文献格式的 MCP Server。
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
- **书籍搜索** (`douban_search`):按书名搜索豆瓣书籍,支持作者/出版年/出版社筛选消歧
|
|
8
|
+
- **详情获取** (`douban_detail`):根据豆瓣 ID 获取完整书籍元数据(ISBN、页数、评分、简介等)
|
|
9
|
+
- **参考文献生成** (`douban_cite`):按六种规范格式化参考文献引用字符串
|
|
10
|
+
|
|
11
|
+
## 支持的参考文献格式
|
|
12
|
+
|
|
13
|
+
| 格式 | style 参数 | 说明 |
|
|
14
|
+
|------|-----------|------|
|
|
15
|
+
| GB/T 7714-2015 | `gb7714` | 中国国家标准 |
|
|
16
|
+
| APA 7th | `apa` | 美国心理学会格式 |
|
|
17
|
+
| MLA 9th | `mla` | 现代语言协会格式 |
|
|
18
|
+
| Chicago 17th Notes-Bibliography | `chicago` | 芝加哥格式 |
|
|
19
|
+
| Harvard | `harvard` | 哈佛格式 |
|
|
20
|
+
| BibTeX | `bibtex` | LaTeX 参考文献格式 |
|
|
21
|
+
|
|
22
|
+
## 安装与运行
|
|
23
|
+
|
|
24
|
+
### 前置要求
|
|
25
|
+
|
|
26
|
+
- Node.js ≥ 18
|
|
27
|
+
|
|
28
|
+
### 直接运行
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx -y @dhcckb/mcp-server-douban
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 在 MCP 客户端中配置
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"mcpServers": {
|
|
39
|
+
"douban": {
|
|
40
|
+
"command": "npx",
|
|
41
|
+
"args": ["-y", "@dhp/mcp-server-douban"]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 工具说明
|
|
48
|
+
|
|
49
|
+
### douban_search
|
|
50
|
+
|
|
51
|
+
按书名搜索豆瓣书籍,返回匹配列表。
|
|
52
|
+
|
|
53
|
+
**参数:**
|
|
54
|
+
- `title` (string, 必填) — 搜索关键词书名
|
|
55
|
+
- `author` (string, 可选) — 作者名,用于消歧筛选
|
|
56
|
+
- `year` (string, 可选) — 出版年份,用于消歧筛选
|
|
57
|
+
- `publisher` (string, 可选) — 出版社名,用于消歧筛选
|
|
58
|
+
- `limit` (number, 可选, 默认 10) — 返回结果数量上限
|
|
59
|
+
|
|
60
|
+
**返回:** 书籍列表,每条含 `douban_id`、`title`、`author`、`year`、`publisher`、`cover_url`。结果数 > 1 且未提供筛选条件时,附带消歧提示和可用筛选字段。
|
|
61
|
+
|
|
62
|
+
### douban_detail
|
|
63
|
+
|
|
64
|
+
获取书籍完整元数据。
|
|
65
|
+
|
|
66
|
+
**参数:**
|
|
67
|
+
- `douban_id` (string, 必填) — 来源于 `douban_search` 返回的 `douban_id`
|
|
68
|
+
|
|
69
|
+
**返回:** 完整书籍元数据,包括 title、subtitle、author、translator、publisher、publish_date、isbn、pages、price、binding、series、rating、summary、author_intro、cover_url 等。
|
|
70
|
+
|
|
71
|
+
### douban_cite
|
|
72
|
+
|
|
73
|
+
生成格式化参考文献字符串。
|
|
74
|
+
|
|
75
|
+
**参数:**
|
|
76
|
+
- `book_data` (object, 必填) — `douban_detail` 返回的完整元数据
|
|
77
|
+
- `style` (string, 必填) — 目标格式,可选:`gb7714` | `apa` | `mla` | `chicago` | `harvard` | `bibtex`
|
|
78
|
+
|
|
79
|
+
**返回:** 格式化的参考文献字符串及格式标签。
|
|
80
|
+
|
|
81
|
+
## 使用示例
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
1. 搜索书籍:
|
|
85
|
+
douban_search({ title: "百年孤独" })
|
|
86
|
+
→ 返回候选列表,选择目标书籍的 douban_id
|
|
87
|
+
|
|
88
|
+
2. 获取详情:
|
|
89
|
+
douban_detail({ douban_id: "1234567" })
|
|
90
|
+
→ 返回完整元数据
|
|
91
|
+
|
|
92
|
+
3. 生成引用:
|
|
93
|
+
douban_cite({ book_data: {...}, style: "gb7714" })
|
|
94
|
+
→ 加西亚·马尔克斯. 百年孤独[M]. 范晔, 译. 南海出版公司, 2011.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 技术架构
|
|
98
|
+
|
|
99
|
+
- **运行时:** Node.js ≥ 18
|
|
100
|
+
- **语言:** TypeScript
|
|
101
|
+
- **依赖:** @modelcontextprotocol/sdk, zod
|
|
102
|
+
- **传输:** stdio (MCP 标准传输)
|
|
103
|
+
- **数据源:** 豆瓣书籍页面(搜索页与详情页 HTML 解析)
|
|
104
|
+
|
|
105
|
+
## 许可证
|
|
106
|
+
|
|
107
|
+
MIT
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* APA 7th 参考文献格式
|
|
3
|
+
*
|
|
4
|
+
* 格式:Author, A. A. (Year). Title of work: Subtitle (T. Translator, Trans.). Publisher.
|
|
5
|
+
*/
|
|
6
|
+
import type { DoubanBookDetail } from "../tools/douban_detail.js";
|
|
7
|
+
export declare function formatAPA(book: DoubanBookDetail): string;
|
|
8
|
+
//# sourceMappingURL=apa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apa.d.ts","sourceRoot":"","sources":["../../src/citations/apa.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CA+CxD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export function formatAPA(book) {
|
|
2
|
+
const parts = [];
|
|
3
|
+
// 作者 — APA 格式: Last, F. M.
|
|
4
|
+
const authorStr = formatAuthorsAPA(book.author);
|
|
5
|
+
parts.push(authorStr);
|
|
6
|
+
// 出版年
|
|
7
|
+
if (book.publish_date) {
|
|
8
|
+
const year = extractYear(book.publish_date);
|
|
9
|
+
parts.push(`(${year}).`);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
parts.push("(n.d.).");
|
|
13
|
+
}
|
|
14
|
+
// 书名(斜体用书名号表示)
|
|
15
|
+
if (book.subtitle) {
|
|
16
|
+
parts.push(`${book.title}: ${book.subtitle}.`);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
parts.push(`${book.title}.`);
|
|
20
|
+
}
|
|
21
|
+
// 译者
|
|
22
|
+
if (book.translator.length > 0) {
|
|
23
|
+
const transNames = book.translator
|
|
24
|
+
.map((t) => {
|
|
25
|
+
const names = t.split(/\s+/);
|
|
26
|
+
if (names.length >= 2) {
|
|
27
|
+
const lastName = names[names.length - 1];
|
|
28
|
+
const initials = names
|
|
29
|
+
.slice(0, -1)
|
|
30
|
+
.map((n) => n.charAt(0).toUpperCase() + ".")
|
|
31
|
+
.join(" ");
|
|
32
|
+
return `${initials} ${lastName}`;
|
|
33
|
+
}
|
|
34
|
+
return t;
|
|
35
|
+
})
|
|
36
|
+
.join(", ");
|
|
37
|
+
parts.push(`(${transNames}, Trans.).`);
|
|
38
|
+
}
|
|
39
|
+
// 出版社
|
|
40
|
+
if (book.publisher) {
|
|
41
|
+
parts.push(`${book.publisher}.`);
|
|
42
|
+
}
|
|
43
|
+
return parts.join(" ");
|
|
44
|
+
}
|
|
45
|
+
function formatAuthorsAPA(authors) {
|
|
46
|
+
if (authors.length === 0)
|
|
47
|
+
return "Anonymous.";
|
|
48
|
+
const formatted = authors.map((a) => formatSingleAuthorAPA(a));
|
|
49
|
+
if (formatted.length === 1) {
|
|
50
|
+
return `${formatted[0]}.`;
|
|
51
|
+
}
|
|
52
|
+
if (formatted.length === 2) {
|
|
53
|
+
return `${formatted[0]}, & ${formatted[1]}.`;
|
|
54
|
+
}
|
|
55
|
+
if (formatted.length <= 20) {
|
|
56
|
+
const last = formatted.pop();
|
|
57
|
+
return `${formatted.join(", ")}, & ${last}.`;
|
|
58
|
+
}
|
|
59
|
+
return `${formatted.slice(0, 19).join(", ")}, ... ${formatted[formatted.length - 1]}.`;
|
|
60
|
+
}
|
|
61
|
+
function formatSingleAuthorAPA(name) {
|
|
62
|
+
// 中英文不同处理
|
|
63
|
+
if (/[一-鿿]/.test(name)) {
|
|
64
|
+
return name; // 中文名保持原样
|
|
65
|
+
}
|
|
66
|
+
const parts = name.split(/\s+/);
|
|
67
|
+
if (parts.length >= 2) {
|
|
68
|
+
const lastName = parts.pop();
|
|
69
|
+
const initials = parts.map((p) => p.charAt(0).toUpperCase() + ".").join(" ");
|
|
70
|
+
return `${lastName}, ${initials}`;
|
|
71
|
+
}
|
|
72
|
+
return name;
|
|
73
|
+
}
|
|
74
|
+
function extractYear(date) {
|
|
75
|
+
const match = date.match(/\d{4}/);
|
|
76
|
+
return match ? match[0] : "n.d.";
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=apa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apa.js","sourceRoot":"","sources":["../../src/citations/apa.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BibTeX 参考文献格式
|
|
3
|
+
*
|
|
4
|
+
* 格式:
|
|
5
|
+
* @book{key,
|
|
6
|
+
* author = {Author},
|
|
7
|
+
* title = {Title},
|
|
8
|
+
* publisher = {Publisher},
|
|
9
|
+
* year = {Year},
|
|
10
|
+
* isbn = {ISBN}
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
import type { DoubanBookDetail } from "../tools/douban_detail.js";
|
|
14
|
+
export declare function formatBibTeX(book: DoubanBookDetail): string;
|
|
15
|
+
//# sourceMappingURL=bibtex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bibtex.d.ts","sourceRoot":"","sources":["../../src/citations/bibtex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CA4D3D"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export function formatBibTeX(book) {
|
|
2
|
+
const lines = [];
|
|
3
|
+
// 生成引用键
|
|
4
|
+
const citeKey = generateCiteKey(book);
|
|
5
|
+
lines.push(`@book{${citeKey},`);
|
|
6
|
+
// 作者
|
|
7
|
+
if (book.author.length > 0) {
|
|
8
|
+
const authorStr = book.author
|
|
9
|
+
.map((a) => formatAuthorBibTeX(a))
|
|
10
|
+
.join(" and ");
|
|
11
|
+
lines.push(` author = {${authorStr}},`);
|
|
12
|
+
}
|
|
13
|
+
// 书名
|
|
14
|
+
if (book.subtitle) {
|
|
15
|
+
lines.push(` title = {${book.title}: ${book.subtitle}},`);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
lines.push(` title = {${book.title}},`);
|
|
19
|
+
}
|
|
20
|
+
// 译者
|
|
21
|
+
if (book.translator.length > 0) {
|
|
22
|
+
const transStr = book.translator.join(" and ");
|
|
23
|
+
lines.push(` translator = {${transStr}},`);
|
|
24
|
+
}
|
|
25
|
+
// 出版社
|
|
26
|
+
if (book.publisher) {
|
|
27
|
+
lines.push(` publisher = {${book.publisher}},`);
|
|
28
|
+
}
|
|
29
|
+
// 出版年
|
|
30
|
+
if (book.publish_date) {
|
|
31
|
+
const year = extractYear(book.publish_date);
|
|
32
|
+
if (year !== "n.d.") {
|
|
33
|
+
lines.push(` year = {${year}},`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// ISBN
|
|
37
|
+
if (book.isbn) {
|
|
38
|
+
lines.push(` isbn = {${book.isbn}},`);
|
|
39
|
+
}
|
|
40
|
+
// 丛书
|
|
41
|
+
if (book.series) {
|
|
42
|
+
lines.push(` series = {${book.series}},`);
|
|
43
|
+
}
|
|
44
|
+
// 页数
|
|
45
|
+
if (book.pages > 0) {
|
|
46
|
+
lines.push(` pages = {${book.pages}},`);
|
|
47
|
+
}
|
|
48
|
+
lines.push("}");
|
|
49
|
+
return lines.join("\n");
|
|
50
|
+
}
|
|
51
|
+
function generateCiteKey(book) {
|
|
52
|
+
const firstAuthor = book.author.length > 0
|
|
53
|
+
? book.author[0].replace(/[^a-zA-Z一-鿿]/g, "").toLowerCase()
|
|
54
|
+
: "anonymous";
|
|
55
|
+
const year = extractYear(book.publish_date);
|
|
56
|
+
const titleFirst = book.title.length > 0
|
|
57
|
+
? book.title.replace(/[^a-zA-Z一-鿿]/g, "").toLowerCase().slice(0, 10)
|
|
58
|
+
: "untitled";
|
|
59
|
+
// 优先使用拼音/英文作者名,中文作者用标题首字辅助
|
|
60
|
+
if (/[一-鿿]/.test(firstAuthor)) {
|
|
61
|
+
return `${titleFirst}${year}`;
|
|
62
|
+
}
|
|
63
|
+
return `${firstAuthor}${year}`;
|
|
64
|
+
}
|
|
65
|
+
function formatAuthorBibTeX(name) {
|
|
66
|
+
if (/[一-鿿]/.test(name)) {
|
|
67
|
+
// 中文名: 姓在前
|
|
68
|
+
return name;
|
|
69
|
+
}
|
|
70
|
+
const parts = name.split(/\s+/);
|
|
71
|
+
if (parts.length >= 2) {
|
|
72
|
+
const lastName = parts.pop();
|
|
73
|
+
const firstNames = parts.join(" ");
|
|
74
|
+
return `${lastName}, ${firstNames}`;
|
|
75
|
+
}
|
|
76
|
+
return name;
|
|
77
|
+
}
|
|
78
|
+
function extractYear(date) {
|
|
79
|
+
const match = date.match(/\d{4}/);
|
|
80
|
+
return match ? match[0] : "n.d.";
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=bibtex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bibtex.js","sourceRoot":"","sources":["../../src/citations/bibtex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chicago 17th Notes-Bibliography 参考文献格式
|
|
3
|
+
*
|
|
4
|
+
* 格式:Author Last, First. Title: Subtitle. Translated by Translator. Place: Publisher, Year.
|
|
5
|
+
*/
|
|
6
|
+
import type { DoubanBookDetail } from "../tools/douban_detail.js";
|
|
7
|
+
export declare function formatChicago(book: DoubanBookDetail): string;
|
|
8
|
+
//# sourceMappingURL=chicago.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chicago.d.ts","sourceRoot":"","sources":["../../src/citations/chicago.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAiC5D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export function formatChicago(book) {
|
|
2
|
+
const parts = [];
|
|
3
|
+
// 作者
|
|
4
|
+
const authorStr = formatAuthorsChicago(book.author);
|
|
5
|
+
parts.push(`${authorStr}.`);
|
|
6
|
+
// 书名(斜体)
|
|
7
|
+
if (book.subtitle) {
|
|
8
|
+
parts.push(`${book.title}: ${book.subtitle}.`);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
parts.push(`${book.title}.`);
|
|
12
|
+
}
|
|
13
|
+
// 译者
|
|
14
|
+
if (book.translator.length > 0) {
|
|
15
|
+
const transNames = book.translator.map((t) => formatNameNormal(t)).join(", ");
|
|
16
|
+
parts.push(`Translated by ${transNames}.`);
|
|
17
|
+
}
|
|
18
|
+
// 出版社, 出版年
|
|
19
|
+
if (book.publisher) {
|
|
20
|
+
parts.push(`${book.publisher},`);
|
|
21
|
+
}
|
|
22
|
+
if (book.publish_date) {
|
|
23
|
+
const year = extractYear(book.publish_date);
|
|
24
|
+
parts.push(`${year}.`);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
parts.push("n.d.");
|
|
28
|
+
}
|
|
29
|
+
return parts.join(" ");
|
|
30
|
+
}
|
|
31
|
+
function formatAuthorsChicago(authors) {
|
|
32
|
+
if (authors.length === 0)
|
|
33
|
+
return "Anonymous";
|
|
34
|
+
const formatted = authors.map((a) => formatNameChicago(a));
|
|
35
|
+
if (formatted.length === 1) {
|
|
36
|
+
return formatted[0];
|
|
37
|
+
}
|
|
38
|
+
if (formatted.length === 2) {
|
|
39
|
+
return `${formatted[0]}, and ${formatted[1]}`;
|
|
40
|
+
}
|
|
41
|
+
if (formatted.length <= 10) {
|
|
42
|
+
const last = formatted.pop();
|
|
43
|
+
return `${formatted.join(", ")}, and ${last}`;
|
|
44
|
+
}
|
|
45
|
+
return `${formatted.slice(0, 7).join(", ")}, et al.`;
|
|
46
|
+
}
|
|
47
|
+
function formatNameChicago(name) {
|
|
48
|
+
if (/[一-鿿]/.test(name)) {
|
|
49
|
+
return name;
|
|
50
|
+
}
|
|
51
|
+
const parts = name.split(/\s+/);
|
|
52
|
+
if (parts.length >= 2) {
|
|
53
|
+
const lastName = parts.pop();
|
|
54
|
+
const firstNames = parts.join(" ");
|
|
55
|
+
return `${lastName}, ${firstNames}`;
|
|
56
|
+
}
|
|
57
|
+
return name;
|
|
58
|
+
}
|
|
59
|
+
function formatNameNormal(name) {
|
|
60
|
+
return name;
|
|
61
|
+
}
|
|
62
|
+
function extractYear(date) {
|
|
63
|
+
const match = date.match(/\d{4}/);
|
|
64
|
+
return match ? match[0] : "n.d.";
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=chicago.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chicago.js","sourceRoot":"","sources":["../../src/citations/chicago.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GB/T 7714-2015 参考文献格式
|
|
3
|
+
*
|
|
4
|
+
* 格式:作者. 书名[M]. 译者, 译. 出版地: 出版社, 出版年.
|
|
5
|
+
* 或: 作者. 书名[M]. 译者, 译. 版次. 出版地: 出版社, 出版年.
|
|
6
|
+
*/
|
|
7
|
+
import type { DoubanBookDetail } from "../tools/douban_detail.js";
|
|
8
|
+
export declare function formatGB7714(book: DoubanBookDetail): string;
|
|
9
|
+
//# sourceMappingURL=gb7714.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gb7714.d.ts","sourceRoot":"","sources":["../../src/citations/gb7714.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAiC3D"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function formatGB7714(book) {
|
|
2
|
+
const parts = [];
|
|
3
|
+
// 作者
|
|
4
|
+
const authors = formatAuthors(book.author);
|
|
5
|
+
parts.push(`${authors}.`);
|
|
6
|
+
// 书名
|
|
7
|
+
parts.push(`${book.title}${book.subtitle ? `: ${book.subtitle}` : ""}[M].`);
|
|
8
|
+
// 译者
|
|
9
|
+
if (book.translator.length > 0) {
|
|
10
|
+
const translators = formatAuthors(book.translator);
|
|
11
|
+
parts.push(`${translators}, 译.`);
|
|
12
|
+
}
|
|
13
|
+
// 出版信息:出版社, 出版年
|
|
14
|
+
const pubParts = [];
|
|
15
|
+
if (book.publisher)
|
|
16
|
+
pubParts.push(book.publisher);
|
|
17
|
+
if (book.publish_date) {
|
|
18
|
+
const year = book.publish_date.match(/\d{4}/);
|
|
19
|
+
if (year)
|
|
20
|
+
pubParts.push(year[0]);
|
|
21
|
+
}
|
|
22
|
+
if (pubParts.length > 0) {
|
|
23
|
+
parts.push(`${pubParts.join(", ")}.`);
|
|
24
|
+
}
|
|
25
|
+
// ISBN (可选)
|
|
26
|
+
if (book.isbn) {
|
|
27
|
+
parts.push(`ISBN ${book.isbn}.`);
|
|
28
|
+
}
|
|
29
|
+
return parts.join(" ");
|
|
30
|
+
}
|
|
31
|
+
function formatAuthors(authors) {
|
|
32
|
+
if (authors.length === 0)
|
|
33
|
+
return "[佚名]";
|
|
34
|
+
if (authors.length <= 3) {
|
|
35
|
+
return authors.join(", ");
|
|
36
|
+
}
|
|
37
|
+
return `${authors.slice(0, 3).join(", ")}, 等`;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=gb7714.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gb7714.js","sourceRoot":"","sources":["../../src/citations/gb7714.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,YAAY,CAAC,IAAsB;IACjD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK;IACL,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;IAE1B,KAAK;IACL,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAE5E,KAAK;IACL,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,gBAAgB;IAChB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,IAAI,CAAC,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,IAAI;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,YAAY;IACZ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,aAAa,CAAC,OAAiB;IACtC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACxC,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harvard 参考文献格式
|
|
3
|
+
*
|
|
4
|
+
* 格式:Author(s) (Year) Title. Edition. Place: Publisher.
|
|
5
|
+
*/
|
|
6
|
+
import type { DoubanBookDetail } from "../tools/douban_detail.js";
|
|
7
|
+
export declare function formatHarvard(book: DoubanBookDetail): string;
|
|
8
|
+
//# sourceMappingURL=harvard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvard.d.ts","sourceRoot":"","sources":["../../src/citations/harvard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAkC5D"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function formatHarvard(book) {
|
|
2
|
+
const parts = [];
|
|
3
|
+
// 作者
|
|
4
|
+
const authorStr = formatAuthorsHarvard(book.author);
|
|
5
|
+
parts.push(authorStr);
|
|
6
|
+
// 出版年
|
|
7
|
+
if (book.publish_date) {
|
|
8
|
+
const year = extractYear(book.publish_date);
|
|
9
|
+
parts.push(`(${year})`);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
parts.push("(n.d.)");
|
|
13
|
+
}
|
|
14
|
+
// 书名(斜体)
|
|
15
|
+
if (book.subtitle) {
|
|
16
|
+
parts.push(`${book.title}: ${book.subtitle}.`);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
parts.push(`${book.title}.`);
|
|
20
|
+
}
|
|
21
|
+
// 版次 (如果有)
|
|
22
|
+
// 丛书信息
|
|
23
|
+
if (book.series) {
|
|
24
|
+
parts.push(`${book.series} series.`);
|
|
25
|
+
}
|
|
26
|
+
// 出版社
|
|
27
|
+
if (book.publisher) {
|
|
28
|
+
parts.push(`${book.publisher}.`);
|
|
29
|
+
}
|
|
30
|
+
return parts.join(" ");
|
|
31
|
+
}
|
|
32
|
+
function formatAuthorsHarvard(authors) {
|
|
33
|
+
if (authors.length === 0)
|
|
34
|
+
return "Anon.";
|
|
35
|
+
if (authors.length === 1) {
|
|
36
|
+
return `${authors[0]} `;
|
|
37
|
+
}
|
|
38
|
+
if (authors.length === 2) {
|
|
39
|
+
return `${authors[0]} and ${authors[1]} `;
|
|
40
|
+
}
|
|
41
|
+
if (authors.length === 3) {
|
|
42
|
+
return `${authors[0]}, ${authors[1]} and ${authors[2]} `;
|
|
43
|
+
}
|
|
44
|
+
return `${authors[0]} et al. `;
|
|
45
|
+
}
|
|
46
|
+
function extractYear(date) {
|
|
47
|
+
const match = date.match(/\d{4}/);
|
|
48
|
+
return match ? match[0] : "n.d.";
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=harvard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvard.js","sourceRoot":"","sources":["../../src/citations/harvard.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,aAAa,CAAC,IAAsB;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK;IACL,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEtB,MAAM;IACN,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;IAED,SAAS;IACT,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACjD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,WAAW;IACX,OAAO;IACP,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,UAAU,CAAC,CAAC;IACvC,CAAC;IAED,MAAM;IACN,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAiB;IAC7C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACzC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1B,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5C,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3D,CAAC;IACD,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;AACjC,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MLA 9th 参考文献格式
|
|
3
|
+
*
|
|
4
|
+
* 格式:Author Last, First. Title of Book. Subtitle, translated by Translator, Publisher, Year.
|
|
5
|
+
*/
|
|
6
|
+
import type { DoubanBookDetail } from "../tools/douban_detail.js";
|
|
7
|
+
export declare function formatMLA(book: DoubanBookDetail): string;
|
|
8
|
+
//# sourceMappingURL=mla.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mla.d.ts","sourceRoot":"","sources":["../../src/citations/mla.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAoCxD"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export function formatMLA(book) {
|
|
2
|
+
const parts = [];
|
|
3
|
+
// 作者 — MLA 格式: Last, First.
|
|
4
|
+
const authorStr = formatAuthorsMLA(book.author);
|
|
5
|
+
parts.push(`${authorStr}.`);
|
|
6
|
+
// 书名 (斜体标记)
|
|
7
|
+
if (book.subtitle) {
|
|
8
|
+
parts.push(`${book.title}: ${book.subtitle}.`);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
parts.push(`${book.title}.`);
|
|
12
|
+
}
|
|
13
|
+
// 译者
|
|
14
|
+
if (book.translator.length > 0) {
|
|
15
|
+
const transNames = book.translator
|
|
16
|
+
.map((t) => reverseName(t))
|
|
17
|
+
.join(", ");
|
|
18
|
+
parts.push(`Translated by ${transNames},`);
|
|
19
|
+
}
|
|
20
|
+
// 出版社
|
|
21
|
+
if (book.publisher) {
|
|
22
|
+
parts.push(`${book.publisher},`);
|
|
23
|
+
}
|
|
24
|
+
// 出版年
|
|
25
|
+
if (book.publish_date) {
|
|
26
|
+
const year = extractYear(book.publish_date);
|
|
27
|
+
parts.push(`${year}.`);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
parts.push("n.d.");
|
|
31
|
+
}
|
|
32
|
+
return parts.join(" ");
|
|
33
|
+
}
|
|
34
|
+
function formatAuthorsMLA(authors) {
|
|
35
|
+
if (authors.length === 0)
|
|
36
|
+
return "Anonymous";
|
|
37
|
+
const formatted = authors.map((a) => reverseName(a));
|
|
38
|
+
if (formatted.length === 1) {
|
|
39
|
+
return formatted[0];
|
|
40
|
+
}
|
|
41
|
+
if (formatted.length === 2) {
|
|
42
|
+
return `${formatted[0]}, and ${formatted[1]}`;
|
|
43
|
+
}
|
|
44
|
+
return `${formatted[0]}, et al.`;
|
|
45
|
+
}
|
|
46
|
+
function reverseName(name) {
|
|
47
|
+
if (/[一-鿿]/.test(name)) {
|
|
48
|
+
return name; // 中文名保持原样
|
|
49
|
+
}
|
|
50
|
+
const parts = name.split(/\s+/);
|
|
51
|
+
if (parts.length >= 2) {
|
|
52
|
+
const lastName = parts.pop();
|
|
53
|
+
const firstNames = parts.join(" ");
|
|
54
|
+
return `${lastName}, ${firstNames}`;
|
|
55
|
+
}
|
|
56
|
+
return name;
|
|
57
|
+
}
|
|
58
|
+
function extractYear(date) {
|
|
59
|
+
const match = date.match(/\d{4}/);
|
|
60
|
+
return match ? match[0] : "n.d.";
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=mla.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mla.js","sourceRoot":"","sources":["../../src/citations/mla.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,SAAS,CAAC,IAAsB;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,4BAA4B;IAC5B,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;IAE5B,YAAY;IACZ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACjD,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK;IACL,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;aAC1B,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,iBAAiB,UAAU,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM;IACN,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,MAAM;IACN,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAiB;IACzC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;AACnC,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,CAAC,UAAU;IACzB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,OAAO,GAAG,QAAQ,KAAK,UAAU,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACnC,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,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { doubanSearchTool } from "./tools/douban_search.js";
|
|
5
|
+
import { doubanDetailTool } from "./tools/douban_detail.js";
|
|
6
|
+
import { doubanCiteTool } from "./tools/douban_cite.js";
|
|
7
|
+
const server = new McpServer({
|
|
8
|
+
name: "@dhcckb/mcp-server-douban",
|
|
9
|
+
version: "1.0.0",
|
|
10
|
+
});
|
|
11
|
+
doubanSearchTool(server);
|
|
12
|
+
doubanDetailTool(server);
|
|
13
|
+
doubanCiteTool(server);
|
|
14
|
+
async function main() {
|
|
15
|
+
const transport = new StdioServerTransport();
|
|
16
|
+
await server.connect(transport);
|
|
17
|
+
console.error("MCP Server @dhp/mcp-server-douban is running via stdio");
|
|
18
|
+
}
|
|
19
|
+
main().catch((err) => {
|
|
20
|
+
console.error("Fatal error during startup:", err);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,2BAA2B;IACjC,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,cAAc,CAAC,MAAM,CAAC,CAAC;AAEvB,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;AAC1E,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|