Skip to main content
Glama
cc1a2b
by cc1a2b

arabicfmt

Arabic-first formatting for JavaScript & TypeScript

Currency symbols · Hijri/Islamic calendar · number-to-words · تفقيط · 6 plural forms · RTL/bidi — correct for all 22 Arab League countries, with zero dependencies and full TypeScript types.

npm version downloads jsDelivr hits gzipped size zero dependencies types included

npm · Live demo · GitHub

arabicfmt is the only JavaScript library that handles the entire Arabic formatting stack in one zero-dependency package — currency symbols, number precision, Hijri/Islamic calendar dates, RTL bidirectional text, Arabic number-to-words and تفقيط — with full TypeScript types. Works in Node, the browser, Deno, Bun and React Native.

npm install arabicfmt

What other libraries get wrong

Problem

Other libraries

arabicfmt

Saudi riyal U+20C1

Emits ﷼ (U+FDFC) — the Iranian rial

Correct U+20C1 with a safe text fallback

Iraqi dinar (IQD) decimals

0 (CLDR practical)

3 decimals — ISO 4217 legal standard

Hijri date output

Varies between Node, Chrome, Safari, Hermes

Frozen Umm al-Qura tables — identical on every engine

Arabic plurals

1–2 forms; Arabic legally needs 6

Full CLDR 6-form system (zero/one/two/few/many/other)

Number to Arabic words

No zero-dep solution

arabicToWords(1234) → "ألف ومئتان وأربعة وثلاثون"

Spell money for cheques (تفقيط)

Build it yourself, get the grammar wrong

spellCurrency(1234.5, {currency:"SAR"}) → "ألف ومئتان وأربعة وثلاثون ريالاً وخمسون هللةً"

Ordinals (ترتيبية)

Missing or gender-blind

arabicOrdinal(25) → "الخامس والعشرون", gender-aware

Spoken durations

Intl.DurationFormat barely supported

formatDuration(7_500_000) → "ساعتان وخمس دقائق" with full agreement

RTL broken sentences

Phone numbers flip mid-sentence

Unicode isolates wrap LTR runs automatically

Eastern Arabic digit parsing

parseInt("١٢٣") → NaN

parseNumber("١٬٢٣٤٫٥٦") → 1234.56

Arabic URL slugs

Strip to empty or mojibake

slugify("مدينة جدة") → "mdynh-jdh"

IBAN / Saudi ID checks

Regex that accepts bad numbers

Real ISO 7064 mod-97 + Luhn checksums


Related MCP server: arabic-dict-mcp

Install

npm install arabicfmt
# or
yarn add arabicfmt
# or
pnpm add arabicfmt

Requirements: Node.js ≥ 18 · TypeScript ≥ 4.7 (optional) · zero runtime dependencies.

Browser / CDN — no build step

Every release is mirrored on the jsDelivr and unpkg CDNs automatically. Import the browser-ready ESM bundle straight from a URL — no install, no bundler:

<script type="module">
  import { formatCurrency, formatHijri } from "https://cdn.jsdelivr.net/npm/arabicfmt/+esm";

  console.log(formatCurrency(1234.5, { currency: "SAR", numerals: "arab" })); // ١٬٢٣٤٫٥٠ ر.س
  console.log(formatHijri(new Date(), { numerals: "arab" }));                 // ٢٧ ذو الحجة ١٤٤٧ هـ
</script>

Subpaths work too — e.g. https://cdn.jsdelivr.net/npm/arabicfmt/dist/currency/index.js for just the currency module. Pin a version for production, e.g. arabicfmt@0.1.


Quick start

import {
  formatCurrency,      // correct symbol + precision for every Arab currency
  formatCompact,       // 1,200,000 → "1.2M" / "١٫٢ مليون"
  arabicToWords,       // 1234 → "ألف ومئتان وأربعة وثلاثون"
  spellCurrency,       // تفقيط: 1234.5 SAR → "...ريالاً وخمسون هللةً"
  arabicOrdinal,       // 25 → "الخامس والعشرون"
  formatDuration,      // 7_500_000ms → "ساعتان وخمس دقائق"
  formatFileSize,      // 1536 → "1.5 كيلوبايت"
  formatRelativeTime,  // "منذ ٣ أيام"
  formatList,          // ["أحمد","علي"] → "أحمد وعلي"
  parseCurrency,       // "١٬٢٣٤٫٥٠ ر.س" → 1234.5
  arabicPlural,        // full 6-form Arabic plural selection
  sortArabic,          // Arabic-locale collation
  slugify,             // "مدينة جدة" → "mdynh-jdh" (URL slugs)
  isValidIBAN,         // ISO 7064 mod-97 IBAN checksum
  isValidSaudiId,      // Saudi national ID / Iqama check digit
  isolateForeign,      // fix broken RTL sentences
  normalizeForSearch,  // search-key normalization
  detectLocale,        // auto-detect from browser / Node environment
} from "arabicfmt";

import { formatHijri, toHijri } from "arabicfmt/umalqura"; // deterministic Hijri calendar

// Currency
formatCurrency(1.2,   { currency: "KWD" });                      // "1.200 د.ك"
formatCurrency(1234,  { locale: "ar-SA", numerals: "arab" });    // "١٬٢٣٤٫٠٠ ر.س"
formatCurrency(-500,  { currency: "SAR", accounting: true });    // "(500.00 ر.س)"
formatCompact(1_500_000, { locale: "ar", numerals: "arab" });    // "١٫٥ مليون"

// Number to Arabic words
arabicToWords(1234);                     // "ألف ومئتان وأربعة وثلاثون"
arabicToWords(1_000_000);               // "مليون"
arabicToWords(5, { gender: "female" }); // "خمس"

// Spell money for invoices & cheques (التفقيط)
spellCurrency(1234.5, { currency: "SAR" });
// "ألف ومئتان وأربعة وثلاثون ريالاً وخمسون هللةً"
spellCurrency(100, { currency: "SAR", suffix: true }); // "مئة ريال فقط لا غير"

// Ordinals — gender-aware
arabicOrdinal(1);                        // "الأول"
arabicOrdinal(25);                       // "الخامس والعشرون"
arabicOrdinal(1, { gender: "female" });  // "الأولى"

// Duration & file size
formatDuration(7_500_000);               // "ساعتان وخمس دقائق"
formatFileSize(1536);                    // "1.5 كيلوبايت"

// Lists
formatList(["أحمد", "محمد", "علي"]);                    // "أحمد ومحمد وعلي"
formatList(["تفاح", "موز"], { type: "disjunction" });   // "تفاح أو موز"

// Hijri dates (deterministic — same output on Node, Chrome, Safari, Hermes)
formatHijri(new Date("2025-09-23"));                            // "1 ربيع الآخر 1447 هـ"
formatHijri(new Date("2025-09-23"), { numerals: "arab" });     // "١ ربيع الآخر ١٤٤٧ هـ"
toHijri(new Date("2025-09-23"));                               // { year: 1447, month: 4, day: 1 }

// Relative time
formatRelativeTime(new Date(Date.now() - 3 * 86400_000));      // "منذ 3 أيام"

// Parse formatted strings back to numbers
parseCurrency("١٬٢٣٤٫٥٠ ر.س");   // 1234.5
parseCurrency("(500.00 SAR)");    // -500

// RTL
isolateForeign("اتصل على +1 (555) 234-5678 الآن"); // phone stays intact in RTL

