Skip to main content
Glama
ShieldLabs-ai

@shieldlabs-ai/mcp

Official

ShieldLabs MCP server

Identification, risk signals and risk scoring through hosted OAuth MCP or a local server.

How it fits

The browser SDK returns an identification ID. Your backend or AI assistant reads the result through the public History API, or receives a signed webhook. A UUID by itself does not prove that ingest succeeded.

Hosted OAuth offers 21 tools for domain setup, webhook management and History reads. Local stdio and single-tenant API-key HTTP mode remain read-only and expose seven tools when both API credentials are configured. The hosted operations reference describes every operation.

Related MCP server: verdex

Install

For guided SDK and MCP setup, give your coding assistant the installation guide. Focused skills are available in ShieldLabs-ai/skills.

Use an MCP client with a remote streamable HTTP server and OAuth:

https://mcp.shieldlabs.ai/mcp

Sign in or register in the browser and approve the connection. If the client does not load new tools automatically, restart that client and continue the same conversation. Keep OAuth approval in the browser that started it.

For local stdio:

{
  "mcpServers": {
    "shieldlabs": {
      "command": "npx",
      "args": ["-y", "@shieldlabs-ai/mcp"],
      "env": { "SHIELDLABS_API_KEY": "sec_your_server_key" }
    }
  }
}

Quick start

  1. Check the hosted connection and call shieldlabs_list_domains.

  2. Use the selected domain's public UUID for every History read. A hostname is not a History selector.

  3. Capture an actual browser identification ID. Read it with shieldlabs_get_identification, using domain, identification_id and optionally wait:true.

  4. Read the returned card's id, domain_id, risk.state, risk.score and signals.state. An unavailable risk remains unknown; it is never substituted with Score 0.

{"domain":"11111111-1111-4111-8111-111111111111","identification_id":"33333333-3333-4333-8333-333333333333","wait":true,"response_format":"json"}

Guide

Review one identification

shieldlabs_get_identification returns {found:true, identification:card}. Cards use type:"identification", id and nested risk, not the legacy row format. wait:true retries reads of the same ID within a ten-second total deadline. It never starts another browser identification. Retry-After and cancellation are respected.

shieldlabs_explain_risk_score accepts a domain UUID plus identification_id, or a pasted identification. It preserves unknown risk and says when detailed signal weights are unavailable. It also accepts scored webhook payloads for offline explanation. Missing weights do not establish that nothing contributed to a nonzero score.

List History

shieldlabs_list_history lists identifications or user in a domain. It does not require a card ID:

{"domain":"11111111-1111-4111-8111-111111111111","resource":"identifications","limit":20,"response_format":"json"}

The result contains data and next_page_token. Preserve the same resource, window and flat filters when passing next_page_token as page_token. Tokens are opaque. The server can invalidate them after a restart; do not silently merge a fresh traversal into an earlier snapshot.

Optional from and to are paired RFC3339 timestamps. The window includes from and excludes to. Filters are flat fields: risk_bands, hre_min_accounts (3-99), hre_min_devices (4-99), ids as one User HID string on the user list, risk_signals, source, campaign and boolean flags such as is_vpn. Nested filter, chips, offset, include_total and sort are rejected.

{"domain":"11111111-1111-4111-8111-111111111111","resource":"identifications","risk_bands":["dangerous"],"is_vpn":true,"from":"2026-10-27T00:00:00Z","to":"2026-10-28T00:00:00Z"}

Visitor, device and IP resources have cards, not lists.

Read one History card

shieldlabs_get_history reads one identification, user, visitor, device or ip card:

{"domain":"11111111-1111-4111-8111-111111111111","resource":"user","resource_id":"exact-user-hid","response_format":"json"}

The result is {resource, entity}. It preserves the API's identification count, risk, related counts and High-Risk Events availability. One card is not one identification, and it does not enumerate the underlying history. Card reads also accept device_id_source. Related-account/device traversal is unavailable; relation, relation_limit and relation_page_token are not accepted.

Webhooks and setup

Hosted tools can create and verify a receiver, send a signed test, read delivery status, manage the stored multiaccount setting and rotate credentials with confirmation. All enabled endpoints with a public HTTPS URL receive group events; the stored multiaccount setting does not gate delivery. A sample test does not prove real delivery. HRE confidence is separate from Risk Score; unknown metadata does not imply a negative result.

Use integrate_shieldlabs to inspect the project and choose installation stages. investigate_user and review_request require an explicit domain UUID and only mention enabled tools. Server-side integrations use the Node SDK's current entities client. Keep the public browser key separate from server credentials.

Reference

Local configuration

Variable

Purpose

SHIELDLABS_API_KEY

Server-only Private API Key for entity History

SHIELDLABS_API_BASE_URL

Public History origin, default https://account.shieldlabs.ai

SHIELDLABS_SECRET_KEY

Optional Management API credential

SHIELDLABS_DOMAIN

Registered hostname for the optional Management profile, separate from the History UUID

SHIELDLABS_MANAGEMENT_BASE_URL

Optional Management origin

SHIELDLABS_WEBHOOK_SECRET

Optional secret for offline signature verification

SHIELDLABS_MCP_TOKEN

Bearer protection for local HTTP mode

History requests require domain in tool input. Browser code must never receive the server key or webhook secret. Run npx -y @shieldlabs-ai/mcp --help for transport and tool allowlist options.

Local tools

Tool

Purpose

shieldlabs_get_identification

Read an identification card by ID and domain UUID

shieldlabs_list_history

List identifications or users with opaque pagination

shieldlabs_get_history

Read one identification, user, visitor, device or ip card

shieldlabs_explain_risk_score

Explain reported risk and weight availability

shieldlabs_get_domain_profile

Read and cache the optional Management profile

shieldlabs_verify_webhook_signature

Verify original bytes before interpreting a webhook

shieldlabs_current_time

Read UTC time for freshness checks

Local resources

The identification template is shieldlabs://domains/{domain}/identifications/{identification_id}. It reads the same entity API once. Static contract/reference resources distinguish scored webhook identifications from entity History cards.

Local prompts

  • integrate_shieldlabs: inspect the stack and configure the selected installation stages.

  • investigate_user: read the supplied User HID's API aggregate card in one domain.

  • review_request: read and assess one identification in one domain.

Security

  • Hosted requests use the user's OAuth grant and signed public /mcp/v1 calls. Private dashboard API routes are never exposed through MCP.

  • Every operation applies account/domain ownership. Foreign-domain responses are rejected by the client as well.

  • Destructive operations require confirm:true. One-time credentials are masked unless an installer explicitly uses include_secret:true; MCP transcripts can record them. Store privately and never repeat them in chat.

  • Browser text is untrusted data. Invisible controls are escaped for display; private/debug fields are stripped, secret-shaped text is masked and output sizes are bounded.

  • Oversized History pages fail with a smaller-page request instead of dropping records behind an opaque cursor.

  • Signature checks use original webhook bytes. A valid signature is separate from the truth or availability of fields in the event.

