Skip to main content
Glama

rtl-mcp

npm CI License: MIT

An MCP server that gives a coding agent right-to-left awareness.

Ask an agent for a card component and you get ml-4 text-left — correct English, broken Arabic. The agent has no way to check itself, because nothing in its toolbox knows what RTL is. This gives it four tools that do.

Install

Point your MCP client at the package. Nothing to install first — npx fetches it.

Claude Code

claude mcp add rtl -- npx -y rtl-mcp

Any client that reads an mcpServers block (Claude Desktop, Cursor, Windsurf, Zed):

{
  "mcpServers": {
    "rtl": {
      "command": "npx",
      "args": ["-y", "rtl-mcp"]
    }
  }
}

Related MCP server: code-review-automation

Tools

Tool

What the agent gets

lint_rtl_code

Pass a snippet and a filename; get every physical CSS property, directional Tailwind utility and dir problem, each with its logical replacement. Powered by rtl-lint.

lint_rtl_path

The same check across a file or a whole directory on disk.

normalize_arabic

Fold the spellings users type interchangeably into one key — strips diacritics and tatweel, unifies the alef forms. For search and matching, not for display.

detect_direction

Whether a string is rtl, ltr, mixed or neutral, and what to set dir to.

Both lint tools accept baseDir: "rtl" for an Arabic-first app — see below.

Why normalize_arabic matters

مُحَمَّد and محمد are the same name and different strings. So are أحمد and احمد. A user who types their name without diacritics will not find their own record, and the bug reads like a broken database rather than a text problem.

normalize_arabic("مُحَمَّدْ") → "محمد"
normalize_arabic("أحـمد")    → "احمد"

The two folds that change meaning — ى → ي and ة → ه — are off by default. They widen fuzzy search and corrupt anything you display.

Pass baseDir: "rtl" for an Arabic-first app

Which logical side a physical one maps to depends on the document's base direction. In ltr, left is the start; in rtl, left is the end. So text-right in an English-first app becomes text-end, and in an app rooted at <html dir="rtl"> it becomes text-start — the opposite edge. Take the default on an Arabic app and the agent mirrors a working layout.

Utilities the author already scoped, like ltr:left-3 rtl:right-3, are left alone entirely.

Why detect_direction is not just a regex

Arabic-Indic digits (٢٠٢٦) live inside the Arabic Unicode block, so the obvious implementation calls them RTL. Under the bidirectional algorithm they are class AN, not AL — they never set the direction of a paragraph. Only strong letters vote here, so ٢٠٢٦ comes back neutral and inherits its container's direction, which is what the spec says should happen.

Zero runtime dependencies

MCP over stdio is JSON-RPC 2.0, one message per line. The reference SDK brings seventeen transitive dependencies — Express, Hono, CORS, JOSE — none of which a stdio server uses. So the protocol layer here is written directly, and the only runtime dependency is rtl-lint.

That trade is only safe if conformance is proven rather than assumed. The test suite drives this server with the official SDK's client over a real stdio pipe. If the hand-written layer ever drifts from the specification, the reference implementation stops talking to it and CI goes red.

Protocol revisions understood: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05. The server negotiates whichever one the client asks for.

Library use

The Arabic helpers work standalone, no MCP involved:

import { normalizeArabic, detectDirection } from "rtl-mcp/arabic";

normalizeArabic("مُحَمَّد");                      // "محمد"
normalizeArabic("٢٠٢٦", { convertDigits: true }); // "2026"
detectDirection("مرحبا React").direction;         // "mixed"

Requirements

Node.js 20 or newer. (Node 18 reached end of life in April 2025.)

License

MIT © Khalel Hawary

Available Tools

4 tools
detect_directionA

