Skip to main content
Glama
ruwadgroup

sabit-mcp

by ruwadgroup

Sabit · ثابت

Verified, not guessed.

A self-hostable email-verification engine in Rust. A layered, free-before-expensive pipeline (syntax → IDN/EAI → typo → gibberish → disposable/role → DNS/MX/null-MX → auth records → SMTP probe → catch-all) emits a 0–100 confidence score plus a coarse safe / risky / invalid / unknown status. The engine runs inside the sabitd server daemon; you reach it three ways — the sabit CLI, an HTTP API, and an MCP server for AI agents — all returning the same result.

License: Apache-2.0 CI Core: Rust MCP Conventional Commits

Getting started · Usage · MCP · CLI · API · Architecture · Docs

Table of contents

Related MCP server: @deliveriq/mcp

Overview

Email verification is sold as a binary checkbox — "is this address valid?" — and that framing is why every vendor's marketed 98–99% accuracy collapses in independent tests. Hunter.io's 2026 benchmark of 15 verifiers on ~3,000 real business addresses found no tool scored above 75%; the top three were Hunter (70.00%), Clearout (68.37%), and Kickbox (67.53%). The hard part isn't syntax — it's that catch-all domains make per-mailbox SMTP probing meaningless (15–28% of B2B domains are catch-all), Yahoo returns 250 for every address as an anti-harvesting measure, and probing from a dirty IP just gets you blocklisted.

Sabit treats verification as what it actually is: a multi-signal probabilistic risk-scoring pipeline, not a yes/no checker. It layers fast, free, local checks ahead of the slow, fragile, network-bound ones, weighs every signal into a single score, and is honest about uncertainty — risky and unknown are first-class outcomes, not failures.

Use it however you work: the sabit CLI for scripts and one-off checks, the HTTP API for your backend or signup flow, or the MCP server so an AI agent can decide — with evidence — whether an address is safe to email instead of trusting a fabricated binary. Every interface talks to the same sabitd engine and returns the same result object.

Features

  • Layered, free-before-expensive pipeline — every check that can run offline runs first; the network is the last resort, and a null-MX or no-MX+no-A domain short-circuits to invalid before any probe.

  • 0–100 confidence score + coarse statussafe / risky / invalid / unknown, modeled on Reacher's taxonomy so existing tooling maps cleanly. You set the threshold per use case (strict for cold outreach, lenient for signup forms).

  • Three interfaces, one result — a CLI, an HTTP API, and an MCP server all call the same engine and return the same object. The MCP tools (verify, submit_batch, task_status, auth_check, parse_bounce, doctor) are honest by design: a tool never returns safe for an address the protocol couldn't confirm.

  • Never sends mail — the prober opens TCP to the MX, does EHLO → MAIL FROM → RCPT TO → QUIT, and reads the reply code. No DATA is ever transmitted, so no message is ever delivered.

  • Catch-all aware — repeated randomized probes detect accept-all domains and downgrade the result to risky instead of a false valid.

  • Disposable & role detection, kept fresh — a real community blocklist (7k+ domains) plus MX-fingerprint clustering and role/free-webmail classification; the daemon auto-refreshes the volatile lists from source on a schedule (or sabit lists update).

  • Deliverability built in — SPF/DKIM/DMARC/BIMI reading, DSN/NDR bounce parsing (RFC 3464/3463), and ARF feedback-loop parsing (RFC 5965), not bolted on.

  • Self-hosted and private — runs on your own unblacklisted VPS; nothing about what you verify leaves your server; no telemetry.

Why Sabit

The state of the art is mostly closed SaaS that hides its method and oversells its accuracy. The strongest open prior art — Reacher / check-if-email-exists — proved the modern technique: SMTP for domains where it still works, headless provider-specific checks where it doesn't, and per-domain rule overrides. Sabit builds on that, adds an explicit weighted scoring model and a deliverability layer, and exposes it through a CLI, an HTTP API, and an MCP server so it fits a script, a backend, or an AI agent equally.

Principle

How Sabit applies it

Cheapest signal first

Local layers (syntax/typo/gibberish/disposable) resolve obvious input before any network call

Probabilistic, not binary

Every signal is weighted into a 0–100 score; risky/unknown exist precisely for the gray zone

Honest about uncertainty

Catch-all, anti-harvesting 250s, and greylisting are reported as such — never hidden as valid

