Skip to main content
Glama

Signal Triage — a context-aware MCP App

An MCP Apps (SEP-1865) experiment that grew from plumbing demo into a small demo engine: signals from multiple mock sources land on one interactive triage board, mapped against a customer case (who the signals matter to) and rendered in a brand (what the customer's world looks like). Both the case and the brand are plain markdown files, swappable at runtime.

Quick start — see it in two minutes

Requires Node 20+. No API keys, no accounts.

npm install
npm run build
npm run serve:http     # terminal 1 — MCP server on http://localhost:3001/mcp
npm run shim           # terminal 2 — minimal host on http://localhost:4180

Open http://localhost:4180/host-shim.html. The shim is a ~100-line reference host: it fetches the UI via resources/read, completes the MCP Apps handshake, and proxies every tool call to the real server — the log under the widget shows each message the app sends. Triage some signals (Keep/Drop/Undo, filter by source), then switch to the Briefing tab and press Draft briefing in chat to watch the v2 hand-back (ui/update-model-context + ui/message) appear in the log.

Triage decisions persist in data/decisions.json (gitignored) — delete it for a fresh board.

Related MCP server: VibeServe

What you'll see

v1 — triage. get_signals aggregates all sources and maps each signal to the case's focus areas by keyword (whole-word, plural-tolerant). The board shows focus-area chips with kept/matched counts, source filter tabs, per-row relevance chips ("No direct match" = drop candidate), and Keep/Drop/Undo. Every click travels back as a record_decision tool call (app-only, invisible to the model).

v2 — briefing. The Briefing tab groups kept signals per focus area and flags areas with no kept coverage as gaps. "Draft briefing in chat" pushes the full briefing into model context and sends a short trigger message so the host's assistant drafts the customer-ready briefing. UI-less hosts get the same synthesis from the get_briefing tool.

Both tools keep plain-text fallbacks, so the server stays useful on hosts without MCP Apps support.

The five inputs

Input

File

Role

Context

CUSTOMER_CASE.md

An OKF concept document (type: Customer Case); its focus_areas frontmatter (id, title, keywords) is the contract every signal is triaged against.

Style

DESIGN.md

A design.md-spec token file. design.ts compiles its frontmatter (colors/typography/rounded) into CSS variables injected into the UI resource at serve time.

Data

data/sources/

Three mock JSON feeds (external news, market intel, internal ops/HR). Mock by design — no API keys.

Knowledge

.claude/skills/signal-triage/

An agent skill whose reference files form an OKF bundle: the case contract, one doc per source, and a triage playbook.

Stories

USER_STORIES.md

Stories 1–2 produced v1 (git tag v1); story 3 produced v2 (tag v2).

Swapping the inputs (no rebuild, no restart)

Both context and style are runtime inputs — the server re-reads CUSTOMER_CASE.md on every tool call, and compiles DESIGN.md into the UI resource every time it's served:

# Switch customer: every signal re-maps to the new focus areas
cp cases/norrsken-freight.md CUSTOMER_CASE.md

# Switch brand: the widget re-renders in the new design tokens
cp designs/nordfrakt.design.md DESIGN.md

Reload the shim (or let the host re-read tool + resource) and the same 14 signals appear re-mapped and re-branded. Ready-made examples live in cases/ and designs/. Unknown or missing design tokens fall back to built-in defaults, and host-provided style variables always win over both.

Where the files come from is the point of the pipeline:

  • CUSTOMER_CASE.md is the planned bridge target for the organisational-stress-test project — one focus_areas entry per stressed area. Contract details: customer case contract.

  • DESIGN.md is what design-md-generator produces from a live website URL — point it at a customer's site and the demo renders in their brand.

Two verified portability experiments back this up: swapping only the style left every behavior identical, and swapping only the case (Norrsken Freight, a 3PL → Kvist & Söner, an industrial wholesaler) inverted relevance — the warehouse-robotics signal that was noise for Norrsken became Kvist's automation signal, while Norrsken's top talent signal dropped to "No direct match". Relevance is a property of the case, not the signal.

Using it from a real host

For stdio hosts (Claude Desktop / Claude Code style config):

{
  "mcpServers": {
    "signal-triage": {
      "command": "node",
      "args": ["/absolute/path/to/dist/main.js", "--stdio"]
    }
  }
}

For the SDK's reference host: clone ext-apps, cd examples/basic-host, npm install (add tsx, cross-env, @types/cors as dev deps if installing standalone), NODE_ENV=development npm run build, then npx tsx serve.ts and open http://localhost:8080 while this server runs on :3001. No bun required.

npm run dev runs the Vite watcher plus the HTTP server together for iteration (UI changes need a rebuild — the served resource is the compiled dist/mcp-app.html).

Stack

Official SDK + patterns: @modelcontextprotocol/ext-apps, vanilla TS/HTML UI bundled to a single file (Vite + vite-plugin-singlefile), Node + Express for Streamable HTTP, stdio also supported. Frontmatter parsed with yaml.

Versions

  • v1 — user stories 1–2: multi-source board + case relevance.

  • v2 — user story 3: briefing view, gaps, hand-back to chat.

  • after v2: portability experiments, then runtime ingestion of both swappable inputs.

The pre-build design sketch this repo started from is preserved on the initial-draft branch.

Learnings

The reflective deliverable of the original experiment is LEARNINGS.md — including a v2 addendum on what building "one level up" from the plumbing taught. The original scope-setting PRD is preserved as MCP_App_Learning_PRD.md.

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/SwePalm/mcp-apps-demo-engine'

If you have feedback or need assistance with the MCP directory API, please join our Discord server