This MCP implements practical checks derived from George Orwell's six rules in Politics and the English Language.
Current implementation ships one MCP tool:
analyze_document(path, ...)
The tool analyzes a single file, aggregates analyzer output, applies server-side
filters, and returns normalized violations plus metadata (cached, errors,
analyzers_run).
- Python
3.11+ - POSIX shell
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -e ".[dev]"
python -m spacy download en_core_web_smRun as a Python module:
source .venv/bin/activate
python -m oldspeak.serverRun through FastMCP CLI:
source .venv/bin/activate
fastmcp run oldspeak/server.py --transport stdio
fastmcp run oldspeak/server.py --transport http --port 8000Inspect server metadata:
source .venv/bin/activate
fastmcp inspect oldspeak/server.py --format fastmcpRequired input:
path: str
Optional filters:
include_analyzers: list[str] | Noneinclude_rules: list[str] | Noneseverities: list[str] | Nonehas_suggestion: bool | Noneline_start: int | Noneline_end: int | Nonelimit: int | None
Validation:
line_startandline_endmust be>= 1when provided.line_start <= line_end.limit >= 0.
Response fields:
path: str(absolute path)violations: list[dict]total: intanalyzers_run: list[str]errors: list[{analyzer: str, error: str}]cached: bool
Violation fields:
analyzer,rule,severity,message,textoffset,length,line,end_linesuggestion,context,meta
Returns the rule summary text used by this server.
oldspeak/server.py: FastMCP registration and input/output surfaceoldspeak/analysis_cache.py: mtime/size cache-aside for file analysesoldspeak/workflow/collector.py: parallel analyzer execution, failure isolation, line normalization, dedupe, stable sortoldspeak/filters.py: post-collection filteringoldspeak/analyzers/*.py: analyzer implementationsoldspeak/wordlists/*: phrase and substitution data
examples/noisy_policy_memo.txtexamples/manifesto_draft.txtexamples/clean_control.txt
Run all tests:
source .venv/bin/activate
pytestTest coverage includes:
- analyzer unit tests
- collector behavior tests
- cache hit/miss/mtime tests
- server filter semantics tests
- example prose integration tests
- MCP runtime tests via
fastmcp.Client(stdio path + filter/failure paths) - HTTP transport smoke test using
StreamableHttpTransport
Local quality/security commands used before publishing:
source .venv/bin/activate
ruff check .
mypy oldspeak
bandit -r oldspeak -q
vulture oldspeak tests --min-confidence 80
pip-audit --ignore-vuln CVE-2025-69872
pytest -qNotes:
CVE-2025-69872(viadiskcache) currently has no published fix version. CI is configured to ignore this one CVE until an upstream patch is available.
source .venv/bin/activate
python - <<'PY'
import asyncio
import json
from fastmcp import Client
async def main():
async with Client("oldspeak/server.py") as client:
result = await client.call_tool("analyze_document", {"path": "examples/noisy_policy_memo.txt", "limit": 5})
payload = json.loads(result.content[0].text)
print(payload["total"], payload["cached"])
asyncio.run(main())
PYTo add an analyzer:
- Add a callable in
oldspeak/analyzers/and decorate with@analyzer(name=..., description=...). - Add module name to
_BUILTIN_MODULESinoldspeak/analyzers/__init__.py. - Add tests under
tests/.