// Locale auto-detection
detectLocale(); // "ar-SA" in a Saudi browser, "ar-EG" in Node with LANG=ar_EG

Currency formatting

Symbol strategy: symbolMode

The Saudi riyal received its own Unicode symbol (U+20C1) in September 2025. Most libraries either emit the wrong ligature (U+FDFC, the Iranian rial) or fall back to SAR. arabicfmt gives you full control:

import { formatCurrency, resolveCurrencySymbol, getCurrencyInfo } from "arabicfmt/currency";

formatCurrency(1234.5, { currency: "SAR" });
// → "1,234.50 ر.س"   (auto: safe text symbol, renders everywhere today)

formatCurrency(1234.5, { currency: "SAR", symbolMode: "new" });
// → "1,234.50 ⃁"     (U+20C1 — use with a webfont; see webfont guide below)

formatCurrency(1234.5, { currency: "SAR", symbolMode: "code" });
// → "1,234.50 SAR"   (ISO code — for accounting tables)

symbolMode

SAR

AED

OMR

Use when

auto (default)

ر.س

U+20C3

U+20C4

Default. AED/OMR use the dedicated sign; SAR stays on safe text

new

U+20C1

U+20C3

U+20C4

Force the dedicated sign (needs font support)

text

ر.س

د.إ

ر.ع.

Always the safe text symbol — renders everywhere

code

SAR

AED

OMR

ISO code

Unicode 18.0 (September 2026): the AED (U+20C3) and OMR (U+20C4) signs are now live, and auto prefers them. Need maximum compatibility today? Use symbolMode: "text". The Saudi riyal keeps its safe text default by design.

Correct decimal precision — all 22 Arab League countries

Generated from CLDR 48.2.0 at build time and verified on every build:

formatCurrency(1.2, { currency: "KWD" });  // "1.200 د.ك"  ← 3 decimals
formatCurrency(1.2, { currency: "BHD" });  // "1.200 د.ب"  ← 3 decimals
formatCurrency(1.2, { currency: "IQD" });  // "1.200 ع.د"  ← 3 decimals (ISO 4217, not CLDR's 0)
formatCurrency(500, { currency: "KMF" });  // "500 ف.ج.ق"  ← 0 decimals
formatCurrency(500, { currency: "SAR" });  // "500.00 ر.س" ← 2 decimals

Decimals

Currencies

3

KWD, BHD, OMR, JOD, IQD, LYD, TND

0

DJF, KMF

2

SAR, AED, QAR, and the rest

All currency options

// Resolve from locale region — no need to know the currency code
formatCurrency(99.9,  { locale: "ar-BH" });                  // "99.900 د.ب"
formatCurrency(1234,  { locale: "ar-AE", numerals: "arab", symbolMode: "text" }); // "١٬٢٣٤٫٠٠ د.إ"  (auto → U+20C3 sign)

// Accounting notation (negatives in parentheses)
formatCurrency(-1234.5, { currency: "SAR", accounting: true }); // "(1,234.50 ر.س)"

// Hide/override
formatCurrency(100, { currency: "SAR", showSymbol: false, fractionDigits: 0 }); // "100"

// Currency metadata
getCurrencyInfo("SAR");
// {
//   code: "SAR", digits: 2,
//   symbols: { auto: "ر.س", text: "ر.س", code: "SAR", new: "⃁" },
//   unicode: { codepoint: "U+20C1", unicodeVersion: "17.0", live: true, autoDefault: false },
//   displayName: "ريال سعودي"
// }

Webfont guide for U+20C1

/* Scope the Saudi Riyal font to just that codepoint — zero impact on body text */
@font-face {
  font-family: "Riyal";
  src: url("/fonts/saudi-riyal.woff2") format("woff2");
  unicode-range: U+20C1;
}
:root { font-family: "Riyal", "Noto Naskh Arabic", sans-serif; }

Number formatting

import {
  formatNumber, formatCompact, formatPercent,
  toArabicDigits, toLatinDigits,
  parseNumber, parseCurrency,
  arabicToWords,
  formatRelativeTime,
} from "arabicfmt/number";

// Standard
formatNumber(1_234_567.89, { locale: "en" });              // "1,234,567.89"
formatNumber(1234.5,       { numerals: "arab" });           // "١٬٢٣٤٫٥"

// Compact / short notation — dashboards and data cards
formatCompact(1_500_000);                                   // "1.5M"
formatCompact(1_500_000, { locale: "ar" });                 // "1.5 مليون"
formatCompact(1_500_000, { locale: "ar", numerals: "arab" }); // "١٫٥ مليون"

// Percent
formatPercent(0.853, { locale: "en" });                    // "85.3%"

// Transliteration
toArabicDigits("Order #2026");                             // "Order #٢٠٢٦"
toLatinDigits("٢٠٢٦");                                     // "2026"  (handles Persian ۰–۹ too)

// Parsing — round-trip support
parseNumber("١٬٢٣٤٫٥٦");         // 1234.56  (Eastern Arabic digits + separators)
parseNumber("1,234.56");          // 1234.56  (Western)
parseCurrency("١٬٢٣٤٫٥٠ ر.س");  // 1234.5
parseCurrency("(500.00 SAR)");   // -500      (accounting notation)

// Relative time
formatRelativeTime(new Date(Date.now() - 3 * 86400_000));            // "منذ 3 أيام"
formatRelativeTime(new Date(Date.now() + 3600_000), new Date(), { locale: "en" }); // "in 1 hour"

Number to Arabic words (arabicToWords)

Convert integers to their Arabic word representation — handles gender agreement and all six scale levels.

import { arabicToWords } from "arabicfmt";

// Basic
arabicToWords(0)       // "صفر"
arabicToWords(1)       // "واحد"
arabicToWords(2)       // "اثنان"
arabicToWords(11)      // "أحد عشر"
arabicToWords(25)      // "خمسة وعشرون"
arabicToWords(100)     // "مئة"
arabicToWords(350)     // "ثلاثمئة وخمسون"

// Thousands
arabicToWords(1000)    // "ألف"
arabicToWords(2000)    // "ألفان"
arabicToWords(5000)    // "خمسة آلاف"
arabicToWords(11000)   // "أحد عشر ألفاً"
arabicToWords(100000)  // "مئة ألف"

// Millions / billions
arabicToWords(1_000_000)    // "مليون"
arabicToWords(2_000_000)    // "مليونان"
arabicToWords(5_000_000)    // "خمسة ملايين"
arabicToWords(1_000_000_000)// "مليار"

// Large composite
arabicToWords(1_234_567)
// "مليون ومئتان وأربعة وثلاثون ألفاً وخمسمئة وسبعة وستون"

// Gender agreement — feminine noun (ليرة، روبية…)
arabicToWords(3, { gender: "female" })  // "ثلاث"
arabicToWords(5, { gender: "female" })  // "خمس"

// Negative
arabicToWords(-42)  // "سالب اثنان وأربعون"

// Decimals — opt in (default truncates, stays backward compatible)
arabicToWords(3.14, { fraction: "digits" })  // "ثلاثة فاصلة واحد أربعة"
arabicToWords(3.14, { fraction: "number" })  // "ثلاثة فاصلة أربعة عشر"

// Common fractions (denominators 2–10)
import { arabicFraction } from "arabicfmt";
arabicFraction(1, 2)  // "نصف"
arabicFraction(3, 4)  // "ثلاثة أرباع"
arabicFraction(2, 3)  // "ثلثان"