Errors and retries

A missing identification or risk.state:"unavailable" is unverified. Do not turn it into a zero score or infer a billing cause from a missing row. Preserve the backend error code in diagnostic reports.

Read polling respects the total wait deadline, Retry-After and cancellation. A 400, 401, 403 or 410 is not healed by polling. A 404 for a fresh identification may be retried with the same ID. Never automatically retry a mutation whose result may already have been committed.

Troubleshooting

Symptom

Action

Only offline tools are listed

Configure SHIELDLABS_API_KEY in the local client and restart that client

A History read rejects a hostname

Use the public UUID from the domain list

endpoint_retired

Update the client to the domain-scoped entity History API

Pagination token rejected

Recheck the original query; a restart can invalidate tokens

snapshot_unavailable

Treat the read as unavailable and retry within a bounded read budget

OAuth rejected

Reconnect using the client's OAuth flow

A webhook test passes but no real event arrives

Check actual source generation and real signed delivery separately

Compatibility

Node.js 20, 22 and 24 are tested in CI. Transports are stdio and streamable HTTP, with resources and prompts. The published Node SDK 1.3.2 entity client is pinned in package-lock.json and bundled into the executable. Scored webhook normalization remains separate from entity History; older row-search SDK methods do not represent the current API.

Hosted service

Use https://mcp.shieldlabs.ai/mcp for the managed OAuth service and its 21 account tools. This repository publishes the local npm server, its seven stdio tools and reusable HTTP source. The managed service is deployed separately. Publishing an npm tag does not deploy that service.

Development droplet

.github/workflows/deploy.yml runs on a push to development and on a manual rerun of that ref. It installs the built server on dev-shield-admin-node-0. The process listens on 127.0.0.1:8787. nginx serves https://dev.mcp.shieldlabs.ai. The gateway key is the GitHub Environment secret MCP_GATEWAY_KEY, not a file in git.

Production host

.github/workflows/production.yml runs on a push to main. It builds the checksummed bundle and, in the Production environment, copies it to H3 and runs deploy/production/install.py. The workflow does not receive the gateway key. The host must already be prod-shield-0 with /etc/shieldlabs-mcp-production.env, the mcp.shieldlabs.ai certificate, and an accepted account backend. A pull request only builds the artifact.

wrangler.jsonc keeps local Worker settings and has no custom domain. Do not run wrangler deploy. npm run worker:check only bundles the Worker and does not upload it.

Domain, History and webhook tools call the public /mcp/v1 API. The connection probe uses GET /mcp/v1/ping; reading a domain or a record is a separate verification step.

Process

The droplet starts node dist/index.js --transport http --mode public --host 127.0.0.1 --port 8787 --trust-proxy. It speaks plain HTTP. nginx terminates TLS and is the only proxy that can reach the port. Rate limits are kept in memory per process, and request logs go to stdout, one JSON line per request. This repository does not push a container image.

The per-address limits use the address of each TCP connection, which behind a proxy is the proxy's for every client. Add --trust-proxy to take the client address from CF-Connecting-IP instead: the proxy must then set that header on every request, replacing any value the client sent. Cloudflare sets it; with nginx, use proxy_set_header CF-Connecting-IP $remote_addr;.

Development

npm ci
# Until @shieldlabs-ai/node is published, build its tarball in a checkout of shieldlabs-node:
(cd ../shieldlabs-node && npm ci && npm pack)
npm install --no-save ../shieldlabs-node/shieldlabs-ai-node-1.0.0.tgz
npm run typecheck
npm run lint
npm test -- --coverage
npm run build
node dist/index.js --help
npm run smoke            # the built server over stdio against the fake History API
npm run test:worker      # the hosted mode in workerd (Node.js 22 or later)
npm run worker:check     # the Worker bundle: no Node.js built-in module, size limit

@shieldlabs-ai/node is bundled into dist/ at build time, so the published package depends only on @modelcontextprotocol/sdk and zod.

Fake History API

scripts/mock-history-api.mjs serves a deterministic dataset (test/mock-data/, generated by scripts/generate-mock-data.mjs) as a fake History API and Management API:

npm run build
node scripts/mock-history-api.mjs --port 8788
# in another terminal: the MCP Inspector CLI passes environment variables with -e
npx @modelcontextprotocol/inspector --cli node dist/index.js \
  -e SHIELDLABS_API_KEY=sec_evaldata-mockdata-00000001 \
  -e SHIELDLABS_API_BASE_URL=http://127.0.0.1:8788 \
  --method tools/list

npm run smoke does the same without extra downloads: it starts the fake API, runs the built server over stdio with the MCP SDK client and calls its tools, resources and prompts.

See CONTRIBUTING.md. Documentation: docs.shieldlabs.ai. Support: contact@shieldlabs.ai.

License

MIT

Available Tools

6 tools
shieldlabs_current_timeCurrent timeA
Read-onlyIdempotent

Return the current time of the machine running this server, in UTC and optionally in one IANA time zone.

Use it to judge freshness: for example whether an identification's observed_at is older than a 5-minute window, or how long ago an account was last seen.

Args:

  • timezone (string, optional): IANA time zone such as "Europe/Berlin"

  • response_format ('markdown' | 'json'): default 'markdown'

Returns (json): { "utc": string, "unix_seconds": number, "unix_ms": number, "timezone": string | null, "local_time": string | null, "utc_offset": string | null }

NameRequiredDescriptionDefault
timezoneNoIANA time zone for an additional local time, for example "Europe/Berlin" or "America/New_York"
response_formatNoOutput format: 'markdown' (default) for readable text, 'json' for structured datamarkdown

Output Schema

NameRequiredDescription
utcYesCurrent time, RFC 3339 UTC with milliseconds
unix_msYes
timezoneYes
local_timeYes
utc_offsetYes
unix_secondsYes

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, non-destructive and openWorldHint=false, so the safety profile is covered. The description adds value beyond that by clarifying that the time is the server's machine clock in UTC (not the caller's local time) and that a caller-supplied timezone only adds a local rendering – a meaningful, non-obvious semantic.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in one sentence, followed by usage rationale, then args and returns in compact list form. The Returns block is largely redundant with the existing output schema, which costs a little length, but the overall structure is clean and skimmable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-required-parameter, read-only utility with an output schema present, the description covers purpose, usage motivation, and parameter intent. An agent has everything needed to call it correctly; the duplicated return block is harmless redundancy rather than a gap.

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 100%, so both parameters are already documented with constraints and defaults. The description restates them (IANA zone example, default 'markdown') without adding syntax, fallback behavior for invalid zones, or offset semantics, so it sits at the baseline.

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 first sentence names a specific verb and resource ('Return the current time of the machine running this server') and scopes it precisely to UTC plus an optional IANA time zone. No sibling tool (identification, history, summarize, risk score, webhook verification) overlaps with this, so differentiation is implicit and unambiguous.

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?

