Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

hardly

PYPI · HARDLY

Generic HAR analysis MCP server: index and query captures without burning tokens on raw files.

Available components

80 Trust /100

Last scanned (21 hours ago)

Scores higher than 80% of PyPI servers

Category Developer Tools

Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security100
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
  • 1 of 23 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency100
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to b1tninja/hardly). View diagnostics → Pass
  • Clear OSI-approved license (MPL-2.0).Pass
  • Actively maintained (last published 6 days ago).Pass
  • Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability73
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (good).Pass
  • Context-footprint check failed: tool/resource definitions use about 11084 tokens (~136/item across 81 items; 71 tools + 10 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management20
  • Stability observed for 6 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage71
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 0% of tool parameters carry a description.Fail
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety75
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • 0 of 7 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "hardly_send_catalog_verify" implies "send" and declares no destructiveHint at all, which the MCP spec reads as destructive by default. See how to fix → Fail
  • An AI judge read all 73 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a current MCP spec version (2026-07-28).Pass
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 3 Nov 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

  • 2 Nov 26 +2
    • Stability: unverified → 0.13 ▲ functional
  • 30 Oct 26 +15
    • Malware scan: unverified → pass ▲ security
  • 29 Oct 26 62

    First indexed and scored.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 4 Nov 2026 · Analysed pypi/hardly@1.0.0

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem pypi
Reason Verified
Discovered via Registry attestation endpoint
Source repo b1tninja/hardly
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/b1tninja/hardly/.github/workflows/release.yml@refs/tags/v1.0.0
Rekor log index 3558925112
Predicate type PyPI publish attestation https://docs.pypi.org/attestations/publish/v1
Subject digest sha256:93338604fb2b1035a72732c25690371184435f36f124a59a97288783545c04eb

Background: How many MCP packages publish verified provenance →

Install scripts 1 script
Hook Tier Command
build_backend allowlisted hatchling.build

Background: Why install scripts are a supply-chain risk →

Dependencies 23 packages
Packages resolved 23
Stale 1
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 71 exposed · ~10,295 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
hardly_auth_report ~206

Authentication evidence; sections: quick (default; auth paths, token responses, header names), patterns, credentials, secret_names, cookies. Names, shapes and entry ids only, never values. Example: hardly_auth_report(session_id='S', sections=['credentials','cookies']). quick: a first auth check. patterns: named schemes (bearer+refresh, OIDC+PKCE, SAML POST, double-submit CSRF, signed requests; ``pattern_kinds`` filters). credentials: password fields, session cookies and flags, anti-forgery names, OAuth params, token shapes and a hypothesised login_flow (use before implementing login in a client). secret_names: sensitive header/field/ query NAMES. cookies: per-server timeline of Set-Cookie / Cookie names.

NameTypeReqDescription
explainboolean––
host–––
limit–––
pattern_kinds–––
sections–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_browser_capture_discover ~341

LIVE (confirm-gated): unattended time-boxed browser capture of a URL; analyze=true also discovers its APIs and returns session_id plus a brief. Without confirm=true it returns only the plan. Example: hardly_browser_capture_discover(url='https://example.com', wait_seconds=8, analyze=true, confirm=true). Refuses loopback, private, link-local and metadata start URLs (host_not_allowed; HARDLY_ALLOW_PRIVATE_HOSTS=1 for a local test site). analyze=false: load the URL, wait wait_seconds (default 20), stop; returns the raw HAR (har_output_path) and, with open_session=true, a session. analyze=true (headless only): optional ``steps`` (goto/wait/aria/click/fill/find_click...) then stop, open a session and return a brief (default wait 5). If the brief shows a wall or captcha, STOP and switch to interactive hardly_browser_start(headed=true, channel='chrome') with a person. budget_seconds is a hard per-call budget (env HARDLY_CAPTURE_BUDGET). exclude_noise=true aborts analytics/ad/font/ map-tile/heavy-media requests while loading (default off: blocking can break sites).

NameTypeReqDescription
analyzeboolean––
budget_seconds–––
channel–––
confirmboolean––
exclude_noiseboolean––
har_output_path–––
headedboolean––
open_sessionboolean––
steps–––
urlstringyes–
url_filter–––
wait_seconds–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_browser_inspect ~196

Read the running browser tab without navigating; sections: url (default), elements (css/xpath locators), aria (accessibility YAML with [ref=eN] handles). Example: hardly_browser_inspect(sections=['aria'], selector='main'). ``url``: current URL and title (cheap check of where a click landed). ``elements``: visible links/buttons/inputs with locators; ``query`` is a CSS selector override, ``limit`` max rows (default 40, max 100). ``aria``: rendered ARIA tree, ``mode='ai'`` (default) asks for refs, ``selector`` scopes it (default body); the refs feed hardly_browser_interact. For offline HAR HTML bodies use hardly_entry_outline.

NameTypeReqDescription
capture_id–––
limit–––
mode–––
query–––
sections–––
selector–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_browser_interact ~204

Drive the running browser tab: action=goto (needs url), click, fill (needs value) or press (key, default Enter). Prefer ref from hardly_browser_inspect(sections=['aria']). Example: hardly_browser_interact(action='click', ref='e12'). Target one element per call with ``ref``, else ``css`` / ``xpath`` (from hardly_browser_inspect(sections=['elements'])), or ``text`` / ``role`` with ``name`` (click). Never type real credentials yourself: ask the person to use an interactive capture. Omit capture_id for the latest running capture.

NameTypeReqDescription
actionstringyes–
capture_id–––
css–––
key–––
name–––
ref–––
role–––
text–––
timeout_secondsnumber––
url–––
value–––
xpath–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_browser_run_steps ~223

Run a scripted list of steps on the running browser tab in one call (cheaper than many single calls). Use once you know the selectors; hardly_session_plan_steps suggests steps from a session. Example: hardly_browser_run_steps(steps=[{'op':'goto','url':'https://example.com'}]). Each step: ``{"op":"goto"|"wait"|"elements"|"click"|"fill"|"press"|"url"|"aria", ...}``. Example steps:: [ {"op":"goto","url":"https://example.com/search"}, {"op":"wait","ms":1000}, {"op":"click","text":"I Accept"}, {"op":"fill","css":"#SearchOnName","value":"EXAMPLE"}, {"op":"click","css":"input[type=submit]"}, {"op":"wait","ms":2000}, {"op":"elements","limit":30} ]

NameTypeReqDescription
capture_id–––
stepsarrayyes–
stop_on_errorboolean––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_browser_start ~312

Launch a real browser that records a HAR (needs the capture extra); returns capture_id. headed=true (default) is interactive: ASK THE PERSON to use the window, then call hardly_browser_stop. Example: hardly_browser_start(url='https://example.com', headed=true, channel='chrome'). Refuses loopback, private, link-local and metadata start URLs (host_not_allowed; HARDLY_ALLOW_PRIVATE_HOSTS=1 for a local test site). headed=false is headless: drive it with hardly_browser_inspect / hardly_browser_interact / hardly_browser_run_steps. For a one-shot unattended load prefer hardly_browser_capture_discover. Requires ``pip install -e ".[capture]"`` + ``playwright install chromium`` (see hardly_server_status). Prefer channel='chrome' for bot walls. url_filter is a Playwright glob. profile keeps cookies. Without har_output_path the HAR is ephemeral (memory only). same_tab (default true) forces target=_blank into the current tab. trace=true writes a ``.trace.zip`` beside the HAR. Waits for a capture slot (HARDLY_CAPTURE_SLOTS); the result carries ``slot``.

NameTypeReqDescription
channel–––
har_output_path–––
headedboolean––
label–––
omit_contentboolean––
profile–––
same_tabboolean––
traceboolean––
url–––
url_filter–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_browser_stop ~123

Stop a running browser capture, flush the HAR and optionally open it as a session. Call when the person says they are done (interactive) or your steps are complete; then continue with hardly_session_site_brief(session_id). Example: hardly_browser_stop(open_session=true). An ephemeral capture (started without har_output_path) lives only in the returned session; save it with hardly_write_session_copy(format='index'). Omit capture_id for the latest running one.

NameTypeReqDescription
capture_id–––
forceboolean––
open_sessionboolean––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_capture_list ~88

List browser captures (running and persisted) with ids and states, or the status of one capture_id. Poll it while a person drives an interactive capture. Example: hardly_capture_list(capture_id='c1'). Use to find a capture_id after a restart. With capture_id the list holds exactly that capture (state, har_output_path, request counts).

NameTypeReqDescription
capture_id–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_catalog_list ~184

List targets from a content-neutral catalog file (JSON/YAML), filtered; no network. detail='summary' returns counts instead of rows. Tags and roles are defined by your project (docs/catalog.md). Example: hardly_catalog_list(catalog_path='/data/targets.json', detail='summary'). One row per endpoint: target, tags, groups, role, kind, status, redacted url, gate classes, stack names. Filters: ``tag`` (comma-separated, all required), ``group`` (object of key->value), ``role``, ``status``, ``target_id``. hardly assigns no meaning to tags, group keys or roles.

NameTypeReqDescription
catalog_pathstringyes–
detailstring––
group–––
role–––
status–––
tag–––
target_id–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_client_build ~117

Build a minimal Python (urllib) client sketch from story steps or chosen entry_ids and return it as text; secrets become PLACEHOLDER_* values. Writes nothing (hardly_write_export format=client_python saves it). Example: hardly_client_build(session_id='S', entry_ids=[12, 14]). Use as the last step of SDK work, after hardly_session_story / hardly_session_site_brief.

NameTypeReqDescription
class_name–––
entry_ids–––
host–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_endpoint_arcgis ~76

List ArcGIS REST endpoints (MapServer/FeatureServer/etc.) seen in the capture: layer ids, parameter names, paging evidence. Sends nothing; the live twin is hardly_send_arcgis_explore. Example: hardly_endpoint_arcgis(session_id='S').

NameTypeReqDescription
host–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_endpoint_graphql ~77

Detect GraphQL operations (operationName, query, mutation) behind shared URLs, with evidence entry ids. Use when POSTs share one URL; then hardly_entry_get for a sample. Example: hardly_endpoint_graphql(session_id='S').

NameTypeReqDescription
host–––
limit–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_endpoint_list ~101

List grouped endpoints (METHOD + path template) with counts, paged by limit/offset. The main API surface view for JSON APIs; for server-rendered pages use hardly_session_site_brief or hardly_page_forms. Example: hardly_endpoint_list(session_id='S', host='api.example.com').

NameTypeReqDescription
exclude_noiseboolean––
host–––
limit–––
offset–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_endpoint_pagination ~74

Recognise cursor, next-link and Link-header pagination, with evidence entry ids. Shapes only. Use before writing a client loop over results. Example: hardly_endpoint_pagination(session_id='S', host='api.example.com').

NameTypeReqDescription
host–––
limit–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_endpoint_schema ~134

Request/response shapes of one endpoint template. Sections: schema (default; JSON field names and types), param_roles (each field static, dynamic or sensitive). Example: hardly_endpoint_schema(session_id='S', method='GET', path_template='/api/items/{id}'). Use after hardly_endpoint_list. param_roles decides which parameters a client must compute versus hard-code. host defaults to the main host. Names and types only.

NameTypeReqDescription
host–––
limit–––
methodstringyes–
path_templatestringyes–
sections–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_endpoint_streams ~101

Summarise non-JSON stream/binary formats: gRPC(-web), protobuf, MessagePack, CSV/TSV, SSE, WebSocket frames, with evidence entry ids. Shapes only. Use when endpoints show odd content types. Example: hardly_endpoint_streams(session_id='S').

NameTypeReqDescription
exclude_noiseboolean––
host–––
kind–––
limit–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_around ~137

Show the requests just before and after one entry in TIME (a click and the XHRs that followed). Use with a navigation or grid-click entry_id to find the API it triggered; inspect rows with positive delta_ms. Example: hardly_entry_around(session_id='S', entry_id=30, after=8). What triggered an entry by the browser's own initiator data is hardly_entry_initiators.

NameTypeReqDescription
afterinteger––
beforeinteger––
entry_idintegeryes–
exclude_noiseboolean––
host–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_body_query ~154

Search inside one large body without loading it: JSONPath-lite ($.a[*].b, ..key) or regex, paged (pass next_offset while has_more). Use instead of hardly_entry_get for big payloads; sensitive values come back as shapes. Example: hardly_entry_body_query(session_id='S', entry_id=12, jsonpath='$.items[*].id').

NameTypeReqDescription
contextinteger––
entry_idintegeryes–
ignore_caseboolean––
jsonpath–––
limit–––
max_chars–––
offset–––
regex–––
session_idstringyes–
sidestring––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_build_curl ~103

Build a curl command for one entry and return it as text (not executed); secrets are redacted by default. Use to show a person a single request; for a full client use hardly_client_build. Example: hardly_entry_build_curl(session_id='S', entry_id=12).

NameTypeReqDescription
entry_idintegeryes–
redactboolean––
session_idstringyes–
use_env_placeholdersboolean––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_compare ~87

Diff headers and JSON body keys between two entries of one session. Use to see what changed between a failing and a working request, or pre/post login. Example: hardly_entry_compare(session_id='S', entry_id=3, other_entry_id=9).

NameTypeReqDescription
entry_idintegeryes–
other_entry_idintegeryes–
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_dependencies ~118

Trace what one request depends on: the earlier response behind each header, cookie, hidden field or value. Returns ordered minimal steps plus inputs the caller must supply. Offline; names and ids only. Example: hardly_entry_dependencies(session_id='S', entry_id=20). Use before writing a client for a multi-step flow; to track one value across the capture use hardly_session_trace_value.

NameTypeReqDescription
entry_idintegeryes–
host–––
max_depthinteger––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_get ~95

Show one entry with redacted headers and truncated bodies (max_body_chars, default 4000). Use after entry_search/endpoint_list gives an entry_id; for large bodies use hardly_entry_body_query instead of raising max_body_chars. Example: hardly_entry_get(session_id='S', entry_id=12).

NameTypeReqDescription
entry_idintegeryes–
max_body_chars–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_initiators ~104

Show the initiator parent and children of an entry (HAR _initiator/pageref): what triggered a request and what it triggered. Use to find who called an API; for time order use hardly_entry_around. Example: hardly_entry_initiators(session_id='S', entry_id=30).

NameTypeReqDescription
child_limit–––
entry_idintegeryes–
exclude_noiseboolean––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_outline ~127

Offline outline of an HTML/XML body from a HAR entry. format: markdown (headings/tables/forms/links), tree (tag tree) or aria (YAML); omit for all three. Example: hardly_entry_outline(session_id='S', entry_id=5, format='markdown'). Use instead of reading raw HTML; for the live tab use hardly_browser_inspect(sections=['aria']).

NameTypeReqDescription
entry_idintegeryes–
format–––
max_depthinteger––
session_idstringyes–
sidestring––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_entry_search ~204

Find entries by host, path, method, status, body text, header or content_kind; returns small paged rows with entry_ids. Use to locate a specific request, then hardly_entry_get. Example: hardly_entry_search(session_id='S', body_contains='token', limit=10). ``content_kind`` uses the classifier: json, jsonl, jsonp, csv, html, html_table (or table), pdf, image, css, javascript, ... Result rows include ``content_kind`` / hints. exclude_noise=false also returns OPTIONS preflights and tracker traffic.

NameTypeReqDescription
body_contains–––
content_kind–––
exclude_noiseboolean––
header_contains–––
header_name–––
host–––
limit–––
method–––
mime_contains–––
offset–––
path_contains–––
session_idstringyes–
status–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_gate_bot_protection ~262

Detect gates in a capture: bot walls, captcha, login, rate limits, 401/403/429 challenges and CDN/WAF bot-protection products. Never evades. Example: hardly_gate_bot_protection(session_id='S', explain=true). Call when requests are blocked, before any retry: every gate is a STOP sign (re-capture interactively with a person). barriers: each barrier (environment_blocked, bot_wall, captcha, proof_of_work, waiting_room, click_through_terms, login, paywall, rate_limit) with evidence names, entry_ids and a policy action (stop | accept_click_through | unknown_rerun). http_challenges: WWW-Authenticate schemes, 429/423/Retry-After lockout signals and captcha widget markup. bot_protection: vendors seen (Cloudflare, Akamai, Imperva, DataDome, HUMAN, ...) with a state each (blocked / challenged / clearance_seen / present). Challenge nonces are never returned; a CDN header on a normal page is informational, not a wall.

NameTypeReqDescription
explainboolean––
host–––
limit–––
sections–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_guide_help ~76

Categorized catalog of tools and workflows; pass topic to filter. Use when you do not know which tool fits (topics: portal, tokens, capture, modes, or a tool name); for a task-specific plan use hardly_guide_task_plan. Example: hardly_guide_help(topic='capture').

NameTypeReqDescription
topic–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_guide_mode ~150

List the three operating modes (archive, headless, interactive), or get the playbook for one mode, or auto-pick a mode from goal / har_path / url. Example: hardly_guide_mode(har_path='/data/capture.har'). With no argument it lists the modes and when to use each. With ``mode`` it returns that mode's step-by-step playbook; with goal / har_path / url (and no mode) a mode is chosen for you. ``hardly_guide_task_plan`` is the better first call for a full ordered plan.

NameTypeReqDescription
goal–––
har_path–––
mode–––
url–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_guide_task_plan ~129

FIRST CALL for a new task: ordered plan of hardly tool calls with example arguments, environment state and recommended tools for the goal. Example: hardly_guide_task_plan(goal='reverse engineer the login flow', har_path='/data/capture.har'). Pass what you know: goal (free text, e.g. 'build a client SDK'), har_path, url. Small output (~2 KB). For one mode's playbook use hardly_guide_mode, for the tool catalog hardly_guide_help.

NameTypeReqDescription
goal–––
har_path–––
url–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_har_file_check ~145

Diagnose a HAR file on disk (truncated/omitted bodies, sanitised cookies, clock skew, noise); no session needed. Findings carry a fix_hint such as recapture flags. Example: hardly_har_file_check(har_path='/data/capture.har'). Session-level body counts are hardly_session_body_coverage. Optional ``config`` (object): checks, exclude, severity_overrides, thresholds{max_entry_bytes, truncation_ratio, clock_skew_s, noise_ratio, min_entries}, strict, fail_on, host, ignore_hosts, ignore_paths, max_findings, fix.

NameTypeReqDescription
config–––
har_pathstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_page_embedded_routes ~164

Mine endpoints the page embeds. Sections: script_routes (URL path literals in JavaScript), data_attrs (endpoints and config in HTML data-* attributes); default both. Example: hardly_page_embedded_routes(session_id='S', sections=['data_attrs'], entry_id=5). Use when search works but the detail URL is unknown, or on JS-heavy pages to find where the page gets its data; then hardly_entry_around on the click entry. data_attrs reports dataset keys, value kinds, embedded endpoint URLs and JSON config, never free text.

NameTypeReqDescription
entry_id–––
explainboolean––
host–––
limit–––
offset–––
sections–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_page_forms ~134

Extract HTML forms and their inputs with signals (hidden fields, tokens, links, handlers). Use to reverse server-rendered pages instead of dumping HTML; entry_id gives the full inventory of one response, omit it to scan the session. Example: hardly_page_forms(session_id='S', entry_id=5). For link/handler/label-first workflows and search links use hardly_page_ui (same scan).

NameTypeReqDescription
entry_id–––
exclude_noiseboolean––
host–––
limit–––
offset–––
session_idstringyes–
sidestring––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_page_list ~69

List HAR pageref groups (browser page loads) with document hints. Use to split a capture into navigations. Example: hardly_page_list(session_id='S').

NameTypeReqDescription
exclude_noiseboolean––
host–––
limit–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_page_tables ~80

List HTML data tables: headers, row/column counts, column kinds and a masked first row (cell values never returned). Use to understand result grids before scraping or modelling them. Example: hardly_page_tables(session_id='S', entry_id=14).

NameTypeReqDescription
entry_id–––
host–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_page_ui ~188

Inventory UI controls. Sections: links, handlers (onclick/onsubmit), labels (default all three), search_links (ranked links likely to lead to a search page). Example: hardly_page_ui(session_id='S', sections=['search_links'], keywords=['search']). Same scan as hardly_page_forms, projected to the UI parts; handler_functions names feed hardly_page_embedded_routes. entry_id inventories one response, omit it to scan the session. search_links takes ``keywords`` (the site's domain vocabulary): repeat per hop until a form with inputs appears; its next_step feeds hardly_browser_run_steps.

NameTypeReqDescription
entry_id–––
exclude_noiseboolean––
host–––
keywords–––
limit–––
offset–––
sections–––
session_idstringyes–
sidestring––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_send_arcgis_explore ~188

LIVE (confirm-gated): politely explore an ArcGIS REST service or layer URL (GET only, at most 7 requests). Without confirm=true it returns only the plan, so show the person the URL first. For captured traffic use hardly_endpoint_arcgis. Example: hardly_send_arcgis_explore(url='https://host/arcgis/rest/services/X/MapServer', confirm=true). Refuses loopback, private, link-local and metadata hosts, also on redirects (host_not_allowed; local test targets: HARDLY_ALLOW_PRIVATE_HOSTS=1). Returns layers, fields (personal-data-like and id fields FLAGGED), query templates and a one-row sample as field names + masked shapes, never values. Stops on 429 and on token-required (498/499); never guesses tokens.

NameTypeReqDescription
confirmboolean––
urlstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_send_catalog_verify ~266

LIVE (confirm-gated): politely verify catalog endpoints (verified|blocked|dead|needs_browser). Without confirm=true it returns only the plan and sends nothing; write_back=true also records statuses in catalog_path. Example: hardly_send_catalog_verify(catalog_path='/data/targets.json', confirm=true, write_back=true). Refuses loopback, private, link-local and metadata hosts, also on redirects (host_not_allowed; local test targets: HARDLY_ALLOW_PRIVATE_HOSTS=1). Per endpoint it runs one robots-aware, honest-UA fetch and records status, gate classes and stack names, never bodies or tokens. Per-host delay, request budget, resumable (already-checked endpoints are skipped unless force / recheck_after_seconds). Stops a host on any gate per docs/gate-policy.md; never evades.

NameTypeReqDescription
catalog_pathstringyes–
confirmboolean––
delay_secondsnumber––
forceboolean––
group–––
max_endpoints–––
max_requestsinteger––
recheck_after_seconds–––
role–––
status–––
tag–––
target_id–––
write_backboolean––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_send_entry ~185

LIVE (confirm-gated): replay ONE captured request. Without confirm=true it returns only the plan and sends nothing, so tell the person what will be sent first. Sensitive HAR headers are skipped unless given in header_overrides. Example: hardly_send_entry(session_id='S', entry_id=12, confirm=true). Refuses loopback, private, link-local and metadata hosts, also on redirects (host_not_allowed; local test targets: HARDLY_ALLOW_PRIVATE_HOSTS=1). For an ordered series use hardly_send_entry_series; to learn which elements are required hardly_send_entry_ablation. The offline curl text is hardly_entry_build_curl.

NameTypeReqDescription
body_override–––
confirmboolean––
entry_idintegeryes–
header_overrides–––
session_idstringyes–
timeout_secondsnumber––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_send_entry_ablation ~276

LIVE (confirm-gated): find which headers, cookies, params, body fields and prior steps a request truly needs by replaying it with ONE element removed at a time. Without confirm=true it returns only the plan. Example: hardly_send_entry_ablation(session_id='S', entry_ids=[12], confirm=true). Refuses loopback, private, link-local and metadata hosts, also on redirects (host_not_allowed; local test targets: HARDLY_ALLOW_PRIVATE_HOSTS=1). Reports REQUIRED vs OPTIONAL names only, never bodies. entry_ids may be an ordered flow (earlier ids are prior steps, the last is the target). Secrets only via ``overrides`` {"headers":{},"cookies":{},"query":{},"body":{}}; missing ones are listed under needs_override. GET/HEAD only unless allow_unsafe=true. Hard stop on 429 / Retry-After / gate stop; captcha token fields are never sent. Budget-skipped items appear under not_tested.

NameTypeReqDescription
allow_gates–––
allow_unsafeboolean––
confirmboolean––
delay_secondsnumber––
entry_idsarrayyes–
max_requestsinteger––
overrides–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_send_entry_series ~222

LIVE (confirm-gated): replay an ordered series and report the first step whose status, content-type or body shape diverges. Without confirm=true it returns the dry-run plan and missing inputs. Example: hardly_send_entry_series(session_id='S', entry_id=20, confirm=true). Refuses loopback, private, link-local and metadata hosts, also on redirects (host_not_allowed; local test targets: HARDLY_ALLOW_PRIVATE_HOSTS=1). Use to verify a client flow works. Secrets only via ``env`` {name: value} or HARDLY_INPUT_<NAME> env vars; values are never printed. GET/HEAD only unless allow_unsafe; halts on 429/Retry-After/ gates.

NameTypeReqDescription
allow_gates–––
allow_unsafeboolean––
confirmboolean––
delay_secondsnumber––
entry_id–––
entry_ids–––
env–––
max_requestsinteger––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_send_redirect_walk ~184

LIVE (confirm-gated): explain a redirect loop (ERR_TOO_MANY_REDIRECTS) by following the chain by hand with and without cookies. Without confirm=true it returns only the plan. Reports statuses, redacted URLs and cookie names only. Example: hardly_send_redirect_walk(url='https://example.com', confirm=true). Refuses loopback, private, link-local and metadata hosts, also on redirects (host_not_allowed; local test targets: HARDLY_ALLOW_PRIVATE_HOSTS=1). Reports the loop shape: www<->apex or http<->https flips, trailing-slash fights, growing return URLs, cookie-dependent redirects, and whether the alternate host resolves. Redirects already in a capture are hardly_session_redirect_history.

NameTypeReqDescription
confirmboolean––
max_hopsinteger––
urlstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_send_site_crawl ~339

LIVE (confirm-gated): curl-first, robots-aware, polite crawl that finds candidate pages (search forms first). Without confirm=true it returns only the plan. Use when headless Chromium is blocked or static HTML suffices; it stops at gates and never evades them. Example: hardly_send_site_crawl(url='https://example.com', keywords=['search'], confirm=true). Refuses loopback, private, link-local and metadata hosts, also on redirects (host_not_allowed; local test targets: HARDLY_ALLOW_PRIVATE_HOSTS=1). Follows only links found in fetched HTML (never guesses hosts or paths), ranks them with ``keywords`` (nouns), honours robots.txt, waits delay_seconds between requests per host, strips session ids, and stops at gates and on 429/Retry-After. Caps: max_pages <= 40, depth <= 4. External registrable domains are only recorded unless follow_external=true (one hop). Returns candidates, per-page form field NAMES, gate classes and needs_browser pages (with `next` advice when explain=true); no bodies, URLs redacted. For needs_browser pages use hardly_browser_capture_discover with a find_click step.

NameTypeReqDescription
confirmboolean––
delay_secondsnumber––
depthinteger––
explainboolean––
follow_externalboolean––
keywords–––
max_pagesinteger––
respect_robotsboolean––
timeout_secondsnumber––
urlstringyes–
user_agent–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_server_status ~101

Server version, feature flags, tool names and browser availability; sections: capabilities (default), browser_setup. Call when a tool seems missing (restart the MCP server) or capture fails. ``capabilities``: version, features, tools, capture_available (small, ~3 KB). ``browser_setup``: Playwright package and browser binaries, with the exact install commands. Example: hardly_server_status(sections=['browser_setup']).

NameTypeReqDescription
sections–––
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_session_body_coverage ~106

Count entries with usable body text versus empty or truncated. Use before trusting schema/client output, or when bodies look missing. Example: hardly_session_body_coverage(session_id='S'). Useful after Playwright captures that used to omit XHR bodies (size=-1). For problems in the HAR file itself use hardly_har_file_check.

NameTypeReqDescription
exclude_noiseboolean––
host–––
limit–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_session_close ~50

Close an open session to free memory (the session is discarded; files saved with hardly_write_session_copy stay). Example: hardly_session_close(session_id='S').

NameTypeReqDescription
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_session_compare ~97

Compare endpoint templates (and credential maps) between two sessions: routes that appeared and disappeared. Use for logged out vs in, or before and after a site change. Example: hardly_session_compare(session_id='A', other_session_id='B').

NameTypeReqDescription
exclude_noiseboolean––
host–––
include_credentialsboolean––
other_session_idstringyes–
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_session_duplicates ~82

Find repeated method+path_template groups (polling, retries). Use to separate noise from real calls before documenting. Example: hardly_session_duplicates(session_id='S', min_count=5).

NameTypeReqDescription
exclude_noiseboolean––
host–––
limit–––
min_countinteger––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_session_issues ~76

List capture-quality issues: empty bodies, 4xx/5xx, redirects without Location. Check before trusting other results; for HAR-file problems use hardly_har_file_check. Example: hardly_session_issues(session_id='S').

NameTypeReqDescription
host–––
limit–––
session_idstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_session_list ~41

List open HAR sessions (session_id, har_path, index_path). Use when you lost a session_id. No arguments. Example: hardly_session_list().

Input schema present but exposes no named parameters.

NameTypeReqDescription
resultstringyes–

No examples provided.

hardly_session_open ~105

Index a HAR file (or open a saved index) into a queryable session and return session_id plus summary counts. Start here for any HAR; never Read the raw HAR. Writes nothing (save an index with hardly_write_session_copy). Example: hardly_session_open(har_path='/data/capture.har'). Opening the same path again returns the same session; force=true re-ingests the HAR.

NameTypeReqDescription
forceboolean––
har_pathstringyes–
NameTypeReqDescription
resultstringyes–

No examples provided.

Install

How do I install the hardly MCP server?

hardly runs locally as a PyPI package, launched with uvx hardly. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

pypi · hardly

# add to Claude Code
claude mcp add b1tninja-hardly -- uvx hardly
Common questions

What is the hardly MCP server?

hardly is an MCP server listed in the public MCP registry as io.github.b1tninja/hardly. Generic HAR analysis MCP server: index and query captures without burning tokens on raw files. This page covers its PyPI package (hardly).

Is the hardly MCP server safe to use?

hardly scores 80 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 4 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the hardly MCP server expose?

hardly exposes 71 tools: hardly_server_status, hardly_guide_help, hardly_guide_mode, hardly_guide_task_plan, hardly_session_open, and 66 more. Their descriptions and schemas cost roughly 10,295 tokens of context every time the server is loaded.

Is the hardly MCP server still maintained?

hardly is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the hardly MCP server under?

hardly declares the MPL-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.