Spell money in words — التفقيط

spellCurrency is the tafqit every Arabic invoice, cheque and contract needs: it turns a numeric amount into its full legal Arabic wording, splitting major and minor units and inflecting every noun for correct grammatical agreement (singular / dual / plural / accusative).

import { spellCurrency } from "arabicfmt";

spellCurrency(1234.5, { currency: "SAR" })
// "ألف ومئتان وأربعة وثلاثون ريالاً وخمسون هللةً"

// Unit agreement is automatic (العدد والمعدود)
spellCurrency(1,   { currency: "SAR" })   // "ريال واحد"      (singular)
spellCurrency(2,   { currency: "SAR" })   // "ريالان"         (dual)
spellCurrency(3,   { currency: "SAR" })   // "ثلاثة ريالات"   (plural, 3–10)
spellCurrency(11,  { currency: "SAR" })   // "أحد عشر ريالاً" (accusative, 11–99)
spellCurrency(100, { currency: "SAR" })   // "مئة ريال"       (genitive singular)

// Minor-unit precision comes from CLDR — KWD = 1000 fils, SAR = 100 halalas
spellCurrency(1.5, { currency: "KWD" })   // "دينار واحد وخمسمئة فلس"
spellCurrency(0.75, { currency: "SAR" })  // "خمس وسبعون هللةً"

// Cheque-ready ending and locale-derived currency
spellCurrency(100, { currency: "SAR", suffix: true }) // "مئة ريال فقط لا غير"
spellCurrency(-5,  { locale: "ar-AE" })               // "سالب خمسة دراهم"

Full Arabic noun paradigms are bundled for all 22 Arab League currencies (SAR, AED, KWD, BHD, QAR, OMR, JOD, EGP, IQD, LYD, TND, DZD, MAD, SDG, LBP, SYP, YER, SOS, DJF, KMF, MRU). Inspect or extend them via the exported CURRENCY_WORDS table.


Ordinal numbers — الأعداد الترتيبية

import { arabicOrdinal } from "arabicfmt";

arabicOrdinal(1)    // "الأول"
arabicOrdinal(2)    // "الثاني"
arabicOrdinal(10)   // "العاشر"
arabicOrdinal(11)   // "الحادي عشر"
arabicOrdinal(25)   // "الخامس والعشرون"

// Gender agreement
arabicOrdinal(1, { gender: "female" })   // "الأولى"
arabicOrdinal(25, { gender: "female" })  // "الخامسة والعشرون"

// Indefinite (drop the article ال)
arabicOrdinal(3, { definite: false })    // "ثالث"
arabicOrdinal(25, { definite: false })   // "خامس وعشرون"

Duration — spelled Arabic

formatDuration turns a time span into its spoken Arabic form, with correct dual/plural/accusative agreement on every unit — something Intl.DurationFormat (still barely supported) does not give you.

import { formatDuration } from "arabicfmt";

formatDuration(7_500_000)                  // "ساعتان وخمس دقائق"  (2h 5m)
formatDuration(90, { input: "s" })         // "دقيقة واحدة وثلاثون ثانيةً"
formatDuration(3_600_000, { largest: 1 })  // "ساعة واحدة"
formatDuration(2 * 86_400_000)             // "يومان"
formatDuration(500)                        // "أقل من ثانية"

// Restrict the units considered
formatDuration(125 * 60_000, { units: ["minute"], largest: 1 })
// "مئة وخمس وعشرون دقيقةً"

largest (default 2) caps how many units appear, biggest first. Want to drive the noun agreement yourself? countedNoun(n, forms) is exported for any custom counted noun.


File size — Arabic data units

import { formatFileSize } from "arabicfmt";

formatFileSize(0)                          // "0 بايت"
formatFileSize(1536)                       // "1.5 كيلوبايت"
formatFileSize(5 * 1024 * 1024)            // "5 ميجابايت"
formatFileSize(1_500_000, { base: 1000 })  // "1.5 ميجابايت"  (decimal/SI)
formatFileSize(2048, { numerals: "arab" }) // "٢ كيلوبايت"
formatFileSize(2048, { unitStyle: "latin" })// "2 KB"

Units scale through بايت · كيلوبايت · ميجابايت · جيجابايت · تيرابايت · بيتابايت, with base: 1024 (binary, default) or base: 1000 (decimal).


Arabic plural rules (6 forms)

Arabic has six plural forms — more than any other major language. Standard i18n libraries handle 1–2 forms and break for Arabic.

import { arabicPluralForm, arabicPlural } from "arabicfmt";

// Get the CLDR form name
arabicPluralForm(0)    // "zero"
arabicPluralForm(1)    // "one"
arabicPluralForm(2)    // "two"
arabicPluralForm(5)    // "few"   (3–10)
arabicPluralForm(15)   // "many"  (11–99)
arabicPluralForm(100)  // "other"

// Select the right string
const forms = {
  zero:  "لا كتب",
  one:   "كتاب واحد",
  two:   "كتابان",
  few:   "كتب",       // 3–10
  many:  "كتاباً",    // 11–99
  other: "كتاب",
};

arabicPlural(0,   forms)  // "لا كتب"
arabicPlural(1,   forms)  // "كتاب واحد"
arabicPlural(2,   forms)  // "كتابان"
arabicPlural(5,   forms)  // "كتب"
arabicPlural(25,  forms)  // "كتاباً"
arabicPlural(100, forms)  // "كتاب"

Hijri / Islamic calendar dates

Two engines with an identical API:

arabicfmt/date

arabicfmt/umalqura

Algorithm

Tabular arithmetic

Official Umm al-Qura tables

Accuracy

±1–2 days

Exact

Bundle

Tiny (no tables)

Larger (frozen ICU tables)

Range

Any year

AH 1300–1599

Deterministic

Yes

Yes — same on Node/Chrome/Safari/Hermes

import { toHijri, fromHijri, formatHijri, umalquraToGregorian } from "arabicfmt/umalqura";

// Convert
toHijri(new Date("2025-09-23"))        // { year: 1447, month: 4, day: 1 }
umalquraToGregorian(1447, 9, 1)        // JavaScript Date — first day of Ramadan 1447

// Format — Arabic
formatHijri(new Date("2025-09-23"))
// "1 ربيع الآخر 1447 هـ"

formatHijri(new Date("2025-09-23"), { numerals: "arab" })
// "١ ربيع الآخر ١٤٤٧ هـ"

// Format — English
formatHijri(new Date("2025-09-23"), { locale: "en" })
// "1 Rabi al-Thani 1447 AH"

// Format — ISO-style numeric
formatHijri(new Date("2025-09-23"), {
  locale: "en", month: "2-digit", day: "2-digit", order: "ymd", era: false,
})
// "1447/04/01"

Month and weekday name tables

import {
  HIJRI_MONTHS_AR,     // Arabic Hijri month names
  HIJRI_MONTHS_EN,     // English Hijri month names
  GREGORIAN_MONTHS_AR, // Arabic Gregorian month names (يناير، فبراير…)
  GREGORIAN_MONTHS_EN,
  ARABIC_WEEKDAYS_AR,  // Arabic weekday names (الأحد، الاثنين…)
  ARABIC_WEEKDAYS_EN,
} from "arabicfmt/date";

HIJRI_MONTHS_AR[8]        // "رمضان"  (index 0 = Muharram)
GREGORIAN_MONTHS_AR[0]    // "يناير"  (index 0 = January)
ARABIC_WEEKDAYS_AR[5]     // "الجمعة" (index 0 = Sunday)

