Skip to content

MCP Apps (UI Resources)

MCP tools return data. MCP Apps render it. Register HTML UIs as resources, and clients that support SEP-1865 will render them inline — dashboards, data viewers, forms, config panels, right next to your tools.

import { ConcurrentMCPServer, MCP_APP_MIME_TYPE } from "@casys/mcp-server";
const server = new ConcurrentMCPServer({
name: "my-server",
version: "1.0.0",
});
server.registerResource(
{
uri: "ui://my-server/viewer",
name: "Data Viewer",
description: "Interactive data viewer",
},
async (uri) => ({
uri: uri.toString(),
mimeType: MCP_APP_MIME_TYPE,
text: `
<html>
<body>
<h1>Data Viewer</h1>
<div id="app"></div>
<script>
// Your interactive UI code here
</script>
</body>
</html>
`,
}),
);
await server.start();

The ui:// URI scheme tells MCP clients that this resource is an interactive HTML application, not raw data.

  • URI format: ui://{server-name}/{path}
  • MIME type: Use MCP_APP_MIME_TYPE (exported constant)
  • Content: Full HTML document as a string

The handler receives the URI and can return different content based on state, fetched data, or anything else:

server.registerResource(
{
uri: "ui://my-server/dashboard",
name: "Dashboard",
description: "Real-time metrics dashboard",
},
async (uri) => {
const metrics = await getMetrics();
return {
uri: uri.toString(),
mimeType: MCP_APP_MIME_TYPE,
text: renderDashboard(metrics), // Fresh data on every read
};
},
);
server.getResourceCount(); // 2
server.getResourceUris(); // ["ui://my-server/viewer", "ui://my-server/dashboard"]