@mcp-consultant-tools/azure-devops 29.0.0 → 30.0.0-beta.1

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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Design System Prompt for Generative UI
3
+ *
4
+ * Delivered to the host LLM as part of the visualize-data tool response.
5
+ * The host LLM follows these rules when generating HTML for render-visualization.
6
+ */
7
+ export declare const DESIGN_SYSTEM_PROMPT: string;
8
+ //# sourceMappingURL=design-system-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-system-prompt.d.ts","sourceRoot":"","sources":["../../src/genui/design-system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,oBAAoB,QA+HzB,CAAC"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Design System Prompt for Generative UI
3
+ *
4
+ * Delivered to the host LLM as part of the visualize-data tool response.
5
+ * The host LLM follows these rules when generating HTML for render-visualization.
6
+ */
7
+ export const DESIGN_SYSTEM_PROMPT = `
8
+ ## Design System for HTML Visualization
9
+
10
+ You are generating an HTML snippet that will be rendered inside an MCP App iframe.
11
+ Follow these rules precisely to produce consistent, attractive, interactive output.
12
+
13
+ ### Structure
14
+ - Return a single root \`<div>\` element containing all content.
15
+ - Do NOT include \`<html>\`, \`<head>\`, or \`<body>\` tags.
16
+ - All CSS must be inline via \`<style>\` tags within the snippet.
17
+ - All JavaScript must be inline via \`<script>\` tags (no \`src\` except Chart.js CDN).
18
+ - Maximum content width: 800px, centered with \`margin: 0 auto\`.
19
+
20
+ ### Typography
21
+ - Font: \`system-ui, -apple-system, "Segoe UI", Roboto, sans-serif\`
22
+ - Base font size: 14px
23
+ - Headings: 20px (h2), 16px (h3), 14px bold (h4)
24
+ - Line height: 1.5
25
+
26
+ ### Color Palette (Light Theme)
27
+ - Background: #FFFFFF
28
+ - Surface/card background: #F8F9FA
29
+ - Text primary: #1A1A1A
30
+ - Text secondary: #6B7280
31
+ - Border: #E5E7EB
32
+ - Link: #0078D4
33
+
34
+ ### ADO State Colors
35
+ - New: #007ACC (blue)
36
+ - Active / In Progress: #009900 (green)
37
+ - Resolved: #FF9D00 (amber)
38
+ - Closed / Done / Completed: #6B7280 (grey)
39
+ - Removed: #CC0000 (red)
40
+
41
+ ### Work Item Type Colors
42
+ - Epic: #FF7B00
43
+ - Feature: #773B93
44
+ - User Story: #009CCC
45
+ - Bug: #CC293D
46
+ - Task: #F2CB1D
47
+
48
+ ### Layout
49
+ - Use CSS Flexbox or Grid for layout.
50
+ - Cards: \`border-radius: 8px; border: 1px solid #E5E7EB; padding: 16px; background: #F8F9FA\`
51
+ - Card grid: \`display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px\`
52
+ - Section spacing: \`margin-bottom: 24px\`
53
+
54
+ ### KPI Cards
55
+ For summary metrics, use KPI cards at the top:
56
+ \`\`\`html
57
+ <div style="text-align:center; padding:16px; background:#F8F9FA; border-radius:8px; border:1px solid #E5E7EB">
58
+ <div style="font-size:28px; font-weight:700; color:#1A1A1A">42</div>
59
+ <div style="font-size:12px; color:#6B7280; text-transform:uppercase; letter-spacing:0.5px">Total Items</div>
60
+ </div>
61
+ \`\`\`
62
+
63
+ ### Tables
64
+ - Full width, border-collapse
65
+ - Header: \`background:#F8F9FA; font-weight:600; text-align:left; padding:8px 12px; border-bottom:2px solid #E5E7EB\`
66
+ - Cells: \`padding:8px 12px; border-bottom:1px solid #E5E7EB\`
67
+ - Hover: \`background:#F0F4FF\`
68
+ - Add sortable column headers with onclick handlers when appropriate
69
+
70
+ ### Charts
71
+ - For complex charts (bar, line, pie, doughnut): use Chart.js from CDN
72
+ \`<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>\`
73
+ - For simple charts (donut, progress bars): use inline SVG
74
+ - Chart.js canvas: \`<canvas id="chart-{unique}" style="max-height:300px"></canvas>\`
75
+ - Initialize Chart.js in a \`<script>\` tag after the canvas element
76
+ - Always set \`responsive: true\` and \`maintainAspectRatio: false\` in Chart.js options
77
+ - Use the ADO state/type colors defined above
78
+
79
+ ### Interactivity
80
+
81
+ #### Clickable Work Item Links
82
+ Every work item ID must be a clickable link opening in a new tab:
83
+ \`\`\`html
84
+ <a href="https://dev.azure.com/{org}/{project}/_workitems/edit/{id}" target="_blank"
85
+ style="color:#0078D4; text-decoration:none; font-weight:600">#{id}</a>
86
+ \`\`\`
87
+
88
+ #### CSV Download Button
89
+ Include a download button that generates a CSV from the displayed data:
90
+ \`\`\`html
91
+ <button onclick="downloadCsv()" style="padding:6px 14px; background:#0078D4; color:white;
92
+ border:none; border-radius:4px; cursor:pointer; font-size:13px">Download CSV</button>
93
+ \`\`\`
94
+ The \`downloadCsv()\` function should:
95
+ 1. Build CSV string from the data
96
+ 2. Create a Blob and object URL
97
+ 3. Trigger download via a temporary \`<a>\` element with \`download\` attribute
98
+
99
+ #### Sortable Tables
100
+ Add sort functionality to table headers:
101
+ - Click to sort ascending, click again for descending
102
+ - Show sort indicator (arrow) in the active column header
103
+ - Implement in a \`<script>\` tag using DOM manipulation
104
+
105
+ ### Security (CRITICAL)
106
+ - **HTML-escape ALL data values** before embedding. Titles, names, descriptions — everything from the data JSON must be escaped:
107
+ \`\`\`javascript
108
+ function esc(str) { const d = document.createElement('div'); d.textContent = String(str ?? ''); return d.innerHTML; }
109
+ \`\`\`
110
+ - Use the \`esc()\` function for every data value rendered into HTML.
111
+ - Never use \`eval()\` or the \`Function()\` constructor.
112
+ - Never load scripts from domains other than \`cdn.jsdelivr.net\`.
113
+ - Never submit data to external URLs.
114
+
115
+ ### Dark Theme (when theme="dark")
116
+ If the theme parameter is "dark", override these colors:
117
+ - Background: #1A1A1A
118
+ - Surface/card: #2D2D2D
119
+ - Text primary: #E5E7EB
120
+ - Text secondary: #9CA3AF
121
+ - Border: #404040
122
+ - Keep ADO state and type colors unchanged (they work on dark backgrounds)
123
+
124
+ ### Content Structure
125
+ 1. **Title bar**: Visualization title + item count + download CSV button
126
+ 2. **KPI cards**: Key metrics in a grid (total, by state, etc.)
127
+ 3. **Primary visualization**: Chart or visual that matches the intent
128
+ 4. **Data table**: Sortable table with all items, work item IDs as links
129
+ 5. **Footer**: "Generated by MCP Apps" + timestamp
130
+
131
+ ### Output Format
132
+ Return ONLY the HTML snippet. No markdown fences, no explanation, no preamble.
133
+ The HTML must be self-contained and render correctly when injected via innerHTML.
134
+ `.trim();
135
+ //# sourceMappingURL=design-system-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-system-prompt.js","sourceRoot":"","sources":["../../src/genui/design-system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+HnC,CAAC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Lightweight HTML sanitizer for LLM-generated visualization HTML.
3
+ *
4
+ * Primary threat: prompt injection via work item data (e.g., a title containing <script>).
5
+ * The design system prompt instructs the LLM to HTML-escape data values (primary defense).
6
+ * This sanitizer is the secondary defense layer.
7
+ *
8
+ * Allows: inline scripts, Chart.js CDN, event handlers (needed for interactivity).
9
+ * Strips: external scripts (non-CDN), iframes, objects, embeds, base, meta, external forms.
10
+ */
11
+ export declare function sanitizeGenUiHtml(html: string): string;
12
+ //# sourceMappingURL=sanitize-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-html.d.ts","sourceRoot":"","sources":["../../src/genui/sanitize-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkBtD"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Lightweight HTML sanitizer for LLM-generated visualization HTML.
3
+ *
4
+ * Primary threat: prompt injection via work item data (e.g., a title containing <script>).
5
+ * The design system prompt instructs the LLM to HTML-escape data values (primary defense).
6
+ * This sanitizer is the secondary defense layer.
7
+ *
8
+ * Allows: inline scripts, Chart.js CDN, event handlers (needed for interactivity).
9
+ * Strips: external scripts (non-CDN), iframes, objects, embeds, base, meta, external forms.
10
+ */
11
+ const ALLOWED_SCRIPT_SRC_PATTERN = /^https:\/\/cdn\.jsdelivr\.net\//;
12
+ const DANGEROUS_ELEMENTS_PATTERN = /<(iframe|object|embed|base|meta)\b[^>]*>[\s\S]*?<\/\1>|<(iframe|object|embed|base|meta)\b[^>]*\/?>/gi;
13
+ const EXTERNAL_FORM_ACTION_PATTERN = /<form\b([^>]*)\baction\s*=\s*["'](https?:\/\/[^"']*)["']([^>]*)>/gi;
14
+ export function sanitizeGenUiHtml(html) {
15
+ let sanitized = html;
16
+ // Strip dangerous elements (with or without closing tags)
17
+ sanitized = sanitized.replace(DANGEROUS_ELEMENTS_PATTERN, '');
18
+ // Strip external script sources — keep inline scripts and Chart.js CDN
19
+ sanitized = sanitized.replace(/<script\b([^>]*)\bsrc\s*=\s*["']([^"']*)["']([^>]*)>/gi, (match, _before, src) => {
20
+ return ALLOWED_SCRIPT_SRC_PATTERN.test(src) ? match : '<!-- stripped external script -->';
21
+ });
22
+ // Strip forms with external actions (keep the form tag but remove the action)
23
+ sanitized = sanitized.replace(EXTERNAL_FORM_ACTION_PATTERN, '<form$1$3>');
24
+ return sanitized;
25
+ }
26
+ //# sourceMappingURL=sanitize-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-html.js","sourceRoot":"","sources":["../../src/genui/sanitize-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,0BAA0B,GAAG,iCAAiC,CAAC;AAErE,MAAM,0BAA0B,GAAG,sGAAsG,CAAC;AAE1I,MAAM,4BAA4B,GAAG,oEAAoE,CAAC;AAE1G,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,0DAA0D;IAC1D,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC;IAE9D,uEAAuE;IACvE,SAAS,GAAG,SAAS,CAAC,OAAO,CAC3B,wDAAwD,EACxD,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QACtB,OAAO,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,mCAAmC,CAAC;IAC5F,CAAC,CACF,CAAC;IAEF,8EAA8E;IAC9E,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC;IAE1E,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAsCH;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAK1D;AAGD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AA6CH;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAK1D;AAGD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC"}
package/build/index.js CHANGED
@@ -27,6 +27,13 @@ function registerUiResources(server) {
27
27
  uri: resourceUri,
28
28
  mimeType: RESOURCE_MIME_TYPE,
29
29
  text: await fs.readFile(htmlPath, "utf-8"),
30
+ _meta: {
31
+ ui: {
32
+ csp: {
33
+ resourceDomains: ["https://cdn.jsdelivr.net"],
34
+ },
35
+ },
36
+ },
30
37
  },
