datasinking 0.2.11__tar.gz → 0.2.12__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.
- {datasinking-0.2.11 → datasinking-0.2.12}/PKG-INFO +1 -1
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking/_version.py +11 -11
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking/mcp_server.py +22 -2
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking.egg-info/PKG-INFO +1 -1
- {datasinking-0.2.11 → datasinking-0.2.12}/LICENSE +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/README.md +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking/__init__.py +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking/client.py +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking.egg-info/SOURCES.txt +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking.egg-info/dependency_links.txt +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking.egg-info/entry_points.txt +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking.egg-info/requires.txt +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/datasinking.egg-info/top_level.txt +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/pyproject.toml +0 -0
- {datasinking-0.2.11 → datasinking-0.2.12}/setup.cfg +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""版本号的**唯一来源**。
|
|
3
|
-
|
|
4
|
-
pyproject.toml 用 `dynamic = ["version"]` 从这里读,`client.py` 的 User-Agent 也读它。
|
|
5
|
-
|
|
6
|
-
为什么单独抽一个文件:之前 pyproject.toml 和 `__init__.py` 各写各的版本号,
|
|
7
|
-
结果 `__version__` 长期停在 0.1.0 没跟上(发 0.2.4 时才发现,User-Agent 里也一直
|
|
8
|
-
写着旧版本)。现在只有这一处需要改。
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
__version__ = "0.2.
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""版本号的**唯一来源**。
|
|
3
|
+
|
|
4
|
+
pyproject.toml 用 `dynamic = ["version"]` 从这里读,`client.py` 的 User-Agent 也读它。
|
|
5
|
+
|
|
6
|
+
为什么单独抽一个文件:之前 pyproject.toml 和 `__init__.py` 各写各的版本号,
|
|
7
|
+
结果 `__version__` 长期停在 0.1.0 没跟上(发 0.2.4 时才发现,User-Agent 里也一直
|
|
8
|
+
写着旧版本)。现在只有这一处需要改。
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__version__ = "0.2.12"
|
|
@@ -33,6 +33,25 @@ try:
|
|
|
33
33
|
except ImportError: # pragma: no cover
|
|
34
34
|
from mcp.server.mcpserver import MCPServer as FastMCP # mcp v2
|
|
35
35
|
|
|
36
|
+
# ⚠️ **工具里必须抛 ToolError,不能抛 RuntimeError。**
|
|
37
|
+
#
|
|
38
|
+
# mcp v2(实测 2.2.0)对两者的处理完全不同:
|
|
39
|
+
# 抛 RuntimeError → 客户端收到 isError:true,但文本是**通用句**
|
|
40
|
+
# 「Error executing tool <名字>」,**消息内容被剥掉**,只进 stderr
|
|
41
|
+
# 抛 ToolError → 客户端收到 isError:true,文本带上你的原话
|
|
42
|
+
# 「Error executing tool <名字>: <你的消息>」
|
|
43
|
+
#
|
|
44
|
+
# 这不是细节:get_section 的描述让模型「用真实标题重试」,标题列表就在消息里;
|
|
45
|
+
# 缺 API key 的提示也只在这里。用 RuntimeError 的话,模型看到的是一个**没有任何线索**的
|
|
46
|
+
# 失败 —— 2026-09-22 用真 key 走 uvx 发布版实测确认(`Error executing tool get_section`,32 字符)。
|
|
47
|
+
try:
|
|
48
|
+
from mcp.server.fastmcp.exceptions import ToolError # mcp v1
|
|
49
|
+
except ImportError: # pragma: no cover
|
|
50
|
+
try:
|
|
51
|
+
from mcp.server.mcpserver.exceptions import ToolError # mcp v2
|
|
52
|
+
except ImportError: # 极老的 mcp 没有这个类:退回普通异常(消息会丢,但不至于起不来)
|
|
53
|
+
ToolError = RuntimeError # type: ignore[assignment,misc]
|
|
54
|
+
|
|
36
55
|
# ⚠️ 参数描述必须写成 `Annotated[T, Field(description=...)]`,**不能只靠 docstring 的 Args 段**。
|
|
37
56
|
# mcp v2(MCPServer)不再解析 docstring 的 Args —— 实测把整段 Args 当散文塞进工具描述,
|
|
38
57
|
# 参数级 description 全是空的(2026-09-22 用真实 stdio 握手验证)。v1 两种都认,所以这样写两边通用。
|
|
@@ -70,7 +89,7 @@ def _get(path: str, params: Optional[dict] = None) -> dict:
|
|
|
70
89
|
也没有可重试的标题(2026-09-22 用真 key 实测,三份实现里这份丢得最干净)。
|
|
71
90
|
"""
|
|
72
91
|
if not API_KEY:
|
|
73
|
-
raise
|
|
92
|
+
raise ToolError(
|
|
74
93
|
"Missing DATASINK_API_KEY environment variable (get a free key at https://datasink.ing)"
|
|
75
94
|
)
|
|
76
95
|
p = dict(params or {})
|
|
@@ -87,7 +106,8 @@ def _get(path: str, params: Optional[dict] = None) -> dict:
|
|
|
87
106
|
available = body.get("available")
|
|
88
107
|
if isinstance(available, list):
|
|
89
108
|
msg += "\nAvailable sections: " + json.dumps(available, ensure_ascii=False)
|
|
90
|
-
|
|
109
|
+
# ToolError 而非 RuntimeError —— 否则 mcp v2 把 msg 剥成通用句,见文件顶部注释
|
|
110
|
+
raise ToolError(msg)
|
|
91
111
|
return r.json()
|
|
92
112
|
|
|
93
113
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|