Skip to main content

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.

Do I need to do anything?

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​

ToolsInWhat it means for you
Rule action previews
preview-rule-actions
New in 2.8See 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 results
get-rule-evaluation-details
Fixed in 2.8A 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 criticality
get-asset-criticality, update-asset-criticality
New in 2.9Your 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 context
get-graph-context, formerly list-entity-types
Renamed in 2.9The starting point for writing a query returns your criticality levels beside the entity classes and types your account holds
Levels in query results
execute-j1ql-query
Updated in 2.9A 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 manuals
get-reference
UpdatedTwo 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 envelope shows 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. unresolvedPaths lists the fields that rendered undefined or nothing. undefinedReads lists 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_ITEM action reports how many items it would iterate over, and its nested actions render for the first sampled row; loopRows renders 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, 0 most 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:

  • levels is the whole list, 2 to 6 levels, most critical first, sent only when the levels change. A level keeps its identity through its slug; a new name renames it, and a level missing from the list is removed.
  • upsertQueries creates queries, or changes and moves existing ones by id. removeQueryIds deletes 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-context returns 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-query returns them beside the rows of any query that reads criticality, including a query still running. A query that filters j1.criticality on 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-criticality resource serves them as Markdown to clients that read MCP resources. On a connection that reaches several accounts, jupiterone://accounts/{accountId}/asset-criticality reads 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-details returned 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 on create-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-actions needs permission to create or update rules.
  • get-asset-criticality needs Assets: Admin, Vulnerabilities: Admin or full admin.
  • update-asset-criticality needs 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.