1- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' ;
2- import { defaultConfig } from './config.js' ;
3- import { toolParamsSchema } from './types.js' ;
1+ #!/usr/bin/env node
2+
3+ import { Server } from "@modelcontextprotocol/sdk/server/index.js" ;
4+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" ;
5+ import {
6+ CallToolRequestSchema ,
7+ ListToolsRequestSchema ,
8+ Tool ,
9+ } from "@modelcontextprotocol/sdk/types.js" ;
410import { validateMarkdown } from './validation.js' ;
5- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' ;
11+ import { defaultConfig } from './config.js' ;
12+
13+ const VALIDATE_TOOL : Tool = {
14+ name : "validate" ,
15+ description :
16+ "Validates markdown content against markdownlint rules. " +
17+ "Checks for common markdown style and formatting issues. " +
18+ "Returns validation results including any errors found. " +
19+ "Can be configured with custom markdownlint rules." ,
20+ inputSchema : {
21+ type : "object" ,
22+ properties : {
23+ content : {
24+ type : "string" ,
25+ description : "The markdown content to validate"
26+ } ,
27+ config : {
28+ type : "object" ,
29+ description : "Optional markdownlint configuration" ,
30+ additionalProperties : true
31+ }
32+ } ,
33+ required : [ "content" ]
34+ }
35+ } ;
36+
37+ const RULES_TOOL : Tool = {
38+ name : "rules" ,
39+ description :
40+ "Returns the available markdownlint rules and their configurations. " +
41+ "Each rule includes its default settings and description." ,
42+ inputSchema : {
43+ type : "object" ,
44+ properties : { } ,
45+ additionalProperties : false
46+ }
47+ } ;
48+
49+ // Server implementation
50+ const server = new Server (
51+ {
52+ name : "markdownlint-server" ,
53+ version : "1.0.0" ,
54+ } ,
55+ {
56+ capabilities : {
57+ tools : { } ,
58+ } ,
59+ }
60+ ) ;
61+
62+ function isValidateArgs ( args : unknown ) : args is { content: string ; config ? : Record < string , any > } {
63+ return (
64+ typeof args === "object" &&
65+ args !== null &&
66+ "content" in args &&
67+ typeof ( args as { content : string } ) . content === "string" &&
68+ ( ! ( "config" in args ) || typeof ( args as { config : unknown } ) . config === "object" )
69+ ) ;
70+ }
71+
72+ function isRulesArgs ( args : unknown ) : args is Record < string , never > {
73+ return (
74+ typeof args === "object" &&
75+ args !== null &&
76+ Object . keys ( args ) . length === 0
77+ ) ;
78+ }
679
7- export class MarkdownlintMcpServer extends McpServer {
8- private currentTransport : StdioServerTransport | null = null ;
80+ // Tool handlers
81+ server.setRequestHandler(ListToolsRequestSchema, async () => ( {
82+ tools : [ VALIDATE_TOOL , RULES_TOOL ] ,
83+ } ));
984
10- constructor ( ) {
11- super ( {
12- name : 'markdownlint-server' ,
13- version : '1.0.0'
14- } ) ;
85+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
86+ try {
87+ const { name, arguments : args } = request . params ;
1588
16- // Define the validate tool
17- this . tool (
18- 'validate' ,
19- toolParamsSchema ,
20- async ( params ) => {
21- const result = await validateMarkdown ( params ) ;
89+ if ( ! args ) {
90+ throw new Error ( "No arguments provided" ) ;
91+ }
92+
93+ switch ( name ) {
94+ case "validate" : {
95+ if ( ! isValidateArgs ( args ) ) {
96+ throw new Error ( "Invalid arguments for validate tool" ) ;
97+ }
98+ const result = await validateMarkdown ( args ) ;
2299 return {
23100 content : [ {
24- type : ' text' ,
101+ type : " text" ,
25102 text : JSON . stringify ( result , null , 2 )
26103 } ] ,
27104 isError : ! result . isValid
28105 } ;
29106 }
30- ) ;
31107
32- // Define the rules tool
33- this . tool (
34- 'rules' ,
35- { } ,
36- async ( ) => {
37- try {
38- return {
39- content : [ {
40- type : 'text' ,
41- text : JSON . stringify ( defaultConfig , null , 2 )
42- } ]
43- } ;
44- } catch ( error ) {
45- return {
46- content : [ {
47- type : 'text' ,
48- text : JSON . stringify ( {
49- error : error instanceof Error ? error . message : 'Unknown error'
50- } , null , 2 )
51- } ] ,
52- isError : true
53- } ;
108+ case "rules ": {
109+ if ( ! isRulesArgs ( args ) ) {
110+ throw new Error ( "Invalid arguments for rules tool" ) ;
54111 }
112+ return {
113+ content : [ {
114+ type : "text" ,
115+ text : JSON . stringify ( defaultConfig , null , 2 )
116+ } ] ,
117+ isError : false
118+ } ;
55119 }
56- ) ;
57- }
58-
59- async connect ( transport : StdioServerTransport ) : Promise < void > {
60- this . currentTransport = transport ;
61- await super . connect ( transport ) ;
62- }
63120
64- disconnect ( ) : void {
65- if ( this . currentTransport ) {
66- this . currentTransport . close ( ) ;
67- this . currentTransport = null ;
121+ default :
122+ return {
123+ content : [ { type : "text" , text : `Unknown tool: ${ name } ` } ] ,
124+ isError : true ,
125+ } ;
68126 }
127+ } catch ( error ) {
128+ return {
129+ content : [
130+ {
131+ type : "text" ,
132+ text : `Error: ${ error instanceof Error ? error . message : String ( error ) } ` ,
133+ } ,
134+ ] ,
135+ isError : true ,
136+ } ;
69137 }
138+ } ) ;
139+
140+ async function runServer ( ) {
141+ const transport = new StdioServerTransport ( ) ;
142+ await server . connect ( transport ) ;
143+ console . error ( "Markdownlint MCP Server running on stdio" ) ;
70144}
71145
72- export function markdownlintMcpServer ( ) {
73- return new MarkdownlintMcpServer ( ) ;
74- }
146+ runServer ( ) . catch ( ( error ) => {
147+ console . error ( "Fatal error running server:" , error ) ;
148+ process . exit ( 1 ) ;
149+ } ) ;
0 commit comments