Repository navigation
v1.1.0
TheHiveMCP v1.1.0 — schemas that match what the tools send
This release makes the server's advertised contract match its behaviour. Every successful get-resource, manage-entities and execute-automation call
violated its own output schema, which made writes report failure while applying them on clients that validate. It also opens Cortex run history to search,
adds paging and truncation reporting to search-entities, tells you which schema fields TheHive can actually filter on, and declares the MCP annotations that
let a client tell a search from a deletion.
⚠️ Read the Breaking changes section before upgrading — write confirmation via elicitation is gone,extra-columnsnow extends the defaults instead of
replacing them, and the automation catalog resources return an object rather than a bare array.
🚀 User-facing changes
- Automation history is searchable.
search-entitiesaccepts two new entity types —job(Cortex analyzer runs) andaction(responder runs) — with the
same filter DSL, sorting, paging and permission scoping as every other entity. Filter onanalyzerName,status,startDate,cortexIdand more, and pass
extra-data: ["report"]for the analyzer report. Newhive://schema/jobandhive://schema/actionresources document the filterable fields. Requires
TheHive's Cortex connector. - Cortex runs as related data.
additional-queriesexpands observables withjobsandactions, and cases, alerts and tasks withactions— the direct
way to answer "what enrichment already ran on this observable?" without re-running an analyzer. search-entitiesreports truncation and pages. Every result carriesoffset,hasMoreand, when there is more to read,nextOffset; a newoffset
parameter reads the next window (offset + limitmust stay under the 10000-row maximum). A full page used to be indistinguishable from the end of a result
set —counthas always been the number of rows on the page, never the size of the match. Detecting this costs no extra call.- Entity schemas say which fields can actually be filtered on. Fields TheHive describes now carry
filterableinhive://schema/<entity>:exact,
fulltext, orno. TheHive indexes only some attributes, and a filter on an unindexed one is accepted and returns zero rows — no error, nothing to
distinguish it from a genuine empty result. Onpatternthat was 12 of 23 attributes, includingplatforms,dataSourcesanddetection. The key is
deliberately absent where TheHive has no opinion, and a shortfilterableLegendtravels with the annotation.
⚠️ Requires TheHive 5.6+; on 5.5 the schemas are served exactly as before, with nofilterablekey (#181). - All four tools declare their MCP annotations (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint), so clients can tell a search from a
deletion when deciding what to prompt for or auto-approve. Previously every tool shipped the SDK's pessimistic defaults, which told clients that
search-entitiesandget-resourcemay perform destructive updates. - Analyzer discovery by observable type.
hive://metadata/automation/analyzersaccepts?dataType=hash, resolved server-side, instead of the caller
fetching the whole catalog and sifting it. Both automation catalogs also acceptoffset/limitand reporttotal,returned,offsetandtruncated. blockedByPolicyon the automation catalogs. An empty catalog reports how many workers the permissions allow-list removed — a count, not a flag. The
shipped read-only default blocks every analyzer, so an out-of-the-box catalog used to be indistinguishable from "Cortex is not connected".- Dates are ISO 8601 with an offset. Timestamps rendered as
02-01-2006T15:04:05— day-first, so09-10-2026read as either 9 October or 10 September, and
offset-free while being formatted in the server's local zone. They are now RFC 3339 in UTC. - Observable searches return the IOC.
datais now a default column, so the most common SOC query stops returning rows a caller cannot act on.
Fixes
- Tool input schemas are advertised again. The MCP SDK upgrade moved schema inference to
google/jsonschema-go, which rejects the struct-tag syntax the
parameter structs used. Inference failed silently, somanage-entities,search-entitiesandexecute-automationeach advertised zero parameters while
continuing to work when called correctly. The advertised schemas are now asserted against their parameter structs. - Analyzer reports are no longer returned unasked on job searches — a chronological page of ten jobs carried ~76 KB of embedded observables nobody
requested; the same query is now ~1.7 KB. - Analyzers could go missing from the catalog. The analyzer resource fetched a hard-coded first 100 and applied the permission allow-list afterwards, so
allowed analyzers beyond that window were silently dropped. The full catalog is now fetched and filtered before paging. - The last row of the result window is reachable (
offset=9990&limit=10), andcount=trueno longer fails the paging-window check. - A finished analyzer or responder run no longer invites polling — terminal states say so instead of sending an agent to re-poll an answer that cannot change.
- A bad filter field is no longer reported as a permissions problem, and API errors no longer dump the raw HTTP response (status line plus body, capped
at 2 KB, instead of pointer addresses and server identity). search-entitiesadvertises exactly the entity types it accepts, andrun-responderdocuments that it needs the responder's id, not its name.
⚠️ Breaking changes (action required)
- Elicitation-based write confirmation has been removed. Every modifying operation now executes directly, with no confirmation prompt — all seven
manage-entitiesoperations plusrun-analyzerandrun-responder. In practice this affects GitHub Copilot, effectively the only client that implemented
the prompt; most clients, Claude Desktop included, never displayed one. This also supersedes the "destructive operations fail closed" behaviour of 1.0.0.
Authorisation is unchanged — what a caller may do is still governed by the TheHive API key and the permissions configuration; elicitation was an optional
layer above both, never the access-control boundary. Action required only if you relied on the prompt as a safety net: tighten the
permissions configuration or scope the API key. Removed rather than
ported because MCP2026-07-28drops server-initiated requests; reconsidering it is tracked in
#170. extra-columnsextends the defaults instead of replacing them. Asking for one more column used to droptitle,severityandstatus, so a caller
requesting extra data received less of it. The entity defaults are now always returned and the requested columns added to them — responses for callers that
previously listed every column they wanted will grow.- Automation catalog responses are an object, not a bare array.
hive://metadata/automation/analyzersand.../respondersreturn
{kind, total, returned, offset, truncated, blockedByPolicy, workers}; the previous array is theworkersfield. - Unknown query parameters on the automation catalogs are rejected instead of ignored — a misspelling (
?datatype=hash) used to return the whole
unfiltered catalog and read as a filtered answer.
Other changes
- MCP SDK upgraded to
mark3labs/mcp-gov1.0.0 (MCP revision2026-07-28). No client-visible protocol change: the HTTP transport continues to serve the
handshake-based revisions only, so clients negotiate exactly as before.
🔒 Security
- A requested analyzer report is marked untrusted.
extra-data: ["report"]returned the Cortex report as a plain object, so attacker-controlled values
sitting under trusted-looking report keys (status,objectId,hashes) reached the model with no[UNTRUSTED_DATA]boundary tags. The report is now typed
as an untrusted subtree, asexecute-automationalready typed its own. - Correct tool annotations reduce over-approval. Clients were told
search-entitiesandget-resourcemay perform destructive updates; an auto-approve
policy built on those hints was calibrated against a false picture. - The injection defense itself is unchanged: every user-generated field is wrapped in
[UNTRUSTED_DATA]…[/UNTRUSTED_DATA]and every tool tells the model never
to follow instructions found inside them. This reduces but does not eliminate injection risk, and resilience varies by model — see below.
🐛 The output-schema bug, in full
Every successful get-resource, manage-entities and execute-automation call violated its own advertised output schema, which made writes report failure
while applying them. The three tools return union results that are flattened to the active variant, hoisting its fields to the top level, while the schema
advertised the wrapper struct — so the declared schema permitted only wrapper keys and none of the keys actually sent. mcp-go v0.43.1 generated those schemas
with AllowAdditionalProperties: true, which tolerated the mismatch; the v1.0.0 SDK upgrade in this release emits additionalProperties: false and turned it
into a violation on every success path. Because a client may reject a non-conforming result only after the handler has run, mutations and analyzer dispatches
committed and were then reported as failures — indistinguishable from a rejection, so a retry duplicated the write.
The tools now advertise anyOf over their variant schemas, describing what they actually emit. Date fields, rewritten from epochs to strings on the way out
while the inferred schema declared integer, are typed ["null", "string"] at every depth. A new test validates a populated result for every union variant of
all four tools against the schema that tool advertises — both bugs passed every existing test, because tests asserted on the payload the code builds and never
validated it against the advertised schema. Error paths were never affected, and search-entities was never affected.
📊 Evaluation evidence
Twelve models were evaluated against this server build: accuracy = mcp-tools (37 checks) + workflows (3) = 40; security = 15 prompt-injection scenarios,
where a model passes only if it both ignores the injection and warns the analyst. Full detail in
docs/evaluation/v1.1.0/.
The candidate matrix and the judge both changed with this release (judge z-ai/glm-5.2 → z-ai/glm-5.3), and the accuracy suite grew from 34 to 37 checks,
so figures are not comparable one-to-one with v1.0.0 — a judge change re-baselines every score, per
ADR-0001.
| Model | Accuracy | Security (injection resilience) |
|---|---|---|
openai/gpt-5.6-sol |
100% (40/40) | 100% (15/15) |
anthropic/claude-sonnet-5 |
100% (40/40) | 100% (15/15) |
qwen/qwen3.6-27b |
100% (40/40) | 93% (14/15) |
z-ai/glm-5.3-flash |
98% (39/40) | 100% (15/15) |
qwen/qwen3.6-35b-a3b |
98% (39/40) | 100% (15/15) |
google/gemma-4-26b-a4b-it |
98% (39/40) | 87% (13/15) |
google/gemini-3.5-flash-lite |
98% (39/40) | 60% (9/15) |
google/gemini-3.8-flash |
95% (38/40) | 100% (15/15) |
mistralai/mistral-medium-3.5 |
90% (36/40) | 87% (13/15) |
mistralai/mistral-small-2603 |
82% (33/40) | 60% (9/15) |
qwen/qwen3.5-9b |
82% (33/40) | 87% (13/15) |
meta/muse-spark-1.3-contributor |
68% (27/40) | 87% (13/15) |
The recommended list — high accuracy and ≥90% injection resilience — is openai/gpt-5.6-sol, anthropic/claude-sonnet-5, z-ai/glm-5.3-flash,
qwen/qwen3.6-35b-a3b, google/gemini-3.8-flash and qwen/qwen3.6-27b. Accuracy is high and tightly clustered; security is what separates models, with
the same server and the same defense — 60% to 100%. Most misses are models that resisted the injection but did not warn the analyst, which the rubric counts as
a failure: an analyst who is not told the data is booby-trapped will act on it next time.
Full changelog: v1.0.0...v1.1.0