Report whether a string is predominantly right-to-left, left-to-right, mixed or neutral, and what to set dir to. Use it when you need to decide the direction of a label, a database field or a block of user content.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe text to inspect.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses that the tool is non-mutating ('Report') and provides the decisioning outcome ('what to set dir to'). It doesn't describe edge cases or return format, but for a simple inspection tool this is adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, directly front-loaded with the action and output, and no wasted words. Every clause adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple, with one parameter and no output schema. The description covers purpose, when to use, and what is reported. It lacks exact return format but that is not critical for selection and invocation. Adequate for a simple detection tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema fully documents the one parameter ('text' with description), and the tool description adds context about use cases (label, database field, user content) but no additional parameter-level semantics. Baseline 3 is appropriate given 100% schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Report') and defines the resource (a string) and the exact output categories (right-to-left, left-to-right, mixed, neutral). It also adds 'what to set dir to', clearly distinguishing this detection tool from siblings like lint_rtl_code and normalize_arabic.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use the tool: 'Use it when you need to decide the direction of a label, a database field or a block of user content.' It gives clear context but does not provide exclusions or alternatives, though the sibling tools are obviously different, so this is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lint_rtl_codeA

Check a snippet of CSS, HTML, JSX or TSX for layout that breaks in right-to-left languages: physical CSS properties, directional Tailwind utilities, and dir problems. Returns each finding with the logical replacement. Use this before handing RTL-facing markup back to the user.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYesThe source to check.
baseDirNoThe base direction of the document. Pass "rtl" when the app root is <html dir="rtl">: in an Arabic-first app "right" is the start side, so the logical replacement is the opposite one. Default "ltr".
filenameYesA filename such as Button.tsx or theme.css. Only the extension matters — it selects which rules run.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the burden. It discloses that the tool returns each finding with the logical replacement, which is a key behavioral detail. It does not mention side effects, but being a linting tool, it is implicitly read-only. The description adds useful behavioral context beyond a simple verb.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the main purpose and includes concrete examples (file types, problem types, return value). Every sentence earns its place; no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 3 params, no output schema, and no annotations, the description covers the main usage, input scope, and return format. It could specify the output structure in more detail, but it gives enough for an agent to understand what to expect. Compared to the tier examples, this is above midpoint.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers 100% of parameters with descriptions. The tool description adds no additional parameter-specific semantics beyond mentioning 'snippet' and 'logical replacement', which are already implied. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool checks CSS/HTML/JSX/TSX for RTL layout issues, listing specific problem categories (physical CSS properties, directional Tailwind utilities, dir problems). It is a specific verb+resource combination that distinguishes it from siblings like lint_rtl_path or detect_direction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit context: 'Use this before handing RTL-facing markup back to the user.' This implies when to use it but doesn't explicitly mention alternatives or exclusions, though sibling tools have distinct names that imply different purposes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lint_rtl_pathA

Check a file or a whole directory on disk for right-to-left layout problems. Skips node_modules and build output.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesFile or directory path to check.
baseDirNoBase direction of the app. Pass "rtl" for an Arabic-first codebase. Default "ltr".

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses a useful behavioral detail: skipping node_modules and build output. However, it does not mention the return format, error handling, or whether the operation is read-only (though 'check' implies it).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long: the first conveys the core purpose, the second adds a key behavioral note about skipping node_modules/build. No fluff, clearly front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity read-only check tool with no output schema, the description covers the essential aspects: purpose, target, and a significant behavioral exception. It omits the return format but that is a minor gap for this simple tool. Overall it is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already explains both parameters clearly (path and baseDir with enum). The description adds no extra semantic information beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Check') and the resource ('a file or a whole directory on disk'), and it specifies the focus on right-to-left layout problems. While it distinguishes from sibling tools by scope (on disk vs. code), it does not explicitly name the alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'on disk' implies this is for files/directories rather than code snippets, but there is no explicit statement about when to use this tool versus siblings like lint_rtl_code. No exclusions or alternative guidance are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

normalize_arabicA