Bidirectional (RTL) text helpers

Stop phone numbers and English words from scrambling Arabic sentences:

import { detectDirection, isolate, isolateForeign, stripBidi } from "arabicfmt/bidi";

// Before fix: "+1 (555) 234-5678" flips the area code in RTL context
// After fix:  the phone number is wrapped in Unicode isolates — sentence intact
isolateForeign("اتصل على +1 (555) 234-5678 الآن");

detectDirection("مرحبا");   // "rtl"
detectDirection("Hello");   // "ltr"

isolate("9:41 AM");         // FSI … PDI isolate around a mixed run
stripBidi(dirtyStr);        // remove every Unicode bidi control character

Match Arabic text despite diacritics, alef variants, hamza and taa marbuta differences:

import {
  stripTashkeel,
  normalizeArabic,
  normalizeForSearch,
  sortArabic,
  compareArabic,
} from "arabicfmt/text";

stripTashkeel("مُحَمَّد")        // "محمد"
normalizeArabic("الأحمد")        // "الاحمد"  (alef variants unified)

// Robust search — these two strings produce the same key:
normalizeForSearch("مُؤسَّسة") === normalizeForSearch("موسسه")  // true

// Arabic-locale collation
sortArabic(["ياسر", "أحمد", "بسام"])   // ["أحمد", "بسام", "ياسر"]
["ج", "أ", "ب"].sort(compareArabic)    // ["أ", "ب", "ج"]

List formatting

Join values into a grammatical Arabic list. Wraps Intl.ListFormat and degrades gracefully on runtimes without it.

import { formatList } from "arabicfmt";

formatList(["أحمد", "محمد", "علي"])                      // "أحمد ومحمد وعلي"
formatList(["تفاح", "موز", "برتقال"], { type: "disjunction" }) // "تفاح أو موز أو برتقال"
formatList([1, 2, 3], { numerals: "arab" })              // "١ و٢ و٣"

Transliteration & URL slugs

Romanize Arabic script to readable Latin, or turn it into URL-safe slugs for routes, filenames and CMS permalinks. Deterministic — short vowels appear only when the text is vowelled (carries tashkeel).

import { transliterate, slugify } from "arabicfmt";

transliterate("مُحَمَّد")    // "muhammad"   (vowelled)
transliterate("محمد")        // "mhmd"       (bare → consonant-only)
transliterate("الرياض")      // "alryad"
transliterate("غرفة ٢٠١")    // "ghrfh 201"  (digits converted)

slugify("مدينة جدة")                      // "mdynh-jdh"
slugify("الرياض 2026")                    // "alryad-2026"
slugify("Hello العالم", { separator: "_" }) // "hello_alalm"
slugify("Hello World", { lowercase: false }) // "Hello-World"

Note: this is a pragmatic, reversible-ish romanization, not a strict academic transliteration (DIN 31635 / ISO 233). It is built for slugs, search keys and readable IDs.


Validation — IBAN & Saudi ID

Real checksums, not regex guesses. isValidIBAN runs the ISO 7064 mod-97 algorithm with SWIFT-registry length checks; isValidSaudiId runs the Luhn check digit and classifies citizen vs. resident.

import { isValidIBAN, formatIBAN, isValidSaudiId, saudiIdType } from "arabicfmt";

isValidIBAN("SA03 8000 0000 6080 1016 7519")  // true
isValidIBAN("SA03 8000 0000 6080 1016 7510")  // false (bad checksum)
formatIBAN("SA0380000000608010167519")        // "SA03 8000 0000 6080 1016 7519"

isValidSaudiId("1012345672")                  // true
saudiIdType("1012345672")                     // "citizen"
saudiIdType("2100000005")                     // "resident"  (Iqama)

Registry lengths are enforced for SA, AE, KW, BH, QA, JO, LB, EG, IQ, PS, TN, MR, LY (plus common partners). Unknown-country IBANs are validated by checksum and the general 15–34 length bound, never accepted on structure alone.


Framework usage

React / Next.js

import { formatCurrency, detectLocale } from "arabicfmt";
import { formatHijri } from "arabicfmt/umalqura";

export function PriceTag({ amount, currency }: { amount: number; currency: string }) {
  const locale = detectLocale();
  return (
    <span dir="rtl">
      {formatCurrency(amount, { currency, locale })}
    </span>
  );
}

export function HijriDate({ date }: { date: Date }) {
  return <time>{formatHijri(date, { numerals: "arab" })}</time>;
}

Vue 3

import { formatCurrency } from "arabicfmt";

// composable
export function useArabicCurrency(currency: string) {
  return (amount: number) =>
    formatCurrency(amount, { currency, numerals: "arab" });
}

Node.js / Express

import { formatCurrency, detectLocale } from "arabicfmt";
import { formatHijri } from "arabicfmt/umalqura";

app.get("/invoice/:id", (req, res) => {
  const locale = req.headers["accept-language"]?.split(",")[0] ?? "ar-SA";
  const total  = formatCurrency(order.total, { locale });
  const date   = formatHijri(order.date, { locale: "ar" });
  res.json({ total, date });
});

Locale auto-detection

import { detectLocale } from "arabicfmt";

// Browser: reads navigator.language
// Node.js: reads LANG / LANGUAGE / LC_ALL / LC_MESSAGES env vars
// Fallback: "ar"

const locale = detectLocale(); // "ar-SA", "ar-EG", "en-US", …
formatCurrency(1234, { locale });

Subpath imports — tree-shakeable

Pick only what you need for the smallest possible bundle:

import { formatCurrency, spellCurrency } from "arabicfmt/currency";
import { formatNumber, arabicToWords, formatDuration, formatFileSize } from "arabicfmt/number";
import { formatHijri, toHijri }  from "arabicfmt/date";       // tabular core (tiny)
import { formatHijri, toHijri }  from "arabicfmt/umalqura";   // accurate, opt-in
import { isolateForeign }        from "arabicfmt/bidi";
import { normalizeForSearch, arabicPlural, slugify } from "arabicfmt/text";
import { isValidIBAN, isValidSaudiId }      from "arabicfmt/validate";

Measured cost of each entry point (esbuild --bundle --minify, gzipped — v0.1.0):

Import

What you get

min + gzip

arabicfmt

everything below

11.4 kB

arabicfmt/currency

22 currencies, تفقيط, Unicode transition data

5.7 kB

arabicfmt/number

words, ordinals, fractions, parse, duration, …

3.5 kB

arabicfmt/umalqura

300 years of official Umm al-Qura tables

2.2 kB

arabicfmt/text

normalize, plurals, collation, lists, slugs

1.6 kB

arabicfmt/date

tabular Hijri core

1.5 kB

arabicfmt/bidi

direction detection + isolates

0.7 kB

arabicfmt/validate

IBAN + Saudi ID checksums

0.6 kB

The complete Arabic formatting stack costs less than a single small image.


Full API reference

Every public function, by module. Full signatures and options are in the sections above and in the bundled TypeScript types.

Module

Functions

arabicfmt/currency

formatCurrency · spellCurrency · getCurrencyInfo · resolveCurrencySymbol

arabicfmt/number

formatNumber · formatPercent · formatCompact · parseNumber · parseCurrency · toArabicDigits · toLatinDigits · arabicToWords · arabicOrdinal · arabicFraction · countedNoun · formatDuration · formatFileSize · formatRelativeTime