Built to integrate

One result contract over a CLI, an HTTP API, and an MCP server — evidence and confidence, not a fabricated yes/no

Responsible probing by default

FCrDNS-checked HELO, real MAIL FROM, per-domain caps, backoff, aggressive caching, no DATA

What Sabit is not

  • Not a sender. Sabit verifies and scores; it never delivers mail. The deliverability layer parses bounces and reads auth records, but the only thing it sends to a target MX is an envelope it abandons before DATA.

  • Not a guarantee. The only ground truth for deliverability and ownership is double opt-in. Everything else is inference. Sabit is built to express confidence, not to fake certainty.

  • Not a list-buying or scraping tool. It has no address-generation or harvesting features; dictionary attacks and list scraping are the abuse it is designed not to be.

  • Not a hosted SaaS. It is software you run. There is no Sabit cloud, no per-check billing, and no telemetry phoning home.

Architecture

   CLIENTS (thin — no verification logic, just point at a sabitd over HTTP)
   ┌──────────────────────────────┐   ┌──────────────────────────────┐
   │ sabit-mcp  (MCP, for agents) │   │ sabit  (CLI: verify/batch/…)  │
   └───────────────┬──────────────┘   └───────────────┬──────────────┘
                   └───────────────┬──────────────────┘
                          HTTPS (REST + task polling)
                                   │
   ════════════════════════════════▼═══════════════════════════════════  server boundary
   ┌──────────────────────────────────────────────────────────────────┐
   │  sabitd — the daemon (runs where probing is possible: port 25,    │
   │  clean IP, PTR/FCrDNS). HTTP API + task/job worker (sabit-server). │
   ├──────────────────────────────────────────────────────────────────┤
   │  sabit-core (Rust — the only place behavior lives)                 │
   │   Local   • Syntax (RFC 5321) • Typo • IDN→Punycode • Gibberish    │
   │           • Disposable + MX-fingerprint • Role / free classify     │
   │   Network • DNS: MX+A/AAAA, null-MX, SPF/DKIM/DMARC/BIMI (hickory) │
   │           • SMTP probe: RCPT-TO, no DATA, greylist retry           │
   │           • Catch-all detection • Per-provider routing             │
   │           • Bounce/DSN parser   • Feedback-loop ingester           │
   │   Scoring • Weighted 0–100 score → {safe|risky|invalid|unknown}    │
   └──────────────────────────────────────────────────────────────────┘

All verification behavior lives in sabit-core, which runs only inside sabitd — the server daemon on a host that can actually probe (outbound port 25, a clean IP, matching PTR/FCrDNS). The sabit CLI and sabit-mcp are deliberately thin: they translate transport and relay the result contract, holding no engine logic, so a laptop or an agent host needs nothing special. The core still splits cleanly into a local half (pure, offline, deterministic — verify --local) and a network half (DNS + SMTP). Full reasoning is in ARCHITECTURE.md.

The result contract

Every interface returns the same object. A verify of one address:

{
  "input": "jane.doe@example.com",
  "status": "safe",
  "score": 96,
  "syntax": {
    "valid": true,
    "normalized": "jane.doe@example.com",
    "domain": "example.com",
    "is_idn": false,
    "is_eai": false
  },
  "mx": { "accepts_mail": true, "null_mx": false, "records": ["aspmx.l.example.com"] },
  "smtp": {
    "can_connect": true,
    "is_deliverable": true,
    "is_catch_all": false,
    "has_full_inbox": false,
    "is_disabled": false,
    "verif_method": "smtp"
  },
  "misc": { "is_disposable": false, "is_role_account": false, "is_free": false },
  "auth": { "spf": true, "dkim": true, "dmarc": "p=reject", "bimi": false },
  "signals": { "gibberish": 0.02, "typo_suggestion": null, "greylisted": false },
  "took_ms": 812
}

status is the coarse verdict; score is the tunable number; signals and the per-layer blocks are the evidence. See the result object and How it works.

Getting started

No compiler needed — the installer pulls prebuilt binaries.

1. Run the server (sabitd) on a probing-capable host (port 25 open, clean IP, PTR/FCrDNS):

curl -fsSL https://raw.githubusercontent.com/ruwadgroup/sabit/main/install.sh | sh -s -- daemon
sudoedit /etc/sabit/sabit.toml        # set smtp.helo to this host's FQDN (matching its PTR)
sudo systemctl enable --now sabitd

