About Sec MCP
Sec MCP is an MCP server published by Montimage in the Developer Tools category: a Python toolkit providing security checks for domains, URLs, IPs, and more. Integrate easily into any Python application, use via terminal CLI, or run as an MCP server to enrich LLM context with real-time threat insights.
The repository has 3 stars and 0 forks, with the last commit yesterday. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/Montimage/sec-mcpThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Sec MCP
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository just now. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.
- !Scoped permissionsDoesn't declare a permission scope. Assume it can do anything its process can.
Releases
README
sec-mcp
Check domains, URLs and IP addresses against live security blacklists — as a Python library, a terminal CLI, or an MCP server that gives LLM agents real-time threat context.
sec-mcp aggregates ten public threat-intelligence feeds into a local SQLite database and answers "is this domain/URL/IP malicious?" in microseconds. Use it inside any Python application, from the terminal with sec-mcp, or as a Model Context Protocol server so tools like Claude Desktop, Cursor and Windsurf can screen indicators against real blacklist data.
Developed by Montimage, a company specializing in cybersecurity and network monitoring solutions.
Table of Contents
- Features
- Demo
- Quick Start
- Installation
- Usage
- Performance Optimization
- Benchmarking
- Configuration
- Project Structure
- Documentation
- Contributing
- Related Publications
- License
- Acknowledgments
Features
- Comprehensive security checks — validate domains, URLs and IPv4/IPv6 addresses, with domain→URL cascade semantics (a blacklisted domain condemns its URLs and subdomains; a blacklisted URL does not condemn its domain) and CIDR-range matching for IPs
- Ten threat-intelligence feeds — OpenPhish, PhishStats, URLhaus, PhishTank, Spamhaus DROP, Dshield, CINSSCORE, EmergingThreats, FeodoTracker and BlocklistDE
- Three interfaces, one engine — Python API (
SecMCP), Click CLI (sec-mcp), and an MCP server (sec-mcp-server, stdio or streamable HTTP) exposing six typed tools - Two storage backends — default SQLite storage (v1), or an in-memory hybrid (v2,
MCP_USE_V2_STORAGE=true) with O(1) per-type indexes; up to ~28,000x faster lookups than the database-only path on the bundled benchmark - URL normalization — one canonicalizer shared by both backends: lowercasing, default-scheme handling and tracking-parameter stripping (
utm_*,fbclid, …), so URL variants share one verdict - Safe feed ingestion — HTTPS-only downloads bounded by
max_feed_bytesand entry-count sanity checks; a failing feed never aborts the others - Scheduled daily updates — a
schedulejob refreshes feeds atupdate_time; forced updates are rate limited to one permin_update_interval_seconds(default 300 s) - Concurrency-friendly — SQLite in WAL mode with
synchronous=NORMAL, a thread-local shared connection per check, and lock-free snapshot reads on the v2 backend - Structured MCP output — every tool publishes a typed
outputSchema, results carrystructuredContent,check_batchreports a tri-state verdict (safe/blacklisted/invalid), and domain failures surface asisErrorresults instead of protocol crashes - Observable —
get_diagnosticsMCP tool (summary / full / health / performance / sample modes), realscheduler_alivereporting and per-source entry counts
Demo
PLACEHOLDER — needs maintainer input before publishing. The repository ships no screenshot or demo assets today. Suggested: an asciinema recording of
sec-mcp update→sec-mcp check <url>, or a screenshot of the six MCP tools inside Claude Desktop. Add the file underdocs/assets/(e.g.docs/assets/demo.gif) and replace this block with.
Quick Start
From zero to a verdict in under five minutes:
pip install sec-mcp
sec-mcp update # download + index the feeds (first run only)
sec-mcp check https://example.com # → Status: Safe / Blacklisted
sec-mcp status # entry counts + per-source breakdown
To run it as an MCP server instead, jump to MCP Server — no install beyond uvx is needed.
Installation
pip install sec-mcp
Requirements
- Python 3.11 or newer (CI tests 3.11–3.14)
- SQLite 3 (bundled with Python)
- Optional:
pytriciaviapip install "sec-mcp[fast-cidr]"for fast CIDR matching; without it a pure-Pythonipaddressmatcher is used (pytriciabuilds from source and needs a C compiler)
From source
Requires uv (pip install uv if needed):
git clone https://github.com/Montimage/sec-mcp.git
cd sec-mcp
uv sync # creates .venv, installs the package editable + dev tools, pinned by uv.lock
Usage
CLI
# Single check — auto-detects domain vs URL vs IP
sec-mcp check https://example.com
sec-mcp check malicious-domain.com
sec-mcp check 192.168.1.1
# Type-specific checks
sec-mcp check-domain example.com
sec-mcp check-url https://example.com/path
sec-mcp check-ip 192.168.1.1
# Batch check from a file (one value per line)
sec-mcp batch urls.txt
# Status, updates, sampling and cache control
sec-mcp status
sec-mcp update
sec-mcp sample -n 20
sec-mcp flush-cache
Every command except sample accepts --json for machine-readable output.
Python API
from sec_mcp import SecMCP
client = SecMCP() # optional: SecMCP(db_path="/path/to/mcp.db")
client.update() # download + index the feeds (first run only)
# Single check — check() returns CheckResult(blacklisted, explanation)
result = client.check("https://example.com")
print(result.blacklisted, result.explanation)
# result.to_dict() -> {"is_safe": True, "explain": "Not blacklisted"}
# Type-specific checks
client.check_domain("example.com")
client.check_url("https://example.com/path")
client.check_ip("192.168.1.1")
# Batch check
urls = ["https://example.com", "https://test.com", "192.168.1.1"]
for value, r in zip(urls, client.check_batch(urls)):
print(f"{value}: {'BLOCKED' if r.blacklisted else 'SAFE'}")
# Status — StatusInfo(entry_count, last_update, sources, server_status)
status = client.get_status()
print(status.entry_count, status.last_update, client.scheduler_alive())
MCP Server
sec-mcp runs as a stdio MCP server for AI/LLM integration (Claude Desktop, Cursor, Windsurf, …). server.json at the repo root ships the matching MCP Registry entry (io.github.montimage/sec-mcp).
-
Install
uv(providesuvx): see the uv installation docs, orpip install uv. -
Populate the blacklist once:
uvx --from sec-mcp sec-mcp update -
Configure your MCP client (e.g.
claude_desktop_config.json):{ "mcpServers": { "sec-mcp": { "command": "uvx", "args": ["--from", "sec-mcp", "sec-mcp-server"], "env": { "MCP_USE_V2_STORAGE": "true" } } } }How it works:
uvxdownloads thesec-mcppackage from PyPI and runs itssec-mcp-serverentry point — no virtual environment or absolute Python path required. Alternatively,pip install sec-mcpinto any environment and use"command": "sec-mcp-server"with noargs.
MCP tools
| Tool | Description |
|---|---|
check_batch |
Check multiple domains/URLs/IPs in one call |
get_status |
Blacklist status: entry counts, per-source breakdown, scheduler_alive |
update_blacklists |
Force an immediate update (rate limited; emits per-source progress) |
get_diagnostics |
Diagnostic info — modes: summary, full, health, performance, sample |
add_entry |
Manually add a blacklist entry (URL/domain or IP, optional score) |
remove_entry |
Remove a blacklist entry by domain, URL or IP |
update_blacklists is rate limited to one forced update per min_update_interval_seconds (default 300 in config.json): a second call inside the window returns {"updated": false, "reason": ...} without starting downloads, and callers that supply a progress token receive one notifications/progress per source.
The get_diagnostics modes:
summary(default): entry counts, sources and last update timesfull: complete diagnostic data including health, stats and performancehealth: database reachability and scheduler state onlyperformance: lookup metrics and hit rates (v2 storage only)sample: random sample of blacklist entries (sample_countparameter, 1–100)
HTTP transport and the landing-page playground
sec-mcp-server speaks stdio by default. Add --http to serve MCP over
streamable HTTP instead, so a browser — including the live playground on the
landing page — can call the tools:
sec-mcp update # populate the database once
sec-mcp-server --http # → http://127.0.0.1:8000/mcp
sec-mcp-server --http --host 0.0.0.0 --port 9000
- CORS allows the origins in
SEC_MCP_CORS_ORIGINS(default: local Vite dev/preview on ports 3000/4173 andhttps://montimage.github.io); credentials are never allowed.*allows any origin and also disables DNS-rebinding protection. - Set
SEC_MCP_HTTP_AUTH_TOKENto requireAuthorization: Bearer <token>on every request. Binding a non-loopback host (e.g.--host 0.0.0.0) without one generates a random token for that run and prints it with a#token=…fragment: append it to the landing-page URL and the playground connects with it. Pass--no-authto opt out (a warning is logged).
Performance Optimization
Enable the in-memory v2 backend for dramatically faster lookups:
export MCP_USE_V2_STORAGE=true
Measured results
Numbers below come from the bundled harness (run_benchmark.sh, see Benchmarking):
| Operation | v1 (Database) | v0.3.0 (Hybrid) | v0.4.0+ (Optimized) | Speedup (vs v1) |
|---|---|---|---|---|
| Domain check | 10 ms | 0.01 ms | 0.006 ms | ~1,600x |
| URL check | 5 ms | 0.001 ms | 0.0007 ms | ~7,000x |
| IP + CIDR check | 200 ms | 0.01 ms | 0.007 ms | ~28,000x |
| Batch 100 items | 2–3 s | 50–100 ms | 50–100 ms | ~30x |
Memory usage
- v1 (default): ~10 MB (database on disk)
- v2: ~40–80 MB in-memory, depending on feed size
How v2 is fast
- One in-memory index per entry type — O(1) hash lookups over single domain/URL/IP indexes; reload builds a scratch index and swaps it under the lock, so readers never block and always see a complete snapshot.
- URL normalization —
HTTP://EVIL.COM/→http://evil.com; tracking parameters (utm_*,fbclid, …) stripped. One canonicalizer shared by both backends means identical verdicts. - Integer IPv4 storage — 4 bytes per IP instead of 13+ as a string.
- CIDR matching —
pytriciawhen thefast-cidrextra is installed, pure-Pythonipaddressotherwise.
Monitoring performance
# v2 storage only — the get_diagnostics MCP tool exposes the same data
metrics = client.storage.get_metrics()
# {"total_lookups": ..., "cache_hits": ..., "hit_rate": ...,
# "avg_lookup_time_ms": ..., "memory_usage_mb": ..., "using_pytricia": ...}
Rollback to v1
export MCP_USE_V2_STORAGE=false # or unset MCP_USE_V2_STORAGE
Benchmarking
Compare storage backends with the bundled harness (requires pip install "sec-mcp[fast-cidr]" for the full comparison; psutil ships with sec-mcp):
./run_benchmark.sh --quick # 10K entries, ~30 s
./run_benchmark.sh # 50K entries, ~2 min
./run_benchmark.sh --full --memory # 100K entries + memory profiling
./run_benchmark.sh --v1 --v2opt # compare specific versions
./run_benchmark.sh --all # all versions
| Flag | Description |
|---|---|
--quick |
Quick benchmark — 10K entries, 500 iterations |
--full |
Full benchmark — 100K entries, 1000 iterations |
--all |
Compare all versions (v1, v0.3.0, v0.4.0+) |
--v1 |
Database-only storage |
--v2 |
Hybrid storage |
--v2opt |
Optimized hybrid storage |
--memory |
Include memory profiling (requires psutil) |
Methodology and expected output: BENCHMARK_PLAYBOOK.md.
Configuration
Environment variables
| Variable | Description | Default |
|---|---|---|
MCP_DB_PATH |
Custom SQLite database location | Platform-specific (see below) |
MCP_USE_V2_STORAGE |
true selects the in-memory HybridStorage backend |
false (v1 storage) |
MCP_LOG_PATH |
Log file location | platformdirs log dir |
MCP_CACHE_DIR |
Feed download cache directory | platformdirs cache dir |
MCP_DISABLE_SCHEDULER |
Set to 1 to not start the daily-update scheduler thread |
unset (scheduler runs) |
SEC_MCP_CORS_ORIGINS |
Comma-separated CORS origins for sec-mcp-server --http; * = any |
local Vite ports + GitHub Pages |
SEC_MCP_HTTP_AUTH_TOKEN |
Bearer token required by sec-mcp-server --http |
unset (generated per run on a non-loopback host) |
Default database locations
- macOS:
~/Library/Application Support/sec-mcp/mcp.db - Linux:
~/.local/share/sec-mcp/mcp.db - Windows:
%APPDATA%\sec-mcp\mcp.db
Configuration file
The shipped sec_mcp/config.json controls feed sources, the update schedule and feed-safety bounds:
{
"blacklist_sources": { "OpenPhish": "...", "PhishStats": "...", "URLhaus": "...", "...": "10 feeds total" },
"update_time": "00:00",
"min_update_interval_seconds": 300,
"cache_size": 10000,
"max_feed_bytes": 67108864,
"min_feed_entries": 1,
"max_feed_entries": 500000,
"max_range_addresses": 65536,
"log_level": "INFO"
}
update_time sets the daily update hour, min_update_interval_seconds rate-limits forced updates, cache_size bounds the v1 positive-hit LRU, and the max_*/min_* keys bound accepted feed sizes.
Project Structure
sec-mcp/
├── sec_mcp/ # The package
│ ├── __init__.py # Public API: SecMCP, CheckResult, StatusInfo, __version__
│ ├── sec_mcp.py # SecMCP facade (check/check_batch/update/get_status/…)
│ ├── cli.py # `sec-mcp` CLI (click)
│ ├── mcp_server.py # Six MCP tools (SDK 2.x MCPServer)
│ ├── start_server.py # `sec-mcp-server` entry point (stdio, or --http)
│ ├── http_transport.py # Streamable-HTTP app: CORS, DNS-rebinding, bearer auth
│ ├── storage.py # Backend selector + v1 database-only storage
│ ├── storage_queries.py # v1 read/query half
│ ├── storage_base.py # Shared schema, DB-path resolution, normalize_url
│ ├── storage_v2.py # v2 HybridStorage (in-memory indexes + metrics)
│ ├── storage_v2_db.py # v2 persistence layer (all SQLite access)
│ ├── storage_v2_index.py # v2 in-memory indexes + CIDR matching
│ ├── storage_v2_writes.py # v2 write path (persistence + rollback)
│ ├── storage_v2_stats.py # v2 stats/reporting mixin
│ ├── feed_parsers.py # One parser per blacklist feed source
│ ├── update_blacklist.py # Feed download, scheduling and ingestion
│ ├── utility.py # Validation, logging, config
│ ├── config.json # Shipped defaults (sources, schedule, bounds)
│ └── tests/ # pytest suite (pytest.ini sets testpaths)
├── docs/ # ARCHITECTURE, DEVELOPMENT, DEPLOYMENT, agent-env, playbook, decisions/, archive/
├── scripts/ # check_test_baseline.sh (CI floor gate)
├── .github/ # CI + PyPI + landing workflows, issue & PR templates
├── benchmark.py # Benchmark script
├── run_benchmark.sh # Benchmark helper
├── server.json # MCP Registry metadata
├── react-landing-page/ # Standalone Vite site (not part of the package)
├── CONTRIBUTING.md # Dev setup, tests, conventions, PR process
├── CODE_OF_CONDUCT.md # Contributor Covenant
├── SECURITY.md # Vulnerability reporting policy
├── CHANGELOG.md # Release history (Keep a Changelog)
├── LICENSE # Apache-2.0
└── README.md # This file
Documentation
| Document | Contents |
|---|---|
| docs/ARCHITECTURE.md | Design overview: components, storage backends, check semantics, MCP layer |
| docs/DEVELOPMENT.md | Dev-workflow hub: setup, repo layout, CI gates, conventions |
| docs/DEPLOYMENT.md | PyPI release flow, end-user MCP-server deployment, landing-page deploy |
| docs/agent-env.md | Toolchain, environment variables, probe isolation |
| docs/playbook.md | Top-10 usage cookbook for MCP clients |
| docs/decisions/ | Architecture decision records (ADRs) |
| BENCHMARK_PLAYBOOK.md | Benchmark methodology and interpretation |
| CONTRIBUTING.md | Dev setup, test/lint/coverage commands, branch & PR conventions |
| SECURITY.md | Supported versions and private vulnerability reporting |
| CHANGELOG.md | Release history |
Contributing
Contributions are welcome! See CONTRIBUTING.md for the dev setup (uv sync is the single install command), test and lint commands, and the branch/commit/PR conventions. All contributors are expected to follow the Code of Conduct, and security issues should be reported privately per SECURITY.md.
- Issues: GitHub Issues — bug report and feature request templates provided
- Email: contact@montimage.eu
- Website: https://www.montimage.eu
Related Publications
No publications referencing sec-mcp are known yet. If you use sec-mcp in academic work, talks or blog posts, please open an issue so we can list it here.
License
Apache License 2.0 — Copyright 2026 Montimage.
Acknowledgments
- Threat-intelligence providers: OpenPhish, PhishStats, URLhaus, PhishTank, Spamhaus, Dshield, CINSSCORE, EmergingThreats, FeodoTracker and BlocklistDE
- Built on the Model Context Protocol Python SDK
- Powered by Python, SQLite, Click and httpx
README fetched from the repository just now. The original is authoritative.