MPS offers the API to create concept declarations programmatically. This may come in handy when writing an importer or a converter, for example. However, it may not always be clear what API to use.

Here is how you create a concept from code:

public class AddConcept { 
    
    public static node<ConceptDeclaration> addConcept(SRepository repo, model-ptr structureModel, string conceptName) { 
    node<ConceptDeclaration> decl = new initialized node<ConceptDeclaration>(); 
    decl.name = conceptName; 
        
    node<PropertyDeclaration> prop = decl.propertyDeclaration.add new initialized(<default>); 
    prop.name = "myproperty"; 
    prop.dataType.set ptr(string); 
        
    node<LinkDeclaration> ref = decl.linkDeclaration.add new initialized(<default>); 
    ref.name = "reference"; 
    ref.metaClass = enum member value/LinkMetaclass : reference/; 
    ref.sourceCardinality = enum member value/Cardinality : 0..1/; 
    ref.target = decl; 
        
    node<LinkDeclaration> children = decl.linkDeclaration.add new initialized(<default>); 
    children.name = "children"; 
    children.metaClass = enum member value/LinkMetaclass : aggregation/; 
    children.sourceCardinality = enum member value/Cardinality : 0..n/; 
    children.target = decl; 
        
    return structureModel.resolve(repo).add root(decl); 
    } 
}

The simplest way to test this code is to use the MPS Console. Call the method as follows:

AddConcept.addConcept(#project.getRepository(), model-ptr/my.existing.language.structure/, "MyTree")

What you should get is a concept declaration looking like this:

concept MyTree extends BaseConcept
               implements <none>

  instance can be root: false
  alias: <no alias>
  short description: <no short description>

  properties:
  myproperty : string

  children:
  children : MyTree[0..n]
  
  references:
  reference : MyTree[0..1]

A few comments on the code: to use the new initialized node construct you need to import the jetbrains.mps.lang.actions language. It calls node factories defined on the given concept. the node factories set up the necessary internal MPS IDs so that we don’t have to do this explicitly for concept, property and link declarations.

You can read more about node factories in the MPS documentation.