Elements

Version 0.2.0 of the specification.

5. Elements

An element is one thing the app shows: the app itself, a window, a document, a list, a row in it, a run of text. Everything a provider reports is an element, and the elements form one tree rooted at the app. Containment in the tree says how things relate: selected words are inside the comment they were selected in, which is inside its thread, which is inside its pane.

A notes-and-threads app with words selected inside a comment, and a second thread in another pane:

{
  "protocol": "0.2.0",
  "instance": "k3f9x2",
  "root": {
    "id": "app", "role": "Application", "title": "Example",
    "children": [
      { "id": "w-1", "role": "Window", "subrole": "pane", "focused": true, "children": [
        { "id": "th-2", "role": "List", "subrole": "thread", "title": "Launch plan", "focused": true, "children": [
          { "id": "c-3", "role": "Row", "subrole": "comment", "title": "Comment by Ada", "focused": true, "children": [
            { "id": "sel-4", "role": "Text", "selected": true,
              "content": [{ "type": "text", "text": "what it shows" }] }
          ] }
        ] }
      ] },
      { "id": "w-2", "role": "Window", "subrole": "pane", "children": [
        { "id": "th-7", "role": "List", "subrole": "thread", "title": "Budget" }
      ] }
    ]
  }
}

5.1 — Fields

FieldTypeRequiredMeaning
idstringyesOpaque. 1 to 128 characters: letters, digits, hyphens and underscores. Unique within one answer and stable for one run of the provider. See 5.4.
rolestringyesHow the thing is shown: a word from the role language in 5.2.
subrolestringnoWhat the thing is, in the app's own word: task, comment, pane, markdown. Any string; an app defines these freely.
titlestringnoOne line a person could read, such as a file name or a task's name.
contentarray of content blocksnoWhat the element contains, for the agent to read or see. See 5.5.
urlstringnoAn address for the thing, when it has one: a file:// URL, a web URL, or a link the app itself opens.
selectedbooleannoThe user selected this. See 5.3.
focusedbooleannoThe keyboard or cursor is here, or inside here. See 5.3.
visiblebooleannoDrawn on screen now. See 5.3.
hoveredbooleannoThe pointer is over this now. See 5.3.
childrenarray of elementsnoThe elements inside this one, in the app's order. An empty list is not sent.
attributesobjectnoAnything else the provider wants an agent to have, by name. See 5.6.

Selected text is a Text element with selected true, placed inside the element it was selected in.

5.2 — Roles

A role is one of the following thirteen words, spelled as shown.

KindRoles
The app and its windowsApplication, Window
ContainersGroup, List, Table
EntriesRow, Cell
TextText, Heading, Link
Pictures and pagesImage, Page
Added by this protocolDocument

Eleven are role names from Apple's Accessibility. Text stands for its three text roles, and Document is this protocol's own. Two roles are kept apart only where an agent or a host would act differently on seeing one or the other. A provider whose platform has more roles reports the nearest of these:

RoleAlso covers, from Apple's list
WindowSheet, Drawer, Popover, TabGroup. A tab or pane says so in the subrole.
DocumentWebArea
GroupSplitGroup, ScrollArea, LayoutArea, LayoutItem
ListOutline, Browser. Nesting shows the hierarchy.
TableGrid. A table is rows of cells; a column is not an element.
TextStaticText, TextField, TextArea

The role says how a thing is shown; the subrole says what it is. A task in a list is a Row with subrole task; the same task on a board is a Cell with subrole task. When no role plainly fits, the provider uses Group.

Rules:

  1. The root is an Application, and no other element is.
  2. A provider's own word goes in subrole, never in role.
  3. A receiver treats a role it does not know as Group. A role added to this list later is therefore not a breaking change.
  4. A provider does not report controls, menus, indicators or window furniture: no buttons, scroll bars or toolbars.
  5. A provider gives a subrole to each thing that is the app's own kind: its tasks, comments, panes. A plain window or a plain run of text needs none.

5.3 — States

Four states say what the user is pointing at and what is on screen. Each is stated once, on the element it describes, and nowhere else in the answer.