Normalise Arabic text so that forms users type interchangeably compare equal — strips diacritics and tatweel and folds the alef variants. Use it for search keys, deduplication and matching, never for text you are about to display.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe Arabic text to normalise.
convertDigitsNoConvert Arabic-Indic digits into 0-9. Default false.
unifyTaaMarbutaNoFold ة into ه. Helps fuzzy matching, changes meaning. Default false.
unifyAlefMaqsuraNoFold ى into ي. Helps fuzzy matching, changes meaning. Default false.
collapseWhitespaceNoCollapse whitespace runs. Default false.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full responsibility for disclosing behavior. It warns that the output is not suitable for display, which conveys the lossy/destructive nature of normalization. It does not mention the optional transformation flags or their implications, but the schema covers those; the description adds the key caveat.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, immediately states the core function, and provides a clear use-case disclaimer. No redundancy or wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has five parameters, all documented in the schema, and the description gives the essential context and usage caveat. It does not explicitly state the return value, but that is inferable from the normalization concept and the schema. The sibling tools are different enough that no confusion arises.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameters with descriptions, so baseline is 3. The description reinforces the overall purpose but does not add parameter-specific details beyond what the schema already states. The mention of stripping diacritics and tatweel corresponds to the default behavior, aligning with the text parameter description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool normalizes Arabic text, specifically stripping diacritics and tatweel and folding alef variants. It distinguishes itself from sibling lint/detection tools by focusing on normalization for matching and deduplication.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly provides usage guidance: use for search keys, deduplication, and matching, and explicitly warns never for display. This is a clear when-to-use and when-not-to-use directive, though it does not reference sibling tools, they are unrelated enough that no alternative is implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.2.0
    • Changedlint_rtl_code1 field changed
      • addedInput schema / properties / baseDir
        Added value: +{
        +  "description": "The base direction of the document. Pass \"rtl\" when the app root is <html dir=\"rtl\">: in an Arabic-first app \"right\" is the start side, so the logical replacement is the opposite one. Default \"ltr\".",
        +  "enum": [
        +    "ltr",
        +    "rtl"
        +  ],
        +  "type": "string"
        +}
    • Changedlint_rtl_path1 field changed
      • addedInput schema / properties / baseDir
        Added value: +{
        +  "description": "Base direction of the app. Pass \"rtl\" for an Arabic-first codebase. Default \"ltr\".",
        +  "enum": [
        +    "ltr",
        +    "rtl"
        +  ],
        +  "type": "string"
        +}
  2. 4 tool updatesv0.1.0
    • First observeddetect_direction
    • First observedlint_rtl_code
    • First observedlint_rtl_path
    • First observednormalize_arabic

TDQS

A4.2/5.0

Scored across 4 tools

Disambiguation5/5

Each tool serves a clearly distinct purpose: linting a snippet versus linting a path are separated by input scope, while direction detection and text normalization address different RTL concerns. The descriptions make the boundaries between tools easy to identify.

Naming Consistency5/5

All tool names follow a consistent verb_object snake_case pattern: lint_rtl_code, lint_rtl_path, detect_direction, and normalize_arabic. The naming style is uniform and predictable.

Tool Count5/5

Four tools is a well-scoped set for an RTL-focused utility server. Each tool covers a distinct RTL need without unnecessary redundancy or bloat.

Completeness4/5

The set covers the main RTL workflows: linting code, checking paths, detecting text direction, and normalizing Arabic text. A minor gap is the lack of equivalent normalization for other RTL scripts or an auto-fix option, but core use cases are well covered.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    MCP server for correct Arabic formatting — currency, Hijri dates, number-to-words, RTL fixes and validation across all 22 Arab countries. Zero-dependency.
    17
    101 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server that gives AI coding agents codebase navigation intelligence, enabling symbol lookup, reference finding, type inspection, and diagnostics through tools like locate, refs, hover, diagnostics, status, and rename.
    351 npm
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    An MCP server for elite Arabic and bilingual RTL/LTR UI/UX design, providing tools for design pipelines, anti-AI-slop auditing, RTL layout conversion, Arabic typography optimization, and accessibility checks.
    14
    MIT