lisa-runtime-kit
v1.0.1
Published
Reusable Angular runtime for manifest-driven LISA dashboards backed by MCP tools.
Maintainers
Readme
lisa-runtime-kit
Reusable Angular runtime for manifest-driven LISA dashboards backed by MCP tools.
In this repo, lisa-runtime-kit is currently consumed by:
- the thin standalone runtime host app
- the authoring preview host app
projects/lisa-runtime-dashboard, a routed dashboard host app with login, project selection, and project-detail rendering
The routed dashboard host app also demonstrates a host-owned SSO pattern:
- Kloudspot browser SSO and
/ui-api/*session ownership stay in the host app - the host app then exchanges that existing Kloudspot UI session for an MCP token through
kspot-mcp lisa-runtime-kititself still only receives the final MCP token plus optional MCP URL overrides
Install
npm install lisa-runtime-kitRequired peer dependencies:
@angular/animations@angular/cdk@angular/common@angular/core@angular/forms@angular/materialapexchartsng-apexcharts
Main Usage
<lisa-runtime-renderer
[manifest]="draftManifest"
[connectionBundle]="connectionBundle"
mode="preview" />Inputs
manifest: inline manifest JSON objectmanifestUrl: URL to fetch the manifest fromconnectionBundle: resolved host-owned MCP connection bundle keyed by manifest server idtoken: legacy single-MCP JWT input kept as a compatibility shimmcpBaseUrl: legacy single-MCP base URL overridemcpEndpoint: legacy single-MCP endpoint overridemode:'preview'or'standalone'
For schemaVersion: "3.0", MCP connection precedence is:
connectionBundle[serverId]manifest.mcpServers[serverId]- legacy single-MCP host inputs for the implicit
defaultserver manifest.mcp- library defaults
Example host usage:
connectionBundle = {
kloudspot: {
transport: 'hostProxy',
proxyUrl: '/ui-api/studio/mcp-servers/<server-id>',
proxyKey: 'kloudspot',
proxyProtocol: 'toolExecute',
credentials: 'include',
headers: {
'X-CSRF-TOKEN': '<csrf-token>'
}
},
'earthquake-public': {
baseUrl: 'https://earthquake.caseyjhand.com',
endpoint: '/mcp'
},
'private-ops': {
transport: 'hostProxy',
proxyUrl: '/api/runtime/mcp/private-ops'
}
};proxyProtocol: "toolExecute" is for host proxies that expose tool execution as:
POST {proxyUrl}/tools/{toolName}/executewith the resolved tool arguments as the JSON body.
If the host app uses the Angular Material date picker UI from this library, it should also provide Angular animations, for example with:
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';Variables
Supported variable types:
datedateRangeselectmultiSelectbooleantextnumber
Variables can also optionally set:
placement: "left" | "right"
Use placement: "right" when a control should sit in the far-right cluster of the filter bar while the rest stay on the left.
select renders as an Angular Material single-select dropdown.
multiSelect renders as an Angular Material multi-select and resolves to a string[].
boolean renders as a compact toggle and resolves to true or false.
Special behavior:
- if a manifest explicitly defines a
booleanvariable withid: "autorefresh"and the toggle is enabled, the runtime automatically refreshes dashboard data every 60 seconds
Example:
{
"id": "selectedLines",
"label": "Lines",
"type": "multiSelect",
"defaultValue": ["LF", "LH"],
"options": [
{ "label": "LF", "value": "LF" },
{ "label": "LH", "value": "LH" }
]
}date renders with an Angular Material date picker inside the runtime UI.
date resolves to a millisecond range for the selected day:
{
"start": 1777100400000,
"end": 1777186799999
}dateRange renders as a paired start/end date picker and is stored as:
{
"start": 1776495600000,
"end": 1777186799999
}That means manifests should reference:
{{variables.someDate.start}}{{variables.someDate.end}}{{variables.someRange.start}}{{variables.someRange.end}}
Theme Presets
Built-in theme presets:
kloudspotwestern-digitalaurora-lightgraphite-orangemint-gardenrose-papercobalt-slatemidnight-tealember-ashforest-night
Theme is currently resolved once per runtime instance and applied globally across the rendered app. For schemaVersion: "2.0" multi-page manifests, all pages share the same resolved theme unless page-level theme overrides are introduced later.
Manifest Versions
schemaVersion: "1.0"
Single-page dashboard manifests use top-level widgets:
{
"schemaVersion": "1.0",
"dashboard": {
"id": "example",
"title": "Example Dashboard",
"team": "Operations"
},
"theme": {
"preset": "kloudspot"
},
"variables": [],
"dataSources": [],
"widgets": []
}schemaVersion: "2.0"
Multi-page runtime app manifests can define shared app metadata plus tabbed pages. Each page can either keep a flat widgets list or switch to structured sections:
{
"schemaVersion": "2.0",
"app": {
"id": "example-app",
"title": "Example App",
"description": "A multi-page runtime app",
"team": "Operations"
},
"layout": {
"navigation": "tabs"
},
"theme": {
"preset": "kloudspot"
},
"variables": [],
"dataSources": [],
"pages": [
{
"id": "overview",
"title": "Overview",
"icon": "📊",
"sections": [
{
"id": "overview-kpis",
"title": "Area KPIs",
"type": "kpiRow",
"variant": "band",
"density": "compact",
"columns": 6,
"widgets": []
},
{
"id": "overview-content",
"title": "Signal Mix",
"type": "grid",
"variant": "hero",
"density": "comfortable",
"columns": 2,
"widgets": []
},
{
"id": "throughput-focus",
"title": "Throughput Focus",
"type": "split",
"splitRatio": "2:1",
"widgets": []
},
{
"id": "throughput-details",
"title": "Detail Tables",
"type": "stack",
"widgets": []
}
]
},
{
"id": "alerts",
"title": "Alerts",
"icon": "🔔",
"widgets": []
}
]
}schemaVersion: "3.0"
3.0 keeps the same app/page model as 2.0, but adds app-level mcpServers
and per-source server selection so a single runtime app can call multiple MCP
servers.
{
"schemaVersion": "3.0",
"app": {
"id": "example-app",
"title": "Example App"
},
"mcpServers": {
"kloudspot": {
"registryServerId": "kloudspot-prod",
"auth": { "kind": "sessionToken" }
},
"earthquake-public": {
"registryServerId": "earthquake-public",
"auth": { "kind": "none" }
}
},
"dataSources": [
{
"id": "sites",
"kind": "mcpTool",
"server": "kloudspot",
"toolName": "list_sites",
"arguments": {}
}
],
"pages": [
{
"id": "overview",
"title": "Overview",
"kind": "dashboard",
"widgets": []
}
]
}Current 2.0 notes:
layout.navigationcurrently supportstabsandsidebar- variables and data sources remain shared across pages
- only the active page's widgets are rendered and refreshed
sidebarnavigation uses a desktop left rail and collapses to a lightweight hamburger drawer on mobile- pages can use either
widgets[]orsections[] - pages can optionally set
loadStrategy: "lazy" | "prefetch" | "eager" - the active page is deep-linkable with
?page=<pageId> - tab clicks update the URL, and browser back/forward restores the selected page
layout.pageParamcan override the query parameter name; default ispagepagedeep links are only honored for manifests withpages[];1.0manifests ignore that param- section types currently support
kpiRow,grid,split, andstack - sections can optionally set
variant: "hero" | "band" | "band-scroll" | "rail" - sections can optionally set
density: "compact" | "comfortable" - sections currently support
columns: 1 | 2 | 3 | 4 | 5 | 6 - section
titleis optional; omit it when you want layout grouping without a visible heading splitsections are designed for two primary widgets and usesplitRatiosuch as"2:1"or"3:2"stacksections render widgets vertically in a single-column group and ignore widgetwidthvariantis visual emphasis only: layout still comes fromgrid,split, orstack, and section titles keep the same base heading styleband-scrollis intended forkpiRowsections and turns the KPI strip into a horizontal scroller instead of wrappingdensityadjusts presentation only: section gaps, header spacing, section widget padding, and section-local typography without changing layout behavior1.0single-page manifests remain supported
loadStrategy behavior:
lazy(default): page data loads when the page becomes activeprefetch: page data loads in the background after the active page settleseager: page data loads during the main refresh pass even while inactive
Reference samples:
- public/manifests/sample-dashboard-v2.json
- public/manifests/sample-dashboard-v2-sidebar.json
- public/manifests/sample-dashboard-v2-split.json
- public/manifests/sample-dashboard-v2-stack.json
- public/manifests/sample-dashboard-v2-variants.json
- public/manifests/sample-dashboard-v2-band-scroll.json
- public/manifests/sample-dashboard-v2-density.json
- public/manifests/sample-dashboard-v2-no-section-titles.json
