{"_id":"@ducks-project/markdownlint-mcpserver","name":"@ducks-project/markdownlint-mcpserver","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@ducks-project/markdownlint-mcpserver","version":"0.2.0","description":"MCP server wrapping markdownlint for AI agents and editors","author":{"name":"Duck Team"},"license":"MIT","keywords":["mcp","markdownlint","markdown","linting","model-context-protocol"],"homepage":"https://github.com/ducks-project/markdownlint-mcpserver#readme","repository":{"type":"git","url":"git+https://github.com/ducks-project/markdownlint-mcpserver.git"},"bugs":{"url":"https://github.com/ducks-project/markdownlint-mcpserver/issues"},"type":"module","main":"dist/index.js","bin":{"markdownlint-mcpserver":"dist/index.js"},"engines":{"node":">=18.0.0"},"dependencies":{"@modelcontextprotocol/sdk":"^1.12.1","markdownlint":"^0.37.4","tinyglobby":"^0.2.17","yaml":"^2.9.0","zod":"^3.25.67"},"devDependencies":{"@commitlint/cli":"^21.0.2","@commitlint/config-conventional":"^21.0.2","@eslint/js":"^9.28.0","@jest/globals":"^29.7.0","@types/jest":"^29.5.14","@types/node":"^22.15.21","eslint":"^9.28.0","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.4.1","fast-check":"^3.23.2","jest":"^29.7.0","lefthook":"^1.11.13","mitata":"^1.0.34","prettier":"^3.5.3","ts-jest":"^29.3.4","ts-node":"^10.9.2","tsx":"^4.19.4","typescript":"^5.8.3","typescript-eslint":"^8.33.1"},"scripts":{"build":"tsc","typecheck":"tsc --noEmit","lint":"eslint 'src/**/*.ts' 'tests/**/*.ts' --no-error-on-unmatched-pattern","format":"prettier --write 'src/**/*.ts' 'tests/**/*.ts'","format:check":"prettier --check 'src/**/*.ts' 'tests/**/*.ts'","test":"jest --coverage --passWithNoTests","benchmark":"tsx benchmarks/index.ts","postinstall":"npx --no lefthook install || true"},"packageManager":"yarn@4.17.0","_id":"@ducks-project/markdownlint-mcpserver@0.2.0","gitHead":"ae5895453cc582be9dfb08aa7b6340f1bf9db592","types":"./dist/index.d.ts","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-nHviWFjMw02n5XP1UtEwftMWDIuBK3YO0zVp41tGuoR0SxZqV+hArCpiFOXnUcn148lkQusDf9FZ4uW8m34zxA==","shasum":"81dd6cb40cec838dce157517dc9ed9f035f5ffd9","tarball":"https://registry.npmjs.org/@ducks-project/markdownlint-mcpserver/-/markdownlint-mcpserver-0.2.0.tgz","fileCount":68,"unpackedSize":203374,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCOHCEhjKU7H+F+cdsc8GJRlj5v8j7RF0rHCRlZRX5wugIgDlDkLHMuCtxJNTXmRG3KsD0RnCSBvs5rQeuDIsKOAU8="}]},"_npmUser":{"name":"donaldinou","email":"donaldinou@gmail.com"},"directories":{},"maintainers":[{"name":"donaldinou","email":"donaldinou@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/markdownlint-mcpserver_0.2.0_1782225312702_0.1363157456586397"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-23T14:35:12.548Z","0.2.0":"2026-06-23T14:35:12.834Z","modified":"2026-06-23T14:35:13.133Z"},"maintainers":[{"name":"donaldinou","email":"donaldinou@gmail.com"}],"description":"MCP server wrapping markdownlint for AI agents and editors","homepage":"https://github.com/ducks-project/markdownlint-mcpserver#readme","keywords":["mcp","markdownlint","markdown","linting","model-context-protocol"],"repository":{"type":"git","url":"git+https://github.com/ducks-project/markdownlint-mcpserver.git"},"author":{"name":"Duck Team"},"bugs":{"url":"https://github.com/ducks-project/markdownlint-mcpserver/issues"},"license":"MIT","readme":"# @ducks-project/markdownlint-mcpserver\n\n[![npm version](https://img.shields.io/npm/v/@ducks-project/markdownlint-mcpserver)](https://www.npmjs.com/package/@ducks-project/markdownlint-mcpserver)\n[![build status](https://img.shields.io/github/actions/workflow/status/ducks-project/markdownlint-mcpserver/ci.yml?branch=main)](https://github.com/ducks-project/markdownlint-mcpserver/actions)\n[![coverage](https://img.shields.io/codecov/c/github/ducks-project/markdownlint-mcpserver)](https://codecov.io/gh/ducks-project/markdownlint-mcpserver)\n[![license](https://img.shields.io/npm/l/@ducks-project/markdownlint-mcpserver)](./LICENSE)\n\nA Model Context Protocol (MCP) server that wraps [markdownlint](https://github.com/DavidAnson/markdownlint)\nto expose markdown linting capabilities to AI agents and editors via stdio transport.\n\n## Features\n\n- Lint markdown content and get structured issue reports\n- Automatically fix markdown issues with deterministic corrections\n- Inspect the full markdownlint configuration and rule statuses\n- Lint files on disk via file path input\n- Discover and apply `.markdownlint.json`, `.markdownlint.yaml`, `.markdownlint-cli2.jsonc` config files\n- Recursively scan directories for markdown files\n- Glob pattern matching for targeted file selection\n- Lightweight stdio transport with JSON-RPC messaging\n- Async linting engine with configurable concurrency\n- Configuration cache for repeated calls\n\n## Installation\n\n```bash\nnpm install -g @ducks-project/markdownlint-mcpserver\n```\n\nOr run directly with npx:\n\n```bash\nnpx -y @ducks-project/markdownlint-mcpserver\n```\n\n## Usage\n\nAdd the server to your MCP client configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"markdownlint\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@ducks-project/markdownlint-mcpserver\"]\n    }\n  }\n}\n```\n\nThe server starts and listens on stdio for JSON-RPC messages following\nthe MCP protocol (version `2024-11-05`).\n\n## Tools\n\n### lint_markdown\n\nLint markdown content and return issues.\n\n**Input:**\n\n```json\n{\n  \"content\": \"# Hello World\\nSome text with trailing spaces   \\n\",\n  \"config\": { \"MD013\": false }\n}\n```\n\nOr lint a file by path:\n\n```json\n{\n  \"filePath\": \"docs/README.md\",\n  \"config\": { \"MD013\": false }\n}\n```\n\n**Output:**\n\n```json\n{\n  \"status\": \"issues_found\",\n  \"issueCount\": 1,\n  \"issues\": [\n    {\n      \"rule\": \"MD009\",\n      \"aliases\": [\"no-trailing-spaces\"],\n      \"line\": 2,\n      \"description\": \"Trailing spaces\",\n      \"detail\": \"Expected: 0 or 2; Actual: 3\",\n      \"context\": null,\n      \"range\": [25, 3],\n      \"fixable\": true\n    }\n  ]\n}\n```\n\n> When `filePath` is provided, the server discovers `.markdownlint.json` / `.markdownlint.yaml` config files\n> from the file's directory tree. If both `filePath` and `content` are provided with a valid file path,\n> an error is returned. If the file path is invalid and `content` is present, content is used as fallback.\n\n### fix_markdown\n\nFix markdown content by applying automatic corrections.\n\n**Input:**\n\n```json\n{\n  \"content\": \"# Hello World\\nSome text with trailing spaces   \\n\",\n  \"config\": { \"MD013\": false }\n}\n```\n\n**Output:**\n\n```json\n{\n  \"fixedContent\": \"# Hello World\\nSome text with trailing spaces\\n\",\n  \"issuesFixed\": 1,\n  \"issuesRemaining\": 0,\n  \"remainingIssues\": []\n}\n```\n\n### get_configuration\n\nGet the resolved markdownlint configuration with all rules.\n\n**Input:**\n\n```json\n{\n  \"config\": { \"MD033\": false }\n}\n```\n\n**Output:**\n\n```json\n{\n  \"config\": { \"default\": true, \"MD013\": false, \"MD033\": false },\n  \"rules\": [\n    {\n      \"rule\": \"MD001\",\n      \"alias\": \"heading-increment\",\n      \"description\": \"Heading levels should only increment by one level at a time\",\n      \"enabled\": true,\n      \"parameters\": null\n    }\n  ],\n  \"summary\": { \"total\": 51, \"enabled\": 49, \"disabled\": 2 }\n}\n```\n\n### lint_directory\n\nLint all markdown files in a directory or matching a glob pattern.\n\n**Input (directory scan):**\n\n```json\n{\n  \"path\": \"docs\",\n  \"config\": { \"MD013\": false }\n}\n```\n\n**Input (glob pattern):**\n\n```json\n{\n  \"path\": \".\",\n  \"glob\": \"docs/**/*.md\",\n  \"concurrency\": 4\n}\n```\n\n**Output:**\n\n```json\n{\n  \"filesScanned\": 3,\n  \"filesWithIssues\": 1,\n  \"totalIssues\": 2,\n  \"results\": [\n    {\n      \"filePath\": \"/project/docs/guide.md\",\n      \"status\": \"issues_found\",\n      \"issueCount\": 2,\n      \"issues\": [...]\n    },\n    {\n      \"filePath\": \"/project/docs/setup.md\",\n      \"status\": \"clean\",\n      \"issueCount\": 0,\n      \"issues\": []\n    }\n  ]\n}\n```\n\n> Content limit: 1MB per file. Glob limit: 1000 matched files (results truncated with a `warning` field).\n> Hidden directories (`.git`, `.vscode`) and `node_modules` are skipped during directory scan.\n\n## Configuration\n\nAll tools accept an optional `config` parameter that overrides the default configuration.\nThe default configuration enables all rules except MD013 (line length):\n\n```json\n{\n  \"default\": true,\n  \"MD013\": false\n}\n```\n\n### Filesystem Configuration Discovery\n\nWhen using `filePath` or `lint_directory`, the server automatically discovers\nconfiguration files from the file's directory tree (walking upward to `process.cwd()`):\n\n1. `.markdownlint.json` (highest priority)\n2. `.markdownlint.yaml`\n3. `.markdownlint-cli2.jsonc`\n\nIf a config file has invalid syntax, the server falls back to the next format in the same directory.\n\n### Configuration Merge Hierarchy (lowest to highest priority)\n\n1. Default config (`{ \"default\": true, \"MD013\": false }`)\n2. Filesystem config (nearest `.markdownlint.json` / `.yaml` / `.jsonc`)\n3. Runtime config (passed in tool `config` parameter)\n\n### Merging Rules\n\n1. If no config is provided, the default is used\n2. User config is shallow-merged over defaults (user values win)\n3. Setting `\"default\": false` disables all rules not explicitly enabled\n4. Rule values can be `true`/`false` (enable/disable) or an object with parameters\n\n## Development Setup\n\n### Prerequisites\n\n- Node.js >= 18.0.0\n- Yarn 4.x (included via `packageManager` field)\n\n### Getting Started\n\n```bash\n# Clone the repository\ngit clone https://github.com/ducks-project/markdownlint-mcpserver.git\ncd markdownlint-mcpserver\n\n# Install dependencies (zero-install: .yarn/cache is committed)\nyarn install\n\n# Build\nyarn build\n\n# Run tests\nyarn test\n\n# Lint\nyarn lint\n\n# Run benchmarks\nyarn benchmark\n```\n\n### Project Structure\n\n```text\nsrc/             # TypeScript source files\ntests/\n  unit/          # Unit tests\n  integration/   # Integration tests (full MCP cycles)\n  property/      # Property-based tests (fast-check)\nbenchmarks/      # Performance benchmarks (mitata)\ndocs/            # Documentation\ndist/            # Compiled output (generated)\n```\n\n### Scripts\n\n| Command             | Description                          |\n| ------------------- | ------------------------------------ |\n| `yarn build`        | Compile TypeScript to ESM in `dist/` |\n| `yarn lint`         | Run ESLint on source and test files  |\n| `yarn test`         | Run Jest with coverage               |\n| `yarn benchmark`    | Run performance benchmarks           |\n| `yarn typecheck`    | Type-check without emitting          |\n| `yarn format`       | Format code with Prettier            |\n| `yarn format:check` | Check formatting without writing     |\n\n### Conventional Commits\n\nThis project enforces [Conventional Commits](https://www.conventionalcommits.org/)\nvia Lefthook + commitlint. All commit messages must follow the format:\n\n```text\ntype(scope): description\n```\n\nValid types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `perf`, `ci`\n\n## License\n\n[MIT](./LICENSE) - Duck Team\n","readmeFilename":"README.md","_rev":"1-c89387ae476e79f0d746b85b5472f051"}