feat(datasource): add yuandian_law legal data source + request-id trace (#611)
Some checks are pending
CI / build (push) Waiting to run
CI / test (push) Waiting to run
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
Nix Build / Check flake.nix workspace sync (push) Waiting to run
Nix Build / nix build .#kimi-code (push) Blocked by required conditions
Release / Release (push) Waiting to run
Release / Deploy docs (push) Blocked by required conditions
Release / Native release artifact (push) Blocked by required conditions
Release / Publish native release assets (push) Blocked by required conditions

- Register the yuandian_law (元典法律数据库) data source for Chinese
  laws/regulations and judicial case search.
- Append a request-id / tool-call-id trace line to every tool result so
  failures can be correlated with backend logs.
- Fix the documented MCP tool names in SKILL.md (-data -> _data).
- Also includes the dev marketplace-server env isolation fix in dev.mjs.

Co-authored-by: qer <Anna_Knapprfr@mail.com>
This commit is contained in:
qer 2026-06-10 22:29:51 +08:00 committed by GitHub
parent d8cdebf3c0
commit 71f5926d0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 173 additions and 25 deletions

View file

@ -5,7 +5,7 @@
"id": "kimi-datasource",
"tier": "official",
"displayName": "Kimi Datasource",
"version": "3.1.2",
"version": "3.2.0",
"description": "Official datasource workflows.",
"keywords": ["data", "mcp"],
"source": "./official/kimi-datasource"

View file

@ -1,5 +1,10 @@
# Changelog
## 3.2.0 - 2026-06-10
- Add the `yuandian_law` data source (元典法律数据库) for Chinese laws/regulations and judicial case search.
- Append a trace line (`request-id` / `tool-call-id`) to every tool result so failures can be correlated with backend logs.
## 3.1.2 - 2026-06-09
- Use OAuth credentials and datasource endpoints that match the active Kimi Code environment.

View file

@ -1,8 +1,8 @@
---
name: kimi-datasource
description: |
Universal data-source assistant. Use this skill when the user wants external structured data such as stocks, financial reports, technical indicators, A-share/HK/US markets, global macroeconomics, Chinese enterprise registry information, arXiv papers, or Google Scholar results.
This plugin exposes tools via MCP server `plugin-kimi-datasource-data`; call them in the flow `mcp__plugin-kimi-datasource-data__get_data_source_desc``mcp__plugin-kimi-datasource-data__call_data_source_tool`.
Universal data-source assistant. Use this skill when the user wants external structured data such as stocks, financial reports, technical indicators, A-share/HK/US markets, global macroeconomics, Chinese enterprise registry information, arXiv papers, Google Scholar results, or Chinese laws/regulations and judicial cases.
This plugin exposes tools via MCP server `plugin-kimi-datasource_data`; call them in the flow `mcp__plugin-kimi-datasource_data__get_data_source_desc``mcp__plugin-kimi-datasource_data__call_data_source_tool`.
---
# kimi-datasource — 通用数据源助手
@ -11,8 +11,8 @@ description: |
本 skill 使用 datasource MCP server 注册的两个工具,不要通过 Bash 手动执行脚本:
- `mcp__plugin-kimi-datasource-data__get_data_source_desc`
- `mcp__plugin-kimi-datasource-data__call_data_source_tool`
- `mcp__plugin-kimi-datasource_data__get_data_source_desc`
- `mcp__plugin-kimi-datasource_data__call_data_source_tool`
这两个工具由 Kimi Code 托管执行,参数直接按 tool schema 传 JSON。
@ -20,7 +20,7 @@ description: |
## 1. 这个 skill 提供什么能力
本 plugin 后面挂了 6 个外部数据源。每一行的"数据源名"就是传给 `get_data_source_desc``name`
本 plugin 后面挂了 7 个外部数据源。每一行的"数据源名"就是传给 `get_data_source_desc``name`
| 能力域 | 数据源名 | 典型问题 |
|---|---|---|
@ -30,6 +30,7 @@ description: |
| **中国企业工商信息** | `tianyancha` | "字节跳动股东"、"比亚迪司法风险"、"宁德时代专利" |
| **arXiv 论文预印本** | `arxiv` | "找 RAG 综述"、"下载 2406.xxxxx" |
| **Google Scholar 学术搜索** | `scholar` | "Hinton 最新论文"、"transformer 综述高引文献" |
| **中国法律法规 / 司法案例** | `yuandian_law` | "民法典关于居住权的规定"、"帮我查劳动合同解除的相关法条"、"找几个不当得利的判例" |
**不支持的能力**:通用 Web 搜索 / 实时新闻。问到这类问题,告诉用户当前数据源不覆盖。
@ -51,16 +52,16 @@ description: |
### 例 1用户问"茅台最近一年走势"
1. 股票走势 → `stock_finance_data`
2. 调用 `mcp__plugin-kimi-datasource-data__get_data_source_desc`,参数 `{"name":"stock_finance_data"}`
2. 调用 `mcp__plugin-kimi-datasource_data__get_data_source_desc`,参数 `{"name":"stock_finance_data"}`
3. 从文档里找到"获取历史价格"那个 API看它要 `ticker / start_date / end_date / file_path`
4. 用 web_search 核对 → 茅台 = `600519.SH`
5. 调用 `mcp__plugin-kimi-datasource-data__call_data_source_tool`,参数形如 `{"data_source_name":"stock_finance_data","api_name":"<文档里写的 api>","params":{"ticker":"600519.SH","start_date":"...","end_date":"...","file_path":"/tmp/mao_1y.csv"}}`
5. 调用 `mcp__plugin-kimi-datasource_data__call_data_source_tool`,参数形如 `{"data_source_name":"stock_finance_data","api_name":"<文档里写的 api>","params":{"ticker":"600519.SH","start_date":"...","end_date":"...","file_path":"/tmp/mao_1y.csv"}}`
### 例 2用户问"找几篇 retrieval augmented generation 的综述"
1. 论文搜索 → `arxiv`(或 `scholar`arxiv 更适合预印本scholar 引用更全)
2. 调用 `mcp__plugin-kimi-datasource-data__get_data_source_desc`,参数 `{"name":"arxiv"}`
2. 调用 `mcp__plugin-kimi-datasource_data__get_data_source_desc`,参数 `{"name":"arxiv"}`
3. 从文档里找到搜索类 API看它要 `query / file_path / max_results`
4. 执行 `call_data_source_tool`
@ -68,7 +69,7 @@ description: |
### 例 3用户问"字节跳动有哪些股东"
1. 企业工商 → `tianyancha`
2. 调用 `mcp__plugin-kimi-datasource-data__get_data_source_desc`,参数 `{"name":"tianyancha"}`
2. 调用 `mcp__plugin-kimi-datasource_data__get_data_source_desc`,参数 `{"name":"tianyancha"}`
3. 注意tianyancha 的 API 是动态注册的,文档会指引你**先用搜索类接口找到合适的 API 名,再调用**
4. **必须使用企业全称**"北京字节跳动科技有限公司"),不要用简称。不知道全称就先用 tianyancha 文档里的"公司搜索"接口查

