@contextlint/mcp-server 0.4.7 → 0.5.1
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/dist/index.js +55 -102
- package/dist/index.js.map +1 -1
- package/package.json +9 -6
- package/dist/format.d.ts +0 -8
- package/dist/format.d.ts.map +0 -1
- package/dist/format.js +0 -38
- package/dist/format.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { relative, resolve } from "node:path";
|
|
2
|
+
import { resolve } from "node:path";
|
|
4
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
-
import { parseDocument, runRules, resolveRule } from "@contextlint/core";
|
|
7
|
-
import { glob } from "glob";
|
|
5
|
+
import { parseDocument, runRules, resolveRule, lintFiles, findConfig, loadConfig, formatContentResults, formatFileResults, } from "@contextlint/core";
|
|
8
6
|
import * as z from "zod/v4";
|
|
9
|
-
import { formatContentResults, formatFileResults, } from "./format.js";
|
|
10
7
|
const server = new McpServer({
|
|
11
8
|
name: "contextlint",
|
|
12
9
|
version: "0.0.0",
|
|
13
10
|
});
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
server.registerTool("lint", {
|
|
12
|
+
description: "Lint markdown content with specified rules",
|
|
13
|
+
inputSchema: {
|
|
14
|
+
content: z.string().describe("Markdown text to lint"),
|
|
15
|
+
rules: z
|
|
16
|
+
.array(z.object({
|
|
17
|
+
rule: z.string().describe("Rule name (e.g. tbl001)"),
|
|
18
|
+
options: z
|
|
19
|
+
.record(z.string(), z.unknown())
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Rule options"),
|
|
22
|
+
}))
|
|
23
|
+
.describe("Rules to apply"),
|
|
24
|
+
},
|
|
25
|
+
}, ({ content, rules: ruleEntries }) => {
|
|
27
26
|
try {
|
|
28
27
|
const rules = ruleEntries.map((entry) => resolveRule(entry.rule, entry.options));
|
|
29
28
|
const document = parseDocument(content);
|
|
@@ -39,95 +38,49 @@ server.tool("lint", "Lint markdown content with specified rules", {
|
|
|
39
38
|
};
|
|
40
39
|
}
|
|
41
40
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
41
|
+
server.registerTool("lint-files", {
|
|
42
|
+
description: "Lint markdown files matching glob patterns using a config file or preset",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
patterns: z
|
|
45
|
+
.array(z.string())
|
|
46
|
+
.optional()
|
|
47
|
+
.describe('Glob patterns (default: ["**/*.md"])'),
|
|
48
|
+
configPath: z
|
|
49
|
+
.string()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('Config file path (default: "contextlint.config.json")'),
|
|
52
|
+
cwd: z
|
|
53
|
+
.string()
|
|
54
|
+
.optional()
|
|
55
|
+
.describe('Working directory (default: ".")'),
|
|
56
|
+
},
|
|
57
|
+
}, ({ patterns, configPath, cwd }) => {
|
|
57
58
|
const resolvedCwd = resolve(cwd ?? ".");
|
|
58
|
-
const resolvedPatterns = patterns ?? ["**/*.md"];
|
|
59
59
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
raw = readFileSync(fullConfigPath, "utf-8");
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
return {
|
|
68
|
-
content: [
|
|
69
|
-
{
|
|
70
|
-
type: "text",
|
|
71
|
-
text: `Error: Cannot read config file: ${fullConfigPath}`,
|
|
72
|
-
},
|
|
73
|
-
],
|
|
74
|
-
isError: true,
|
|
75
|
-
};
|
|
60
|
+
let resolvedConfigPath;
|
|
61
|
+
if (configPath) {
|
|
62
|
+
resolvedConfigPath = resolve(resolvedCwd, configPath);
|
|
76
63
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
isError: true,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
if (!config.rules || !Array.isArray(config.rules)) {
|
|
93
|
-
return {
|
|
94
|
-
content: [
|
|
95
|
-
{
|
|
96
|
-
type: "text",
|
|
97
|
-
text: `Error: Config must have a "rules" array: ${fullConfigPath}`,
|
|
98
|
-
},
|
|
99
|
-
],
|
|
100
|
-
isError: true,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
const rules = config.rules.map((entry) => resolveRule(entry.rule, entry.options));
|
|
104
|
-
const docRules = rules.filter((r) => (r.scope ?? "document") === "document");
|
|
105
|
-
const projectRules = rules.filter((r) => r.scope === "project");
|
|
106
|
-
// Find and lint files
|
|
107
|
-
const files = await glob(resolvedPatterns, {
|
|
108
|
-
cwd: resolvedCwd,
|
|
109
|
-
absolute: true,
|
|
110
|
-
});
|
|
111
|
-
files.sort();
|
|
112
|
-
const projectFiles = files.map((f) => relative(resolvedCwd, f));
|
|
113
|
-
const results = [];
|
|
114
|
-
// Run project-scoped rules once
|
|
115
|
-
if (projectRules.length > 0) {
|
|
116
|
-
const emptyDoc = parseDocument("");
|
|
117
|
-
const messages = runRules(projectRules, emptyDoc, "<project>", {
|
|
118
|
-
projectFiles,
|
|
119
|
-
});
|
|
120
|
-
if (messages.length > 0) {
|
|
121
|
-
results.push({ filePath: "<project>", messages });
|
|
64
|
+
else {
|
|
65
|
+
const found = findConfig(resolvedCwd);
|
|
66
|
+
if (!found) {
|
|
67
|
+
return {
|
|
68
|
+
content: [
|
|
69
|
+
{
|
|
70
|
+
type: "text",
|
|
71
|
+
text: "Error: No contextlint.config.json found. Provide a configPath or create a config file.",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
isError: true,
|
|
75
|
+
};
|
|
122
76
|
}
|
|
77
|
+
resolvedConfigPath = found;
|
|
123
78
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
results.push({ filePath, messages });
|
|
130
|
-
}
|
|
79
|
+
const config = loadConfig(resolvedConfigPath);
|
|
80
|
+
const resolvedPatterns = patterns && patterns.length > 0
|
|
81
|
+
? patterns
|
|
82
|
+
: config.include ?? ["**/*.md"];
|
|
83
|
+
const results = lintFiles(resolvedPatterns, config, resolvedCwd);
|
|
131
84
|
const text = formatFileResults(results, resolvedCwd);
|
|
132
85
|
return { content: [{ type: "text", text }] };
|
|
133
86
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contextlint/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "MCP server for contextlint",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
7
|
-
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
8
12
|
"bin": {
|
|
9
13
|
"contextlint-mcp": "dist/index.js"
|
|
10
14
|
},
|
|
@@ -16,10 +20,9 @@
|
|
|
16
20
|
"typecheck": "tsc --noEmit"
|
|
17
21
|
},
|
|
18
22
|
"dependencies": {
|
|
19
|
-
"@contextlint/core": "0.
|
|
23
|
+
"@contextlint/core": "0.5.1",
|
|
20
24
|
"@modelcontextprotocol/sdk": "^1.27.0",
|
|
21
|
-
"
|
|
22
|
-
"zod": "^4.0.0"
|
|
25
|
+
"zod": "^4.3.6"
|
|
23
26
|
},
|
|
24
27
|
"publishConfig": {
|
|
25
28
|
"access": "public"
|
package/dist/format.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { LintMessage } from "@contextlint/core";
|
|
2
|
-
export interface FileLintResult {
|
|
3
|
-
filePath: string;
|
|
4
|
-
messages: LintMessage[];
|
|
5
|
-
}
|
|
6
|
-
export declare function formatContentResults(messages: LintMessage[]): string;
|
|
7
|
-
export declare function formatFileResults(results: FileLintResult[], cwd: string): string;
|
|
8
|
-
//# sourceMappingURL=format.d.ts.map
|
package/dist/format.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAkBpE;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EAAE,EACzB,GAAG,EAAE,MAAM,GACV,MAAM,CAkCR"}
|
package/dist/format.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { relative } from "node:path";
|
|
2
|
-
export function formatContentResults(messages) {
|
|
3
|
-
if (messages.length === 0) {
|
|
4
|
-
return "No issues found.";
|
|
5
|
-
}
|
|
6
|
-
const lines = [];
|
|
7
|
-
for (const msg of messages) {
|
|
8
|
-
lines.push(` line ${msg.line} ${msg.severity} ${msg.message} ${msg.ruleId}`);
|
|
9
|
-
}
|
|
10
|
-
lines.push("");
|
|
11
|
-
const errorWord = messages.length === 1 ? "error" : "errors";
|
|
12
|
-
lines.push(`${messages.length} ${errorWord}`);
|
|
13
|
-
return lines.join("\n");
|
|
14
|
-
}
|
|
15
|
-
export function formatFileResults(results, cwd) {
|
|
16
|
-
const filesWithErrors = results.filter((r) => r.messages.length > 0);
|
|
17
|
-
if (filesWithErrors.length === 0) {
|
|
18
|
-
return "No issues found.";
|
|
19
|
-
}
|
|
20
|
-
const lines = [];
|
|
21
|
-
let totalErrors = 0;
|
|
22
|
-
for (const result of filesWithErrors) {
|
|
23
|
-
const label = result.filePath === "<project>"
|
|
24
|
-
? "(project)"
|
|
25
|
-
: relative(cwd, result.filePath);
|
|
26
|
-
lines.push(label);
|
|
27
|
-
for (const msg of result.messages) {
|
|
28
|
-
lines.push(` line ${msg.line} ${msg.severity} ${msg.message} ${msg.ruleId}`);
|
|
29
|
-
totalErrors++;
|
|
30
|
-
}
|
|
31
|
-
lines.push("");
|
|
32
|
-
}
|
|
33
|
-
const fileWord = filesWithErrors.length === 1 ? "file" : "files";
|
|
34
|
-
const errorWord = totalErrors === 1 ? "error" : "errors";
|
|
35
|
-
lines.push(`${totalErrors} ${errorWord} in ${filesWithErrors.length} ${fileWord}`);
|
|
36
|
-
return lines.join("\n");
|
|
37
|
-
}
|
|
38
|
-
//# sourceMappingURL=format.js.map
|
package/dist/format.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAQrC,MAAM,UAAU,oBAAoB,CAAC,QAAuB;IAC1D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CACR,UAAU,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,MAAM,EAAE,CACtE,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC7D,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;IAE9C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,OAAyB,EACzB,GAAW;IAEX,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAErE,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,KAAK,GACT,MAAM,CAAC,QAAQ,KAAK,WAAW;YAC7B,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAElB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CACR,UAAU,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,MAAM,EAAE,CACtE,CAAC;YACF,WAAW,EAAE,CAAC;QAChB,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,MAAM,SAAS,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzD,KAAK,CAAC,IAAI,CACR,GAAG,WAAW,IAAI,SAAS,OAAO,eAAe,CAAC,MAAM,IAAI,QAAQ,EAAE,CACvE,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|