One local MCP server wrapping five free prose linters (proselint, alex, write-good, blocklint, textstat) plus an AI-tell detector — for catching weak, inflated, exclusionary, or LLM-generated writing without per-word subscription costs
Server provides 7 prose-linting tools with consistent naming (verb_noun: lint_*, check_*, audit_*) and reasonable descriptions (100-200 chars). All tools accept text OR path parameters with clear descriptions. However, schemas lack explicit type definitions for input parameters, they are inferred from function signatures rather than formally declared. Output schemas are documented in descriptions but not in structured JSON Schema format. Error handling is present but generic; no recovery guidance or actionable error messages. Security is well-handled (path validation, file size caps, allow-list). Composition is sound, each tool has one responsibility. Baseline: avg tool description ~150 chars (within 10-1024 range); all params described; but schema formality is weak.
Run all five linters (proselint, alex, write-good, blocklint, textstat) plus AI-tells check at once and return a merged report. Provide either `text` or `path`. Returns {results: {proselint: {...}, alex: {...}, write_good: {...}, blocklint: {...}, textstat: {...}, ai_tells: {...}}, summary: {total_issues, source}}.
Detect common AI-generated writing patterns (repetitive phrasing, hedging language, overuse of 'delve', 'explore', 'nuance', etc.). Provide either `text` or `path`. Returns {findings: [{pattern, message, count, examples}], score, source}.
Run alex (inclusive-language linter) on prose. Flags gender-favoring, ableist, race-related, and other insensitive constructions in Markdown/MDX/HTML/plain text. Provide either `text` or `path`. Returns {findings: [{ruleId, message, line, column, severity}], count, source}.
Run blocklint on prose (non-inclusive language in source/identifiers — e.g. master/slave, blacklist/whitelist). Provide either `text` or `path`. Returns {findings: [{rule, message, line, column}], count, source}.
Run proselint on prose (Bryan Garner / DFW / Pinker / Orwell-style rules — adverbs, cliches, hyperbole, redundancy, vague modifiers). Provide either `text` (a string) OR `path` (absolute file path). Returns {findings: [{check, message, line, column, severity, replacements?}], count, source}.
Input schemas lack formal JSON Schema type declarations. Parameters (text, path) are documented in descriptions but not explicitly typed in schema objects. Rubric requires 'parameters lack type definitions → schema score cannot exceed 30' per tool.
Output schemas documented only in tool descriptions, not as structured JSON Schema. LLMs cannot parse unstructured prose descriptions to infer response structure. Rubric: 'Document the output schema. LLMs need to know what fields to expect.'
Error handling returns generic error dicts without recovery guidance. Rubric: 'Error responses must tell the LLM what to do next.' Example: FILE_TOO_LARGE error should suggest 'Split the file or increase PROSE_RICH_MAX_FILE_BYTES.'
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 51 | 2026-07-28+ | v2 |
Run textstat on prose (readability + stylometric stats: Flesch-Kincaid, Gunning Fog, SMOG, Coleman-Liau, Automated Readability Index, Dale-Chall, Linsear Write, etc.). Provide either `text` or `path`. Returns {stats: {flesch_kincaid_grade, gunning_fog, smog_index, ...}, source}.
Run write-good on prose (passive voice, weasel words, lexical illusions, repeated words). Provide either `text` or `path`. Returns {findings: [{rule, message, line, column}], count, source}.
Mutually exclusive parameters (text vs path) documented in descriptions but not enforced at schema level. Rubric: 'If parameters are mutually exclusive, state this in descriptions.' Current approach relies on runtime validation; schema-level oneOf would be clearer.
Tool descriptions lack 'when to use' guidance. Rubric: 'Write descriptions as if prompt-engineering. State WHAT the tool does, WHEN to use it, and any prerequisites.' E.g., lint_proselint should clarify when to prefer it over lint_write_good.