View file

@ -18,7 +18,7 @@ import { arch, homedir, hostname, release, type } from 'node:os';
import path from 'node:path';
import readline from 'node:readline';
const VERSION = '3.1.2';
const VERSION = '3.2.0';
const DEFAULT_KIMI_CODE_OAUTH_HOST = 'https://auth.kimi.com';
const DEFAULT_KIMI_CODE_BASE_URL = 'https://api.kimi.com/coding/v1';
const API_URL = datasourceApiUrl();
@ -65,6 +65,7 @@ const TOOLS = [
'tianyancha',
'arxiv',
'scholar',
'yuandian_law',
],
description: 'Data source name.',
},
@ -123,17 +124,18 @@ async function runTool(params) {
isError: true,
};
}
const trace = {};
try {
const built = handler.buildParams(args);
const response = await callKimiTool(handler.method, built);
const response = await callKimiTool(handler.method, built, trace);
const fileWarnings = await writeResponseFiles(response, expectedResponseFilePath(built));
const text = extractText(response);
const formatted = (handler.format?.(text, built) ?? text).trim();
return { content: [{ type: 'text', text: appendWarnings(formatted, fileWarnings) }] };
return { content: [{ type: 'text', text: appendTrace(appendWarnings(formatted, fileWarnings), trace) }] };
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
return {
content: [{ type: 'text', text: message }],
content: [{ type: 'text', text: appendTrace(message, trace) }],
isError: true,
};
}
@ -206,6 +208,25 @@ function appendWarnings(text, warnings) {
return `${text}\n\n${warnings.join('\n')}`;
}
// Pick the backend request id from the response headers, if the gateway sends one.
function extractRequestId(headers) {
for (const key of ['x-request-id', 'x-trace-id', 'x-msh-request-id', 'x-msh-trace-id', 'request-id']) {
const value = headers.get(key);
if (typeof value === 'string' && value.trim().length > 0) return value.trim();
}
return undefined;
}
// Append a trace line so failures can be correlated with backend logs. The
// tool-call-id is the `X-Msh-Tool-Call-Id` header we send on every request.
function appendTrace(text, trace) {
if (trace === undefined || trace.toolCallId === undefined) return text;
const parts = [];
if (trace.requestId !== undefined) parts.push(`request-id: ${trace.requestId}`);
parts.push(`tool-call-id: ${trace.toolCallId}`);
return `${text}\n\n[kimi-datasource] ${parts.join(' · ')}`;
}
function resolveKimiHome() {
const explicit = process.env.KIMI_CODE_HOME?.trim();
return explicit && explicit.length > 0 ? explicit : path.join(homedir(), '.kimi-code');
@ -287,8 +308,10 @@ async function loadAccessToken() {
return { kimiHome, token };
}
async function callKimiTool(method, params) {
async function callKimiTool(method, params, trace = {}) {
const { kimiHome, token } = await loadAccessToken();
const toolCallId = randomUUID();
trace.toolCallId = toolCallId;
const controller = new AbortController();
const timeout = setTimeout(() => {
controller.abort();
@ -296,10 +319,11 @@ async function callKimiTool(method, params) {
try {
const response = await fetch(API_URL, {
method: 'POST',
headers: await buildHeaders(kimiHome, token),
headers: await buildHeaders(kimiHome, token, toolCallId),
body: JSON.stringify({ method, params }),
signal: controller.signal,
});
trace.requestId = extractRequestId(response.headers);
const text = await response.text();
if (!response.ok) {
throw new Error(`HTTP ${response.status} error: ${text}`);
@ -319,11 +343,11 @@ async function callKimiTool(method, params) {
}
}
async function buildHeaders(kimiHome, token) {
async function buildHeaders(kimiHome, token, toolCallId) {
return {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
'X-Msh-Tool-Call-Id': randomUUID(),
'X-Msh-Tool-Call-Id': toolCallId,
'X-Msh-Platform': asciiHeader(process.env.KIMI_MSH_PLATFORM ?? 'kimi-code-cli'),
'X-Msh-Version': asciiHeader(process.env.KIMI_MSH_VERSION ?? VERSION),
'X-Msh-Device-Name': asciiHeader(process.env.KIMI_MSH_DEVICE_NAME ?? hostname()),

View file

@ -1,8 +1,8 @@
{
"name": "kimi-datasource",
"version": "3.1.2",
"description": "Finance, macro, enterprise, and academic data tools for Kimi Code.",
"keywords": ["finance", "data-source", "mcp"],
"version": "3.2.0",
"description": "Finance, macro, enterprise, academic, and legal data tools for Kimi Code.",
"keywords": ["finance", "data-source", "mcp", "legal"],
"mcpServers": {
"data": {
"command": "node",
@ -12,7 +12,7 @@
},
"interface": {
"displayName": "Kimi Datasource",
"shortDescription": "Finance, macro, enterprise, and academic data tools",
"shortDescription": "Finance, macro, enterprise, academic, and legal data tools",
"developerName": "Moonshot AI"
}
}