arabicfmt/umalqura

formatHijri · toHijri · fromHijri · gregorianToUmalqura · umalquraToGregorian

arabicfmt/date

formatHijri · toHijri · fromHijri (tabular core)

arabicfmt/text

stripTashkeel · removeTatweel · normalizeArabic · normalizeForSearch · arabicPlural · arabicPluralForm · sortArabic · compareArabic · createArabicCollator · formatList · transliterate · slugify

arabicfmt/bidi

isolateForeign · isolate · wrapLTR · wrapRTL · stripBidi · detectDirection · isRTL · charDirection

arabicfmt/validate

isValidIBAN · formatIBAN · normalizeIBAN · isValidSaudiId · saudiIdType

arabicfmt (root)

re-exports everything above + detectLocale


MCP server — use arabicfmt from AI agents

AI agents (Claude Desktop, Claude Code, Cursor) can call arabicfmt directly through the arabicfmt-mcp Model Context Protocol server — 17 tools (format_currency, spell_currency, format_hijri, arabic_to_words, isolate_foreign, validate_iban, …). Add it to your client's mcpServers config:

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

Source and full tool list: mcp/.

Examples

Runnable scripts for every feature live in examples/:

cd examples && npm install
node currency.mjs   # or numbers / words / dates / text / bidi / validate

Engineering

Dependencies

Zero runtime dependencies

Size

~11.4 kB min+gzip for the whole library; subpath imports from 0.6 kB

Formats

Dual ESM + CJS, full .d.ts / .d.cts types

Tree-shaking

"sideEffects": false — pay only for what you import

Data source

CLDR 48.2.0 + ICU — verified at build time, not hand-typed

Test coverage

194 tests — currency transition, precision, Hijri, plurals, words, tafqit, durations, IBAN/ID

Platforms

Node ≥ 18, all evergreen browsers, React Native / Hermes, Deno, Bun

Published with

npm provenance (GitHub Actions attestation)


Unicode currency-sign transition

Live since Unicode 18.0 (September 2026)

The UAE dirham (U+20C3) and Omani rial (U+20C4) signs are now live, and symbolMode: "auto" prefers them — completing the transition that began with the Saudi riyal sign (U+20C1) in Unicode 17.0. Because system-font coverage for brand-new signs still varies, symbolMode: "text" always returns the safe Arabic abbreviation (د.إ, ر.ع.), and the Saudi riyal keeps the text symbol as its auto default by design.

Currency

Sign

Unicode

auto default

Saudi riyal (SAR)

U+20C1

17.0 (2025)

text ر.س (conservative)

UAE dirham (AED)

U+20C3

18.0 (2026)

sign

Omani rial (OMR)

U+20C4

18.0 (2026)

sign


Live demo

arabicfmt.vercel.app — the whole library, interactive and computed live in your browser. Change any input and watch the Arabic update in real time: currency studio, تفقيط, Hijri converter, plurals, RTL fixes and more.

arabicfmt interactive playground

Run it locally:

cd demo && npm install && npm run dev

Contributing

Issues and pull requests are welcome on GitHub.


License

MIT — free for commercial and personal use.


Author &amp; more projects

Built and maintained by cc1a2b.

If arabicfmt saves you time, please star it on GitHub — it helps other Arabic developers find it. Explore my other open-source projects, or open an issue with ideas, bugs and feature requests.

Available Tools

17 tools
arabic_ordinalA

Convert an integer to its Arabic ordinal words (e.g. 25 -> "الخامس والعشرون").

ParametersJSON Schema
NameRequiredDescriptionDefault
nYesThe integer to convert to an Arabic ordinal.
feminineNoUse feminine grammatical gender.

TDQS

A3.5/5.0
Behavior2/5

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

No annotations provided, so description bears full burden. It does not disclose behaviors such as handling of negative numbers, zero, the effect of the 'feminine' parameter, or any error conditions. The example only shows a positive ordinal.

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?

Single sentence with an example. Extremely concise and immediately conveys the purpose without extra words.

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

Completeness3/5

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

Simple tool, but missing key context: no mention of the feminine option, return format (string implied), or limitations. Adequate for basic use but leaves gaps for advanced agents.

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 coverage is 100% with descriptions for both parameters. The description adds a usage example but does not explain the 'feminine' parameter or provide additional semantics beyond the schema.

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 converts an integer to Arabic ordinal words, with a specific example (25 -> "الخامس والعشرون"). This verb+resource pair is distinct from sibling tools like arabic_to_words (cardinal) or arabic_plural (plural forms).

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?

No explicit guidance on when to use this tool vs alternatives like arabic_to_words or arabic_plural. The description implies ordinal conversion context via the example, but lacks when-not-to-use or prerequisite information.

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

arabic_pluralA

Select the correct Arabic plural form for a count from the six CLDR categories (e.g. 5 books -> "كتب"). Returns the chosen word.

ParametersJSON Schema
NameRequiredDescriptionDefault
nYesThe count that selects the plural form.
formsYesArabic plural forms keyed by CLDR category. 'other' is required; 'zero','one','two','few','many' are optional.

TDQS

A3.7/5.0
Behavior2/5

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

No annotations are provided, and the description lacks behavioral details such as input validation, error handling, or edge cases (e.g., missing forms). It only states the basic return, adding minimal value beyond the purpose.

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 a single sentence with a concrete example, front-loaded with the core function. No extraneous words.

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

Completeness3/5

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

The description covers the basic purpose and example but does not explain the return format (e.g., a string, the exact word from forms) or behavior when not all CLDR forms are provided. Given no output schema, more detail is warranted.

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

Parameters4/5

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

Schema coverage is 100%, with both parameters described. The description adds value with an example and mentions CLDR categories, slightly enhancing the schema's information.

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's purpose: selecting the correct Arabic plural form based on a count and CLDR categories, with an example. It distinguishes from sibling tools (e.g., arabic_ordinal) by focusing on plural forms.

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 description implies usage for Arabic plural selection but provides no explicit guidance on when to use or avoid this tool, nor does it compare with alternatives like arabic_to_words.

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

arabic_to_wordsA

Convert an integer to its full Arabic cardinal words (e.g. 1234567 -> "مليون ومئتان وأربعة وثلاثون ألفاً وخمسمئة وسبعة وستون").

ParametersJSON Schema
NameRequiredDescriptionDefault
nYesThe integer to convert to Arabic words.
feminineNoUse feminine grammatical gender for the counted noun.

TDQS

A3.8/5.0
Behavior3/5

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

No annotations provided; description does not disclose edge cases, error handling, or performance traits. For a simple conversion tool, minimal disclosure is acceptable but not thorough.

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?

Single sentence with embedded example, zero wasted words. Front-loaded with core purpose.

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 a simple integer-to-words conversion with no output schema, the description plus schema sufficiently explain behavior. Missing minor detail about feminine parameter effect on output, but schema mitigates.

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 both parameters with descriptions. Description adds value via example showing correct output and implying the result format, but does not elaborate on feminine parameter usage beyond schema.

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?

Description clearly states verb (convert), resource (integer to Arabic cardinal words), and provides an illustrative example. Distinguishes from siblings like arabic_ordinal or arabic_plural by specifying cardinal words.

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?

Implies usage for converting integers to cardinal Arabic words, contrasting with ordinal/plural siblings, but lacks explicit when-to-use/when-not-to-use guidance or alternatives.

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

