MPS Intentions Aspect
SkillDev toolsUse when defining or editing MPS intentions (the Alt+Enter context-action aspect) — adding `IntentionDeclaration` roots, parameterized or surround-with variants, description/isApplicable/execute blocks, child-filter functions, factory-initialized AST splicing, or debugging why an intention is not offered. Lives in the language's `intentions` model and uses `jetbrains.mps.lang.intentions`.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the MPS Intentions Aspect skill
What this skill tells your AI
The instructions your AI receives, as published by jetbrains/mps in .agents/skills/mps-aspect-intentions/SKILL.md and read by ahel’s review.
Intentions are user-invoked transformations shown in the Alt+Enter popup on a node. They are the canonical way to offer optional refactorings (wrap, convert, introduce, preview) alongside quick-fixes. Authoring lives in <lang>/languageModels/intentions.mps, language jetbrains.mps.lang.intentions.
Critical Directives
- Edit intention roots through MPS MCP tools (
mps_mcp_insert_root_node_from_json,mps_mcp_update_node,mps_mcp_parse_java_and_insert). Do not hand-edit serialized.mpsfiles. - The intentions model must list every language used in any block body as a used language. In particular, the
add new initialized(...)surface syntax requiresjetbrains.mps.lang.actions— add it withmps_mcp_model_used_language(kind="language"). Plain (non-NF_*) variants likeparent.role.add new(C)do not need this import. - Use
n as C(MPSSNodeTypeCastExpressionwithasCast=true) — never a Java(C) ncast. - Use
:eq:(NPEEqualsExpression) instead of==whenever either operand might benull. - The execute body runs on the EDT inside an MPS write action automatically — do not spawn threads or open dialogs that block.
descriptionFunctionruns every time the Alt+Enter popup opens — keep it cheap.- After editing, validate with
mps_mcp_check_root_node_problemson the intention root and rebuild the language before testing.
Common-Path Workflow
- Ensure an
intentionsmodel exists in the language (create withmps_mcp_create_modelandmodelName: "<lang>.intentions"— aspect IDintentions, case-sensitive, no@suffix; see aspect-model-stereotypes.md). Used languages:jetbrains.mps.lang.intentions; addjetbrains.mps.lang.actionsif you will use factory-initialized splicing. - Insert an
IntentionDeclarationroot withmps_mcp_insert_root_node_from_json(see blueprint inreferences/json-blueprints.md). Setname,forConcept, andisAvailableInChildNodesif the popup should bubble from descendants. - Fill
descriptionFunction(returns a short label String),executeFunction(the transformation), and optionallyisApplicableFunction(gate predicate) andchildFilterFunction(per-descendant filter whenisAvailableInChildNodes=true). - For multiple menu entries per blueprint use
ParameterizedIntentionDeclarationwithparamType+queryFunction; useIntentionParameterwherever you want "the current value" inside other blocks. - For wrap-the-selection transforms use
SurroundWithIntentionDeclarationand readeditorContext.getSelectedNodes(). - Validate (
mps_mcp_check_root_node_problems), rebuild the language, exercise via Alt+Enter on a sandbox instance. Headlessly: after MAKE, callmps_mcp_list_node_intentionson a sandbox node to confirm the intention is registered and shows the expected description, thenmps_mcp_apply_intention(nodeReference = <the entry's targetNode>, intentionId = <the entry's id>)to smoke-testexecuteFunction(for parameterized declarations also pass the rowdescription). Surround-with intentions are not covered by these tools.
Implicit parameters available in every block
| Alias | FQN | Where |
|---|---|---|
node | jetbrains.mps.lang.intentions.structure.ConceptFunctionParameter_node | All blocks; typed as forConcept. In ChildFilterFunction this is the nearest enclosing forConcept ancestor. |
editorContext | jetbrains.mps.lang.sharedConcepts.structure.ConceptFunctionParameter_editorContext | All blocks; the current EditorContext. |
childNode | jetbrains.mps.lang.intentions.structure.ConceptFunctionParameter_childNode | Only inside ChildFilterFunction; the descendant under the cursor. |
parameter (IntentionParameter) | jetbrains.mps.lang.intentions.structure.IntentionParameter | Only inside ParameterizedIntentionDeclaration blocks; resolves to the current queried value. |
Related Skills
mps-aspect-actions— when the intention needs factory-initialized children, the NodeFactories live there.mps-aspect-constraints— for gating that should apply everywhere (not just Alt+Enter), prefer can-be rules overisApplicable.mps-aspect-editor-menus-and-keymaps— when the action belongs on a substitute/transformation menu or a keystroke, not in the Alt+Enter popup.mps-model-manipulation— full smodel/baseLanguage/collections reference; covers theNF_*family and the dualIsEmptyOperation.mps-node-editing— MCP recipes for inserting children, updating references, and staged construction.mps-aspect-structure-concepts— when adding the concept thatforConcepttargets.mps-quotations— when the execute body builds a complex subtree literal.mps-tests→EditorTestCase— for testing that an intention is offered and produces the expected tree.
Reference Index
- Open
references/blocks-and-parameters.mdwhen wiringdescriptionFunction,isApplicableFunction,executeFunction, orchildFilterFunction, or when you need to look up the implicit parameter concept FQNs for any of them. - Open
references/execute-idioms.mdwhen writing anexecuteFunctionbody — typical AST-editing operations (insert sibling, isInstanceOf, asCast, list add, select-in-editor), the verbatimWrapInParensandAddOnEntryexamples, the attach-an-annotation (node attribute) idiom (forConcept = BaseConcept+ context-gatedisApplicable,.@role.add(...)vs.@Mark = ...), and theSelectInEditorOperationJSON shape live there. - Open
references/factory-initialized.mdwhen anexecuteFunctionallocates new nodes and you want the concept's NodeFactory to seed defaults — theNF_*family table, theadd new initialized(<default>)semantics, and the used-language requirement live there. - Open
references/parameterized-intentions.mdwhen authoring or debugging aParameterizedIntentionDeclaration—paramType+queryFunctionsemantics,IntentionParameterusage, the per-valueisApplicableFunctionfilter, and the fullSetCardinalityToexample and JSON skeleton are there. - Open
references/surround-and-child-filter.mdwhen authoring aSurroundWithIntentionDeclarationor when configuringisAvailableInChildNodes+ aChildFilterFunction— verbatimWrapInParensandAddOnEntry.childFilterFunctionwalk-throughs are there. - Open
references/json-blueprints.mdwhen inserting an intention root viamps_mcp_insert_root_node_from_json— minimal blueprints forIntentionDeclaration,ParameterizedIntentionDeclaration, andSurroundWithIntentionDeclarationand the validated concept-reference table. - Open
references/common-failures.mdwhen an intention does not appear, fires on the wrong node, leaves the caret in the wrong place, or shows duplicates — the symptom/cause/fix table is there.
Signals
- GitHub stars
- 2k
- Forks
- 309
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
mps-aspect-intentions- Source
- github.com/jetbrains/mps