law-mcp-server 0.1.5 → 0.1.7
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/bin/law-mcp-server.js +0 -0
- package/dist/lawApi.js +19 -3
- package/dist/src/index.js +3 -2
- package/dist/src/lawApi.js +33 -4
- package/dist/src/tools.js +5 -4
- package/package.json +1 -1
package/bin/law-mcp-server.js
CHANGED
|
File without changes
|
package/dist/lawApi.js
CHANGED
|
@@ -40,7 +40,23 @@ export const fetchLawData = async (lawId, revisionDate) => {
|
|
|
40
40
|
};
|
|
41
41
|
export const searchLaws = async (keyword) => {
|
|
42
42
|
const base = config.apiBase.endsWith("/") ? config.apiBase : `${config.apiBase}/`;
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const queryUrl = new URL(`lawsearch`, base);
|
|
44
|
+
queryUrl.searchParams.set("keyword", keyword);
|
|
45
|
+
try {
|
|
46
|
+
return await request(queryUrl.toString());
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50
|
+
if (message.includes("404")) {
|
|
51
|
+
const pathUrl = new URL(`lawsearch/${encodeURIComponent(keyword)}`, base);
|
|
52
|
+
try {
|
|
53
|
+
return await request(pathUrl.toString());
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
57
|
+
throw new Error(`Law search failed for keyword "${keyword}". Tried query and path styles. Upstream: ${msg}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
46
62
|
};
|
package/dist/src/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { StdioJsonRpcServer } from "./mcp.js";
|
|
3
|
-
import { tools, resolveTool } from "./tools.js";
|
|
3
|
+
import { tools, resolveTool, usageInstructions } from "./tools.js";
|
|
4
4
|
const server = new StdioJsonRpcServer();
|
|
5
|
-
const serverInfo = { name: "law-mcp-server", version: "0.1.
|
|
5
|
+
const serverInfo = { name: "law-mcp-server", version: "0.1.6" };
|
|
6
6
|
server.register("initialize", async (params) => {
|
|
7
7
|
const payload = (params ?? {});
|
|
8
8
|
const protocolVersion = typeof payload.protocolVersion === "string"
|
|
@@ -11,6 +11,7 @@ server.register("initialize", async (params) => {
|
|
|
11
11
|
return {
|
|
12
12
|
protocolVersion,
|
|
13
13
|
serverInfo,
|
|
14
|
+
instructions: usageInstructions,
|
|
14
15
|
capabilities: {
|
|
15
16
|
tools: {
|
|
16
17
|
list: true,
|
package/dist/src/lawApi.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { fetch } from "undici";
|
|
2
2
|
import { cache } from "./cache.js";
|
|
3
3
|
import { config } from "./config.js";
|
|
4
|
+
class HttpError extends Error {
|
|
5
|
+
status;
|
|
6
|
+
body;
|
|
7
|
+
constructor(status, body) {
|
|
8
|
+
super(`Request failed ${status}: ${body}`);
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.body = body;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
4
13
|
const withTimeout = async (promise, ms) => {
|
|
5
14
|
const controller = new AbortController();
|
|
6
15
|
const timer = setTimeout(() => controller.abort(), ms);
|
|
@@ -23,7 +32,7 @@ const request = async (url, context) => {
|
|
|
23
32
|
if (res.status === 404 && context?.lawId) {
|
|
24
33
|
throw new Error(`Law not found for lawId "${context.lawId}". Use the official LawID (e.g., 平成十五年法律第五十七号 => H15HO57). Upstream: ${body}`);
|
|
25
34
|
}
|
|
26
|
-
throw new
|
|
35
|
+
throw new HttpError(res.status, body);
|
|
27
36
|
}
|
|
28
37
|
const data = (await res.json());
|
|
29
38
|
return data;
|
|
@@ -47,7 +56,27 @@ export const searchLaws = async (keyword) => {
|
|
|
47
56
|
const base = config.apiBase.endsWith("/")
|
|
48
57
|
? config.apiBase
|
|
49
58
|
: `${config.apiBase}/`;
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
const queryUrl = new URL(`lawsearch`, base);
|
|
60
|
+
queryUrl.searchParams.set("keyword", keyword);
|
|
61
|
+
try {
|
|
62
|
+
return await request(queryUrl.toString());
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
const is404 = error instanceof HttpError && error.status === 404;
|
|
66
|
+
// Some deployments return 404 for no hits; normalize to empty result.
|
|
67
|
+
if (is404) {
|
|
68
|
+
const pathUrl = new URL(`lawsearch/${encodeURIComponent(keyword)}`, base);
|
|
69
|
+
try {
|
|
70
|
+
return await request(pathUrl.toString());
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const path404 = err instanceof HttpError && err.status === 404;
|
|
74
|
+
if (path404) {
|
|
75
|
+
return { numberOfHits: 0, referencelaw: [] };
|
|
76
|
+
}
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
53
82
|
};
|
package/dist/src/tools.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fetchLawData, searchLaws } from "./lawApi.js";
|
|
2
2
|
import { checkConsistency } from "./consistency.js";
|
|
3
|
+
export const usageInstructions = `Usage guidelines:\n\n- To find laws by Japanese name/keyword, call search_laws first. It returns canonical e-Gov LawID values (e.g., 個人情報保護法 -> H15HO57).\n- Always pass the canonical LawID to fetch_law, list_revisions, and check_consistency (lawIds). Do not pass the Japanese title string.\n- fetch_law accepts optional revisionDate when you need a specific revision.\n- check_consistency requires at least one LawID in lawIds. Use search_laws to discover the IDs before calling.\n- summarize_law can take an optional articles array of article numbers to limit the summary.`;
|
|
3
4
|
const requireString = (value, field) => {
|
|
4
5
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
5
6
|
throw new Error(`Field ${field} is required`);
|
|
@@ -14,7 +15,7 @@ const requireArrayOfStrings = (value, field) => {
|
|
|
14
15
|
};
|
|
15
16
|
const fetchLaw = {
|
|
16
17
|
name: "fetch_law",
|
|
17
|
-
description: "Fetch a law by LawID and optional revision date",
|
|
18
|
+
description: "Fetch a law by canonical e-Gov LawID (e.g., H15HO57) and optional revision date. Use search_laws to look up the LawID first.",
|
|
18
19
|
inputSchema: {
|
|
19
20
|
type: "object",
|
|
20
21
|
properties: {
|
|
@@ -32,7 +33,7 @@ const fetchLaw = {
|
|
|
32
33
|
};
|
|
33
34
|
const search = {
|
|
34
35
|
name: "search_laws",
|
|
35
|
-
description: "Search laws by keyword",
|
|
36
|
+
description: "Search laws by Japanese keyword/name and return canonical LawID values for use with other tools.",
|
|
36
37
|
inputSchema: {
|
|
37
38
|
type: "object",
|
|
38
39
|
properties: {
|
|
@@ -81,7 +82,7 @@ const summarize = {
|
|
|
81
82
|
};
|
|
82
83
|
const listRevisions = {
|
|
83
84
|
name: "list_revisions",
|
|
84
|
-
description: "List known revisions for a law
|
|
85
|
+
description: "List known revisions for a law (requires canonical LawID from search_laws).",
|
|
85
86
|
inputSchema: {
|
|
86
87
|
type: "object",
|
|
87
88
|
properties: {
|
|
@@ -100,7 +101,7 @@ const listRevisions = {
|
|
|
100
101
|
};
|
|
101
102
|
const check = {
|
|
102
103
|
name: "check_consistency",
|
|
103
|
-
description: "Check a document against one or more laws",
|
|
104
|
+
description: "Check a document against one or more laws (lawIds must be canonical LawIDs from search_laws).",
|
|
104
105
|
inputSchema: {
|
|
105
106
|
type: "object",
|
|
106
107
|
properties: {
|