format_compactA

Format a number in compact notation with Arabic scale words (e.g. 1200000 with locale "ar" -> "1.2 مليون").

ParametersJSON Schema
NameRequiredDescriptionDefault
valueYesThe number to format compactly.
localeNoBCP-47 locale, e.g. 'ar', 'ar-SA', 'en'. Defaults to 'ar'.
numeralsNoNumeral system: 'latn' (1234), 'arab' (Eastern Arabic ١٢٣٤), or 'arabext' (Persian/Urdu ۱۲۳۴).
compactDisplayNoCompact form: 'short' or 'long'.

TDQS

A3.5/5.0
Behavior2/5

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

No annotations are provided, so the description carries full burden. It states the core formatting behavior but does not disclose edge cases (e.g., handling of very large numbers, negative numbers), error conditions, or additional behavioral traits beyond the example. The description is minimal.

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 a single concise sentence with a relevant example, front-loading the core functionality. No unnecessary words.

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

Completeness3/5

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

For a 4-parameter tool with no output schema, the description provides a basic understanding of the tool's purpose but lacks details on parameter combinations, return format, or locale-specific behavior beyond the example. It is minimally adequate but not comprehensive.

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 coverage is 100%, so the schema already documents all parameters. The description adds context by mentioning 'Arabic scale words' and providing an example that illustrates the effect of locale and value, but does not elaborate on each parameter individually. Baseline of 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 formats numbers in compact notation with Arabic scale words, and provides a concrete example. It effectively distinguishes itself from sibling tools like format_number, which likely handles more general formatting.

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 description implies usage for compact formatting with Arabic locale via the example, but it does not explicitly state when to use this tool over alternatives (e.g., format_number for other locales) or when not to use it. The guidance is implicit.

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

format_currencyA

Format a number as an Arabic currency amount with the correct symbol, grouping, and decimal precision (e.g. 1234.5 SAR -> "1,234.50 ر.س"). Handles the 2025-2026 Unicode currency-symbol transition (Saudi Riyal U+20C1, etc.).

ParametersJSON Schema
NameRequiredDescriptionDefault
amountYesThe monetary amount to format.
localeNoBCP-47 locale, e.g. 'ar', 'ar-SA', 'en'. Defaults to 'ar'.
currencyNoISO 4217 currency code, e.g. 'SAR', 'AED', 'KWD'. Defaults to SAR-area default.
numeralsNoNumeral system: 'latn' (1234), 'arab' (Eastern Arabic ١٢٣٤), or 'arabext' (Persian/Urdu ۱۲۳۴).

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations, the description carries full burden. It discloses handling of the Unicode symbol transition and indicates input/output format but does not cover error behavior (e.g., invalid locale/currency), edge cases (negative amounts), or whether the operation is read-only. Some transparency is provided but gaps remain.

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, tightly written with no redundancy. The key purpose and example are front-loaded, making it efficient for an agent to parse quickly.

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

Completeness3/5

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

Given 4 parameters and no output schema, the description covers basic input/output and a notable behavioral detail (Unicode transition). However, it lacks explicit return type (string) and error scenarios, leaving some uncertainty. A more complete description would mention the string output and handle edge cases.

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 coverage is 100%, so baseline is 3. The description adds an example and mentions Unicode transition but does not elaborate on parameter semantics beyond what the schema provides. It confirms the output format but adds no new meaning per parameter.

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 that the tool formats a number as an Arabic currency amount with correct symbol, grouping, and decimal precision. It provides a concrete example (1234.5 SAR -> '1,234.50 ر.س') and differentiates from siblings like format_number and spell_currency by specifying Arabic currency context.

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 description implies usage for Arabic currency formatting but does not explicitly state when to use this tool versus siblings like format_number (general formatting) or spell_currency (spelling out). No when-not or alternatives are mentioned, leaving the agent to infer context from the purpose.

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

format_durationA

Format a duration in milliseconds as natural Arabic words (e.g. 7500000 -> "ساعتان وخمس دقائق").

ParametersJSON Schema
NameRequiredDescriptionDefault
valueYesDuration in milliseconds.
localeNoBCP-47 locale, e.g. 'ar', 'ar-SA', 'en'. Defaults to 'ar'.
numeralsNoNumeral system: 'latn' (1234), 'arab' (Eastern Arabic ١٢٣٤), or 'arabext' (Persian/Urdu ۱۲۳۴).

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations, the description carries full burden. It discloses the input unit and output format, but does not specify behavior for edge cases (negative, zero, large values) or locale/numerals effects beyond schema defaults.

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

Conciseness4/5

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

The description is a single sentence with an example, which is efficient and front-loaded. Minimal but no wasted words; the example aids understanding.

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 simple formatting tool with no output schema, the description adequately explains input (milliseconds) and output (Arabic words). It covers the main purpose, though could mention return type or handle more edge cases.

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%, so baseline is 3. The description provides an example but adds no extra meaning to parameters beyond what the schema already describes for 'value', 'locale', and 'numerals'.

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 formats a duration in milliseconds to natural Arabic words, with a concrete example. It distinguishes from siblings like 'arabic_ordinal' and 'format_relative_time' which handle different formats.

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?

No explicit guidance on when to use this tool versus alternatives like 'format_relative_time'. The description implies its use for Arabic duration formatting but lacks 'when not to use' context.

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

format_hijriB

Format a Gregorian date as a Hijri (Islamic) date string with Arabic month names and era (e.g. 2025-09-23 -> "٢٣ رمضان ١٤٤٧ هـ").

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesGregorian date as ISO 8601 string, e.g. '2025-09-23' or '2025-09-23T00:00:00Z'.
localeNoBCP-47 locale, e.g. 'ar', 'ar-SA', 'en'. Defaults to 'ar'.
numeralsNoNumeral system: 'latn' (1234), 'arab' (Eastern Arabic ١٢٣٤), or 'arabext' (Persian/Urdu ۱۲۳۴).

TDQS

B3.1/5.0
Behavior2/5

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

No annotations are provided, so the description must fully cover behavioral traits. It only states the output format with an example but does not disclose error handling, timezone sensitivity, input validation, or any side effects. This is insufficient for a tool with no annotations.

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 a single sentence with an example, containing zero waste. It is front-loaded with the core purpose and efficient.

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

Completeness3/5

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

For a simple tool with three parameters and no output schema, the description provides the essential purpose and an example. However, it lacks details about parameter interactions, error scenarios, or the behavior for invalid dates, which feels incomplete for production use.

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 input schema already describes all three parameters (date, locale, numerals) with 100% coverage. The description adds value by showing an example output format, but does not elaborate on how locale or numerals affect the result. Baseline 3 is appropriate.

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 tool converts a Gregorian date to a Hijri date string with Arabic month names and era, and provides an illustrative example. However, it does not explicitly distinguish this from the sibling tool 'to_hijri', so the purpose is clear but differentiation is missing.

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

Usage Guidelines2/5

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

The description does not provide any guidance on when to use this tool versus alternatives like 'to_hijri' or other formatting tools. It implies usage for Hijri conversion with Arabic month names but lacks explicit context or exclusions.

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

format_numberA

Format a number with locale-aware grouping, decimal separators, and optional Eastern Arabic numerals (e.g. 1234567.89 with numerals "arab" -> "١٬٢٣٤٬٥٦٧٫٨٩").

