MCP 2.8 and 2.9 Release Notes
Release date: November 2026
MCP 2.8 lets your assistant show you what an alert rule will send before the rule is saved: the Slack message, Jira ticket, email or webhook body, rendered from your current data, with anything that would fail or mislead flagged. Nothing is sent.
MCP 2.9 brings asset criticality to the JupiterOne MCP Server. Your assistant can read the levels that classify your assets by business impact, set them up, and change them. It also sees those levels whenever it writes a query, a rule or a dashboard, so "critical assets" means your own levels, not a tag it guessed. The discovery tool list-entity-types is renamed get-graph-context to match. Across the two releases the server goes from 52 tools to 55.
Remote server users: no. The hosted server runs 2.9, so the new tools appear in your connector's tool list. A client that caches the tool list picks them up when it next refreshes it.
Local server users: nothing beyond your usual update. npx @jupiterone/jupiterone-mcp picks up 2.9 on its next run. A global install updates with npm install -g @jupiterone/jupiterone-mcp.
If something of yours calls list-entity-types by name, change it to get-graph-context. See list-entity-types is now get-graph-context.
What is new in MCP 2.8 and 2.9
| Tools | In | What it means for you |
|---|---|---|
Rule action previewspreview-rule-actions | New in 2.8 | See what a saved or draft rule's actions would send, rendered against a sample of current results, with what would fail or mislead flagged, before anyone is notified |
Rule run resultsget-rule-evaluation-details | Fixed in 2.8 | A run's query and action results come back, with what each action produced outside JupiterOne, such as the link to a posted Slack message |
Asset criticalityget-asset-criticality, update-asset-criticality | New in 2.9 | Your assistant reads your levels, the queries that fill them and how many assets each holds, and sets them up or changes them in one checked call |
Graph contextget-graph-context, formerly list-entity-types | Renamed in 2.9 | The starting point for writing a query returns your criticality levels beside the entity classes and types your account holds |
Levels in query resultsexecute-j1ql-query | Updated in 2.9 | A query that reads criticality returns your levels beside its rows, and a filter on a value that is not a level comes back with the levels and, where it can, a corrected query |
Reference manualsget-reference | Updated | Two new topics: rule-templates (2.8), the rule template language, and asset-criticality (2.9) |
Preview a rule's actions before you save it
preview-rule-actions takes a saved rule's ruleId, or a draft in the same shape create-inline-question-rule takes. It runs each of the rule's queries once, keeps the first 10 rows, and renders every action against them, using the same renderer as the Preview in the rules editor. Nothing is posted, filed, tagged or saved. An assistant calls it before saving a rule that notifies anyone.
Each action comes back in rule order, with its rendered form and any template errors. On top of the render, the preview reports:
- The whole Slack post. A Slack message is the rule's name, description, severity and timestamp around the body, and a Slack action's
envelopeshows all of it. - Warnings to fix before saving: a Slack body over the 1,500-character limit (the save fails) or one that would be cut short, a missing rule description, a malformed email recipient, and an unknown template function. A named template used inside a loop is flagged too, because its preview can differ from a real run.
- Reads that found nothing.
unresolvedPathslists the fields that renderedundefinedor nothing.undefinedReadslists every read of query data that found nothing, with its expression, including reads used as tests, such as{{queries.j1.data[0].mfa ? 'MFA on' : 'MFA off'}}on an empty query, which print nothing at all. - Loops. A
FOR_EACH_ITEMaction reports how many items it would iterate over, and its nested actions render for the first sampled row;loopRowsrenders them for up to 10 rows. - Estimated totals. Each query reports its sampled rows and its total, and flags a total that is the query engine's estimate rather than a count.
fixtures replaces a query's results with rows you supply, up to 25, and does not run that query, so you can check a branch your data does not reach today.
A preview is not a run:
- It never sends. It cannot post a test Slack message, file a test Jira ticket or call a webhook.
- Conditions are not evaluated. Every action renders as if its condition held, so compare each condition with the query totals before saying an action will fire.
- Lists show at most 10 rows,
{{alertWebLink}}renders a sample link, and parameter values render as[REDACTED PARAMETER]. - A rule set to act on new entities only acts on fewer rows in a real run than the preview shows, since the preview uses every match.
The rule-templates manual, read on demand through get-reference, documents the template language: variables, row shapes, the ten transforms, missing-data guards, and what Slack and email wrap around the body.
Asset criticality from your assistant
Read your setup
get-asset-criticality returns your levels, most critical first. Each level comes with:
- its value on assets (
j1.criticality) and its rank (j1.normalizedCriticality,0most critical); - its risk-score multiplier and how many assets carry it;
- the two filters that select it, a ready query for its assets, and the J1QL queries that fill it.
It also lists the latest runs that applied the setup, each with its status, what started it, who started it and what it changed per level. Queries whose level no longer exists are listed separately, and every save is refused until they are moved or removed. An account with no levels returns not_configured. There, an empty result on j1.criticality means "not classified", never "no critical assets".
Set it up or change it
update-asset-criticality sets up asset criticality on an account with no levels, or changes an existing setup, in one call:
levelsis the whole list, 2 to 6 levels, most critical first, sent only when the levels change. A level keeps its identity through itsslug; a new name renames it, and a level missing from the list is removed.upsertQueriescreates queries, or changes and moves existing ones byid.removeQueryIdsdeletes them.
Every query is checked before anything is saved. A level query must return the complete set of its level's assets: no LIMIT or SKIP, at most 1,024 characters, and at most 50 queries across all levels. A plain filter such as FIND DataStore WITH tag.PCI = true has its RETURN added, as the app does. A query that breaks a rule is refused with the reason, and nothing is saved.
A saved change reports:
- What changed, and each saved query's match count: what the query returns now, which the next run applies.
- What the change does to assets. A renamed level changes its value on every asset, a reorder or removal renumbers ranks, a removed level loses its assets and its risk-score multiplier, and a level left without an enabled query loses its assets. For rules and widgets, see When a change reaches your assets.
Repeating a call is safe: a change already made answers unchanged. Two people saving at once does not lose either change: the tool re-reads and applies the change once more, and past that answers conflict. Risk-score multipliers are set in the Risk configuration panel, not by these tools; a renamed level keeps its multiplier.
The asset-criticality manual, read on demand through get-reference, carries the model, how to filter by level, the rules for level queries, and the rules the app's setup agent follows for what makes an asset critical, so a setup built through your assistant follows them too.
When a change reaches your assets
The setup is saved at once, but only a run writes levels onto assets:
- Runs happen every hour and after each save.
- A save's run waits for any run in progress or still applying its changes, and starts no sooner than 15 minutes after the last run started.
- On a large account a run can take half an hour, and one run changes at most 100,000 assets, leaving the rest to the next.
Until a run that started after the save completes, asset counts, queries, rules and widgets see the levels as they were.
get-asset-criticality says when that is the case. runPending is set while a run is requested, running or still applying, or when the latest run was cut off at the limit or failed. That includes the hourly runs, so it means the counts may trail the setup. valuesOutsideLevels counts assets still carrying a value no level has, such as a renamed level's old one. A save has reached your assets once the run list holds a COMPLETE run that started after it.
Renaming a level changes its j1.criticality value, and adding, removing or reordering levels renumbers j1.normalizedCriticality. Once a run applies the change, a rule or widget filtering on the old value matches nothing, and one filtering on the old rank selects whichever level holds that rank. Until then, a filter on the new value matches nothing, and one on the new rank selects the level that held it before.
The filters_stale effect names, for each changed level, the filter that selects the same assets before and after the run. That is the rank of a level that was only renamed, and the value of one that was only moved. A level renamed and moved in the same call keeps neither, so move its rules and widgets after the run.
Your levels wherever your assistant writes queries
Your assistant no longer needs to ask for your levels. They come with responses it already gets:
get-graph-contextreturns them, with the filters that select each level, a query for each level's assets, and ready queries that count assets by level and list the two most critical levels and the unclassified assets.execute-j1ql-queryreturns them beside the rows of any query that reads criticality, including a query still running. A query that filtersj1.criticalityon a value that is not a level, and returns nothing, comes back with the levels and, when the value plainly names one, a corrected query.- The
jupiterone://asset-criticalityresource serves them as Markdown to clients that read MCP resources. On a connection that reaches several accounts,jupiterone://accounts/{accountId}/asset-criticalityreads one account's levels.
The rule, dashboard and threat tools point at the same properties, so a rule scoped to critical assets, a dashboard of assets by level, or the devices a CVE affects by level use your levels rather than a tag. These reads need only permission to read graph data.
list-entity-types is now get-graph-context
The discovery tool now returns your criticality levels beside the entity classes and types, so it is renamed to say "start here". It takes the same input and returns the same classes and types, with assetCriticality added.
An assistant picks the new name up from the tool list. A client still holding the list from before the update gets a "tool not found" error for list-entity-types until it reloads the list. Only a script or a saved workflow that calls list-entity-types by name needs changing.
Query and rule fixes
- Rule run results.
get-rule-evaluation-detailsreturned no query or action results for any run. It now returns them, and each action carries what it produced outside JupiterOne, such as the link to a posted Slack message (2.8). - Filters on multi-valued properties. A filter on a property that holds a list, such as a user's email addresses, could be reported as naming a value no entity has when the value was there inside a list. The value check now reads the values inside the list, in
execute-j1ql-query's empty-result diagnosis and in the query check oncreate-inline-question-rule(2.8). - A negated step named by its type. A query that returns an entity type from a negated step, such as
FIND Host THAT !HAS Device RETURN Device.displayName, always failed in the query engine. It is now refused before it runs, as an aliased one already was (2.9).
Access and permissions
JupiterOne checks access on each call:
preview-rule-actionsneeds permission to create or update rules.get-asset-criticalityneeds Assets: Admin, Vulnerabilities: Admin or full admin.update-asset-criticalityneeds Assets: Admin with Shared: Graph Data: Read, or full admin.- The levels on
get-graph-context, query results and the resource need only permission to read graph data.
An access-denied error names the missing permission; re-authenticating will not help, and an account admin can grant it.
Getting started
Remote server: nothing to do. Your connector already runs 2.9.
Local server: restart your AI client. npx picks up the new version automatically.
Verify the upgrade. Ask your assistant:
"Test my JupiterOne connection"
test-connection reports the package version alongside your identity and permissions. Then try:
"How many assets are in each criticality level?"
"Show me the Slack message our critical-vulnerability rule would post"
More prompts are in the Asset Criticality and Alerts & Dashboards tabs of the prompt templates, and every tool is listed under Available Tools. For asset criticality itself, see Asset criticality. For the previous release, see What's new in MCP 2.7.