31
38
  ],
32
39
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD;;GAEG;AACH,SAAS,mBAAmB,CAAC,MAAW;IACtC,MAAM,WAAW,GAAG,qBAAqB,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,qBAAqB,CAAC,CAAC;IAE7E,mBAAmB,CACjB,MAAM,EACN,WAAW,EACX,WAAW,EACX,EAAE,QAAQ,EAAE,kBAAkB,EAAE,EAChC,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,WAAW;gBAChB,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;aAC3C;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAW;IAClD,MAAM,GAAG,GAAG,oBAAoB,EAAE,CAAC;IACnC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,gBAAgB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,8BAA8B;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAI5D,wBAAwB;AACxB,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG5E;;;GAGG;AACH,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1E,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;IAClC,OAAO,EAAE,CAAC;IAEV,MAAM,MAAM,GAAG,eAAe,CAAC;QAC7B,IAAI,EAAE,oCAAoC;QAC1C,OAAO,EAAE,OAAO;QAChB,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,SAAS,EAAE,EAAE;SACd;KACF,CAAC,CAAC;IAEH,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAEjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,KAAY,EAAE,EAAE;QAC/C,OAAO,CAAC,KAAK,CAAC,gEAAgE,EAAE,KAAK,CAAC,CAAC;QACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;AAC9E,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -11,4 +11,5 @@ export { registerBuildTools } from './build-tools.js';
11
11
  export { registerVariableGroupTools } from './variable-group-tools.js';
