Skip to content
PalmaPlan — the wiki ← PalmaPlan

The embedded view

show_schedule shows a live schedule inside the conversation. It is not an image or an export: it is PalmaPlan's Gantt chart, drawn by the same code as the screen. It is editable if your role allows it, and it keeps up when someone else writes.

show_schedule { schedule: "S/4HANA Migration", view: "gantt", critical_path: true }

Options:

The user's actual role is always the ceiling: editable never grants more than a role allows.

What the view is: a native MCP App

PalmaPlan serves an MCP App: the resource ui://palmaplan/planning/<fingerprint>, of type text/html;profile=mcp-app. The fingerprint follows the page's content: a host that keeps the view it read under an address reads a new view again. It is a single page: its HTML, JavaScript and CSS are inline, and nothing loads from elsewhere. show_schedule, what_if and diff_versions point to it (_meta.ui.resourceUri). A host that renders MCP Apps shows it in the conversation, in an isolated frame. It opens inline, then full screen on request, in the host's theme colours (light or dark), language and time zone.

The view only talks to the host. Its CSP opens no domain: no connectDomains, no frameDomains, no resourceDomains. It reads and writes by calling the server's tools (tools/call), which the host relays under the connector's token or OAuth. So the view has no token of its own, no nested frame and no direct access to PalmaPlan. Four tools are reserved for it (_meta.ui.visibility: ["app"]); the host hides them from the model:

ToolWhat it returns
get_schedule_pagethe schedule in pages, each response under 120,000 characters (Claude caps a tool result at about 150,000)
get_changes_sincethe journal entries after a rank, to stay up to date
get_schedule_absencesthe agenda: the dates of the members' absences, naming no one — the view says “you”, “Member 1”, “Member 2”… —, never the reason or the e-mail
open_homethe home screen: my spaces and my schedules, most recent first — PalmaPlan's entry point in a host's sidebar (see below)

In a host's sidebar

On top of _meta.ui.resourceUri, open_home carries OpenAI's key _meta["openai/ui"].entrypoints: [{ "type": "global" }]: ChatGPT then lists PalmaPlan in its sidebar, like an app, and opens it full screen on the home screen — spaces, schedules, a search, and for each one the Gantt, the kanban or the calendar. Opening a schedule is show_schedule called by the view: same rights, same path; “All schedules” goes back home. A deep link (/schedules/<id>?view=kanban) opens the schedule it names. A host that does not know the key ignores it. Not yet tried in the real ChatGPT.

The three views, and the before/after

"Accept" applies exactly what the before/after shows, and nothing else.

Gestures

In the Gantt chart, when the role allows it:

Each gesture calls an existing tool (move_periods, resize_period, set_action_status, undo…), as the agent would. So the journal, undo and real time are the screen's. A refused write (role, lock, conflict) shows in the view. A viewer gets a read-only view.

Live updates: the view rereads the journal through get_changes_since, every two seconds at first, then less and less often while nothing moves (up to fifteen seconds). It stops while the frame is hidden. Each show_schedule call mounts a new frame; an older view of the same schedule withdraws on its own and says a newer view is open further down.

Talking to the model

Negotiation: who sees what

An MCP Apps host announces the io.modelcontextprotocol/ui extension with the type text/html;profile=mcp-app. The server reads three routes, and the first that announces it is enough:

  1. capabilities.extensions["io.modelcontextprotocol/ui"] at initialize (the stable spec's route);
  2. capabilities.experimental["io.modelcontextprotocol/ui"] (the older route);
  3. _meta["io.modelcontextprotocol/clientCapabilities"] on a request: the stateless protocol's route. The server's SDK (1.x) does not speak that protocol yet, but the route is read.

What depends on it:

An MCP Apps hostA client without MCP Apps (Claude Code)
tools/listthe 113 tools; the host hides the four view-only tools from the modelthe 109 model tools: the four view-only tools are not listed (nothing there would hide them from the model, and get_schedule_page returns up to 120,000 characters)
show_schedulethe view; a text that sums it up; no link and no tokenthe text and the one-hour /embed link
what_if, diff_versionsthe before/after, and their texttheir text

Calling a view-only tool still works for everyone. Visibility is not a permission boundary: the same data reads through palmaplan://schedule/{id}/json, under the same rights. And a host that rendered the view without announcing the extension does not find it empty.

What Claude Code shows: text

Claude Code does not render MCP Apps. There, show_schedule returns a text that stands on its own: the name, the period, the number of groups, rows, bars and milestones, the risks (violated links, bars at risk of absence) and the one-hour link:

Planning « S/4HANA Migration » — du 2026-11-02 au 2026-12-18 ; 2 groupes, 6 lignes, 6 blocs, 1 jalon.
Risques : 1 bloc à risque d absence.
Cet hôte n'affiche pas les vues MCP Apps : cette adresse ouvre le planning, valable une heure, en lecture seule : http://127.0.0.1:4785/embed/<id>?t=…

(The tools' texts are in French.) Its structuredContent is compact: { schedule_id, name, view, options, rank, read_only, shown_at, url, expires_at }. It never carries the model, because Claude Code gives it to the model instead of the text. A test checks all 109 model tools the same way: each returns a useful text (a result, or a refusal that says what to fix) and a compact structuredContent.

The link opens PalmaPlan's screen, reduced to the schedule, in a browser or in an iframe on another site. It carries a signed token valid for one hour, capped to the schedule and to the actual role. This link:

It is not a named token: it does not appear under Settings › Connections and agents › Connected applications (see Tokens and scopes).

Limits

What is proven, and what is not

Proven, in the repository:

Run in a real host on 13/10/2026: Claude, through a claude.ai custom connector to https://palmaplan.com/mcp, displayed the view in the conversation (the Code tab of Claude Desktop) — the Gantt painted, editable, the toolbar, and the model context (the selected block) sent back. Two defects seen there and nowhere before: in dark mode, the host's colours (written light-dark(), then light) painted a white header and dark ink — the view no longer adopts a colour that contradicts the theme; and the host keeps the view it read under an address — hence the fingerprint. Not proven yet: fullscreen, kanban and agenda in that host, claude.ai in a browser, the mobile app; and exactly how Claude announces the MCP Apps capability, which the view does not need to know to work.