1102-mcp 0.1.0__tar.gz
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.
- 1102_mcp-0.1.0/1102_mcp.egg-info/PKG-INFO +64 -0
- 1102_mcp-0.1.0/1102_mcp.egg-info/SOURCES.txt +8 -0
- 1102_mcp-0.1.0/1102_mcp.egg-info/dependency_links.txt +1 -0
- 1102_mcp-0.1.0/1102_mcp.egg-info/requires.txt +2 -0
- 1102_mcp-0.1.0/1102_mcp.egg-info/top_level.txt +1 -0
- 1102_mcp-0.1.0/PKG-INFO +64 -0
- 1102_mcp-0.1.0/README.md +55 -0
- 1102_mcp-0.1.0/pyproject.toml +13 -0
- 1102_mcp-0.1.0/setup.cfg +4 -0
- 1102_mcp-0.1.0/souyun_mcp.py +176 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: 1102-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: fastmcp>=4.1.5
|
|
8
|
+
Requires-Dist: msgpack>=1.1.0
|
|
9
|
+
|
|
10
|
+
# 搜韵诗词 MCP
|
|
11
|
+
|
|
12
|
+
基于搜韵网开放接口的 FastMCP 服务,通过 stdio 向 MCP 客户端提供诗词检索、韵典查询和歌词素材汇总工具。
|
|
13
|
+
|
|
14
|
+
## 环境准备
|
|
15
|
+
|
|
16
|
+
- Python 3.13 或更高版本
|
|
17
|
+
- [uv](https://docs.astral.sh/uv/)
|
|
18
|
+
- 运行时可访问 `api.sou-yun.cn`
|
|
19
|
+
|
|
20
|
+
在项目目录安装依赖:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
uv sync
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 启动
|
|
27
|
+
|
|
28
|
+
MCP 服务使用 stdio,由 MCP 客户端按需启动并管理进程:
|
|
29
|
+
|
|
30
|
+
```powershell
|
|
31
|
+
uv run python .\souyun_mcp.py
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
也可以直接使用项目虚拟环境:
|
|
35
|
+
|
|
36
|
+
```powershell
|
|
37
|
+
.\.venv\Scripts\python.exe .\souyun_mcp.py
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## MCP 客户端配置
|
|
41
|
+
|
|
42
|
+
在客户端的 MCP 配置中添加一个 stdio server。将示例中的目录替换为本机项目的绝对路径:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"souyun-poem": {
|
|
48
|
+
"command": "D:\\path\\to\\1102-mcp\\.venv\\Scripts\\python.exe",
|
|
49
|
+
"args": [
|
|
50
|
+
"D:\\path\\to\\1102-mcp\\souyun_mcp.py"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 可用工具
|
|
58
|
+
|
|
59
|
+
- `search_poems`: 按关键词检索诗词。`scope` 支持 `All`、`Author`、`Title`、`Sentence` 或数字 `0` 到 `3`;也可按 `dynasty`、`type_`、`rhyme` 和 `pageno` 筛选,`jsontype` 控制 JSON 返回格式。
|
|
60
|
+
- `get_poem`: 按 `poem_id` 查询单首诗词详情。
|
|
61
|
+
- `rhyme_dictionary`: 按 `char` 查询韵典;`qtype` 为 `0` 查全部、`1` 查韵目、`2` 查词末典故、`3` 查词首、`4` 查词末、`5` 查句末诗例。可通过 `page_no` 翻页。
|
|
62
|
+
- `couplet_words`: 查询与 `word` 对仗的词汇。
|
|
63
|
+
- `rhyme_category`: 不传 `rhyme` 时查询平水韵总目;传入韵部时查询该韵包含的字。
|
|
64
|
+
- `collect_lyrics_material`: 按 `theme` 汇总候选诗词、诗句和韵部建议。可设置 `top_n`、`dynasty`、`type_`;传入 `rhyme_char` 时还会返回相关对仗词和典故。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
souyun_mcp
|
1102_mcp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: 1102-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: fastmcp>=4.1.5
|
|
8
|
+
Requires-Dist: msgpack>=1.1.0
|
|
9
|
+
|
|
10
|
+
# 搜韵诗词 MCP
|
|
11
|
+
|
|
12
|
+
基于搜韵网开放接口的 FastMCP 服务,通过 stdio 向 MCP 客户端提供诗词检索、韵典查询和歌词素材汇总工具。
|
|
13
|
+
|
|
14
|
+
## 环境准备
|
|
15
|
+
|
|
16
|
+
- Python 3.13 或更高版本
|
|
17
|
+
- [uv](https://docs.astral.sh/uv/)
|
|
18
|
+
- 运行时可访问 `api.sou-yun.cn`
|
|
19
|
+
|
|
20
|
+
在项目目录安装依赖:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
uv sync
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 启动
|
|
27
|
+
|
|
28
|
+
MCP 服务使用 stdio,由 MCP 客户端按需启动并管理进程:
|
|
29
|
+
|
|
30
|
+
```powershell
|
|
31
|
+
uv run python .\souyun_mcp.py
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
也可以直接使用项目虚拟环境:
|
|
35
|
+
|
|
36
|
+
```powershell
|
|
37
|
+
.\.venv\Scripts\python.exe .\souyun_mcp.py
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## MCP 客户端配置
|
|
41
|
+
|
|
42
|
+
在客户端的 MCP 配置中添加一个 stdio server。将示例中的目录替换为本机项目的绝对路径:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"souyun-poem": {
|
|
48
|
+
"command": "D:\\path\\to\\1102-mcp\\.venv\\Scripts\\python.exe",
|
|
49
|
+
"args": [
|
|
50
|
+
"D:\\path\\to\\1102-mcp\\souyun_mcp.py"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 可用工具
|
|
58
|
+
|
|
59
|
+
- `search_poems`: 按关键词检索诗词。`scope` 支持 `All`、`Author`、`Title`、`Sentence` 或数字 `0` 到 `3`;也可按 `dynasty`、`type_`、`rhyme` 和 `pageno` 筛选,`jsontype` 控制 JSON 返回格式。
|
|
60
|
+
- `get_poem`: 按 `poem_id` 查询单首诗词详情。
|
|
61
|
+
- `rhyme_dictionary`: 按 `char` 查询韵典;`qtype` 为 `0` 查全部、`1` 查韵目、`2` 查词末典故、`3` 查词首、`4` 查词末、`5` 查句末诗例。可通过 `page_no` 翻页。
|
|
62
|
+
- `couplet_words`: 查询与 `word` 对仗的词汇。
|
|
63
|
+
- `rhyme_category`: 不传 `rhyme` 时查询平水韵总目;传入韵部时查询该韵包含的字。
|
|
64
|
+
- `collect_lyrics_material`: 按 `theme` 汇总候选诗词、诗句和韵部建议。可设置 `top_n`、`dynasty`、`type_`;传入 `rhyme_char` 时还会返回相关对仗词和典故。
|
1102_mcp-0.1.0/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# 搜韵诗词 MCP
|
|
2
|
+
|
|
3
|
+
基于搜韵网开放接口的 FastMCP 服务,通过 stdio 向 MCP 客户端提供诗词检索、韵典查询和歌词素材汇总工具。
|
|
4
|
+
|
|
5
|
+
## 环境准备
|
|
6
|
+
|
|
7
|
+
- Python 3.13 或更高版本
|
|
8
|
+
- [uv](https://docs.astral.sh/uv/)
|
|
9
|
+
- 运行时可访问 `api.sou-yun.cn`
|
|
10
|
+
|
|
11
|
+
在项目目录安装依赖:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
uv sync
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 启动
|
|
18
|
+
|
|
19
|
+
MCP 服务使用 stdio,由 MCP 客户端按需启动并管理进程:
|
|
20
|
+
|
|
21
|
+
```powershell
|
|
22
|
+
uv run python .\souyun_mcp.py
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
也可以直接使用项目虚拟环境:
|
|
26
|
+
|
|
27
|
+
```powershell
|
|
28
|
+
.\.venv\Scripts\python.exe .\souyun_mcp.py
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## MCP 客户端配置
|
|
32
|
+
|
|
33
|
+
在客户端的 MCP 配置中添加一个 stdio server。将示例中的目录替换为本机项目的绝对路径:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"souyun-poem": {
|
|
39
|
+
"command": "D:\\path\\to\\1102-mcp\\.venv\\Scripts\\python.exe",
|
|
40
|
+
"args": [
|
|
41
|
+
"D:\\path\\to\\1102-mcp\\souyun_mcp.py"
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 可用工具
|
|
49
|
+
|
|
50
|
+
- `search_poems`: 按关键词检索诗词。`scope` 支持 `All`、`Author`、`Title`、`Sentence` 或数字 `0` 到 `3`;也可按 `dynasty`、`type_`、`rhyme` 和 `pageno` 筛选,`jsontype` 控制 JSON 返回格式。
|
|
51
|
+
- `get_poem`: 按 `poem_id` 查询单首诗词详情。
|
|
52
|
+
- `rhyme_dictionary`: 按 `char` 查询韵典;`qtype` 为 `0` 查全部、`1` 查韵目、`2` 查词末典故、`3` 查词首、`4` 查词末、`5` 查句末诗例。可通过 `page_no` 翻页。
|
|
53
|
+
- `couplet_words`: 查询与 `word` 对仗的词汇。
|
|
54
|
+
- `rhyme_category`: 不传 `rhyme` 时查询平水韵总目;传入韵部时查询该韵包含的字。
|
|
55
|
+
- `collect_lyrics_material`: 按 `theme` 汇总候选诗词、诗句和韵部建议。可设置 `top_n`、`dynasty`、`type_`;传入 `rhyme_char` 时还会返回相关对仗词和典故。
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "1102-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Add your description here"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"fastmcp>=4.1.5",
|
|
9
|
+
"msgpack>=1.1.0",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[tool.setuptools]
|
|
13
|
+
py-modules = ["souyun_mcp"]
|
1102_mcp-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""FastMCP server for the Souyun open poem APIs."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from typing import Any
|
|
5
|
+
from urllib.parse import urlencode
|
|
6
|
+
from urllib.request import Request, urlopen
|
|
7
|
+
|
|
8
|
+
from fastmcp import FastMCP
|
|
9
|
+
|
|
10
|
+
API_BASE = "https://api.sou-yun.cn/open"
|
|
11
|
+
REQUEST_TIMEOUT_SECONDS = 25
|
|
12
|
+
|
|
13
|
+
mcp = FastMCP("搜韵诗词")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _get(path: str, params: dict[str, Any]) -> Any:
|
|
17
|
+
query = urlencode(
|
|
18
|
+
{key: value for key, value in params.items() if value is not None}
|
|
19
|
+
)
|
|
20
|
+
request = Request(
|
|
21
|
+
f"{API_BASE}{path}?{query}",
|
|
22
|
+
headers={"User-Agent": "Mozilla/5.0", "Accept": "application/json"},
|
|
23
|
+
)
|
|
24
|
+
with urlopen(request, timeout=REQUEST_TIMEOUT_SECONDS) as response:
|
|
25
|
+
return json.loads(response.read().decode("utf-8"))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _text(node: Any) -> str:
|
|
29
|
+
if isinstance(node, dict):
|
|
30
|
+
return node.get("Content") or node.get("content") or ""
|
|
31
|
+
if isinstance(node, str):
|
|
32
|
+
return node
|
|
33
|
+
return ""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _search_poems(
|
|
37
|
+
keyword: str,
|
|
38
|
+
scope: str | int = "All",
|
|
39
|
+
dynasty: str | None = None,
|
|
40
|
+
type_: str | None = None,
|
|
41
|
+
rhyme: str | None = None,
|
|
42
|
+
pageno: int = 0,
|
|
43
|
+
jsontype: bool = True,
|
|
44
|
+
) -> Any:
|
|
45
|
+
params: dict[str, Any] = {
|
|
46
|
+
"key": keyword,
|
|
47
|
+
"scope": scope,
|
|
48
|
+
"jsontype": str(jsontype).lower(),
|
|
49
|
+
"pageno": pageno,
|
|
50
|
+
}
|
|
51
|
+
if dynasty:
|
|
52
|
+
params["dynasty"] = dynasty
|
|
53
|
+
if type_:
|
|
54
|
+
params["type"] = type_
|
|
55
|
+
if rhyme:
|
|
56
|
+
params["rhyme"] = rhyme
|
|
57
|
+
return _get("/poem", params)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _rhyme_dictionary(char: str, qtype: int = 0, page_no: int = 0) -> Any:
|
|
61
|
+
return _get("/rhymeDictionary", {"id": char, "qtype": qtype, "pageNo": page_no})
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _couplet_words(word: str) -> Any:
|
|
65
|
+
return _get("/coupletwords", {"id": word})
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _rhyme_category(rhyme: str | None = None) -> Any:
|
|
69
|
+
if rhyme:
|
|
70
|
+
return _get("/RhymeCategory", {"id": rhyme})
|
|
71
|
+
return _get("/RhymeCategory", {"list": ""})
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _collect_lyrics_material(
|
|
75
|
+
theme: str,
|
|
76
|
+
top_n: int = 8,
|
|
77
|
+
rhyme_char: str | None = None,
|
|
78
|
+
dynasty: str | None = None,
|
|
79
|
+
type_: str | None = None,
|
|
80
|
+
) -> dict[str, Any]:
|
|
81
|
+
poems = _search_poems(theme, scope="All", dynasty=dynasty, type_=type_, pageno=0)
|
|
82
|
+
poem_rows = (poems.get("ShiData") or [])[:top_n]
|
|
83
|
+
|
|
84
|
+
candidate_poems = []
|
|
85
|
+
candidate_lines = []
|
|
86
|
+
rhyme_count: dict[str, int] = {}
|
|
87
|
+
for poem in poem_rows:
|
|
88
|
+
candidate_poems.append(
|
|
89
|
+
{
|
|
90
|
+
"id": poem.get("Id"),
|
|
91
|
+
"title": _text(poem.get("Title")),
|
|
92
|
+
"author": poem.get("Author"),
|
|
93
|
+
"dynasty": poem.get("Dynasty"),
|
|
94
|
+
"type": poem.get("Type"),
|
|
95
|
+
"rhyme": poem.get("Rhyme"),
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
rhyme = poem.get("Rhyme")
|
|
99
|
+
if rhyme:
|
|
100
|
+
rhyme_count[rhyme] = rhyme_count.get(rhyme, 0) + 1
|
|
101
|
+
for clause in poem.get("Clauses") or []:
|
|
102
|
+
line = _text(clause)
|
|
103
|
+
if line:
|
|
104
|
+
candidate_lines.append(line)
|
|
105
|
+
|
|
106
|
+
result: dict[str, Any] = {
|
|
107
|
+
"theme": theme,
|
|
108
|
+
"candidate_poems": candidate_poems,
|
|
109
|
+
"candidate_lines": candidate_lines,
|
|
110
|
+
"rhyme_suggestions": rhyme_count,
|
|
111
|
+
}
|
|
112
|
+
if rhyme_char:
|
|
113
|
+
result["couplet_words"] = _couplet_words(rhyme_char)
|
|
114
|
+
dictionary = _rhyme_dictionary(rhyme_char)
|
|
115
|
+
result["allusions"] = (
|
|
116
|
+
dictionary.get("Allusions") if isinstance(dictionary, dict) else None
|
|
117
|
+
)
|
|
118
|
+
return result
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@mcp.tool
|
|
122
|
+
def search_poems(
|
|
123
|
+
keyword: str,
|
|
124
|
+
scope: str | int = "All",
|
|
125
|
+
dynasty: str | None = None,
|
|
126
|
+
type_: str | None = None,
|
|
127
|
+
rhyme: str | None = None,
|
|
128
|
+
pageno: int = 0,
|
|
129
|
+
jsontype: bool = True,
|
|
130
|
+
) -> Any:
|
|
131
|
+
"""按关键词检索诗词;scope 可选 All、Author、Title、Sentence 或 0 到 3。"""
|
|
132
|
+
return _search_poems(keyword, scope, dynasty, type_, rhyme, pageno, jsontype)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@mcp.tool
|
|
136
|
+
def get_poem(poem_id: str) -> Any:
|
|
137
|
+
"""按诗词 ID 获取单首详情。"""
|
|
138
|
+
return _get("/poem", {"key": poem_id, "jsontype": "true"})
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@mcp.tool
|
|
142
|
+
def rhyme_dictionary(char: str, qtype: int = 0, page_no: int = 0) -> Any:
|
|
143
|
+
"""查询韵典;qtype 为 0 查全部,1 查韵目,2 查词末典故,3/4 查词首/词末,5 查句末诗例。"""
|
|
144
|
+
return _rhyme_dictionary(char, qtype, page_no)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@mcp.tool
|
|
148
|
+
def couplet_words(word: str) -> Any:
|
|
149
|
+
"""查询与输入字词对仗的词汇参考。"""
|
|
150
|
+
return _couplet_words(word)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@mcp.tool
|
|
154
|
+
def rhyme_category(rhyme: str | None = None) -> Any:
|
|
155
|
+
"""查询平水韵总目,或查询指定韵部包含的字。"""
|
|
156
|
+
return _rhyme_category(rhyme)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@mcp.tool
|
|
160
|
+
def collect_lyrics_material(
|
|
161
|
+
theme: str,
|
|
162
|
+
top_n: int = 8,
|
|
163
|
+
rhyme_char: str | None = None,
|
|
164
|
+
dynasty: str | None = None,
|
|
165
|
+
type_: str | None = None,
|
|
166
|
+
) -> dict[str, Any]:
|
|
167
|
+
"""汇总主题相关诗词、诗句、韵部建议,可选附加对仗词和典故。"""
|
|
168
|
+
return _collect_lyrics_material(theme, top_n, rhyme_char, dynasty, type_)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def main() -> None:
|
|
172
|
+
mcp.run(transport="stdio")
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
main()
|