rampart
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@rampartprobe https://my-mcp.example/mcp --fail-on high --min-score 90"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Development Experiment 023 — rampart
Offline, dependency-free transport-layer hardening auditor for the MCP Streamable HTTP transport.
rampart probes (or audits a recorded probe of) an MCP Streamable HTTP endpoint for the transport-perimeter defects the MCP spec's three-line "Security Warning" exists to prevent — and that half a dozen 2026 CVEs prove SDKs keep getting wrong:
DNS rebinding via missing/naive
OriginandHostvalidationpermissive / credentialed CORS
weak, guessable, reused or state-leaking
Mcp-Session-Idvalues, and session fixationcleartext / NeighborJack exposure and missing auth on non-loopback binds
MCP-Protocol-Versionand endpoint/method conformance
It ships two byte-stable reference servers — a hardened one that scores a clean 100/A, and a vulnerable one that demonstrates 15 ground-truth defects (three CRITICAL) — plus a severity-weighted score, letter grade and a CI exit-code gate.
Pure Python standard library. No third-party runtime dependencies. pytest only for tests.
Thesis
Experiments #011–#022 in this series each audited one message/content channel of MCP
(tools, prompts, resources, roots, sampling, elicitation, completion, tasks, the stateless
lifecycle, and cross-channel taint flow). #016 deputy covered OAuth authorization.
But underneath every one of those sits the raw HTTP transport, and that is where MCP
is actually bleeding in 2026: the most-CVE'd real MCP vulnerability class of the year is
DNS rebinding against local MCP servers — the Python, Java, Go and Ruby SDKs and the
official MCP Inspector (CVSS 9.4) all shipped without the Origin validation the spec
marks MUST. Backslash's "NeighborJack" scan found most public MCP servers bind
0.0.0.0 by default; BlueRock found 36.7% of 7,000 servers SSRF-exposed.
The MCP spec's transport hardening requirements are three sentences long. rampart turns those three sentences (plus the session-ID contract and the protocol-version rule) into a battery of active HTTP probes and a deterministic rule engine, so a developer can answer "is my MCP endpoint rebinding-safe?" in one command — the smallest thing that proves the transport perimeter can be checked mechanically, offline, with no LLM and no dependencies.
This is the series' second dynamic entry (after #011 gauntlet, which drove stdio)
and its first on the HTTP transport / perimeter layer.
Related MCP server: mcp-security-audit
How to run
# 1) Audit the bundled reference servers end-to-end (spins up loopback servers, probes them)
python main.py demo --kind both
make run # equivalent
# 2) Probe a live MCP endpoint you own
python main.py probe http://127.0.0.1:8000/mcp
python main.py probe https://my-mcp.example/mcp --fail-on high --min-score 90 --json
# 3) Audit a previously recorded probe report, fully offline
python main.py audit captures/vulnerable.probe.json
# 4) Print the rule catalog
python main.py catalog
# 5) Regenerate the shipped captures
python main.py save-captures captures
# Tests
python -m pytest # 60 tests
make testNo installation is required (zero runtime deps). Optionally pip install -e . to get a
rampart console script.
Exit codes (CI gate)
0 pass · 2 gate failed (a finding at/above --fail-on, default high, or score below
--min-score) · 1 usage/runtime error. Drop rampart probe … --fail-on high into a CI
step to block a rebinding-vulnerable server from shipping.
Architecture
touches network pure & deterministic
┌───────────────────────────┐ ┌────────────────────────────────────┐
│ prober.py │ Probe │ analyzer.py catalog.py │
│ crafts a fixed battery │ Report │ ProbeReport -> [Finding] │
│ of HTTP probes, each ├───────►│ 6 family analyzers, 24 rules │
│ isolating ONE property │ (JSON)│ no clock, no randomness, no net │
└───────────────────────────┘ └───────────────┬────────────────────┘
▲ │
│ drives ▼
┌────────┴───────────┐ scoring.py (weight→score→grade→gate)
│ refserver.py │ report.py (text / JSON)
│ hardened | vulnerable│ cli.py (probe|audit|demo|catalog)
│ one handler, a Policy│
└─────────────────────┘Separation of observation from judgement is the core design choice. The prober is the
only module that touches the network; it emits a normalised ProbeReport (status, headers,
a small body excerpt per probe — plain data, no interpretation). The analyzer consumes a
ProbeReport and is pure: no network, no clock, no randomness, so the same report always
yields the same findings. Two consequences fall out for free:
rampart grades a live probe and a recorded report through the identical code path (
probevsaudit), so evidence can be captured once and re-audited forever.every one of the 24 rules is unit-testable with a hand-written
ProbeReport— no sockets in the rule tests.
Each probe isolates exactly one property. The origin_foreign probe sends a foreign
Origin but a legitimate Host, version and session, so a finding points at Origin
validation and nothing else. This "one variable per probe" design is what lets the analyzer
map an outcome straight to a rule.
The reference servers share every line of transport code and differ only in a Policy
dataclass (validate Origin? exact vs substring match? enforce sessions? secure vs sequential
session factory? …). That is precisely rampart's thesis rendered executable: the gap between
a safe and a catastrophic MCP server is configuration/defaults, not code.
Rule families (24 rules)
Family | What it checks | Flagship |
RBND | DNS rebinding: |
|
CORS | Cross-origin sharing posture |
|
SESS |
|
|
XPORT | Cleartext, NeighborJack bind, missing auth, verbose errors |
|
VER |
|
|
CONF | Streamable-HTTP endpoint/method conformance (GET→405, notify→202) |
|
Severity weights: CRITICAL 40 · HIGH 15 · MEDIUM 6 · LOW 2 · INFO 0. Score = max(0, 100 − Σweights). Grade: A≥90, B≥75, C≥60, D≥40, else F.
Trade-offs & design decisions
Dynamic prober vs passive log auditor. A passive auditor (like #013–#022) can only see what a capture happens to contain; transport hardening lives in how a server responds to a hostile request, which a benign trace never exercises. So rampart is an active prober — but it stores its evidence as a
ProbeReportand analyses that, keeping the offline-auditable, deterministic, LLM-free character of the series (and enablingsave-captures→ commit →auditin CI without a live server).Loopback-only reference servers. The vulnerable server is a teaching artefact; it binds
127.0.0.1:0and derives its weak session IDs from a counter + fixed epoch base, so captures are byte-stable and nothing insecure is ever exposed.Heuristic session analysis. Entropy (
SESS02) and sequential-ID (SESS01) detection are heuristics over a small sample, not a statistical randomness proof — deliberately conservative (64-bit floor; boundary-anchored epoch match) to avoid flagging real cryptographic IDs. This matches the "cheap, offline, high-signal" posture of the series.Origin: absentis INFO, not a defect. Browsers always attachOriginon cross-origin requests and legit CLI clients omit it, so missing-Origin acceptance is not itself exploitable; it is recorded (RBND05) but never lowers the score. This is why the hardened server scores a true 100/A while remaining CLI-compatible.http.serverover a framework. Zero dependencies keeps the prototype auditable and portable; the cost is a hand-rolled minimal MCP endpoint, which is fine for a prober target.
Assumptions & limitations
rampart audits the transport perimeter, not application logic or the message channels (those are experiments #011–#022). A 100/A means the HTTP front door is hardened, not that the tools behind it are safe.
The prober assumes a single MCP endpoint path (default derived from the URL, e.g.
/mcp) that speaks the Streamable HTTP transport. Old HTTP+SSE-only servers will read as conformance findings, not crashes.Some checks are posture-conditional:
XPORT01/02/03(cleartext, NeighborJack, missing-auth) only fire for a non-loopback target, because they are not risks on127.0.0.1. Audit a remote deployment to exercise them (unit tests cover them synthetically).rampart sends a small, benign battery (initialize / tools/list / notifications / a malformed body / a CORS preflight). It is a hardening check for servers you own or are authorised to test, not an internet scanner.
Session entropy/prediction is heuristic (see trade-offs). A server using a novel-but-secure scheme could in principle draw a false
SESS02; the 64-bit floor is set well below a UUIDv4.
Sample run
python main.py demo --kind both (loopback ports vary per run):
### reference server: hardened ###
======================================================================
rampart - MCP Streamable HTTP transport hardening audit
======================================================================
target : http://127.0.0.1:64673/mcp
host : 127.0.0.1 (loopback=True, scheme=http)
note : probed 14 vectors, 4 session IDs sampled
SCORE : 100/100 GRADE: A
FINDINGS: 1 [critical=0 high=0 medium=0 low=0 info=1]
----------------------------------------------------------------------
[RBND]
INFO RBND05 Missing Origin accepted on a state-changing request
A state-changing request with no Origin header was accepted (HTTP 200).
----------------------------------------------------------------------
### reference server: vulnerable ###
======================================================================
rampart - MCP Streamable HTTP transport hardening audit
======================================================================
target : http://127.0.0.1:64692/mcp
host : 127.0.0.1 (loopback=True, scheme=http)
note : probed 14 vectors, 4 session IDs sampled
SCORE : 0/100 GRADE: F
FINDINGS: 15 [critical=3 high=4 medium=2 low=5 info=1]
----------------------------------------------------------------------
[RBND]
CRITICAL RBND01 Foreign Origin accepted
Request with Origin 'https://attacker.example' was accepted (HTTP 200); the server does not validate Origin.
CRITICAL RBND02 Foreign Host accepted (DNS rebinding)
Request with a foreign Host header 'attacker.example' was accepted (HTTP 200) over a loopback connection.
HIGH RBND03 Origin allowlist bypass via suffix/substring match
Suffix-bypass Origin 'http://127.0.0.1:64692.attacker.example' was accepted (HTTP 200); validation likely uses substring matching.
HIGH RBND04 Origin: null accepted
Origin: null was accepted (HTTP 200).
INFO RBND05 Missing Origin accepted on a state-changing request
[CORS]
CRITICAL CORS03 Credentialed CORS for a foreign origin
Access-Control-Allow-Origin: * is combined with Access-Control-Allow-Credentials: true, exposing authenticated responses to a foreign origin.
LOW CORS04 Overly permissive CORS methods/headers
[SESS]
HIGH SESS01 Predictable / sequential session IDs
Issued session IDs are sequential: ['sess-1-1700000001', 'sess-2-1700000002', ...].
HIGH SESS05 Client-supplied (unissued) session ID accepted (session fixation)
MEDIUM SESS06 Request without session ID accepted where a session is required
MEDIUM SESS07 Session ID embeds decodable / sensitive data
Session ID leaks internal state (embeds an epoch-like timestamp 1700000001): 'sess-1-1700000001'.
[XPORT]
LOW XPORT04 Verbose error / stack-trace disclosure
[VER]
LOW VER01 Invalid MCP-Protocol-Version not rejected with 400
[CONF]
LOW CONF01 GET without SSE support does not return 405
LOW CONF02 Notification/response not acknowledged with 202
----------------------------------------------------------------------The demo --kind both exits 0 because the hardened server passes the gate; the
vulnerable server's expected failure is reported but does not fail the run. demo --kind vulnerable exits 2.
Layout
rampart/
model.py ProbeResult / ProbeReport / Finding / Severity
catalog.py 24 rules across 6 families (identity & description)
analyzer.py pure ProbeReport -> [Finding] engine (per-family)
scoring.py severity weights -> score/grade + CI gate
report.py text and JSON renderers
prober.py active HTTP probe battery (the only networked module)
refserver.py hardened + vulnerable reference servers (one handler, a Policy)
cli.py probe | audit | demo | catalog | save-captures
captures/ hardened.probe.json (100/A) · vulnerable.probe.json (0/F)
tests/ 60 tests: per-rule analyzer, scoring, catalog, e2e loopback, CLI
main.py convenience entry (== python -m rampart)See RESEARCH.md for the 2026 signals — CVEs, incidents and spec text — that motivated it.
License
MIT — see LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityAmaintenanceA stdio MCP server that audits other MCP servers over the live protocol. It connects to any MCP target (stdio or HTTP), lints every tool's schema for agent-usability, then actually calls the tools with deliberately broken inputs to see how the server handles them, and returns a 0–100 conformance score with a per-dimension breakdown rendered as Markdown.Last updated66MIT
- Alicense-qualityCmaintenanceSecurity auditor for MCP servers that enumerates tools, resources, and prompts, scans for injection patterns, classifies risk levels, and produces a scored report (0-100, grades A-F).Last updated2MIT
- FlicenseAqualityAmaintenanceAI-native HTTP security testing MCP server — 18 tools with raw HTTP/1.1 + HTTP/2 controlLast updated18
- Alicense-qualityBmaintenancePassive security scanner that audits a running MCP server against the OWASP MCP Top 10 and grades it A-F. Read-only static analysis of the advertised tools, prompts and resources with console/JSON/SARIF output, and it also runs as an MCP server itself.Last updated44MIT
Related MCP Connectors
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Scan any website or MCP server for agent-trust-readiness; returns a signed, verifiable scorecard.
MCP Spec Compliance MCP — audits any MCP server.json against the official Model Context Protocol
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/freyesperales/dev-experiment-023'
If you have feedback or need assistance with the MCP directory API, please join our Discord server