It gives concrete when-to-use scenarios tied to sibling concepts: judging whether an identification's observed_at is older than a 5-minute window, or how long ago an account was last seen. It lacks any when-not-to-use or named alternative, but no plausible alternative exists among the siblings, so the guidance is nearly complete.

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

shieldlabs_explain_risk_scoreExplain Risk ScoreB
Read-onlyIdempotent

Read an identification card or explain a pasted identification. Missing signal weights are unavailable, never zero contribution. HRE confidence is separate from Risk Score.

NameRequiredDescriptionDefault
domainNoPublic domain UUID from shieldlabs_list_domains, not the hostname.
identificationNo
response_formatNomarkdown
identification_idNo

Output Schema

NameRequiredDescription
riskNo
signalsYes
risk_scoreNo
identification_idYes
weights_availableNo
untrusted_data_noteYes

TDQS

B3.4/5.0
Behavior4/5

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

The description adds valuable behavioral context beyond the standard annotations. Specifically, it clarifies that missing signal weights are never zero contribution and that HRE confidence is tracked separately from the final Risk Score, which an AI agent needs to understand the logic of the output.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficient, front-loading the primary function in the first sentence. It avoids unnecessary jargon or fluff, making it easy for an agent to parse the tool's capability quickly.

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?

Given the low schema coverage and the complex domain of risk scoring, the description is sufficiently complete. It addresses the scoring assumptions and input formats sufficiently for an agent to make an informed decision before invoking the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Since schema description coverage is low (25%), the qualitative information provided in the description is very high value. It explains the nature of the input (reading/pasting) and the logic behind the scoring (signal weights, HRE confidence), which the schema omits.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The title ('Explain Risk Score') and the description clearly state the core function—analyzing an identification for risk. However, the description does not explicitly state what the tool outputs or how this differs structurally from the other ShieldLabs tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance provided on when to use this tool versus alternatives (e.g., if the data is already in a domain or already an identification object). It lacks a clear 'use this when...' statement.

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

shieldlabs_get_historyGet History recordB
Read-onlyIdempotent

Read one identification, user, visitor, device or ip card. domain is the public UUID and resource_id is the record id. The same flat list filters apply, plus device_id_source (legacy or fp21_record). relation, relation_limit and relation_page_token are not accepted. Nested filter, chips, offset and include_total are rejected.

NameRequiredDescriptionDefault
toNo
idsNo
fromNo
ai_botNo
domainYesPublic domain UUID from shieldlabs_list_domains, not the hostname.
is_torNo
is_vpnNo
sourceNo
campaignNo
is_proxyNo
resourceYes
snapshotNo
banned_ipNo
ai_browserNo
risk_bandsNo
ip_mismatchNo
resource_idYes
is_incognitoNo
latency_testNo
risk_signalsNo
is_antidetectNo
is_search_botNo
is_js_disabledNo
is_os_mismatchNo
device_spoofingNo
hre_min_devicesNo
response_formatNomarkdown
check_incompleteNo
device_id_sourceNo
hre_min_accountsNo
is_privacy_relayNo
is_os_not_detectedNo
is_timezone_mismatchNo
is_browser_automationNo
network_check_incompleteNo

Output Schema

NameRequiredDescription
entityYes
resourceYes
untrusted_data_noteYes

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds real value by enumerating rejected parameters and clarifying that `domain` is the public UUID rather than a hostname, but says nothing about not-found behavior, error shapes, or how the filter params constrain a single-record fetch.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, front-loaded with the read action and the two required identifiers before the filter rules. No filler, though the two rejection sentences could be merged into one.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/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 values need not be described. However, for a 35-parameter tool with 3% schema coverage, the description leaves the bulk of the filter surface unexplained and offloads it to a sibling tool's documentation — an agent could call this correctly only by reading shieldlabs_list_history first.

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 3% across 35 parameters, so the description carries most of the burden — and it only explains `domain`, `resource_id`, `device_id_source` (whose values are already an enum) and the rejected params. The ~30 boolean/array filters (risk_bands, hre_min_devices, is_antidetect, etc.) get no explanation at all beyond the pointer to the list tool's 'flat list filters'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource: 'Read one identification, user, visitor, device or ip card', which maps directly to the `resource` enum and distinguishes it from the list sibling by the word 'one'. It never names shieldlabs_list_history explicitly, so the agent must infer the single-vs-list split from context.

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?

The exclusions are genuinely useful ('relation, relation_limit and relation_page_token are not accepted', 'nested filter, chips, offset and include_total are rejected'), steering the agent away from params it might otherwise guess. But 'The same flat list filters apply' is an unqualified cross-reference that only makes sense if the agent has already loaded shieldlabs_list_history, and there is no statement of when to prefer this over that sibling.

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

shieldlabs_get_identificationGet identificationA
Read-onlyIdempotent

Read one identification card by identification_id in a public domain UUID. wait polls missing results for at most 10 seconds; unavailable risk remains unavailable.

NameRequiredDescriptionDefault
toNo
fromNo
waitNo
domainYesPublic domain UUID from shieldlabs_list_domains, not the hostname.
response_formatNomarkdown
identification_idYes

Output Schema

NameRequiredDescription
foundYes
identificationYes
untrusted_data_noteYes

TDQS

A3.7/5.0
Behavior4/5

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

The annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false. The description adds useful behavioral context beyond annotations by explaining that wait polls missing results for at most 10 seconds and that unavailable risk remains unavailable. It does not cover auth or rate limits, but it meaningfully supplements the annotation profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and front-loads the core purpose. Its second sentence is compact but somewhat cryptic, especially "unavailable risk remains unavailable," which could be clearer without adding much length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the essential read-by-ID behavior and the wait polling semantics, and an output schema exists so return values need not be described. However, with low schema description coverage across six parameters, it does not fully explain the optional date filters or response format, leaving clear gaps for an agent invoking the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 17%, so the description must compensate for undocumented parameters. It mentions identification_id, domain, and wait semantics, but leaves to, from, and response_format unexplained, despite those being present in the schema.

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 states a specific verb and resource: "Read one identification card by identification_id in a public domain UUID." It clearly identifies the key lookup inputs and is distinguishable from the listed sibling tools, which cover history, risk scores, webhook signatures, and time.

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 implied by "Read one identification card by identification_id," so an agent can infer this is for fetching a single record rather than listing or searching. However, there is no explicit guidance on when to use this versus alternatives or when not to use it.

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

shieldlabs_list_historyList HistoryA
Read-onlyIdempotent

List identifications or users in one domain. domain is the public UUID from shieldlabs_list_domains. Repeat page_token with the same resource, window and flat filters. Filters are risk_bands, hre_min_accounts (3-99), hre_min_devices (4-99), ids (one user id on the user list), risk_signals, source, campaign and boolean flags. Dates are RFC3339 and the window is half-open. Nested filter, chips, offset, include_total and sort are rejected. visitor, device and ip have a card, not a list.