12
12
  export { registerSyncTools } from './sync-tools.js';
13
13
  export { registerChecklistTools } from './checklist-tools.js';
14
+ export { registerVisualizeTools } from './visualize-tools.js';
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAUlD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAgBvE;AAED,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAWlD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAiBvE;AAED,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -6,6 +6,7 @@ import { registerBuildTools } from './build-tools.js';
6
6
  import { registerVariableGroupTools } from './variable-group-tools.js';
7
7
  import { registerSyncTools } from './sync-tools.js';
8
8
  import { registerChecklistTools } from './checklist-tools.js';
9
+ import { registerVisualizeTools } from './visualize-tools.js';
9
10
  export function registerAllTools(server, ctx) {
10
11
  registerConfigurationTools(server, ctx);
11
12
  registerWikiTools(server, ctx);
@@ -15,9 +16,10 @@ export function registerAllTools(server, ctx) {
15
16
  registerVariableGroupTools(server, ctx);
16
17
  registerSyncTools(server, ctx);
17
18
  registerChecklistTools(server, ctx);
19
+ registerVisualizeTools(server, ctx);
18
20
  // Log registration summary
19
- // 1 config + 11 wiki + 10 work-item + 6 PR-read + 3 build + 2 variable-group + 8 sync + 8 checklist = 49
20
- const baseToolsCount = 49;
21
+ // 1 config + 11 wiki + 10 work-item + 6 PR-read + 3 build + 2 variable-group + 8 sync + 8 checklist + 2 visualize = 51
22
+ const baseToolsCount = 51;
21
23
  const prWriteToolsCount = getPrWriteToolCount();
22
24
  const totalToolsCount = baseToolsCount + prWriteToolsCount;
23
25
  console.error(`azure-devops tools registered: ${totalToolsCount} tools (${baseToolsCount} base + ${prWriteToolsCount} PR write)`);
@@ -30,4 +32,5 @@ export { registerBuildTools } from './build-tools.js';
30
32
  export { registerVariableGroupTools } from './variable-group-tools.js';
31
33
  export { registerSyncTools } from './sync-tools.js';
32
34
  export { registerChecklistTools } from './checklist-tools.js';
35
+ export { registerVisualizeTools } from './visualize-tools.js';
33
36
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,UAAU,gBAAgB,CAAC,MAAW,EAAE,GAAmB;IAC/D,0BAA0B,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,0BAA0B,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,sBAAsB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEpC,2BAA2B;IAC3B,yGAAyG;IACzG,MAAM,cAAc,GAAG,EAAE,CAAC;IAC1B,MAAM,iBAAiB,GAAG,mBAAmB,EAAE,CAAC;IAChD,MAAM,eAAe,GAAG,cAAc,GAAG,iBAAiB,CAAC;IAC3D,OAAO,CAAC,KAAK,CAAC,kCAAkC,eAAe,WAAW,cAAc,WAAW,iBAAiB,YAAY,CAAC,CAAC;AACpI,CAAC;AAED,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,UAAU,gBAAgB,CAAC,MAAW,EAAE,GAAmB;IAC/D,0BAA0B,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtC,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,0BAA0B,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,sBAAsB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACpC,sBAAsB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEpC,2BAA2B;IAC3B,uHAAuH;IACvH,MAAM,cAAc,GAAG,EAAE,CAAC;IAC1B,MAAM,iBAAiB,GAAG,mBAAmB,EAAE,CAAC;IAChD,MAAM,eAAe,GAAG,cAAc,GAAG,iBAAiB,CAAC;IAC3D,OAAO,CAAC,KAAK,CAAC,kCAAkC,eAAe,WAAW,cAAc,WAAW,iBAAiB,YAAY,CAAC,CAAC;AACpI,CAAC;AAED,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ServiceContext } from '../types.js';
2
+ export declare function registerVisualizeTools(server: any, ctx: ServiceContext): void;
3
+ //# sourceMappingURL=visualize-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visualize-tools.d.ts","sourceRoot":"","sources":["../../src/tools/visualize-tools.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAgI7E"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Visualization Tools — Generative UI via MCP Apps
3
+ *
4
+ * Two-tool pattern:
5
+ * 1. visualize-data: Fetches work items, returns data + design system prompt to host LLM
6
+ * 2. render-visualization: Receives LLM-generated HTML, sanitizes it, returns structuredContent
7
+ *
8
+ * The host LLM generates the HTML using its own subscription — no API key, no extra cost.
9
+ */
10
+ import { z } from 'zod';
11
+ import { registerAppTool } from '@modelcontextprotocol/ext-apps/server';
12
+ import { DESIGN_SYSTEM_PROMPT } from '../genui/design-system-prompt.js';
13
+ import { sanitizeGenUiHtml } from '../genui/sanitize-html.js';
14
+ export function registerVisualizeTools(server, ctx) {
15
+ const workItemsResourceUri = "ui://ado/work-items";
16
+ // Tool 1: Fetch data and instruct host LLM to generate HTML
17
+ server.tool("visualize-data", "Fetch work item data and prepare it for interactive visualization. Returns raw data + design system rules. " +
18
+ "After receiving this response, you MUST generate a complete HTML snippet following the design system rules, " +
19
+ "then call the render-visualization tool with the generated HTML. Do not skip the render step.", {
20
+ project: z.string().describe("The ADO project name"),
21
+ wiql: z.string().describe("WIQL query to fetch work items. Example: SELECT [System.Id], [System.Title], [System.State], " +
22
+ "[System.WorkItemType], [System.AssignedTo] FROM WorkItems WHERE [System.TeamProject] = 'MyProject' " +
23
+ "AND [System.State] <> 'Removed' ORDER BY [System.ChangedDate] DESC"),
24
+ intent: z.string().describe("What visualization to create. Examples: 'sprint status dashboard', 'burndown chart', " +
25
+ "'team workload by assignee', 'priority breakdown', 'bug trend over time'"),
26
+ theme: z.enum(["light", "dark"]).optional().describe("Color theme (default: light)"),
27
+ maxResults: z.number().optional().describe("Maximum work items to fetch (default: 200)"),
28
+ }, async ({ project, wiql, intent, theme, maxResults }) => {
29
+ try {
30
+ const result = await ctx.workItem.queryWorkItems(project, wiql, maxResults);
31
+ const items = Array.isArray(result) ? result : result?.workItems ?? result;
32
+ const itemCount = Array.isArray(items) ? items.length : 0;
33
+ const org = process.env.AZUREDEVOPS_ORGANIZATION || 'unknown-org';
34
+ const effectiveTheme = theme || 'light';
35
+ return {
36
+ content: [{
37
+ type: "text",
38
+ text: [
39
+ `## Visualization Data (${itemCount} work items)`,
40
+ `**Intent:** ${intent}`,
41
+ `**Theme:** ${effectiveTheme}`,
42
+ `**Organization:** ${org}`,
43
+ `**Project:** ${project}`,
44
+ ``,
45
+ `### Work Item Data`,
46
+ '```json',
47
+ JSON.stringify(items, null, 2),
48
+ '```',
49
+ ``,
50
+ `### Design System Rules`,
51
+ ``,
52
+ DESIGN_SYSTEM_PROMPT,
53
+ ``,
54
+ `### Instructions`,
55
+ ``,
56
+ `Generate a complete HTML snippet following the design system rules above.`,
57
+ `Use the organization "${org}" and project "${project}" to construct work item URLs.`,
58
+ `The visualization intent is: "${intent}"`,
59
+ `Theme: "${effectiveTheme}"`,
60
+ ``,
61
+ `After generating the HTML, call the \`render-visualization\` tool with:`,
62
+ `- \`html\`: the complete HTML snippet`,
63
+ `- \`title\`: a short title for the visualization`,
64
+ ``,
65
+ `Return ONLY the HTML when calling render-visualization. No markdown, no explanation.`,
66
+ ].join('\n'),
67
+ }],
68
+ };
69
+ }
70
+ catch (error) {
71
+ console.error("Error in visualize-data:", error);
72
+ return {
73
+ content: [{ type: "text", text: `Failed to fetch work item data: ${error.message}` }],
74
+ isError: true,
75
+ };
76
+ }
77
+ });
78
+ // Tool 2: Receive generated HTML and render it via MCP App
79
+ registerAppTool(server, "render-visualization", {
80
+ title: "Render Visualization",
81
+ description: "Render generated HTML as an interactive visualization in the MCP App. " +
82
+ "Call this after generating HTML from visualize-data results. " +
83
+ "Pass the complete HTML snippet — it will be sanitized and rendered in an iframe.",
84
+ inputSchema: {
85
+ html: z.string().describe("The complete HTML snippet to render. Must be self-contained with inline CSS and scripts."),
86
+ title: z.string().optional().describe("Short title for the visualization (e.g. 'Sprint Status Dashboard')"),
87
+ },
88
+ _meta: { ui: { resourceUri: workItemsResourceUri } },
89
+ }, async ({ html, title }) => {
90
+ try {
91
+ // Validate: basic HTML check
92
+ if (!html || (!html.includes('<') && !html.includes('>'))) {
93
+ return {
94
+ content: [{
95
+ type: "text",
96
+ text: "Error: The provided content does not appear to be valid HTML. Please regenerate following the design system rules.",
97
+ }],
98
+ isError: true,
99
+ };
100
+ }
101
+ // Strip markdown code fences if the LLM wrapped the HTML
102
+ let cleanHtml = html;
103
+ if (cleanHtml.startsWith('```')) {
104
+ cleanHtml = cleanHtml.replace(/^```(?:html)?\n?/i, '').replace(/\n?```$/i, '').trim();
105
+ }
106
+ // Sanitize
107
+ const sanitized = sanitizeGenUiHtml(cleanHtml);
108
+ const displayTitle = title || 'Visualization';
109
+ return {
110
+ content: [{ type: "text", text: `Rendered: ${displayTitle}` }],
111
+ structuredContent: { type: "genui", html: sanitized, title: displayTitle },
112
+ };
113
+ }
114
+ catch (error) {
115
+ console.error("Error in render-visualization:", error);
116
+ return {
117
+ content: [{ type: "text", text: `Failed to render visualization: ${error.message}` }],
118
+ isError: true,
119
+ };
120
+ }
121
+ });
122
+ }
123
+ //# sourceMappingURL=visualize-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visualize-tools.js","sourceRoot":"","sources":["../../src/tools/visualize-tools.ts"],"names":[],"mappings":"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"}