ParametersJSON Schema
NameRequiredDescriptionDefault
valueYesThe number to format.
localeNoBCP-47 locale, e.g. 'ar', 'ar-SA', 'en'. Defaults to 'ar'.
numeralsNoNumeral system: 'latn' (1234), 'arab' (Eastern Arabic ١٢٣٤), or 'arabext' (Persian/Urdu ۱۲۳۴).

TDQS

A3.8/5.0
Behavior3/5

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

Since no annotations are provided, the description carries the full burden. It discloses core formatting behavior (grouping, decimals, numerals) but omits details on edge cases like negative numbers, precision, or error handling, leaving some ambiguity.

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 a single sentence with an example, containing no redundant information. Every word serves a purpose.

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 tool with 3 parameters and no output schema, the description provides sufficient context through an illustrative example. However, it does not fully explain the locale parameter's impact or defaults, leaving minor gaps.

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 coverage is 100%, so baseline is 3. The description adds an example tying value and numerals together but does not elaborate on locale effects or default values beyond what the schema provides.

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's function: formatting a number with locale-aware grouping, decimal separators, and optional numeral systems. It provides a concrete example and is distinct from sibling tools like format_currency or format_compact.

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 description implicitly suggests usage for locale-aware number formatting but does not explicitly state when to use this tool over siblings like format_compact or format_currency. No alternatives or exclusions are mentioned.

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

format_relative_timeA

Format a date relative to a base date in Arabic (e.g. three days ago -> "منذ ٣ أيام"). Defaults the base to now.

ParametersJSON Schema
NameRequiredDescriptionDefault
baseNoBase/reference date as ISO 8601 string. Defaults to the current time.
dateYesTarget date as ISO 8601 string, e.g. '2025-09-20'.
localeNoBCP-47 locale, e.g. 'ar', 'ar-SA', 'en'. Defaults to 'ar'.
numeralsNoNumeral system: 'latn' (1234), 'arab' (Eastern Arabic ١٢٣٤), or 'arabext' (Persian/Urdu ۱۲۳۴).

TDQS

A3.7/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 mentions defaulting base to now and provides an example, but doesn't disclose edge cases (e.g., future dates, timezone handling, or output when date equals base). There is no contradiction with annotations.

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?

A single sentence with a parenthetical example. Every word earns its place; no redundancy or unnecessary details.

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

Completeness3/5

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

The description adequately explains the core purpose and provides an example. However, it omits details about the output format for future dates, error handling, and does not cover all parameters' behaviors adequately.

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 coverage is 100%, so the baseline is 3. The description adds an example and explains the relative concept, but does not provide additional meaning beyond what the schema already offers for each parameter.

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 verb 'Format', the resource 'date relative to a base date', and specifies the language 'Arabic'. The example 'three days ago -> "منذ ٣ أيام"' makes the purpose immediately obvious and distinguishes it from sibling tools like format_duration or arabic_plural.

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 description implies usage for relative time formatting in Arabic, but lacks explicit guidance on when to use this tool versus alternatives (e.g., format_duration for lengths, arabic_plural for plurals). No 'when not to use' or exclusions are provided.

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

isolate_foreignA

Wrap foreign/LTR runs (phone numbers, Latin text, URLs) inside Arabic text with Unicode bidi isolates so they render correctly in RTL contexts (e.g. "اتصل على +1 (555) 234-5678 الآن").

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe mixed-direction text to process.

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries full burden. It discloses that the tool modifies text by adding Unicode bidi isolates, and the example shows the effect. However, it could mention that the original text content is preserved aside from the wrapping, but overall it's sufficient for a text transformation.

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 a single sentence with an example, containing no unnecessary words. Every part is informative and earns its place.

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

Completeness5/5

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

Given the tool's simplicity (one required parameter, no output schema), the description explains the purpose, usage, and behavior completely. No additional context is needed.

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

Parameters4/5

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

The input schema has 100% coverage with a description for the `text` parameter. The tool description adds value by providing an example and listing the types of foreign runs (phone numbers, Latin text, URLs) that should be isolated, going beyond the schema.

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 wraps foreign/LTR runs inside Arabic text with Unicode bidi isolates, using specific examples like phone numbers and URLs. It distinguishes itself from sibling tools which deal with formatting numbers, plurals, etc., rather than bidi handling.

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?

The description provides a clear use case (rendering foreign text correctly in RTL contexts) with an example. While it doesn't explicitly state when not to use or mention alternatives, the sibling list makes this tool unique for bidi isolation, so the guidance is adequate.

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

parse_numberA

Parse a string containing Latin or Eastern Arabic digits (with Arabic grouping/decimal separators) into a JavaScript number (e.g. "١٬٢٣٤٫٥٦" -> 1234.56). Returns the number as a string.

ParametersJSON Schema
NameRequiredDescriptionDefault
inputYesThe numeric string to parse, e.g. '١٬٢٣٤٫٥٦' or '1,234.56'.

TDQS

A4/5.0
Behavior3/5

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

No annotations provided; description discloses return type (number as string) but does not mention error handling, character validation, or behavior for invalid input.

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 with an example; no wasted words, front-loaded with purpose.

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?

No output schema; description states return format. Missing edge-case handling but adequate for a simple parsing tool given other context.

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

Parameters4/5

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

Schema covers the single parameter with description; description adds value with explicit input format examples, enhancing understanding beyond schema.

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's action: parse a string containing Latin or Eastern Arabic digits with Arabic separators into a JavaScript number, and gives an example. It distinguishes from sibling tools like format_number.

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 description implies usage for parsing numeric strings with Arabic digits but does not explicitly state when to use this tool vs alternatives like format_number or other parsing options.

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

slugifyA

Convert Arabic (or mixed) text into a URL-safe slug (e.g. "مدينة جدة" -> "mdynh-jdh").

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe text to slugify.
separatorNoWord separator character. Defaults to '-'.

TDQS

A4/5.0
Behavior3/5

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

With no annotations, the description carries full burden. It states the conversion to a URL-safe slug and gives an example, but does not disclose details like the transliteration algorithm, handling of non-Arabic characters, or edge cases (e.g., empty string, special symbols).

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 a single sentence with an example, front-loading the action and result. Every part is useful and there is no redundancy.

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 simple slugification tool, the description provides purpose and example. However, it lacks details about the underlying algorithm (appears to be phonetic transliteration) and separator behavior, which would help an agent understand edge cases. It is mostly adequate but not exhaustive.

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% for both parameters ('text' and 'separator'). The description adds context about Arabic-specific conversion but does not explain the separator parameter or its default behavior. Thus, it adds minimal value beyond the schema.

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 verb 'Convert' and the resource 'Arabic (or mixed) text', with a concrete example showing the output format ('mdynh-jdh'). It distinguishes slugify from sibling tools which handle other Arabic text operations like pluralization and number formatting.

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?

The description implies the tool is used for generating URL-safe slugs from Arabic text, which is a unique capability among siblings. However, it does not explicitly specify when to use or not use it, such as cases where exact transliteration is needed versus other formatting.

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

spell_currencyA

Spell out a currency amount in full Arabic words, including the major and minor units with correct grammatical agreement (e.g. 1234.5 SAR -> "ألف ومئتان وأربعة وثلاثون ريالاً وخمسون هللة").

ParametersJSON Schema
NameRequiredDescriptionDefault
amountYesThe monetary amount to spell out.
localeNoBCP-47 locale, e.g. 'ar', 'ar-SA', 'en'. Defaults to 'ar'.
currencyNoISO 4217 currency code, e.g. 'SAR', 'AED', 'KWD'.