Front it with a TLS-terminating proxy and enable server.api_key_file before exposing it. Full guide: packaging/README.md.

2. Point a client at it (laptop / CI / next to an agent):

curl -fsSL https://raw.githubusercontent.com/ruwadgroup/sabit/main/install.sh | sh -s -- cli mcp
mkdir -p ~/.config/sabit && $EDITOR ~/.config/sabit/config.toml   # set your sabitd url + token

sabit doctor                          # can the SERVER probe? (port 25, PTR/FCrDNS)
sabit verify jane.doe@example.com     # one address
sabit batch contacts.csv --out results.jsonl   # async task: submit, poll, fetch

# Or use it from an AI agent (Claude Code) over MCP:
SABIT_SERVER=https://sabit.example.com SABIT_TOKEN=sk_live_… \
  claude mcp add sabit -- sabit-mcp

See Getting started and Use with AI agents.

Documentation

Doc

What you'll find

Getting started

Install the server, configure a client, first verification

Usage

Everyday CLI usage — verify, batch tasks, auth, bounces

Use with AI agents

The MCP server: setup, tools, a typical agent flow

CLI reference

Every command and flag

HTTP API

Endpoints, bearer auth, the result object, errors

Configuration

Server (sabit.toml) and client config

Deployment

Running sabitd in production (port 25, systemd, TLS, scaling)

How it works

The scoring model, the pipeline, and honest uncertainty

Architecture

The deep design reference

Start at docs/README.md.

Repository layout

sabit/
├── crates/
│   ├── sabit-core/     # the engine: local + network layers + scoring (server-side only)
│   ├── sabit-server/   # HTTP API + task/job worker (lib, used by sabitd)
│   ├── sabitd/         # the server DAEMON — runs the engine + API on a probing-capable host
│   ├── sabit-client/   # thin HTTP client + multi-instance config (shared by the clients)
│   ├── sabit-cli/      # the `sabit` binary — a thin client of a sabitd instance
│   └── sabit-mcp/      # the MCP server — a thin client that exposes sabitd to agents
├── packaging/          # systemd unit, sysusers/tmpfiles, default config, nfpm (.deb/.rpm)
├── data/               # disposable lists, MX fingerprints, rules.json, name corpus
├── conformance/        # fixtures + cross-interface accuracy harness
├── docs/               # everything in the table above
└── .github/            # CI, release, security scanning, templates

Server vs. client. Verification only happens in sabitd, which must run where SMTP probing is possible — a host with outbound port 25, a clean IP, and matching PTR/FCrDNS (a VPS, not a laptop). The sabit CLI and sabit-mcp carry no verification logic; they point at one (or more) sabitd instances over HTTP and relay the result. Install and operate the daemon per packaging/README.md.

Roadmap

The engine (local + DNS + SMTP layers, catch-all detection, per-provider routing, scoring), the sabitd HTTP API with the async task system, bearer auth, the deliverability parsers (DSN, ARF), and the Linux packaging are in place. On the roadmap: populated community data bundles with a refresh mechanism, an SMTP-verdict cache, a broader per-provider headless module set (Outlook B2C / Yahoo), real STARTTLS upgrade, a Streamable-HTTP MCP transport, and shared/persistent task storage. Full plan: ROADMAP.md.

Responsible use

SMTP probing uses the same handshake spammers use to harvest addresses, and aggressive probing can violate a receiving provider's ToS and get your IP blocklisted. Sabit ships responsible defaults — FCrDNS-checked HELO, a real MAIL FROM, per-domain rate caps, jittered backoff, and never sending DATA — but the operator is responsible for lawful use. Verifying a list you already hold for a legitimate purpose is generally defensible; probing arbitrary harvested addresses is not. See Deployment → responsible probing. This is technical guidance, not legal advice.

Contributing

Contributions are welcome — especially disposable-domain and MX-fingerprint updates, per-provider rules (data/rules.json), accuracy-corpus addresses (with permission), and SMTP edge-case reports. Read CONTRIBUTING.md for the invariants, dev setup, and commit conventions (Conventional Commits with enforced scopes).

Community & support

License

Apache-2.0. Sabit bundles community disposable-domain lists and an n-gram name corpus under their own licenses — see LICENSING.md.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

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/ruwadgroup/sabit'

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