StateMeaningWhen absentHow many
selectedThe user selected this element.FalseAny number
focusedThe keyboard or cursor is in this element.FalseOne path, see below
visibleThe element is drawn on screen now.The parent's value; the root is visibleAny number
hoveredThe pointer is over this element now.FalseAt most one

A provider sends selected, focused and hovered only when true. visible is sent with either value where it differs from the parent's.

Focus is a path. focused is set on every element on the path from a child of the root down to the user's position, with no gaps, so the position is found by following focused elements down from the root. The root itself need not be marked. Two focused siblings are an error, and so is a focused element whose parent, below the root, is not focused.

Hover is one element. At most one element in an answer has hovered true: the innermost reported element under the pointer. Its ancestors are not marked; containment already says what holds it. A provider does not create elements, such as one per word, in order to mark them. The state describes the moment the provider answers and says nothing about clicks, dragging or how long the pointer has rested. It is optional: a provider that never sets it is correct.

When hovered is absent everywhere, the pointer is outside the app's windows, or over something the provider does not report, or the provider does not track the pointer. A receiver cannot tell these apart and must not infer anything from the absence.

Visible is about drawing, not focus. A document in a background tab, a pane scrolled out of view and a minimized window are not visible. An element can be visible without being focused, and several windows can be visible at once.

5.4 — Ids and instances

An id names one appearance of a thing: the same task shown in two panes is two elements with two ids.

An id means something only together with the provider that issued it and that provider's instance. Two providers may both issue sel-23, and a provider that restarts may issue it again for something else. The full name of an element is therefore the provider, its instance and the id. Keeping the three together is the host's job (9.2); an agent sees only the id.

Within one run, an id keeps referring to the thing it was minted for (9.1). The form is restricted to letters, digits, hyphens and underscores because locate puts the id in an address.

5.5 — Content

content uses MCP's ContentBlock type unchanged, so a host can hand the blocks to an agent without translating them. The block types, as of MCP schema 2026-07-28:

typeRequired fieldsUse here
texttextSelected text, or a short description of the element.
imagedata (base64), mimeTypeA small rendering of something visual: a frame, a chart, a region of a canvas.
audiodata (base64), mimeTypeRarely needed.
resource_linkuri, nameA pointer to the full thing, for the agent to fetch if it needs it.
resourceresource (a uri with text or blob)The full thing, embedded.

An element that is text sends a text block. An element that is not text sends an image, a link, or both. A selected frame in a design tool, which is neither a row nor a cell and so is a Group:

{
  "id": "node-7",
  "role": "Group",
  "subrole": "frame",
  "title": "Checkout / Payment form",
  "url": "https://design.example.com/file/AbC123?node=160-34",
  "selected": true,
  "content": [
    { "type": "image", "data": "iVBORw0KGgo…", "mimeType": "image/png" },
    { "type": "resource_link", "uri": "https://design.example.com/file/AbC123?node=160-34", "name": "Checkout / Payment form" }
  ],
  "attributes": { "width": 390, "height": 844, "layers": 14 }
}

Identity and position work the same as for text: the id is opaque, and locate returns the frame's bounding box as a list of one rectangle.

A provider should keep content small: a selection's text, a thumbnail and not a full-resolution export. Anything large belongs behind a resource_link.

5.6 — Attributes

attributes is an object of named values the app defines freely: line numbers, a due date, a status. A receiver ignores names it does not know.

Two names are reserved:

NameValueMeaning
authorstringWho wrote the thing. A provider sends it only where the app already shows it.
relatedarrayLinks that are not containment. Each entry has a relation name and another element's id or an address.

A link between two things that is not containment is expressed in related, not by placing one element inside the other.

5.7 — What to report

A provider decides how much of the app to report. The tree is not a copy of everything the app holds, or of its whole interface. It carries what the user has open and is pointing at: the windows, the documents or views in them, and what is selected, focused or hovered. An editor with forty open files might report them all, since each costs one line. A task manager would report the open view and the selected tasks, not its whole database.

A tree makes it easy to report more than a list did. The rule is unchanged: a provider reports what is useful and what the user would expect (9.1), and a host sends an agent only what the user's action warrants (9.2).

Limits on the size of a tree, its depth and an element's content are not yet set (section 13).

On this page