TDQS

A3.7/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It discloses key behavior: it handles major and minor units with grammatical agreement and uses locales and currency codes. However, it does not explain behavior for edge cases like zero amounts, large numbers, or unsupported currencies. The description is adequate but not exhaustive.

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 a single, well-structured sentence with an example. It front-loads the core purpose and is free of any extraneous text. Every part earns its place.

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

Completeness3/5

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

Given no output schema, the description explains the return format well. It covers the main use case but lacks details on parameter defaults, supported currencies, and error handling. For a tool with 3 parameters and 1 required, it is reasonably complete but could be more thorough.

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 coverage is 100%, so each parameter already has a description. The tool description adds value by explaining the overall output format and the inclusion of grammatical agreement, but it does not provide additional constraints or examples for each parameter beyond what the schema offers. Baseline of 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 spells out a currency amount in full Arabic words, including major and minor units with grammatical agreement. It provides a concrete example, making the purpose unmistakable. This distinguishes it from sibling tools like arabic_to_words and format_currency.

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 description implies when to use the tool (when you need Arabic spelling of a currency amount), but it does not explicitly compare with alternatives or mention when not to use it. It lacks guidance on prerequisites or edge cases.

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

to_hijriA

Convert a Gregorian date to its Hijri components. Returns a JSON object string like {"year":1447,"month":9,"day":23}.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesGregorian date as ISO 8601 string, e.g. '2025-09-23'.

TDQS

A3.6/5.0
Behavior3/5

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

The description discloses the output format (JSON object string) and components. However, it does not mention potential errors (e.g., invalid date input), edge cases, or any limitations. No annotations are provided, so the description carries the full burden.

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?

One concise sentence that includes the essential information: operation, input, and output format. No unnecessary 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 is simple with one parameter and no output schema. The description adequately explains the output format and content. Could mention that the output is a string representation of a JSON object, but that is clear. Minor improvement would be to clarify that the date must be in the format YYYY-MM-DD.

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 description adds the example '2025-09-23' which is already implied by the ISO 8601 specification in the schema. No additional semantic value beyond the schema.

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 action (convert), the inputs (Gregorian date), the outputs (Hijri components), and the output format (JSON object string). It is distinct from sibling tools like format_hijri which likely formats an existing Hijri date.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus alternatives. For example, if a user wants a formatted Hijri string, format_hijri might be better. The description does not mention any prerequisites or exclusions.

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

transliterateA

Transliterate Arabic text to Latin script (e.g. "مُحَمَّد" -> "muhammad").

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe Arabic text to transliterate.

TDQS

A3.6/5.0
Behavior2/5

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

No annotations exist, so the description carries full burden. It only states the script transformation, omitting details like transliteration standard, handling of diacritics, or whether it's reversible.

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?

Single sentence with an embedded example—maximally concise and front-loaded with purpose.

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 single-parameter tool, the description covers input (Arabic text) and output (transliterated Latin script) via example. No output schema exists, but the example implies string return; slightly lacking in stating output type explicitly.

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 coverage is 100% with property description matching the tool. The description adds an example but no extra parameter-level insight beyond the existing schema documentation.

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 it transliterates Arabic text to Latin script with a concrete example ('مُحَمَّد' -> 'muhammad'), which distinguishes it from siblings like arabic_to_words or arabic_ordinal that perform different operations.

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 description implies usage when Arabic-to-Latin transliteration is needed but provides no explicit guidance on when not to use it or alternatives among sibling tools.

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

validate_ibanA

Validate an IBAN (International Bank Account Number) using its checksum and country length (e.g. "SA03 8000 0000 6080 1016 7519" -> "true"). Returns "true" or "false".

ParametersJSON Schema
NameRequiredDescriptionDefault
ibanYesThe IBAN to validate; spaces are allowed.

TDQS

A3.8/5.0
Behavior3/5

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

No annotations provided. Description mentions the validation method (checksum, country length) and return type. Lacks details on edge cases, but behavior is simple and mostly transparent.

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

Conciseness4/5

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

Two concise sentences with an example. No unnecessary words, but could be slightly more structured.

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

Completeness5/5

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

For a simple validation tool with one parameter and no output schema, the description is complete. It covers what the tool does, how it works, and returns.

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?

Only one parameter 'iban' with schema description covering 100%. Description adds no extra meaning beyond the schema.

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 validates an IBAN using checksum and country length, returns 'true' or 'false', and provides an example. It distinguishes from sibling tools like validate_saudi_id.

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?

No explicit when-to-use or when-not-to-use guidance, but the purpose is clear. Sibling tools include other validations, but no differentiation is provided.

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

validate_saudi_idA

Validate a Saudi national/iqama ID number using its Luhn-style checksum (e.g. "1012345672" -> "true"). Returns "true" or "false".

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe 10-digit Saudi ID number to validate.

TDQS

A4/5.0
Behavior3/5

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

No annotations are provided, so the description carries full burden. It discloses the checksum algorithm and return values but does not mention error handling, side effects, or performance. Sufficient but not thorough.

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, front-loaded with the main action and an example. No unnecessary words, highly efficient.

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 simple validation tool with one parameter and no output schema, the description is fairly complete. It explains return values. Minor gap: does not clarify behavior for invalid input format (e.g., non-numeric or wrong length), though likely returns false.

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

Parameters4/5

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

The schema already covers the parameter with 100% description coverage. The description adds value by specifying 'Saudi national/iqama ID number' and providing an example, enhancing meaning beyond the schema's generic 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 validates a Saudi national/iqama ID using a Luhn-style checksum, with an example input and output. It distinguishes itself from sibling tools which handle formatting, translation, or other validation (validate_iban).

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 description implies usage for validating Saudi IDs but does not explicitly state when to use it or provide alternatives. No exclusions are mentioned.

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. Dates show when Glama detected each change.

  1. 17 tool updatesv0.1.0
    • First observedarabic_ordinal
    • First observedarabic_plural
    • First observedarabic_to_words
    • First observedformat_compact
    • First observedformat_currency
    • First observedformat_duration
    • First observedformat_hijri
    • First observedformat_number
    • First observedformat_relative_time
    • First observedisolate_foreign
    • First observedparse_number
    • First observedslugify
    • First observedspell_currency
    • First observedto_hijri
    • First observedtransliterate
    • First observedvalidate_iban
    • First observedvalidate_saudi_id

TDQS

A3.6/5.0
Disambiguation4/5

Most tools have clearly distinct purposes, though some overlap exists (e.g., format_number vs format_compact, format_currency vs spell_currency). Descriptions effectively differentiate them, so confusion is minimal.

Naming Consistency3/5

All names use snake_case, but patterns vary: some are verb_noun (format_currency), some descriptive noun (arabic_ordinal), and some single verbs (slugify). This mild inconsistency prevents a higher score.

Tool Count4/5

17 tools cover a wide range of Arabic formatting and validation tasks without feeling excessive. The count is appropriate for the server's scope, though it could potentially be trimmed by merging some overlapping functions.

Completeness4/5

The set covers number conversion, date formatting (Hijri), currency, duration, relative time, transliteration, and validation (IBAN, Saudi ID). Missing a general Gregorian date formatter, but the core domain is well-served.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cc1a2b/arabicfmt'

If you have feedback or need assistance with the MCP directory API, please join our Discord server