NameRequiredDescriptionDefault
toNo
idsNo
fromNo
limitNo
ai_botNo
domainYesPublic domain UUID from shieldlabs_list_domains, not the hostname.
is_torNo
is_vpnNo
sourceNo
campaignNo
is_proxyNo
resourceYes
snapshotNo
banned_ipNo
ai_browserNo
page_tokenNo
risk_bandsNo
ip_mismatchNo
is_incognitoNo
latency_testNo
risk_signalsNo
is_antidetectNo
is_search_botNo
is_js_disabledNo
is_os_mismatchNo
device_spoofingNo
hre_min_devicesNo
response_formatNomarkdown
check_incompleteNo
hre_min_accountsNo
is_privacy_relayNo
is_os_not_detectedNo
is_timezone_mismatchNo
is_browser_automationNo
network_check_incompleteNo

Output Schema

NameRequiredDescription
dataYes
resourceYes
next_page_tokenYes
untrusted_data_noteYes

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open-world), so the description mainly adds scoping rules. It does add genuine behavioral context — RFC3339 dates, half-open window, pagination requiring identical filters, and a list of rejected parameters — but says nothing about the pagination token's lifetime or result ordering.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: the core operation, the domain provenance, and the pagination rule come first. Sentences are telegraphic yet each carries distinct information; some reads ('visitor, device and ip have a card, not a list') are cryptic out of context but still earn their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 35-parameter tool with near-zero schema descriptions, the definition leaves meaningful gaps: the boolean flag set, the meaning of snapshot, the limit cap, and the from/to pairing rules are unaddressed. An output schema exists, so return values needn't be explained, which keeps it from being worse.

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?

With only 3% schema description coverage across 35 parameters, the description has to carry nearly the full burden. It names several filters (risk_bands, hre_min_accounts 3-99, hre_min_devices 4-99, ids as one user id on the user list, risk_signals, source, campaign) but lumps roughly two dozen booleans into 'boolean flags', and never explains from/to, limit, snapshot, page_token or response_format semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('identifications or users in one domain'), which is clearly distinct from the card-style sibling shieldlabs_get_identification. It also disambiguates the resource enum by noting that visitor, device and ip have a card, not a list. It does not, however, contrast with shieldlabs_get_history, leaving that boundary implicit.

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?

Gives concrete operational guidance: domain must be the public UUID from shieldlabs_list_domains, page_token must be repeated with the same resource/window/flat filters, and nested filter, chips, offset, include_total and sort are rejected. That is real when/how guidance, though it never explicitly says when to prefer this over shieldlabs_get_history or the card tools.

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

shieldlabs_verify_webhook_signatureVerify webhook signatureA
Read-onlyIdempotent

Check a received ShieldLabs webhook delivery: does its X-Shield-Signature header match the raw body for the endpoint signing secret? For debugging a webhook endpoint. SHIELDLABS_WEBHOOK_SECRET is not set on this server, so pass secret.

The signature is "sha256=" plus the lowercase hex HMAC-SHA256 of the raw body, keyed with the full signing secret including its whsec_ prefix. While a secret is rotated, give several secrets separated by commas (in secret or in SHIELDLABS_WEBHOOK_SECRET): the delivery is valid when any of them matches, and matched_secret tells which. When the signature does not match a body of up to 64 KB, the tool tests common body changes (re-serialized JSON, unescaped characters, added newline) and says which one explains the mismatch. It never returns a secret or an expected signature.

Args:

  • payload (string): raw body exactly as received

  • signature_header (string): value of X-Shield-Signature

  • secret (string, optional): whsec_... signing secret of the endpoint, or several separated by commas

  • payload_encoding ('utf8' | 'base64'): default 'utf8'

  • response_format ('markdown' | 'json'): default 'markdown'

Returns (json): { "valid": boolean, "secret_source": "argument" | "environment", "secrets_checked": number, "matched_secret": number | null, "checks": [{ check, ok, detail }], "event": { event_type, schema_version, created_at, event_id, identification_id, risk_score, risk_band } | null, "hint": string | null }

NameRequiredDescriptionDefault
secretNoEndpoint signing secret including its whsec_ prefix, or several separated by commas while you rotate. Defaults to SHIELDLABS_WEBHOOK_SECRET from the server environment.
payloadYesThe raw request body exactly as received: the bytes that were signed. Do not pretty-print, re-serialize or trim it.
response_formatNoOutput format: 'markdown' (default) for readable text, 'json' for structured datamarkdown
payload_encodingNo'utf8' (default) when payload is the body text; 'base64' when payload is the body bytes encoded as base64 (use it when exact bytes such as a trailing newline matter)utf8
signature_headerYesValue of the X-Shield-Signature header, for example "sha256=ea26857...fdd8"

Output Schema

NameRequiredDescription
hintYes
eventYes
validYes
checksYes
secret_sourceYes
matched_secretYesPosition, from 1, of the secret that matches, in the order given; null when none
secrets_checkedYesHow many signing secrets were checked (several while a secret is rotated)

TDQS

A4.8/5.0
Behavior5/5

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

The description goes far beyond the readOnly/destructive hints by explaining technical constraints (64 KB body limit), the underlying cryptographic process (sha256+ hex HMAC-SHA256), and critical failure modes—specifically that it 'never returns a secret or an expected signature.' It even mentions active error mitigation (testing for re-serialized JSON changes).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is necessarily detailed due to the complex technical requirements (signature format, secret rotation, error testing), making it long but highly functional. It prioritizes the core purpose and constraints upfront.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity and the presence of a rich output schema, the description is extremely complete. It details the security mechanisms, the logic of multi-secret checking, and the error-handling capabilities of the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

