Intent Metadata
Photon derives surface-neutral intent from the MCP-visible method contract. There is no required @intent tag. Authors express intent through names, descriptions, types, MCP annotations, and format hints; Photon publishes the derived contract under _meta["photon/render"].intent.
The server stays lean: it runs business logic and returns MCP data. Each surface decides how to render or launch the method.
Contract Shape
{
"_meta": {
"photon/render": {
"version": 1,
"mode": "auto",
"intent": {
"action": "list",
"subject": "tasks",
"confidence": 0.85,
"sources": ["description", "format", "schema"],
"safety": { "readOnly": true },
"input": { "requiresInput": false },
"output": { "structured": true, "format": "table" }
},
"format": "table"
}
}
}action is one of:
| Action | Typical source |
|---|---|
view | get, show, read, open |
list | list, browse, @format table/list |
search | search, find, query |
create | create, add, import, upload |
update | update, edit, set, configure |
delete | delete, remove, clear, @destructive |
monitor | status, metrics, watch, dashboards/charts |
run | run, start, execute, fallback |
Authoring Rules
Prefer literal method names and first-sentence descriptions:
/**
* List tasks.
* @readOnly
* @format table {@title title}
*/
async tasks() {
return [{ title: 'Ship Photon' }];
}
/**
* Create task.
*/
async createTask(params: { title: string; notes?: string }) {
return { id: crypto.randomUUID(), ...params };
}
/**
* Delete task.
* @destructive
*/
async deleteTask(params: { id: string }) {
return await this.db.delete(params.id);
}These produce enough intent for every surface:
- Beam renders
tasksas a direct load/refresh action with a table. - CLI runs
tasksdirectly, prompts forcreateTask.title, and confirmsdeleteTask. - Desktop can map
tasksto a menu item,createTaskto a dialog, anddeleteTaskto a destructive confirmation. - MCP clients still receive normal
tools/list,tools/call,content, andstructuredContent.
Surface Mapping
| Intent field | Beam | CLI | Desktop |
|---|---|---|---|
input.requiresInput=false | direct run / refresh | direct command | menu item |
input.requiresInput=true | form/dialog | prompt or help | modal dialog |
safety.destructive=true or action=delete | confirmation | confirmation unless -y | destructive alert |
output.format | renderer fallback | formatter fallback | native view selection |
action=configure / settings-like update | settings panel | settings command | preferences pane |
MCP Boundary
Intent metadata is Photon-specific, but it remains MCP-compliant because it lives inside _meta. Discovery still uses tools/list, execution still uses tools/call, custom UI still loads through resources/read, and generated HTML still runs as a sandboxed MCP Apps resource.
Legacy x-output-format and x-layout-hints remain compatibility aliases while clients migrate, but _meta["photon/render"] is authoritative.
