mcp-dashboards 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -9
- package/dist/index.js +38 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-app.html +407 -359
- package/dist/preview-server.d.ts +3 -2
- package/dist/preview-server.d.ts.map +1 -1
- package/dist/preview-server.js +69 -10
- package/dist/preview-server.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +375 -81
- package/dist/server.js.map +1 -1
- package/dist/url-safety.d.ts +30 -0
- package/dist/url-safety.d.ts.map +1 -0
- package/dist/url-safety.js +164 -0
- package/dist/url-safety.js.map +1 -0
- package/package.json +21 -14
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ We use AI for everything - analysis, reports, strategy. But when it comes to act
|
|
|
26
26
|
|
|
27
27
|
## The solution
|
|
28
28
|
|
|
29
|
-
MCP Dashboards renders interactive charts, dashboards, and KPI widgets directly inside your AI conversation. 31 tools covering 44+ chart subtypes (bar has stacked/drilldown, hero has 11 variants, etc.), 21 themes, live polling, PNG/PPT/A4 export - all from a single MCP server. No browser tabs, no copy-paste, no context switching.
|
|
29
|
+
MCP Dashboards renders interactive charts, dashboards, and KPI widgets directly inside your AI conversation. 31 chart tools covering 44+ chart subtypes (bar has stacked/drilldown, hero has 11 variants, etc.), 21 themes, 4 visual discovery catalogs, live polling, PNG/PPT/A4 export - all from a single MCP server. No browser tabs, no copy-paste, no context switching.
|
|
30
30
|
|
|
31
31
|
## Quick Start
|
|
32
32
|
|
|
@@ -58,9 +58,11 @@ claude mcp add dashboard -- npx -y mcp-dashboards --stdio
|
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
60
|
npx mcp-dashboards
|
|
61
|
-
# Server starts on http://
|
|
61
|
+
# Server starts on http://127.0.0.1:3001/mcp
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
Bound to localhost by default. See [Configuration](#configuration) if you need to expose it on your network or allow browser access from a non-localhost origin.
|
|
65
|
+
|
|
64
66
|
### Supported clients
|
|
65
67
|
|
|
66
68
|
Works in any MCP Apps-compatible client: **Claude Desktop**, **Claude Web**, **VS Code** (GitHub Copilot), **Goose**, **Postman**, **MCPJam**. ChatGPT support is rolling out.
|
|
@@ -79,6 +81,8 @@ No API to learn. Describe what you want in plain English:
|
|
|
79
81
|
|
|
80
82
|
The AI picks the right tool, formats your data, and renders the chart inline. Click any data point to ask follow-up questions.
|
|
81
83
|
|
|
84
|
+
**Don't know where to start?** Ask *"show me the catalog"* — opens a master dashboard with one live visual tile per customization dimension (a real bar chart for charts, a pie for themes, a progress ring for hero variants, a neon-glowing card for effects). Click any tile, hit Ask, and you'll drill into that sub-catalog.
|
|
85
|
+
|
|
82
86
|
## Interactive charts, not images
|
|
83
87
|
|
|
84
88
|
Every chart is **interactive HTML** rendered directly in your conversation:
|
|
@@ -88,7 +92,7 @@ Every chart is **interactive HTML** rendered directly in your conversation:
|
|
|
88
92
|
- **Export anywhere** - PPT (16:9 slides), A4 (paginated with smart page breaks), PNG, CSV
|
|
89
93
|
|
|
90
94
|
<details>
|
|
91
|
-
<summary><strong>All
|
|
95
|
+
<summary><strong>All Tools</strong></summary>
|
|
92
96
|
|
|
93
97
|
| Tool | Type | Best For |
|
|
94
98
|
|------|------|----------|
|
|
@@ -124,6 +128,18 @@ Every chart is **interactive HTML** rendered directly in your conversation:
|
|
|
124
128
|
| `render_from_json` | Auto-detect | Any JSON data - picks the best chart automatically |
|
|
125
129
|
| `render_from_url` | URL fetch | Fetches JSON from a URL and auto-visualizes |
|
|
126
130
|
|
|
131
|
+
**Discovery / Catalogs** — visual entry points for browsing what's available:
|
|
132
|
+
|
|
133
|
+
| Tool | Shows | When to use |
|
|
134
|
+
|------|-------|-------------|
|
|
135
|
+
| `render_catalog` | Master catalog with 4 live preview tiles | Don't know where to start. Click any tile, hit Ask, drill in. |
|
|
136
|
+
| `render_chart_catalog` | All 31 chart types with mini previews | Looking for the right chart for your data |
|
|
137
|
+
| `render_theme_catalog` | All 21 themes with color/typography/effects | Picking a theme |
|
|
138
|
+
| `render_hero_catalog` | All 11 hero metric variants | Picking a KPI widget style |
|
|
139
|
+
| `render_effects_catalog` | All 5 effect presets, each applied to a real card | Picking an animation/glow style |
|
|
140
|
+
|
|
141
|
+
Typography is still configurable on every chart via `typography=<name>` (8 options listed under [Themes](#themes)) — it just doesn't have its own catalog because all 8 options were visually identical without per-card font loading, which wasn't worth the build for one preview tool.
|
|
142
|
+
|
|
127
143
|
</details>
|
|
128
144
|
|
|
129
145
|
<details>
|
|
@@ -204,13 +220,33 @@ Built on [MCP Apps](https://modelcontextprotocol.io/docs/extensions/apps). You a
|
|
|
204
220
|
|
|
205
221
|
**MCP Apps supported** (inline rendering): Claude Desktop, VS Code Insiders + MCP Apps extension, Goose, Postman.
|
|
206
222
|
|
|
207
|
-
**No MCP Apps support?** No problem.
|
|
208
|
-
-
|
|
209
|
-
-
|
|
223
|
+
**No MCP Apps support?** No problem. Every chart response also includes a clickable link to the same interactive chart in your browser:
|
|
224
|
+
- `http://localhost:PORT/chart/{id}` - the clickable link in chat. Backed by a tiny same-machine HTTP server bound to 127.0.0.1, lazy-started on the first preview request.
|
|
225
|
+
- `file:///.../chart-{id}.html` - the persistent shareable artifact. Same HTML bytes, written to disk so you can email, archive, or open it after the server has shut down.
|
|
226
|
+
|
|
227
|
+
Why both: Claude Code (VS Code) strips `file://`, `vscode://`, and `command://` URL schemes from chat markdown, so only `http://` produces a working clickable link. The file:// path is provided for sharing and offline viewing. Tool annotations (`readOnlyHint`, `idempotentHint`, `openWorldHint`) help clients reason about tool behavior.
|
|
210
228
|
|
|
211
|
-
|
|
229
|
+
## Configuration
|
|
212
230
|
|
|
213
|
-
|
|
231
|
+
All optional. Defaults are safe — set these only if you need to override.
|
|
232
|
+
|
|
233
|
+
| Env var | Default | What it does |
|
|
234
|
+
|---------|---------|--------------|
|
|
235
|
+
| `MCP_DASHBOARDS_RETAIN_DAYS` | `7` | How long to keep chart preview HTML files on disk. `0` disables auto-cleanup. |
|
|
236
|
+
| `MCP_DASHBOARDS_DISABLE_PREVIEW` | unset | Kill switch — no HTML files written, no preview server started, no preview links. Inline rendering still works in MCP Apps clients. |
|
|
237
|
+
| `MCP_HTTP_BIND_HOST` | `127.0.0.1` | HTTP-transport bind host. Stays on localhost by default. Set to `0.0.0.0` only if you trust your network. |
|
|
238
|
+
| `MCP_CORS_ALLOWED_ORIGINS` | localhost only | Comma-separated origins allowed to call the HTTP endpoint from a browser. Set this to add a non-localhost origin (e.g. `https://your-app.com`). |
|
|
239
|
+
| `MCP_URL_ALLOWLIST` | empty | Comma-separated hostnames that bypass the SSRF guard for `render_from_url` / `poll_http`. Use only for internal endpoints you fully trust. |
|
|
240
|
+
| `MCP_OUTBOUND_RATE_PER_SEC` | `10` | Per-host throttle for outbound HTTP calls. |
|
|
241
|
+
| `MCP_OUTBOUND_BURST` | `20` | How many initial requests can fire immediately before the rate kicks in. |
|
|
242
|
+
| `POLL_PRESET_<NAME>_URL` | — | Server-side preset URL for live polling. See [Live Polling](#live-polling). |
|
|
243
|
+
| `POLL_PRESET_<NAME>_HEADERS` | — | Auth headers (JSON object) for the matching preset URL. |
|
|
244
|
+
|
|
245
|
+
### What's on disk
|
|
246
|
+
|
|
247
|
+
Chart HTML files are written to `<system temp>/mcp-dashboards/` and auto-deleted after 7 days. The chart's built-in download button (PNG / PPT / A4) is the recommended way to save anything permanently.
|
|
248
|
+
|
|
249
|
+
Ask your AI to *"list chart files"* or *"delete chart files older than 1 day"* anytime — invokes `list_chart_files` / `delete_chart_files`.
|
|
214
250
|
|
|
215
251
|
**Requirements:** Node.js 18+.
|
|
216
252
|
|
|
@@ -237,7 +273,11 @@ If MCP Dashboards is useful to you:
|
|
|
237
273
|
|
|
238
274
|
## Privacy
|
|
239
275
|
|
|
240
|
-
All processing happens locally. No data is collected, transmitted, or stored
|
|
276
|
+
All processing happens locally. No data is collected, transmitted, or stored externally.
|
|
277
|
+
|
|
278
|
+
External calls only happen when *you* explicitly ask — `render_from_url` and `poll_http` need a URL or preset you provide. Both refuse to fetch private, loopback, or link-local addresses (your `192.168.*` network, AWS metadata at `169.254.169.254`, etc.) so a prompt-injected AI can't quietly reach internal services. They also throttle per hostname so a runaway loop won't get your IP banned from a real API.
|
|
279
|
+
|
|
280
|
+
Credentials in env var presets never leave your machine. The browser preview server and the optional HTTP transport both bind to `127.0.0.1` by default and are not reachable from other devices. Chart HTML files live in your system temp folder and auto-delete after 7 days. See [Configuration](#configuration) to change any of this.
|
|
241
281
|
|
|
242
282
|
## License
|
|
243
283
|
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,36 @@ async function startStreamableHTTPServer(factory) {
|
|
|
12
12
|
const express = await import("express");
|
|
13
13
|
const cors = await import("cors");
|
|
14
14
|
const app = express.default();
|
|
15
|
-
|
|
15
|
+
// CORS: default to localhost-only to prevent drive-by attacks from any
|
|
16
|
+
// webpage the user happens to visit (a malicious site could otherwise POST
|
|
17
|
+
// to http://localhost:3001/mcp and invoke our tools - save_file etc.).
|
|
18
|
+
// Override with MCP_CORS_ALLOWED_ORIGINS=https://your-host.com,... for
|
|
19
|
+
// legitimate browser-based access from non-localhost origins.
|
|
20
|
+
const defaultOrigins = [
|
|
21
|
+
`http://localhost:${port}`,
|
|
22
|
+
`http://127.0.0.1:${port}`,
|
|
23
|
+
];
|
|
24
|
+
const envOrigins = (process.env.MCP_CORS_ALLOWED_ORIGINS ?? "")
|
|
25
|
+
.split(",")
|
|
26
|
+
.map((s) => s.trim())
|
|
27
|
+
.filter(Boolean);
|
|
28
|
+
const allowedOrigins = envOrigins.length > 0 ? envOrigins : defaultOrigins;
|
|
29
|
+
if (envOrigins.includes("*")) {
|
|
30
|
+
console.warn("[mcp-dashboards] WARNING: MCP_CORS_ALLOWED_ORIGINS contains '*' - allowing any origin. This is a serious security risk; only use for trusted environments.");
|
|
31
|
+
}
|
|
32
|
+
app.use(cors.default({
|
|
33
|
+
origin: (origin, cb) => {
|
|
34
|
+
// Same-origin requests / curl / non-browser callers have no Origin header
|
|
35
|
+
if (!origin)
|
|
36
|
+
return cb(null, true);
|
|
37
|
+
if (allowedOrigins.includes("*") || allowedOrigins.includes(origin)) {
|
|
38
|
+
return cb(null, true);
|
|
39
|
+
}
|
|
40
|
+
cb(null, false);
|
|
41
|
+
},
|
|
42
|
+
credentials: false,
|
|
43
|
+
methods: ["GET", "POST", "OPTIONS"],
|
|
44
|
+
}));
|
|
16
45
|
app.use(express.default.json());
|
|
17
46
|
app.all("/mcp", async (req, res) => {
|
|
18
47
|
const server = factory();
|
|
@@ -38,8 +67,14 @@ async function startStreamableHTTPServer(factory) {
|
|
|
38
67
|
}
|
|
39
68
|
}
|
|
40
69
|
});
|
|
41
|
-
|
|
42
|
-
|
|
70
|
+
// Default-bind to 127.0.0.1 so LAN attackers can't reach port 3001 directly
|
|
71
|
+
// and bypass the CORS allowlist (cors only triggers when an Origin header is
|
|
72
|
+
// sent; a raw curl from another machine has no Origin and would otherwise
|
|
73
|
+
// be waved through). Override with MCP_HTTP_BIND_HOST=0.0.0.0 (or any
|
|
74
|
+
// interface) for trusted deployment scenarios.
|
|
75
|
+
const bindHost = process.env.MCP_HTTP_BIND_HOST || "127.0.0.1";
|
|
76
|
+
const httpServer = app.listen(port, bindHost, () => {
|
|
77
|
+
console.log(`MCP Dashboards server listening on http://${bindHost}:${port}/mcp`);
|
|
43
78
|
});
|
|
44
79
|
const shutdown = () => {
|
|
45
80
|
console.log("\nShutting down...");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";AAEA;;;;GAIG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAGnG,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,yBAAyB,CACtC,OAAwB;IAExB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IAEtD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IAElC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|