While the schema coverage is 100% (baseline 3), the description adds essential operational context that the schema misses. It clarifies that the `secret` can be a comma-separated list for rotation, and it specifies required formats for `payload` (no pretty-printing).

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 clearly defines the function as checking if an X-Shield-Signature header matches the raw body, specifically for 'debugging a webhook endpoint.' This is highly specific and immediately distinguishes it from the list or get operations of sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit guidance on when to use the tool (debugging) and how to handle complexity, such as providing multiple rotating secrets separated by commas. It also notes environmental constraints ('SHIELDLABS_WEBHOOK_SECRET is not set on this server').

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. 7 tool updatesv1.1.0
    • Changedshieldlabs_explain_risk_score25 fields changed
      • addedInput schema / properties / domain
        Added value: +{
        +  "description": "Public domain UUID from shieldlabs_list_domains, not the hostname.",
        +  "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
        +  "type": "string"
        +}
      • changedInput schema / properties / identification / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": true,
        -    "propertyNames": {
        -      "type": "string"
        -    },
        -    "type": "object"
        -  },
        -  {
        -    "maxLength": 500000,
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": {},
        +    "propertyNames": {
        +      "type": "string"
        +    },
        +    "type": "object"
        +  },
        +  {
        +    "maxLength": 500000,
        +    "type": "string"
        +  }
        +]
      • removedInput schema / properties / identification / description
        Removed value: -"An identification to explain without an API call: a normalized identification (for example the json output of shieldlabs_get_identification), a webhook event or its data object, or a raw History API row. A JSON object or its JSON text."
      • addedInput schema / properties / identification_id
        Added value: +{
        +  "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
        +  "type": "string"
        +}
      • removedInput schema / properties / request_id
        Removed value: -{
        -  "description": "Request ID of the identification to explain, read from the History API (needs SHIELDLABS_API_KEY; waits up to about 10 seconds for a new identification, like shieldlabs_get_identification). Give either request_id or identification.",
        -  "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
        -  "type": "string"
        -}
      • removedInput schema / properties / response_format / description
        Removed value: -"Output format: 'markdown' (default) for readable text, 'json' for structured data"
      • changedOutput schema / additionalProperties
        Previous value: -falseNew value: +{}
      • removedOutput schema / properties / band_meaning
        Removed value: -{
        -  "type": "string"
        -}
      • removedOutput schema / properties / band_range
        Removed value: -{
        -  "type": "string"
        -}
      • removedOutput schema / properties / connection_type
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "additionalProperties": false,
        -      "properties": {
        -        "label": {
        -          "type": "string"
        -        },
        -        "meaning": {
        -          "type": "string"
        -        },
        -        "value": {
        -          "type": "string"
        -        }
        -      },
        -      "required": [
        -        "value",
        -        "label",
        -        "meaning"
        -      ],
        -      "type": "object"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ]
        -}
      • removedOutput schema / properties / detection_flags
        Removed value: -{
        -  "items": {
        -    "additionalProperties": false,
        -    "properties": {
        -      "flag": {
        -        "type": "string"
        -      },
        -      "label": {
        -        "type": "string"
        -      },
        -      "meaning": {
        -        "type": "string"
        -      },
        -      "scored": {
        -        "type": "boolean"
        -      }
        -    },
        -    "required": [
        -      "flag",
        -      "label",
        -      "scored",
        -      "meaning"
        -    ],
        -    "type": "object"
        -  },
        -  "type": "array"
        -}
      • addedOutput schema / properties / identification_id
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • removedOutput schema / properties / notes
        Removed value: -{
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": "array"
        -}
      • removedOutput schema / properties / request_id
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "description": "Request ID of the explained identification, when known",
        -      "type": "string"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ]
        -}
      • addedOutput schema / properties / risk
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "as_of": {
        +          "type": "string"
        +        },
        +        "band": {
        +          "enum": [
        +            "trusted",
        +            "suspicious",
        +            "dangerous"
        +          ],
        +          "type": "string"
        +        },
        +        "score": {
        +          "maximum": 100,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "state": {
        +          "const": "ok",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "state",
        +        "band",
        +        "as_of"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "as_of": {
        +          "type": "null"
        +        },
        +        "band": {
        +          "type": "null"
        +        },
        +        "state": {
        +          "const": "unavailable",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "state",
        +        "band",
        +        "as_of"
        +      ],
        +      "type": "object"
        +    }
        +  ]
        +}
      • removedOutput schema / properties / risk_band
        Removed value: -{
        -  "enum": [
        -    "trusted",
        -    "suspicious",
        -    "dangerous",
        -    "rate_limited"
        -  ],
        -  "type": "string"
        -}
      • addedOutput schema / properties / signals / anyOf
        Added value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "items": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "maxItems": 100,
        +        "type": "array"
        +      },
        +      "state": {
        +        "enum": [
        +          "ok",
        +          "unavailable"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "state",
        +      "items"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "items": {
        +      "additionalProperties": {},
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "type": "array"
        +  }
        +]
      • removedOutput schema / properties / signals / items
        Removed value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "in_catalog": {
        -      "type": "boolean"
        -    },
        -    "label": {
        -      "type": "string"
        -    },
        -    "meaning": {
        -      "type": "string"
        -    },
        -    "name": {
        -      "type": "string"
        -    },
        -    "reading": {
        -      "anyOf": [
        -        {
        -          "description": "How to read the risk signal next to others; null outside the catalog",
        -          "type": "string"
        -        },
        -        {
        -          "type": "null"
        -        }
        -      ]
        -    },
        -    "related_flag": {
        -      "anyOf": [
        -        {
        -          "description": "Detection flag that usually comes with the risk signal",
        -          "type": "string"
        -        },
        -        {
        -          "type": "null"
        -        }
        -      ]
        -    },
        -    "typical_weight": {
        -      "anyOf": [
        -        {
        -          "maximum": 9007199254740991,
        -          "minimum": -9007199254740991,
        -          "type": "integer"
        -        },
        -        {
        -          "type": "null"
        -        }
        -      ]
        -    },
        -    "weight": {
        -      "maximum": 9007199254740991,
        -      "minimum": -9007199254740991,
        -      "type": "integer"
        -    }
        -  },
        -  "required": [
        -    "name",
        -    "weight",
        -    "label",
        -    "meaning",
        -    "reading",
        -    "typical_weight",
        -    "related_flag",
        -    "in_catalog"
        -  ],
        -  "type": "object"
        -}
      • removedOutput schema / properties / signals / type
        Removed value: -"array"
      • removedOutput schema / properties / source
        Removed value: -{
        -  "enum": [
        -    "history",
        -    "webhook",
        -    "input"
        -  ],
        -  "type": "string"
        -}
      • removedOutput schema / properties / truncated
        Removed value: -{
        -  "description": "Only present (true) when this server shortened the explanation",
        -  "type": "boolean"
        -}
      • removedOutput schema / properties / truncation_message
        Removed value: -{
        -  "description": "What was shortened: risk signals left out, or long pasted values cut",
        -  "type": "string"
        -}
      • addedOutput schema / properties / untrusted_data_note
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / weights_available
        Added value: +{
        +  "type": "boolean"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "request_id",
        -  "risk_score",
        -  "risk_band",
        -  "band_range",
        -  "band_meaning",
        -  "signals",
        -  "detection_flags",
        -  "connection_type",
        -  "notes",
        -  "source"
        -]New value: +[
        +  "identification_id",
        +  "signals",
        +  "untrusted_data_note"
        +]
    • Addedshieldlabs_get_history
    • Changedshieldlabs_get_identification59 fields changed
      • addedInput schema / properties / domain
        Added value: +{
        +  "description": "Public domain UUID from shieldlabs_list_domains, not the hostname.",
        +  "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / from
        Added value: +{
        +  "format": "date-time",
        +  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +  "type": "string"
        +}
      • addedInput schema / properties / identification_id
        Added value: +{
        +  "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
        +  "type": "string"
        +}
      • removedInput schema / properties / request_id
        Removed value: -{
        -  "description": "Request ID of one identification: the UUID the browser agent returned for the protected action, for example \"02f1d973-84db-4156-a7f7-e799e6bf389b\"",
        -  "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
        -  "type": "string"
        -}
      • removedInput schema / properties / response_format / description
        Removed value: -"Output format: 'markdown' (default) for readable text, 'json' for structured data"
      • addedInput schema / properties / to
        Added value: +{
        +  "format": "date-time",
        +  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
        +  "type": "string"
        +}
      • removedInput schema / properties / wait / description
        Removed value: -"Wait for the verdict when the identification is not stored yet, polling for up to about 10 seconds in total (default true). Use false to read once, for example to read a refined verdict again."
      • changedInput schema / required
        Previous value: -[
        -  "request_id"
        -]New value: +[
        +  "domain",
        +  "identification_id"
        +]
      • addedOutput schema / properties / identification / properties / attributes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "browser": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "connection_type": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "countries": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ]
        +        },
        +        "device_type": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "local_countries": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "type": "string"
        +              },
        +              "maxItems": 100,
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ]
        +        },
        +        "os": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "countries",
        +        "local_countries",
        +        "browser",
        +        "os",
        +        "device_type",
        +        "connection_type"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / identification / properties / band_split
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "dangerous": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "suspicious": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "trusted": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "trusted",
        +        "suspicious",
        +        "dangerous"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • changedOutput schema / properties / identification / properties / browser / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / identification / properties / connection_type / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / identification / properties / cookie_id / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / identification / properties / country
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / identification / properties / created_at
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • removedOutput schema / properties / identification / properties / detection_flags
        Removed value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "abuser": {
        -      "type": "boolean"
        -    },
        -    "anti_detect_browser": {
        -      "type": "boolean"
        -    },
        -    "browser_automation": {
        -      "type": "boolean"
        -    },
        -    "browser_vpn_proxy": {
        -      "type": "boolean"
        -    },
        -    "check_incomplete": {
        -      "type": "boolean"
        -    },
        -    "datacenter_ip": {
        -      "type": "boolean"
        -    },
        -    "incognito": {
        -      "type": "boolean"
        -    },
        -    "ip_mismatch": {
        -      "type": "boolean"
        -    },
        -    "javascript_disabled": {
        -      "type": "boolean"
        -    },
        -    "os_mismatch": {
        -      "type": "boolean"
        -    },
        -    "os_not_detected": {
        -      "type": "boolean"
        -    },
        -    "privacy_relay": {
        -      "type": "boolean"
        -    },
        -    "proxy": {
        -      "type": "boolean"
        -    },
        -    "search_bot": {
        -      "type": "boolean"
        -    },
        -    "stun_not_checked": {
        -      "type": "boolean"
        -    },
        -    "suspicious_paid_click": {
        -      "type": "boolean"
        -    },
        -    "timezone_mismatch": {
        -      "type": "boolean"
        -    },
        -    "tor": {
        -      "type": "boolean"
        -    },
        -    "vpn": {
        -      "type": "boolean"
        -    }
        -  },
        -  "required": [
        -    "vpn",
        -    "privacy_relay",
        -    "browser_vpn_proxy",
        -    "tor",
        -    "proxy",
        -    "datacenter_ip",
        -    "abuser",
        -    "os_mismatch",
        -    "os_not_detected",
        -    "timezone_mismatch",
        -    "anti_detect_browser",
        -    "browser_automation",
        -    "ip_mismatch",
        -    "incognito",
        -    "search_bot",
        -    "suspicious_paid_click",
        -    "javascript_disabled",
        -    "stun_not_checked",
        -    "check_incomplete"
        -  ],
        -  "type": "object"
        -}
      • changedOutput schema / properties / identification / properties / device_id / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / identification / properties / device_id_source
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / identification / properties / device_identity
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "hardware_id": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "hardware_ids": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "maxItems": 100,
        +          "type": "array"
        +        },
        +        "legacy_device_id": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "legacy_device_ids": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "maxItems": 100,
        +          "type": "array"
        +        },
        +        "record_ids": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "maxItems": 100,
        +          "type": "array"
        +        },
        +        "state": {
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • changedOutput schema / properties / identification / properties / device_type / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / identification / properties / domain_id
        Added value: +{
        +  "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
        +  "type": "string"
        +}
      • removedOutput schema / properties / identification / properties / escaped_fields
        Removed value: -{
        -  "description": "Only present when a value contained invisible or control characters: paths of the fields where this server replaced them with visible \\uXXXX or \\u{XXXXX} escapes. Such a value differs from the stored one: do not search by it.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": "array"
        -}
      • addedOutput schema / properties / identification / properties / first_seen
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / identification / properties / high_risk_events
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "as_of": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "items": {
        +          "items": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "code": {
        +                "type": "string"
        +              },
        +              "confidence": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "code",
        +              "confidence"
        +            ],
        +            "type": "object"
        +          },
        +          "maxItems": 100,
        +          "type": "array"
        +        },
        +        "state": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "state",
        +        "as_of",
        +        "items"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / identification / properties / id
        Added value: +{
        +  "maxLength": 512,
        +  "minLength": 1,
        +  "type": "string"
        +}
      • addedOutput schema / properties / identification / properties / identifications
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 9007199254740991,
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / identification / properties / identity_risk
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "device": {
        +          "anyOf": [
        +            {
        +              "anyOf": [
        +                {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "as_of": {
        +                      "type": "string"
        +                    },
        +                    "band": {
        +                      "enum": [
        +                        "trusted",
        +                        "suspicious",
        +                        "dangerous"
        +                      ],
        +                      "type": "string"
        +                    },
        +                    "score": {
        +                      "maximum": 100,
        +                      "minimum": 0,
        +                      "type": "integer"
        +                    },
        +                    "state": {
        +                      "const": "ok",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "state",
        +                    "band",
        +                    "as_of"
        +                  ],
        +                  "type": "object"
        +                },
        +                {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "as_of": {
        +                      "type": "null"
        +                    },
        +                    "band": {
        +                      "type": "null"
        +                    },
        +                    "state": {
        +                      "const": "unavailable",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "state",
        +                    "band",
        +                    "as_of"
        +                  ],
        +                  "type": "object"
        +                }
        +              ]
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ]
        +        },
        +        "ip": {
        +          "anyOf": [
        +            {
        +              "anyOf": [
        +                {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "as_of": {
        +                      "type": "string"
        +                    },
        +                    "band": {
        +                      "enum": [
        +                        "trusted",
        +                        "suspicious",
        +                        "dangerous"
        +                      ],
        +                      "type": "string"
        +                    },
        +                    "score": {
        +                      "maximum": 100,
        +                      "minimum": 0,
        +                      "type": "integer"
        +                    },
        +                    "state": {
        +                      "const": "ok",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "state",
        +                    "band",
        +                    "as_of"
        +                  ],
        +                  "type": "object"
        +                },
        +                {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "as_of": {
        +                      "type": "null"
        +                    },
        +                    "band": {
        +                      "type": "null"
        +                    },
        +                    "state": {
        +                      "const": "unavailable",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "state",
        +                    "band",
        +                    "as_of"
        +                  ],
        +                  "type": "object"
        +                }
        +              ]
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ]
        +        },
        +        "user": {
        +          "anyOf": [
        +            {
        +              "anyOf": [
        +                {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "as_of": {
        +                      "type": "string"
        +                    },
        +                    "band": {
        +                      "enum": [
        +                        "trusted",
        +                        "suspicious",
        +                        "dangerous"
        +                      ],
        +                      "type": "string"
        +                    },
        +                    "score": {
        +                      "maximum": 100,
        +                      "minimum": 0,
        +                      "type": "integer"
        +                    },
        +                    "state": {
        +                      "const": "ok",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "state",
        +                    "band",
        +                    "as_of"
        +                  ],
        +                  "type": "object"
        +                },
        +                {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "as_of": {
        +                      "type": "null"
        +                    },
        +                    "band": {
        +                      "type": "null"
        +                    },
        +                    "state": {
        +                      "const": "unavailable",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "state",
        +                    "band",
        +                    "as_of"
        +                  ],
        +                  "type": "object"
        +                }
        +              ]
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ]
        +        },
        +        "visitor": {
        +          "anyOf": [
        +            {
        +              "anyOf": [
        +                {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "as_of": {
        +                      "type": "string"
        +                    },
        +                    "band": {
        +                      "enum": [
        +                        "trusted",
        +                        "suspicious",
        +                        "dangerous"
        +                      ],
        +                      "type": "string"
        +                    },
        +                    "score": {
        +                      "maximum": 100,
        +                      "minimum": 0,
        +                      "type": "integer"
        +                    },
        +                    "state": {
        +                      "const": "ok",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "state",
        +                    "band",
        +                    "as_of"
        +                  ],
        +                  "type": "object"
        +                },
        +                {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "as_of": {
        +                      "type": "null"
        +                    },
        +                    "band": {
        +                      "type": "null"
        +                    },
        +                    "state": {
        +                      "const": "unavailable",
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "state",
        +                    "band",
        +                    "as_of"
        +                  ],
        +                  "type": "object"
        +                }
        +              ]
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ]
        +        }
        +      },
        +      "required": [
        +        "visitor",
        +        "device",
        +        "user",
        +        "ip"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • addedOutput schema / properties / identification / properties / last_seen
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / identification / properties / local_country
        Added value: +{
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • removedOutput schema / properties / identification / properties / local_ip / additionalProperties
        Removed value: -false
      • removedOutput schema / properties / identification / properties / local_ip / properties
        Removed value: -{
        -  "country": {
        -    "description": "English country name (for example \"Germany\"), or \"\" when unknown",
        -    "type": "string"
        -  },
        -  "ip": {
        -    "description": "Dotted IPv4 address, or \"\" when none is known",
        -    "type": "string"
        -  }
        -}
      • removedOutput schema / properties / identification / properties / local_ip / required
        Removed value: -[
        -  "ip",
        -  "country"
        -]
      • changedOutput schema / properties / identification / properties / local_ip / type
        Previous value: -"object"New value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / identification / properties / observed_at
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "description": "When the identification was observed, RFC 3339 UTC with milliseconds",
        -      "type": "string"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ]
        -}
      • changedOutput schema / properties / identification / properties / os / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / identification / properties / public_ip / additionalProperties
        Removed value: -false
      • removedOutput schema / properties / identification / properties / public_ip / properties
        Removed value: -{
        -  "country": {
        -    "description": "English country name (for example \"Germany\"), or \"\" when unknown",
        -    "type": "string"
        -  },
        -  "ip": {
        -    "description": "Dotted IPv4 address, or \"\" when none is known",
        -    "type": "string"
        -  }
        -}
      • removedOutput schema / properties / identification / properties / public_ip / required
        Removed value: -[
        -  "ip",
        -  "country"
        -]
      • changedOutput schema / properties / identification / properties / public_ip / type
        Previous value: -"object"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / identification / properties / related_counts
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "cookies": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "devices": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "public_ips": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "sessions": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "users": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "visitors": {
        +          "maximum": 9007199254740991,
        +          "minimum": 0,
        +          "type": "integer"
        +        }
        +      },
        +      "required": [
        +        "cookies",
        +        "sessions"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • removedOutput schema / properties / identification / properties / request_id
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / properties / identification / properties / risk
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "as_of": {
        +          "type": "string"
        +        },
        +        "band": {
        +          "enum": [
        +            "trusted",
        +            "suspicious",
        +            "dangerous"
        +          ],
        +          "type": "string"
        +        },
        +        "score": {
        +          "maximum": 100,
        +          "minimum": 0,
        +          "type": "integer"
        +        },
        +        "state": {
        +          "const": "ok",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "state",
        +        "band",
        +        "as_of"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "as_of": {
        +          "type": "null"
        +        },
        +        "band": {
        +          "type": "null"
        +        },
        +        "state": {
        +          "const": "unavailable",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "state",
        +        "band",
        +        "as_of"
        +      ],
        +      "type": "object"
        +    }
        +  ]
        +}
      • removedOutput schema / properties / identification / properties / risk_band
        Removed value: -{
        -  "enum": [
        -    "trusted",
        -    "suspicious",
        -    "dangerous",
        -    "rate_limited"
        -  ],
        -  "type": "string"
        -}
      • removedOutput schema / properties / identification / properties / risk_score
        Removed value: -{
        -  "maximum": 9007199254740991,
        -  "minimum": -9007199254740991,
        -  "type": "integer"
        -}
      • changedOutput schema / properties / identification / properties / session_id / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / identification / properties / signals / additionalProperties
        Added value: +false
      • removedOutput schema / properties / identification / properties / signals / items
        Removed value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "description": {
        -      "anyOf": [
        -        {
        -          "description": "Always null: internal score-detail text is not returned",
        -          "type": "string"
        -        },
        -        {
        -          "type": "null"
        -        }
        -      ]
        -    },
        -    "name": {
        -      "type": "string"
        -    },
        -    "weight": {
        -      "maximum": 9007199254740991,
        -      "minimum": -9007199254740991,
        -      "type": "integer"
        -    }
        -  },
        -  "required": [
        -    "name",
        -    "weight",
        -    "description"
        -  ],
        -  "type": "object"
        -}
      • addedOutput schema / properties / identification / properties / signals / properties
        Added value: +{
        +  "items": {
        +    "items": {
        +      "type": "string"
        +    },
        +    "maxItems": 100,
        +    "type": "array"
        +  },
        +  "state": {
        +    "enum": [
        +      "ok",
        +      "unavailable"
        +    ],
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / properties / identification / properties / signals / required
        Added value: +[
        +  "state",
        +  "items"
        +]
      • changedOutput schema / properties / identification / properties / signals / type
        Previous value: -"array"New value: +"object"
      • removedOutput schema / properties / identification / properties / source
        Removed value: -{
        -  "enum": [
        -    "webhook",
        -    "history"
        -  ],
        -  "type": "string"
        -}
      • addedOutput schema / properties / identification / properties / traffic
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "properties": {
        +        "channel": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "click_id_type": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "entry_url": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "referrer_domain": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "utm_campaign": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "utm_content": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "utm_medium": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "utm_source": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "utm_term": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "channel",
        +        "referrer_domain",
        +        "entry_url",
        +        "click_id_type",
        +        "utm_source",
        +        "utm_medium",
        +        "utm_campaign",
        +        "utm_content",
        +        "utm_term"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ]
        +}
      • removedOutput schema / properties / identification / properties / traffic_source
        Removed value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "channel": {
        -      "type": "string"
        -    },
        -    "click_id_type": {
        -      "type": "string"
        -    },
        -    "landing_url": {
        -      "type": "string"
        -    },
        -    "referrer_domain": {
        -      "type": "string"
        -    },
        -    "utm_campaign": {
        -      "type": "string"
        -    },
        -    "utm_content": {
        -      "type": "string"
        -    },
        -    "utm_medium": {
        -      "type": "string"
        -    },
        -    "utm_source": {
        -      "type": "string"
        -    },
        -    "utm_term": {
        -      "type": "string"
        -    }
        -  },
        -  "required": [
        -    "channel",
        -    "referrer_domain",
        -    "landing_url",
        -    "click_id_type",
        -    "utm_source",
        -    "utm_medium",
        -    "utm_campaign",
        -    "utm_content",
        -    "utm_term"
        -  ],
        -  "type": "object"
        -}
      • removedOutput schema / properties / identification / properties / truncated_fields
        Removed value: -{
        -  "description": "Only present when this server shortened values: paths of the fields cut to 1000 characters as serialized in JSON (100 for risk signal names), and \"signals\" when only the first 50 risk signals are listed. A shortened value is a prefix of the stored one: do not search by it.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": "array"
        -}
      • addedOutput schema / properties / identification / properties / type
        Added value: +{
        +  "enum": [
        +    "identification",
        +    "user",
        +    "visitor",
        +    "device",
        +    "ip"
        +  ],
        +  "type": "string"
        +}
      • removedOutput schema / properties / identification / properties / user_hid / anyOf
        Removed value: -[
        -  {
        -    "description": "User HID as sent by the browser: \"anonymous\" for anonymous checks, null when it was empty",
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / identification / properties / user_hid / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / identification / properties / visitor_id / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / identification / required
        Previous value: -[
        -  "request_id",
        -  "visitor_id",
        -  "device_id",
        -  "session_id",
        -  "cookie_id",
        -  "user_hid",
        -  "domain",
        -  "public_ip",
        -  "local_ip",
        -  "connection_type",
        -  "os",
        -  "browser",
        -  "device_type",
        -  "traffic_source",
        -  "risk_score",
        -  "risk_band",
        -  "signals",
        -  "detection_flags",
        -  "observed_at",
        -  "source"
        -]New value: +[
        +  "type",
        +  "id",
        +  "domain_id",
        +  "domain",
        +  "risk",
        +  "signals"
        +]
    • Addedshieldlabs_list_history
    • Removedshieldlabs_search_history
    • Removedshieldlabs_summarize_entity
    • Changedshieldlabs_verify_webhook_signature1 field changed
      • changedOutput schema / properties / event / anyOf
        Previous value: -[
        -  {
        -    "additionalProperties": false,
        -    "properties": {
        -      "created_at": {
        -        "type": "string"
        -      },
        -      "event_type": {
        -        "type": "string"
        -      },
        -      "request_id": {
        -        "anyOf": [
        -          {
        -            "description": "Request ID of an identification.scored event",
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ]
        -      },
        -      "risk_band": {
        -        "anyOf": [
        -          {
        -            "enum": [
        -              "trusted",
        -              "suspicious",
        -              "dangerous",
        -              "rate_limited"
        -            ],
        -            "type": "string"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ]
        -      },
        -      "risk_score": {
        -        "anyOf": [
        -          {
        -            "maximum": 9007199254740991,
        -            "minimum": -9007199254740991,
        -            "type": "integer"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ]
        -      },
        -      "schema_version": {
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "event_type",
        -      "schema_version",
        -      "created_at",
        -      "request_id",
        -      "risk_score",
        -      "risk_band"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "additionalProperties": false,
        +    "properties": {
        +      "created_at": {
        +        "type": "string"
        +      },
        +      "event_id": {
        +        "anyOf": [
        +          {
        +            "description": "Signed event_id when the delivery includes one",
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "event_type": {
        +        "type": "string"
        +      },
        +      "identification_id": {
        +        "anyOf": [
        +          {
        +            "description": "Identification ID of an identification.scored event.",
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "risk_band": {
        +        "anyOf": [
        +          {
        +            "enum": [
        +              "trusted",
        +              "suspicious",
        +              "dangerous",
        +              "banned_ip"
        +            ],
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "risk_score": {
        +        "anyOf": [
        +          {
        +            "maximum": 9007199254740991,
        +            "minimum": -9007199254740991,
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "schema_version": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "event_type",
        +      "schema_version",
        +      "created_at",
        +      "event_id",
        +      "identification_id",
        +      "risk_score",
        +      "risk_band"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
  2. 6 tool updatesv1.0.0
    • First observedshieldlabs_current_time
    • First observedshieldlabs_explain_risk_score
    • First observedshieldlabs_get_identification
    • First observedshieldlabs_search_history
    • First observedshieldlabs_summarize_entity
    • First observedshieldlabs_verify_webhook_signature

TDQS

A3.7/5.0

Scored across 6 tools

Disambiguation3/5

While all tools have distinct prefixes and functions, there is some overlap between list_history, get_identification, and get_history. An agent might confuse which specific getter tool to use depending on the granularity of the required record.

Naming Consistency5/5

All tool names strictly adhere to the shieldlabs_verb_noun pattern. The use of snake_case is uniform across the entire set, making the set highly predictable and easy to parse.

Tool Count5/5

The 6 tools are well-scoped and earn their place. They successfully cover the core functionalities needed for a data-heavy security/risk information retrieval service.

Completeness2/5

The tool set is critically incomplete as it lacks any mutation capabilities. The entire surface appears read-only, missing essential CRUD operations (create, update, delete) for the identified entities.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Lets an AI agent read a Pyxis dashboard's analytics — overviews, funnels, devices, acquisition, backend requests, visits and project settings — using a read-only access token created by an admin and revocable at any time. It runs locally over stdio, holds no state, and exposes only GET-style reads of the live Pyxis API.
    16
    1,507 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Exposes read-only local analysis tools for source auditing, web traffic review, binary reverse engineering, exploit scaffolding, OSINT, and reporting via JSON-RPC over stdio, enabling LLMs to orchestrate evidence-based security workflows without executing targets or sending network requests.
    1
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to perform internet-facing reconnaissance and vulnerability research by looking up open ports, banners and TLS details for IPs, searching devices with Shodan query syntax, resolving DNS records in batch, and retrieving CVE/CPE intelligence with CVSS, EPSS and KEV status. Tools are read-only, credit-aware, and exposed over stdio or HTTP streaming.
    MIT
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to query traces, sessions, exceptions, prompts, datasets, scores, and metrics for enhanced debugging and observability. Supports local stdio or HTTP deployment, selective tool loading, and read-only mode.
    -