Skip to main content
Glama

Regex Check

CI npm downloads OpenSSF Scorecard License: MIT

A regular expression means different things to different engines, and agents write them as if it did not: (?P<name>...) is Python and refused by JavaScript, lookbehind is refused by Go and RE2, \d matches Arabic-Indic digits in Python and not in JavaScript, ^abc$ matches "abc\n" in Python and PHP and not in JavaScript, and ^(a+)+$ hangs a server on one crafted input. Regex Check runs the pattern on the real engines, in process:

  • JavaScript (V8), Python (CPython's re, through Pyodide), PCRE2 10.48 (PHP's preg_*, grep -P, nginx) and RE2 (the syntax Go's regexp and BigQuery accept).

  • Each engine's own verdict: its compile error with the position, or every match with its groups and named groups, and the result of a replacement written in that engine's syntax. Positions are counted in characters for all four, and the report lists where the engines disagree.

  • ReDoS: whether a pattern can be made to backtrack catastrophically, exponential or polynomial, the part to blame marked in the pattern, an attack string, and how long each engine actually took on it.

Offline, no key.

Built and maintained by Arhan Canli.

Install

Install in Cursor Install in VS Code Install in Goose

Needs Node.js 20 or newer. No account or key.

Claude Code

claude mcp add regex-check -- npx -y regex-check-mcp

Claude Desktop: download regex-check-mcp-<version>.mcpb from the latest release and open it. The bundle is signed; verify it with gh attestation verify <file> --repo arhancanli/regex-check-mcp.

Any other client (Windsurf, Zed, Cline, Continue and others), in its MCP config file:

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

Docker

docker build -t regex-check-mcp https://github.com/arhancanli/regex-check-mcp.git && docker run -i --rm regex-check-mcp

Hosted (Streamable HTTP): node src/server.mjs --http serves stateless MCP at POST /mcp (port from PORT, default 3000).

Related MCP server: regex-toolkit-api

Example

An agent calls test_regex with:

{
  "pattern": "(?P<year>\\d{4})-(\\d{2})",
  "inputs": [
    "on 2026-09",
    "٢٠٢٦-٠٩ and 1999-12"
  ],
  "replacement": "\\2/\\1"
}

and gets back (recorded from the live server on 2026-09-27):

{
  "engines": [
    {
      "flavor": "javascript",
      "engine": "V8 13.6.233.17-node.51 (Node v24.19.0)",
      "error": {
        "message": "Invalid group"
      }
    },
    {
      "flavor": "python",
      "engine": "CPython 3.14.2 re (Pyodide)",
      "results": [
        {
          "matches": [
            {
              "index": 3,
              "text": "2026-09",
              "groups": [
                "2026",
                "09"
              ],
              "named": {
                "year": "2026"
              }
            }
          ],
          "match_count": 1,
          "replaced": "on 09/2026"
        },
        {
          "matches": [
            {
              "index": 0,
              "text": "٢٠٢٦-٠٩",
              "groups": [
                "٢٠٢٦",
                "٠٩"
              ],
              "named": {
                "year": "٢٠٢٦"
              }
            },
            {
              "index": 12,
              "text": "1999-12",
              "groups": [
                "1999",
                "12"
              ],
              "named": {
                "year": "1999"
              }
            }
          ],
          "match_count": 2,
          "replaced": "٠٩/٢٠٢٦ and 12/1999"
        }
      ]
    },
... (89 more lines)

Tools

Tool

What it does

check_redos

Checks a regex for catastrophic backtracking (ReDoS): safe or vulnerable, exponential or polynomial, the part of the pattern to blame, an attack string, and how long each real engine (JavaScript, Python, PCRE2, RE2) takes on it. Use before a pattern runs on untrusted input.

test_regex

Runs a regex on real engines: JavaScript (V8), Python (CPython re), PCRE2 (PHP, grep -P), RE2 (Go, BigQuery). Each gives its compile error with position, or every match with groups and named groups, and the replacement result in its own syntax. Positions are in characters. Lists where engines disagree.

How it behaves

  • Nothing leaves your machine and there is no network access (factory.allowHosts is empty): the engines are compiled to WebAssembly (Python, PCRE2, RE2) or are Node's own (JavaScript).

  • Each engine runs in its own worker thread with a time limit (5 s per call, REGEX_CHECK_TIMEOUT_MS to change it): a pattern that backtracks forever on an input stops that engine only, which is replaced, and the others still answer. The engines start in the background when the server starts, so the first call does not wait for Python to load.

  • PCRE2 runs in UTF mode, as PHP's /u modifier uses it, with its default match limit. RE2 takes JavaScript-style $1 replacements, as Go's ReplaceAllString does. Up to 10,000 matches are counted per input and max_matches (default 20) are listed.

  • The ReDoS analysis is recheck (MIT), which proves a problem by building an attack string; the attack is then timed on each engine for 2 seconds.

  • Results are compact JSON with a matching output schema.

Benchmark

Not yet measured.

Performance

Measured 2026-09-27 from Dubai, home connection against the live upstream, Node 24.19.0 (bench/perf.json, scripts/perf.mjs in the factory).

Call

First call

Repeat

Result size

test_regex: Python-style named groups and \d across four engines

983 ms

3.8 ms

1,576 chars

test_regex: a lookbehind, which RE2 refuses

859 ms

0.6 ms

750 chars

check_redos: nested repetition, measured on the engines

2991 ms

0.3 ms

915 chars

check_redos: an email pattern that is safe

68 ms

0.3 ms

128 chars

First call: a fresh server process, including the TLS connection and the upstream's own time. Repeat: the same call again, answered from the in-process cache, so it shows this server's own overhead.

Tool definitions the model reads on every turn (name, description, input schema): 1,490 characters, against 1,251 for @jkumonpm/regex-tester-mcp, a published regex MCP server (JavaScript engine only). The full tool list, with the output schemas and annotations clients use to validate results, is 2,124 characters (1,439 for the alternative).

More MCP servers by Arhan Canli

  • Actions Check: Checks GitHub Actions workflows: outdated actions, old Node runtimes, retired runners, injection.

  • Config Check: Validates config files against their official schemas: tsconfig, compose, workflows, 1,400+ more.

  • Cron Check: Explains cron expressions, lists next run times in any time zone, converts between cron dialects.

  • Dockerfile Check: Checks Dockerfiles: build-breaking mistakes, base image tags that exist, digests, platforms, EOL.

  • Domain Health: Email and domain checks: SPF lookup limits, DKIM keys, DMARC, DNS records, registration expiry.

  • End of Life: Is this version still supported? EOL dates, latest patch and upgrade target for 470+ products.

  • Internet Standards: RFC sections, status, obsoleted-by chains, errata and IANA registries for coding agents.

  • Kube Check: Checks Kubernetes manifests for your version: removed APIs, unknown fields, Pod Security, risks.

  • The whole collection, 12 more

License

MIT, Copyright (c) 2026 Arhan Canli.

Available Tools

2 tools
check_redosCan this regex be made to hang?A
Read-onlyIdempotent

Checks a regex for catastrophic backtracking (ReDoS): safe or vulnerable, exponential or polynomial, the part of the pattern to blame, an attack string, and how long each real engine (JavaScript, Python, PCRE2, RE2) takes on it. Use before a pattern runs on untrusted input.

ParametersJSON Schema
NameRequiredDescriptionDefault
flagsNo
verifyNotime the attack on the engines (default true)
patternYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description goes beyond that by disclosing the shape of the analysis (verdict, complexity class, blamed subpattern, attack string) and that it reports timing across four named real engines, which a caller planning untrusted-input gating needs to know.

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 dense clause enumerating the analysis outputs followed by a single usage sentence; the verdict and use case are front-loaded and no sentence is filler.

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?

An output schema exists, so return structure needn't be described, and annotations cover the safety profile. The remaining gap is the undocumented 'flags' parameter, which neither the schema nor the description explains; otherwise the definition is complete for calling this 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?

Schema description coverage is only 33%: only 'verify' is documented, and the description itself only indirectly touches it via 'how long each real engine... takes'. The 'flags' parameter has no explanation in either the schema or the description, so the description does not compensate for the coverage gap. Baseline 3 for a low-coverage, 3-param tool.

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?

States a specific analysis verb+resource ('checks a regex for catastrophic backtracking') and enumerates exactly what the result contains: verdict, exponential vs polynomial, culprit subpattern, attack string, and per-engine timings. This is clearly distinct from the sibling test_regex, which would test matching behavior rather than ReDoS vulnerability.

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?

'Use before a pattern runs on untrusted input' gives a clear triggering context. It stops short of naming an alternative or stating when-not-to-use (e.g. trusted static patterns), so it falls just short of 5.

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

test_regexTest a regex on real enginesA
Read-onlyIdempotent

Runs a regex on real engines: JavaScript (V8), Python (CPython re), PCRE2 (PHP, grep -P), RE2 (Go, BigQuery). Each gives its compile error with position, or every match with groups and named groups, and the replacement result in its own syntax. Positions are in characters. Lists where engines disagree.

ParametersJSON Schema
NameRequiredDescriptionDefault
flagsNoany of i m s x u
inputsYes
flavorsNodefault all four
patternYes
max_matchesNo
replacementNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
enginesYes

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare the operation safe, idempotent, non-destructive, and closed-world, so the description's job is narrower. It still adds substantial value by disclosing return behavior per engine (compile error with position vs. matches with groups/named groups vs. replacement result in each engine's own syntax) and the character-based position convention. It does not mention input size limits or the 20-input cap.

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?

Four sentences, roughly 55 words, front-loaded with the action and engine list, then return format, then the position convention, then the differentiator. Every sentence contributes information; nothing is redundant or padding.

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 6-parameter tool with an output schema, the description covers the engine set and result shape well enough to call correctly, and the output schema carries return structure. Remaining gaps are flags semantics and max_matches behavior, plus the input array limits, but these are minor against the annotations and output schema.

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 only 33%, so the description must carry weight; it partially does by naming the engines behind the flavors enum and framing what 'replacement' produces. It says nothing about 'flags' (only i m s x u) or 'max_matches', leaving two parameters undocumented in both the schema and the prose.

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 gives a precise verb+resource ('runs a regex on real engines') and immediately enumerates the four concrete engines (V8, CPython re, PCRE2, RE2) with their real-world bindings. This scope is so specific that an agent can trivially separate it from the sibling check_redos, which is about backtracking risk rather than match behavior.

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?

Usage is only implied: it's evident you would call this to compare regex behavior across engines, and 'Lists where engines disagree' hints at the cross-engine comparison use case. However, there is no explicit when-to-use, when-not-to-use, or named alternative (e.g. check_redos) to route the agent.

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.1.0
    • First observedcheck_redos
    • First observedtest_regex

TDQS

A4.2/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: check_redos analyzes a pattern for catastrophic backtracking safety, while test_regex executes a pattern to report matches, groups, and engine differences. An agent can easily tell which to call based on whether the goal is safety analysis or behavior testing.

Naming Consistency5/5

Both names follow the same snake_case verb_noun convention (check_redos, test_regex), with 'redos' and 'regex' as the clear noun targets. The pattern is fully predictable and consistent.

Tool Count4/5

Two tools is on the thin side, but each is a substantial, well-defined operation covering a genuinely narrow domain (regex safety and engine behavior analysis). The scope justifies the small surface, though a third operation could round it out.

Completeness4/5

The surface covers the two core needs—vulnerability detection and cross-engine matching/testing—giving decent lifecycle coverage for the domain. Minor gaps exist (e.g., no pattern explanation or syntax conversion), but agents can work around them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    RegexForge gives AI agents a reliable way to get a regex without asking an LLM to hallucinate one. Pass in labeled examples (strings that should match, strings that shouldn't) plus an optional description; get back the regex, a proof matrix showing it handles every example, and a backtracking-risk audit flagging catastrophic-backtracking patterns. Pure symbolic synthesis over a template bank with
    -
  • A
    license
    A
    quality
    D
    maintenance
    Provides tools to test regex patterns for correctness, performance (ReDoS), and memory usage, and suggests safe rewrites. Enables LLMs to iterate on regex generation with verifiable feedback.
    9
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Lets users generate regex patterns from plain-English descriptions, then verifies them with Python's real re engine against generated positive and negative test strings, iterating on failures until they pass. It exposes this as a tool callable from MCP clients such as Claude Desktop or Claude Code.
    -