@jurislm/judicial-mcp 1.3.0 → 1.6.2
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 +68 -9
- package/bin/judicial-mcp.ts +2 -0
- package/package.json +30 -17
- package/src/index.ts +20 -0
- package/src/public-judgment-source.ts +487 -0
- package/src/regulation-cache.ts +38 -0
- package/src/regulation-source.ts +536 -0
- package/src/response.ts +74 -0
- package/src/server.ts +70 -0
- package/src/source-error.ts +50 -0
- package/src/tools.ts +409 -0
- package/types/index.d.ts +1 -113
- package/types/public-judgment-source.d.ts +2 -0
- package/types/regulation-cache.d.ts +8 -0
- package/types/regulation-source.d.ts +29 -0
- package/types/response.d.ts +20 -0
- package/types/server.d.ts +3 -0
- package/types/source-error.d.ts +14 -0
- package/types/tools.d.ts +236 -0
- package/bin/judicial-mcp.js +0 -18
- package/src/index.js +0 -76
- package/src/response.js +0 -44
- package/src/tools.js +0 -360
package/types/tools.d.ts
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
export interface TokenArgs {
|
|
2
|
+
token: string;
|
|
3
|
+
}
|
|
4
|
+
export interface GetJudgmentArgs {
|
|
5
|
+
token: string;
|
|
6
|
+
jid: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ListResourcesArgs {
|
|
9
|
+
categoryNo: string;
|
|
10
|
+
token: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DownloadFileArgs {
|
|
13
|
+
fileSetId: string;
|
|
14
|
+
token: string;
|
|
15
|
+
top?: number;
|
|
16
|
+
skip?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface SearchJudgmentsArgs extends Record<string, unknown> {
|
|
19
|
+
keyword?: string;
|
|
20
|
+
court?: string;
|
|
21
|
+
year?: number;
|
|
22
|
+
caseNumber?: string;
|
|
23
|
+
limit?: number;
|
|
24
|
+
page?: number;
|
|
25
|
+
offset?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface FetchJudgmentTextArgs extends Record<string, unknown> {
|
|
28
|
+
caseId: string;
|
|
29
|
+
}
|
|
30
|
+
export interface QueryRegulationArgs extends Record<string, unknown> {
|
|
31
|
+
lawName: string;
|
|
32
|
+
articleNumber: string;
|
|
33
|
+
refresh?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export declare const TOOLS_CONFIG: {
|
|
36
|
+
readonly auth_token: {
|
|
37
|
+
readonly name: "auth_token";
|
|
38
|
+
readonly description: "取得司法院裁判書查詢系統的授權 Token。帳密從環境變數 JUDICIAL_USER / JUDICIAL_PASSWORD 讀取。";
|
|
39
|
+
readonly inputSchema: {
|
|
40
|
+
readonly type: "object";
|
|
41
|
+
readonly properties: {};
|
|
42
|
+
readonly additionalProperties: false;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
readonly list_judgments: {
|
|
46
|
+
readonly name: "list_judgments";
|
|
47
|
+
readonly description: "取得裁判書異動清單,包含新增、修改或刪除的裁判書資訊。";
|
|
48
|
+
readonly inputSchema: {
|
|
49
|
+
readonly type: "object";
|
|
50
|
+
readonly properties: {
|
|
51
|
+
readonly token: {
|
|
52
|
+
readonly type: "string";
|
|
53
|
+
readonly description: "從 auth_token 工具取得的授權 Token";
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
readonly required: readonly ["token"];
|
|
57
|
+
readonly additionalProperties: false;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
readonly get_judgment: {
|
|
61
|
+
readonly name: "get_judgment";
|
|
62
|
+
readonly description: "取得特定裁判書的完整內容,包含裁判全文。";
|
|
63
|
+
readonly inputSchema: {
|
|
64
|
+
readonly type: "object";
|
|
65
|
+
readonly properties: {
|
|
66
|
+
readonly token: {
|
|
67
|
+
readonly type: "string";
|
|
68
|
+
readonly description: "從 auth_token 工具取得的授權 Token";
|
|
69
|
+
};
|
|
70
|
+
readonly jid: {
|
|
71
|
+
readonly type: "string";
|
|
72
|
+
readonly description: "從 list_judgments 工具取得的裁判書 ID";
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
readonly required: readonly ["token", "jid"];
|
|
76
|
+
readonly additionalProperties: false;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
readonly list_categories: {
|
|
80
|
+
readonly name: "list_categories";
|
|
81
|
+
readonly description: "取得司法院開放資料平台的所有主題分類清單。";
|
|
82
|
+
readonly inputSchema: {
|
|
83
|
+
readonly type: "object";
|
|
84
|
+
readonly properties: {
|
|
85
|
+
readonly token: {
|
|
86
|
+
readonly type: "string";
|
|
87
|
+
readonly description: "從 member_token 工具取得的會員授權 Token";
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
readonly required: readonly ["token"];
|
|
91
|
+
readonly additionalProperties: false;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
readonly list_resources: {
|
|
95
|
+
readonly name: "list_resources";
|
|
96
|
+
readonly description: "取得指定分類下的所有資料源清單。";
|
|
97
|
+
readonly inputSchema: {
|
|
98
|
+
readonly type: "object";
|
|
99
|
+
readonly properties: {
|
|
100
|
+
readonly categoryNo: {
|
|
101
|
+
readonly type: "string";
|
|
102
|
+
readonly description: "從 list_categories 工具取得的分類編號";
|
|
103
|
+
};
|
|
104
|
+
readonly token: {
|
|
105
|
+
readonly type: "string";
|
|
106
|
+
readonly description: "從 member_token 工具取得的會員授權 Token";
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
readonly required: readonly ["categoryNo", "token"];
|
|
110
|
+
readonly additionalProperties: false;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
readonly download_file: {
|
|
114
|
+
readonly name: "download_file";
|
|
115
|
+
readonly description: "下載指定檔案集的資料檔案,支援分頁參數。";
|
|
116
|
+
readonly inputSchema: {
|
|
117
|
+
readonly type: "object";
|
|
118
|
+
readonly properties: {
|
|
119
|
+
readonly fileSetId: {
|
|
120
|
+
readonly type: "string";
|
|
121
|
+
readonly description: "從 list_resources 工具取得的檔案集 ID";
|
|
122
|
+
};
|
|
123
|
+
readonly top: {
|
|
124
|
+
readonly type: "integer";
|
|
125
|
+
readonly description: "限制回傳筆數(可選)";
|
|
126
|
+
readonly minimum: 0;
|
|
127
|
+
};
|
|
128
|
+
readonly skip: {
|
|
129
|
+
readonly type: "integer";
|
|
130
|
+
readonly description: "跳過筆數,用於分頁(可選)";
|
|
131
|
+
readonly minimum: 0;
|
|
132
|
+
};
|
|
133
|
+
readonly token: {
|
|
134
|
+
readonly type: "string";
|
|
135
|
+
readonly description: "從 member_token 工具取得的會員授權 Token";
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
readonly required: readonly ["fileSetId", "token"];
|
|
139
|
+
readonly additionalProperties: false;
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
readonly member_token: {
|
|
143
|
+
readonly name: "member_token";
|
|
144
|
+
readonly description: "取得司法院開放平台的會員授權 Token,用於存取會員專屬資源。帳密從環境變數 JUDICIAL_USER / JUDICIAL_PASSWORD 讀取。";
|
|
145
|
+
readonly inputSchema: {
|
|
146
|
+
readonly type: "object";
|
|
147
|
+
readonly properties: {};
|
|
148
|
+
readonly additionalProperties: false;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
readonly search_judgments: {
|
|
152
|
+
readonly name: "search_judgments";
|
|
153
|
+
readonly description: "透過司法院公開裁判書查詢頁搜尋裁判,不需要授權 Token。year 可使用西元或民國年;完整案號可同時指定案類。";
|
|
154
|
+
readonly inputSchema: {
|
|
155
|
+
readonly type: "object";
|
|
156
|
+
readonly properties: {
|
|
157
|
+
readonly keyword: {
|
|
158
|
+
readonly type: "string";
|
|
159
|
+
readonly description: "裁判全文關鍵字,最多 128 字元";
|
|
160
|
+
};
|
|
161
|
+
readonly court: {
|
|
162
|
+
readonly type: "string";
|
|
163
|
+
readonly description: "司法院法院名稱或官方法院代碼";
|
|
164
|
+
};
|
|
165
|
+
readonly year: {
|
|
166
|
+
readonly type: "integer";
|
|
167
|
+
readonly description: "裁判年度,可使用西元或民國年";
|
|
168
|
+
readonly minimum: 1;
|
|
169
|
+
readonly maximum: 9999;
|
|
170
|
+
};
|
|
171
|
+
readonly caseNumber: {
|
|
172
|
+
readonly type: "string";
|
|
173
|
+
readonly description: "案號數字,或「年度案類字第號」格式";
|
|
174
|
+
};
|
|
175
|
+
readonly limit: {
|
|
176
|
+
readonly type: "integer";
|
|
177
|
+
readonly description: "每頁最多回傳筆數,預設 5,上限 10";
|
|
178
|
+
readonly minimum: 1;
|
|
179
|
+
readonly maximum: 10;
|
|
180
|
+
};
|
|
181
|
+
readonly page: {
|
|
182
|
+
readonly type: "integer";
|
|
183
|
+
readonly description: "官方結果頁頁碼,預設 1,上限 50";
|
|
184
|
+
readonly minimum: 1;
|
|
185
|
+
readonly maximum: 50;
|
|
186
|
+
};
|
|
187
|
+
readonly offset: {
|
|
188
|
+
readonly type: "integer";
|
|
189
|
+
readonly description: "官方結果頁內的起始位置,預設 0,範圍 0–19;依回傳的 next_page 與 next_offset 繼續查詢";
|
|
190
|
+
readonly minimum: 0;
|
|
191
|
+
readonly maximum: 19;
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
readonly additionalProperties: false;
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
readonly fetch_judgment_text: {
|
|
198
|
+
readonly name: "fetch_judgment_text";
|
|
199
|
+
readonly description: "依 search_judgments 回傳的 case_id 取得司法院公開裁判全文,不需要授權 Token。";
|
|
200
|
+
readonly inputSchema: {
|
|
201
|
+
readonly type: "object";
|
|
202
|
+
readonly properties: {
|
|
203
|
+
readonly caseId: {
|
|
204
|
+
readonly type: "string";
|
|
205
|
+
readonly description: "search_judgments 回傳的 case_id";
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
readonly required: readonly ["caseId"];
|
|
209
|
+
readonly additionalProperties: false;
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
readonly query_regulation: {
|
|
213
|
+
readonly name: "query_regulation";
|
|
214
|
+
readonly description: "依官方法規名稱與條號查詢全國法規資料庫現行條文,回傳版本日期與官方來源;不提供歷史版本。";
|
|
215
|
+
readonly inputSchema: {
|
|
216
|
+
readonly type: "object";
|
|
217
|
+
readonly properties: {
|
|
218
|
+
readonly lawName: {
|
|
219
|
+
readonly type: "string";
|
|
220
|
+
readonly description: "法規名稱;若名稱不是唯一精確匹配,會回傳候選清單";
|
|
221
|
+
};
|
|
222
|
+
readonly articleNumber: {
|
|
223
|
+
readonly type: "string";
|
|
224
|
+
readonly description: "條號數字,可含連字號,例如 1 或 1-1";
|
|
225
|
+
};
|
|
226
|
+
readonly refresh: {
|
|
227
|
+
readonly type: "boolean";
|
|
228
|
+
readonly description: "設為 true 時略過快取並重新讀取官方來源";
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
readonly required: readonly ["lawName", "articleNumber"];
|
|
232
|
+
readonly additionalProperties: false;
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
export declare const TOOL_HANDLERS: Record<string, (_args: Record<string, unknown>) => Promise<unknown>>;
|
package/bin/judicial-mcp.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file judicial-mcp.js
|
|
5
|
-
* @description 司法院 MCP 伺服器的命令列介面 (CLI) 入口點
|
|
6
|
-
* 此檔案作為全域安裝時的可執行檔案,直接啟動伺服器
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 引入並執行 MCP 伺服器
|
|
11
|
-
* 直接載入 src/index.js 來啟動 MCP 伺服器
|
|
12
|
-
*
|
|
13
|
-
* 使用方式:
|
|
14
|
-
* - 全域安裝後:judicial-mcp
|
|
15
|
-
* - 或直接執行:node bin/judicial-mcp.js
|
|
16
|
-
* - MCP 客戶端連接:透過 stdio 傳輸協定
|
|
17
|
-
*/
|
|
18
|
-
require('../src/index.js');
|
package/src/index.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file src/index.js
|
|
5
|
-
* @description 司法院 MCP 伺服器 - 遵循 Model Context Protocol 規範
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const originalConsole = { ...console };
|
|
9
|
-
console.log = console.info = console.warn = () => {};
|
|
10
|
-
try {
|
|
11
|
-
require('dotenv').config();
|
|
12
|
-
} finally {
|
|
13
|
-
Object.assign(console, originalConsole);
|
|
14
|
-
}
|
|
15
|
-
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
|
|
16
|
-
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
17
|
-
const { CallToolRequestSchema, ListToolsRequestSchema } = require('@modelcontextprotocol/sdk/types.js');
|
|
18
|
-
const { TOOLS_CONFIG, TOOL_HANDLERS } = require('./tools.js');
|
|
19
|
-
const { createSuccessResponse, createErrorResponse } = require('./response.js');
|
|
20
|
-
const { version } = require('../package.json');
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* MCP 伺服器實例
|
|
24
|
-
*/
|
|
25
|
-
const server = new Server(
|
|
26
|
-
{
|
|
27
|
-
name: 'judicial-mcp',
|
|
28
|
-
version,
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
capabilities: {
|
|
32
|
-
tools: {},
|
|
33
|
-
},
|
|
34
|
-
}
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* 列出所有可用的工具
|
|
39
|
-
*/
|
|
40
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
41
|
-
return {
|
|
42
|
-
tools: Object.values(TOOLS_CONFIG),
|
|
43
|
-
};
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* 處理工具調用請求
|
|
48
|
-
*/
|
|
49
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
50
|
-
const { name, arguments: args } = request.params;
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
if (!TOOL_HANDLERS[name]) {
|
|
54
|
-
throw new Error(`未知的工具: ${name}`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const result = await TOOL_HANDLERS[name](args || {});
|
|
58
|
-
return createSuccessResponse(result);
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.error(`執行工具 ${name} 時發生錯誤:`, error?.message);
|
|
61
|
-
return createErrorResponse(error, `執行工具 ${name} 時發生錯誤`);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* 啟動 MCP 伺服器
|
|
67
|
-
*/
|
|
68
|
-
async function main() {
|
|
69
|
-
const transport = new StdioServerTransport();
|
|
70
|
-
await server.connect(transport);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
main().catch((error) => {
|
|
74
|
-
console.error('伺服器啟動失敗:', error);
|
|
75
|
-
process.exit(1);
|
|
76
|
-
});
|
package/src/response.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file src/response.js
|
|
3
|
-
* @description MCP 規範回應格式工具函數
|
|
4
|
-
*
|
|
5
|
-
* MCP spec: CallToolResult = { content: ContentBlock[], isError?: boolean }
|
|
6
|
-
* - 成功:isError 省略(預設 false)
|
|
7
|
-
* - 失敗:isError: true,讓 client 能分辨工具錯誤與成功回應
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 建立成功的 MCP 工具回應
|
|
12
|
-
* @param {*} data - 回傳的資料(會序列化為 JSON)
|
|
13
|
-
* @returns {Object} MCP CallToolResult
|
|
14
|
-
*/
|
|
15
|
-
const createSuccessResponse = (data) => ({
|
|
16
|
-
content: [
|
|
17
|
-
{
|
|
18
|
-
type: 'text',
|
|
19
|
-
text: JSON.stringify(data, null, 2),
|
|
20
|
-
},
|
|
21
|
-
],
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 建立失敗的 MCP 工具回應
|
|
26
|
-
* MCP 規範要求錯誤回應必須包含 isError: true
|
|
27
|
-
* @param {Error|Object} error - 錯誤物件
|
|
28
|
-
* @param {string} message - 錯誤描述
|
|
29
|
-
* @returns {Object} MCP CallToolResult with isError: true
|
|
30
|
-
*/
|
|
31
|
-
const createErrorResponse = (error, message) => {
|
|
32
|
-
const detail = error?.response?.data ?? error?.message ?? String(error);
|
|
33
|
-
return {
|
|
34
|
-
content: [
|
|
35
|
-
{
|
|
36
|
-
type: 'text',
|
|
37
|
-
text: JSON.stringify({ error: message, detail }, null, 2),
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
isError: true,
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
module.exports = { createSuccessResponse, createErrorResponse };
|