@cloudgrid-io/mcp 0.5.5 → 0.6.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.
- package/package.json +1 -1
- package/src/corpus/examples/dashboard/index.html +121 -0
- package/src/corpus/examples/deck/index.html +180 -0
- package/src/corpus/examples/landing-page/index.html +98 -0
- package/src/corpus/examples/report/index.html +112 -0
- package/src/corpus/examples/web-app/index.html +125 -0
- package/src/corpus/install.md +2 -1
- package/src/corpus/skills-readme.md +3 -2
- package/src/corpus/templates/dashboard/index.html +118 -0
- package/src/corpus/templates/deck/index.html +149 -0
- package/src/corpus/templates/landing-page/index.html +97 -0
- package/src/corpus/templates/report/index.html +93 -0
- package/src/corpus/templates/web-app/index.html +99 -0
- package/src/corpus/usage.md +6 -5
- package/src/corpus/workflows/dashboard.md +31 -0
- package/src/corpus/workflows/landing-page.md +29 -0
- package/src/corpus/workflows/presentation.md +28 -0
- package/src/corpus/workflows/report.md +31 -0
- package/src/corpus/workflows/web-app.md +31 -0
- package/src/docs.js +14 -2
- package/src/tools.js +314 -76
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudgrid-io/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "MCP server for CloudGrid. Three editions: a local stdio server (full toolset), a hosted web server (light, CLI-free toolset), and a public docs server (search_cloudgrid_documentation) over MCP Streamable HTTP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Service Health Dashboard</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #0b0f17;
|
|
10
|
+
--panel: #121826;
|
|
11
|
+
--fg: #e8edf5;
|
|
12
|
+
--muted: #9aa7bd;
|
|
13
|
+
--accent: #5b8cff;
|
|
14
|
+
--good: #46d19e;
|
|
15
|
+
--border: #223049;
|
|
16
|
+
}
|
|
17
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
18
|
+
body {
|
|
19
|
+
background: var(--bg);
|
|
20
|
+
color: var(--fg);
|
|
21
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
22
|
+
-webkit-font-smoothing: antialiased;
|
|
23
|
+
padding: clamp(1.25rem, 4vw, 2.5rem);
|
|
24
|
+
}
|
|
25
|
+
header { margin-bottom: 1.75rem; }
|
|
26
|
+
h1 { font-size: clamp(1.6rem, 4vw, 2.3rem); letter-spacing: -0.02em; }
|
|
27
|
+
.status { color: var(--muted); margin-top: 0.35rem; }
|
|
28
|
+
.grid { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
|
|
29
|
+
.card {
|
|
30
|
+
background: var(--panel); border: 1px solid var(--border);
|
|
31
|
+
border-radius: 14px; padding: 1.25rem 1.4rem;
|
|
32
|
+
}
|
|
33
|
+
.card .label { color: var(--muted); font-size: 0.85rem; }
|
|
34
|
+
.card .value { font-size: 2rem; font-weight: 600; margin: 0.35rem 0; font-variant-numeric: tabular-nums; }
|
|
35
|
+
.card .trend { font-size: 0.85rem; color: var(--good); }
|
|
36
|
+
.charts { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); margin-top: 1.1rem; }
|
|
37
|
+
.chart-card { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; padding: 1.25rem 1.4rem; }
|
|
38
|
+
.chart-card h2 { font-size: 1rem; color: var(--muted); font-weight: 600; margin-bottom: 0.9rem; }
|
|
39
|
+
svg { width: 100%; height: auto; display: block; }
|
|
40
|
+
</style>
|
|
41
|
+
</head>
|
|
42
|
+
<body>
|
|
43
|
+
<header>
|
|
44
|
+
<h1>Service Health Dashboard</h1>
|
|
45
|
+
<div class="status">All systems operational — updated a moment ago</div>
|
|
46
|
+
</header>
|
|
47
|
+
|
|
48
|
+
<section class="grid">
|
|
49
|
+
<div class="card">
|
|
50
|
+
<div class="label">Requests / min</div>
|
|
51
|
+
<div class="value">18.4k</div>
|
|
52
|
+
<div class="trend">+6.2% vs last hour</div>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="card">
|
|
55
|
+
<div class="label">p95 latency</div>
|
|
56
|
+
<div class="value">142ms</div>
|
|
57
|
+
<div class="trend">-11ms vs last hour</div>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="card">
|
|
60
|
+
<div class="label">Error rate</div>
|
|
61
|
+
<div class="value">0.08%</div>
|
|
62
|
+
<div class="trend">within target</div>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="card">
|
|
65
|
+
<div class="label">Uptime (30d)</div>
|
|
66
|
+
<div class="value">99.98%</div>
|
|
67
|
+
<div class="trend">no incidents</div>
|
|
68
|
+
</div>
|
|
69
|
+
</section>
|
|
70
|
+
|
|
71
|
+
<section class="charts">
|
|
72
|
+
<div class="chart-card">
|
|
73
|
+
<h2>Requests by region</h2>
|
|
74
|
+
<svg id="bar" viewBox="0 0 320 160" role="img" aria-label="Bar chart of requests by region"></svg>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="chart-card">
|
|
77
|
+
<h2>Latency over the last 12 hours</h2>
|
|
78
|
+
<svg id="line" viewBox="0 0 320 160" role="img" aria-label="Line chart of latency over time"></svg>
|
|
79
|
+
</div>
|
|
80
|
+
</section>
|
|
81
|
+
|
|
82
|
+
<script>
|
|
83
|
+
var barData = [42, 58, 31, 49, 66, 38];
|
|
84
|
+
var lineData = [160, 154, 148, 151, 139, 142, 137, 144, 140, 135, 142, 138];
|
|
85
|
+
|
|
86
|
+
var NS = "http://www.w3.org/2000/svg";
|
|
87
|
+
function el(name, attrs) {
|
|
88
|
+
var n = document.createElementNS(NS, name);
|
|
89
|
+
for (var k in attrs) n.setAttribute(k, attrs[k]);
|
|
90
|
+
return n;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
(function drawBars() {
|
|
94
|
+
var svg = document.getElementById("bar");
|
|
95
|
+
var W = 320, H = 160, pad = 20;
|
|
96
|
+
var max = Math.max.apply(null, barData.concat([1]));
|
|
97
|
+
var bw = (W - pad * 2) / barData.length;
|
|
98
|
+
barData.forEach(function (v, i) {
|
|
99
|
+
var h = (v / max) * (H - pad * 2);
|
|
100
|
+
svg.appendChild(el("rect", {
|
|
101
|
+
x: pad + i * bw + bw * 0.15, y: H - pad - h,
|
|
102
|
+
width: bw * 0.7, height: h, rx: 3, fill: "var(--accent)"
|
|
103
|
+
}));
|
|
104
|
+
});
|
|
105
|
+
svg.appendChild(el("line", { x1: pad, y1: H - pad, x2: W - pad, y2: H - pad, stroke: "var(--border)" }));
|
|
106
|
+
})();
|
|
107
|
+
|
|
108
|
+
(function drawLine() {
|
|
109
|
+
var svg = document.getElementById("line");
|
|
110
|
+
var W = 320, H = 160, pad = 20;
|
|
111
|
+
var max = Math.max.apply(null, lineData.concat([1]));
|
|
112
|
+
var step = (W - pad * 2) / Math.max(1, lineData.length - 1);
|
|
113
|
+
var pts = lineData.map(function (v, i) {
|
|
114
|
+
return (pad + i * step) + "," + (H - pad - (v / max) * (H - pad * 2));
|
|
115
|
+
}).join(" ");
|
|
116
|
+
svg.appendChild(el("polyline", { points: pts, fill: "none", stroke: "var(--good)", "stroke-width": 2.5 }));
|
|
117
|
+
svg.appendChild(el("line", { x1: pad, y1: H - pad, x2: W - pad, y2: H - pad, stroke: "var(--border)" }));
|
|
118
|
+
})();
|
|
119
|
+
</script>
|
|
120
|
+
</body>
|
|
121
|
+
</html>
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>The Solar System</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #0b0f17;
|
|
10
|
+
--panel: #121826;
|
|
11
|
+
--fg: #e8edf5;
|
|
12
|
+
--muted: #9aa7bd;
|
|
13
|
+
--accent: #5b8cff;
|
|
14
|
+
--border: #223049;
|
|
15
|
+
}
|
|
16
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
17
|
+
html, body { height: 100%; }
|
|
18
|
+
body {
|
|
19
|
+
background: var(--bg);
|
|
20
|
+
color: var(--fg);
|
|
21
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
22
|
+
-webkit-font-smoothing: antialiased;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
}
|
|
25
|
+
#deck { position: relative; height: 100vh; width: 100vw; }
|
|
26
|
+
.slide {
|
|
27
|
+
position: absolute;
|
|
28
|
+
inset: 0;
|
|
29
|
+
display: none;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
padding: clamp(2rem, 8vw, 8rem);
|
|
33
|
+
gap: 1.25rem;
|
|
34
|
+
animation: fade 0.35s ease;
|
|
35
|
+
}
|
|
36
|
+
.slide.active { display: flex; }
|
|
37
|
+
@keyframes fade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
|
|
38
|
+
.slide[data-role="title"] h1 {
|
|
39
|
+
font-size: clamp(2.5rem, 7vw, 5rem);
|
|
40
|
+
line-height: 1.05;
|
|
41
|
+
letter-spacing: -0.02em;
|
|
42
|
+
}
|
|
43
|
+
.slide[data-role="title"] p {
|
|
44
|
+
font-size: clamp(1.1rem, 2.5vw, 1.6rem);
|
|
45
|
+
color: var(--muted);
|
|
46
|
+
max-width: 40ch;
|
|
47
|
+
}
|
|
48
|
+
.slide h2 {
|
|
49
|
+
font-size: clamp(1.8rem, 4.5vw, 3rem);
|
|
50
|
+
letter-spacing: -0.01em;
|
|
51
|
+
}
|
|
52
|
+
.slide .body {
|
|
53
|
+
font-size: clamp(1.05rem, 2.2vw, 1.5rem);
|
|
54
|
+
color: var(--muted);
|
|
55
|
+
max-width: 60ch;
|
|
56
|
+
line-height: 1.5;
|
|
57
|
+
}
|
|
58
|
+
.slide .body ul { padding-left: 1.4em; display: grid; gap: 0.6em; }
|
|
59
|
+
.accent-bar {
|
|
60
|
+
width: 64px; height: 5px; border-radius: 99px;
|
|
61
|
+
background: var(--accent);
|
|
62
|
+
}
|
|
63
|
+
#chrome {
|
|
64
|
+
position: fixed; bottom: 0; left: 0; right: 0;
|
|
65
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
66
|
+
padding: 0.9rem 1.4rem;
|
|
67
|
+
border-top: 1px solid var(--border);
|
|
68
|
+
background: color-mix(in srgb, var(--panel) 85%, transparent);
|
|
69
|
+
backdrop-filter: blur(6px);
|
|
70
|
+
font-size: 0.85rem; color: var(--muted);
|
|
71
|
+
}
|
|
72
|
+
#chrome button {
|
|
73
|
+
background: transparent; color: var(--fg);
|
|
74
|
+
border: 1px solid var(--border); border-radius: 8px;
|
|
75
|
+
padding: 0.35rem 0.7rem; cursor: pointer; font: inherit;
|
|
76
|
+
}
|
|
77
|
+
#chrome button:hover { border-color: var(--accent); }
|
|
78
|
+
#counter { font-variant-numeric: tabular-nums; }
|
|
79
|
+
#progress {
|
|
80
|
+
position: fixed; top: 0; left: 0; height: 3px;
|
|
81
|
+
background: var(--accent); transition: width 0.3s ease; z-index: 10;
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
84
|
+
</head>
|
|
85
|
+
<body>
|
|
86
|
+
<div id="progress"></div>
|
|
87
|
+
<div id="deck">
|
|
88
|
+
<section class="slide active" data-role="title">
|
|
89
|
+
<div class="accent-bar"></div>
|
|
90
|
+
<h1>The Solar System</h1>
|
|
91
|
+
<p>A quick tour of the Sun and the worlds that orbit it.</p>
|
|
92
|
+
</section>
|
|
93
|
+
|
|
94
|
+
<section class="slide">
|
|
95
|
+
<div class="accent-bar"></div>
|
|
96
|
+
<h2>The Sun</h2>
|
|
97
|
+
<div class="body">
|
|
98
|
+
A star at the center of it all, holding roughly 99.8% of the system's
|
|
99
|
+
mass. Its gravity keeps every planet, moon, and comet in orbit, and its
|
|
100
|
+
fusion powers nearly all life on Earth.
|
|
101
|
+
</div>
|
|
102
|
+
</section>
|
|
103
|
+
|
|
104
|
+
<section class="slide">
|
|
105
|
+
<div class="accent-bar"></div>
|
|
106
|
+
<h2>The Rocky Inner Planets</h2>
|
|
107
|
+
<div class="body">
|
|
108
|
+
<ul>
|
|
109
|
+
<li>Mercury: smallest and fastest, scorched and cratered.</li>
|
|
110
|
+
<li>Venus: a runaway greenhouse, hottest surface of all.</li>
|
|
111
|
+
<li>Earth: the only known world with liquid water and life.</li>
|
|
112
|
+
<li>Mars: cold, red, and rich with signs of an ancient wetter past.</li>
|
|
113
|
+
</ul>
|
|
114
|
+
</div>
|
|
115
|
+
</section>
|
|
116
|
+
|
|
117
|
+
<section class="slide">
|
|
118
|
+
<div class="accent-bar"></div>
|
|
119
|
+
<h2>The Gas and Ice Giants</h2>
|
|
120
|
+
<div class="body">
|
|
121
|
+
<ul>
|
|
122
|
+
<li>Jupiter: the largest planet, with a centuries-old storm.</li>
|
|
123
|
+
<li>Saturn: famous for its bright, wide ring system.</li>
|
|
124
|
+
<li>Uranus: an ice giant tipped on its side.</li>
|
|
125
|
+
<li>Neptune: windiest world, far out in the cold dark.</li>
|
|
126
|
+
</ul>
|
|
127
|
+
</div>
|
|
128
|
+
</section>
|
|
129
|
+
|
|
130
|
+
<section class="slide">
|
|
131
|
+
<div class="accent-bar"></div>
|
|
132
|
+
<h2>Beyond the Planets</h2>
|
|
133
|
+
<div class="body">
|
|
134
|
+
Dwarf planets like Pluto, the icy Kuiper Belt, and the distant Oort
|
|
135
|
+
Cloud mark the edges. Comets and asteroids are leftovers from the
|
|
136
|
+
system's birth about 4.6 billion years ago.
|
|
137
|
+
</div>
|
|
138
|
+
</section>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<div id="chrome">
|
|
142
|
+
<span id="deck-name">The Solar System</span>
|
|
143
|
+
<span>
|
|
144
|
+
<button id="prev" aria-label="Previous slide">Prev</button>
|
|
145
|
+
<span id="counter">1 / 1</span>
|
|
146
|
+
<button id="next" aria-label="Next slide">Next</button>
|
|
147
|
+
</span>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<script>
|
|
151
|
+
(function () {
|
|
152
|
+
var slides = Array.prototype.slice.call(document.querySelectorAll(".slide"));
|
|
153
|
+
var idx = 0;
|
|
154
|
+
var counter = document.getElementById("counter");
|
|
155
|
+
var progress = document.getElementById("progress");
|
|
156
|
+
|
|
157
|
+
function render() {
|
|
158
|
+
slides.forEach(function (s, i) { s.classList.toggle("active", i === idx); });
|
|
159
|
+
counter.textContent = (idx + 1) + " / " + slides.length;
|
|
160
|
+
progress.style.width = ((idx + 1) / slides.length * 100) + "%";
|
|
161
|
+
}
|
|
162
|
+
function go(delta) {
|
|
163
|
+
idx = Math.max(0, Math.min(slides.length - 1, idx + delta));
|
|
164
|
+
render();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
document.getElementById("next").addEventListener("click", function () { go(1); });
|
|
168
|
+
document.getElementById("prev").addEventListener("click", function () { go(-1); });
|
|
169
|
+
document.addEventListener("keydown", function (e) {
|
|
170
|
+
if (e.key === "ArrowRight" || e.key === "PageDown" || e.key === " ") { go(1); e.preventDefault(); }
|
|
171
|
+
else if (e.key === "ArrowLeft" || e.key === "PageUp") { go(-1); e.preventDefault(); }
|
|
172
|
+
else if (e.key === "Home") { idx = 0; render(); }
|
|
173
|
+
else if (e.key === "End") { idx = slides.length - 1; render(); }
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
render();
|
|
177
|
+
})();
|
|
178
|
+
</script>
|
|
179
|
+
</body>
|
|
180
|
+
</html>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Cadence</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #0b0f17;
|
|
10
|
+
--panel: #121826;
|
|
11
|
+
--fg: #e8edf5;
|
|
12
|
+
--muted: #9aa7bd;
|
|
13
|
+
--accent: #5b8cff;
|
|
14
|
+
--border: #223049;
|
|
15
|
+
}
|
|
16
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
17
|
+
body {
|
|
18
|
+
background: var(--bg);
|
|
19
|
+
color: var(--fg);
|
|
20
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
21
|
+
-webkit-font-smoothing: antialiased;
|
|
22
|
+
line-height: 1.5;
|
|
23
|
+
}
|
|
24
|
+
header, section, footer { padding: clamp(2rem, 6vw, 5rem) clamp(1.25rem, 6vw, 6rem); }
|
|
25
|
+
nav {
|
|
26
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
27
|
+
padding: 1.1rem clamp(1.25rem, 6vw, 6rem);
|
|
28
|
+
border-bottom: 1px solid var(--border);
|
|
29
|
+
}
|
|
30
|
+
nav .brand { font-weight: 600; letter-spacing: -0.01em; }
|
|
31
|
+
nav a { color: var(--muted); text-decoration: none; }
|
|
32
|
+
.hero { text-align: center; display: grid; gap: 1.25rem; place-items: center; }
|
|
33
|
+
.hero h1 {
|
|
34
|
+
font-size: clamp(2.4rem, 6vw, 4.5rem);
|
|
35
|
+
line-height: 1.05; letter-spacing: -0.02em; max-width: 20ch;
|
|
36
|
+
}
|
|
37
|
+
.hero p { font-size: clamp(1.05rem, 2.4vw, 1.5rem); color: var(--muted); max-width: 48ch; }
|
|
38
|
+
.cta {
|
|
39
|
+
display: inline-block; margin-top: 0.5rem;
|
|
40
|
+
background: var(--accent); color: #fff; text-decoration: none;
|
|
41
|
+
padding: 0.85rem 1.6rem; border-radius: 10px; font-weight: 600;
|
|
42
|
+
}
|
|
43
|
+
.cta:hover { filter: brightness(1.08); }
|
|
44
|
+
.features {
|
|
45
|
+
display: grid; gap: 1.25rem;
|
|
46
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
47
|
+
border-top: 1px solid var(--border);
|
|
48
|
+
}
|
|
49
|
+
.feature {
|
|
50
|
+
background: var(--panel); border: 1px solid var(--border);
|
|
51
|
+
border-radius: 14px; padding: 1.5rem;
|
|
52
|
+
}
|
|
53
|
+
.feature h3 { font-size: 1.15rem; margin-bottom: 0.5rem; letter-spacing: -0.01em; }
|
|
54
|
+
.feature p { color: var(--muted); }
|
|
55
|
+
.closing { text-align: center; border-top: 1px solid var(--border); display: grid; gap: 1.25rem; place-items: center; }
|
|
56
|
+
.closing h2 { font-size: clamp(1.8rem, 4.5vw, 3rem); letter-spacing: -0.01em; max-width: 24ch; }
|
|
57
|
+
footer { border-top: 1px solid var(--border); color: var(--muted); font-size: 0.9rem; text-align: center; }
|
|
58
|
+
</style>
|
|
59
|
+
</head>
|
|
60
|
+
<body>
|
|
61
|
+
<nav>
|
|
62
|
+
<span class="brand">Cadence</span>
|
|
63
|
+
<a class="cta" href="#start">Start free</a>
|
|
64
|
+
</nav>
|
|
65
|
+
|
|
66
|
+
<header class="hero">
|
|
67
|
+
<h1>Ship your week in a single view</h1>
|
|
68
|
+
<p>Cadence turns scattered tasks, notes, and deadlines into one calm weekly plan your whole team can trust.</p>
|
|
69
|
+
<a class="cta" href="#start">Start free</a>
|
|
70
|
+
</header>
|
|
71
|
+
|
|
72
|
+
<section class="features">
|
|
73
|
+
<div class="feature">
|
|
74
|
+
<h3>One weekly board</h3>
|
|
75
|
+
<p>Every task, meeting, and milestone lands on a single board that resets each Monday so nothing slips.</p>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="feature">
|
|
78
|
+
<h3>Automatic rollover</h3>
|
|
79
|
+
<p>Unfinished work carries forward with its context intact, so you never rebuild a plan from scratch.</p>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="feature">
|
|
82
|
+
<h3>Quiet by design</h3>
|
|
83
|
+
<p>Notifications batch into two calm digests a day, keeping focus time genuinely free of interruptions.</p>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="feature">
|
|
86
|
+
<h3>Shared without noise</h3>
|
|
87
|
+
<p>Teammates see the same board and status without a stream of pings, comments, or status meetings.</p>
|
|
88
|
+
</div>
|
|
89
|
+
</section>
|
|
90
|
+
|
|
91
|
+
<section class="closing" id="start">
|
|
92
|
+
<h2>Plan less, finish more this week</h2>
|
|
93
|
+
<a class="cta" href="#start">Start free</a>
|
|
94
|
+
</section>
|
|
95
|
+
|
|
96
|
+
<footer>Cadence — a sample landing page built on CloudGrid.</footer>
|
|
97
|
+
</body>
|
|
98
|
+
</html>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Q2 Support Operations Review</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #0b0f17;
|
|
10
|
+
--panel: #121826;
|
|
11
|
+
--fg: #e8edf5;
|
|
12
|
+
--muted: #9aa7bd;
|
|
13
|
+
--accent: #5b8cff;
|
|
14
|
+
--border: #223049;
|
|
15
|
+
}
|
|
16
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
17
|
+
body {
|
|
18
|
+
background: var(--bg);
|
|
19
|
+
color: var(--fg);
|
|
20
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
21
|
+
-webkit-font-smoothing: antialiased;
|
|
22
|
+
line-height: 1.6;
|
|
23
|
+
}
|
|
24
|
+
.page {
|
|
25
|
+
max-width: 820px; margin: 0 auto;
|
|
26
|
+
padding: clamp(2rem, 6vw, 4.5rem) clamp(1.25rem, 5vw, 3.5rem);
|
|
27
|
+
}
|
|
28
|
+
header { border-bottom: 1px solid var(--border); padding-bottom: 1.5rem; margin-bottom: 2rem; }
|
|
29
|
+
.accent-bar { width: 64px; height: 5px; border-radius: 99px; background: var(--accent); margin-bottom: 1.1rem; }
|
|
30
|
+
h1 { font-size: clamp(1.9rem, 4.5vw, 2.8rem); line-height: 1.1; letter-spacing: -0.02em; }
|
|
31
|
+
.subtitle { color: var(--muted); font-size: 1.1rem; margin-top: 0.5rem; }
|
|
32
|
+
.meta { color: var(--muted); font-size: 0.9rem; margin-top: 0.75rem; }
|
|
33
|
+
.summary {
|
|
34
|
+
background: var(--panel); border: 1px solid var(--border);
|
|
35
|
+
border-radius: 12px; padding: 1.25rem 1.4rem; margin-bottom: 2rem; color: var(--muted);
|
|
36
|
+
}
|
|
37
|
+
section { margin-bottom: 2rem; }
|
|
38
|
+
section h2 { font-size: 1.35rem; letter-spacing: -0.01em; margin-bottom: 0.6rem; }
|
|
39
|
+
section p { color: var(--muted); }
|
|
40
|
+
table { width: 100%; border-collapse: collapse; margin-top: 0.5rem; }
|
|
41
|
+
th, td { text-align: left; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--border); }
|
|
42
|
+
th { color: var(--muted); font-size: 0.85rem; font-weight: 600; }
|
|
43
|
+
td { font-variant-numeric: tabular-nums; }
|
|
44
|
+
footer { border-top: 1px solid var(--border); padding-top: 1.25rem; color: var(--muted); font-size: 0.85rem; }
|
|
45
|
+
@media print {
|
|
46
|
+
:root { --bg: #ffffff; --panel: #f4f6fa; --fg: #10151f; --muted: #4a5568; --border: #d5dbe6; }
|
|
47
|
+
body { background: #fff; }
|
|
48
|
+
.page { padding: 0; }
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
51
|
+
</head>
|
|
52
|
+
<body>
|
|
53
|
+
<div class="page">
|
|
54
|
+
<header>
|
|
55
|
+
<div class="accent-bar"></div>
|
|
56
|
+
<h1>Q2 Support Operations Review</h1>
|
|
57
|
+
<div class="subtitle">Ticket volume, response times, and satisfaction</div>
|
|
58
|
+
<div class="meta">Prepared by the Support team, quarter ending June 30</div>
|
|
59
|
+
</header>
|
|
60
|
+
|
|
61
|
+
<div class="summary">
|
|
62
|
+
Support handled 12% more tickets than Q1 while cutting median first-response
|
|
63
|
+
time by nearly a third. Satisfaction held steady at 94%. The main risk into
|
|
64
|
+
Q3 is billing-related volume, which grew faster than headcount.
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<section>
|
|
68
|
+
<h2>Volume and staffing</h2>
|
|
69
|
+
<p>
|
|
70
|
+
The team resolved 8,420 tickets across the quarter, up from 7,510 in Q1.
|
|
71
|
+
Two agents joined in May, bringing the desk to nine. Even so, the
|
|
72
|
+
tickets-per-agent load rose slightly, absorbed mostly by faster tooling
|
|
73
|
+
rather than longer hours.
|
|
74
|
+
</p>
|
|
75
|
+
</section>
|
|
76
|
+
|
|
77
|
+
<section>
|
|
78
|
+
<h2>Response and resolution</h2>
|
|
79
|
+
<p>
|
|
80
|
+
Median first-response time fell from 4.6 hours to 3.1 hours after the
|
|
81
|
+
canned-reply library was rebuilt. Full resolution time was flat, since the
|
|
82
|
+
slowest tickets are billing disputes that depend on the finance team.
|
|
83
|
+
</p>
|
|
84
|
+
</section>
|
|
85
|
+
|
|
86
|
+
<section>
|
|
87
|
+
<h2>Outlook</h2>
|
|
88
|
+
<p>
|
|
89
|
+
Billing questions are the fastest-growing category and the least
|
|
90
|
+
self-serviceable. The recommendation for Q3 is a dedicated billing macro
|
|
91
|
+
set plus a short help-center article, before adding more headcount.
|
|
92
|
+
</p>
|
|
93
|
+
</section>
|
|
94
|
+
|
|
95
|
+
<section>
|
|
96
|
+
<h2>Key metrics</h2>
|
|
97
|
+
<table>
|
|
98
|
+
<thead>
|
|
99
|
+
<tr><th>Metric</th><th>Q1</th><th>Q2</th></tr>
|
|
100
|
+
</thead>
|
|
101
|
+
<tbody>
|
|
102
|
+
<tr><td>Tickets resolved</td><td>7,510</td><td>8,420</td></tr>
|
|
103
|
+
<tr><td>Median first response</td><td>4.6h</td><td>3.1h</td></tr>
|
|
104
|
+
<tr><td>Satisfaction</td><td>93%</td><td>94%</td></tr>
|
|
105
|
+
</tbody>
|
|
106
|
+
</table>
|
|
107
|
+
</section>
|
|
108
|
+
|
|
109
|
+
<footer>A sample report built on CloudGrid. Figures are illustrative.</footer>
|
|
110
|
+
</div>
|
|
111
|
+
</body>
|
|
112
|
+
</html>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Tip Splitter</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #0b0f17;
|
|
10
|
+
--panel: #121826;
|
|
11
|
+
--fg: #e8edf5;
|
|
12
|
+
--muted: #9aa7bd;
|
|
13
|
+
--accent: #5b8cff;
|
|
14
|
+
--border: #223049;
|
|
15
|
+
}
|
|
16
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
17
|
+
body {
|
|
18
|
+
background: var(--bg);
|
|
19
|
+
color: var(--fg);
|
|
20
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
21
|
+
-webkit-font-smoothing: antialiased;
|
|
22
|
+
min-height: 100vh;
|
|
23
|
+
display: grid; place-items: center;
|
|
24
|
+
padding: 1.5rem;
|
|
25
|
+
}
|
|
26
|
+
.app {
|
|
27
|
+
width: 100%; max-width: 420px;
|
|
28
|
+
background: var(--panel); border: 1px solid var(--border);
|
|
29
|
+
border-radius: 16px; padding: 1.75rem;
|
|
30
|
+
}
|
|
31
|
+
h1 { font-size: 1.5rem; letter-spacing: -0.01em; margin-bottom: 0.35rem; }
|
|
32
|
+
.subtitle { color: var(--muted); font-size: 0.95rem; margin-bottom: 1.4rem; }
|
|
33
|
+
label { display: block; font-size: 0.85rem; color: var(--muted); margin: 0.9rem 0 0.35rem; }
|
|
34
|
+
input {
|
|
35
|
+
width: 100%; font: inherit; color: var(--fg);
|
|
36
|
+
background: var(--bg); border: 1px solid var(--border);
|
|
37
|
+
border-radius: 10px; padding: 0.65rem 0.75rem;
|
|
38
|
+
}
|
|
39
|
+
input:focus { outline: none; border-color: var(--accent); }
|
|
40
|
+
.row { display: flex; gap: 0.75rem; }
|
|
41
|
+
.row > * { flex: 1; }
|
|
42
|
+
.tips { display: flex; gap: 0.5rem; margin-top: 0.35rem; }
|
|
43
|
+
.tips button {
|
|
44
|
+
flex: 1; font: inherit; cursor: pointer;
|
|
45
|
+
background: var(--bg); color: var(--fg);
|
|
46
|
+
border: 1px solid var(--border); border-radius: 10px; padding: 0.55rem 0;
|
|
47
|
+
}
|
|
48
|
+
.tips button.active { border-color: var(--accent); color: var(--accent); }
|
|
49
|
+
.result {
|
|
50
|
+
margin-top: 1.5rem; padding: 1.1rem 1.25rem;
|
|
51
|
+
background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
|
|
52
|
+
display: grid; gap: 0.6rem;
|
|
53
|
+
}
|
|
54
|
+
.result .line { display: flex; align-items: baseline; justify-content: space-between; }
|
|
55
|
+
.result .label { color: var(--muted); font-size: 0.85rem; }
|
|
56
|
+
.result .value { font-size: 1.15rem; font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
57
|
+
.result .line.total .value { font-size: 1.7rem; color: var(--accent); }
|
|
58
|
+
</style>
|
|
59
|
+
</head>
|
|
60
|
+
<body>
|
|
61
|
+
<main class="app">
|
|
62
|
+
<h1>Tip Splitter</h1>
|
|
63
|
+
<p class="subtitle">Split a bill and tip evenly across the table.</p>
|
|
64
|
+
|
|
65
|
+
<label for="bill">Bill amount</label>
|
|
66
|
+
<input id="bill" type="number" min="0" step="0.01" value="86.40" inputmode="decimal" />
|
|
67
|
+
|
|
68
|
+
<label>Tip percentage</label>
|
|
69
|
+
<div class="tips" id="tips">
|
|
70
|
+
<button data-tip="10">10%</button>
|
|
71
|
+
<button data-tip="15" class="active">15%</button>
|
|
72
|
+
<button data-tip="18">18%</button>
|
|
73
|
+
<button data-tip="20">20%</button>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<label for="people">Number of people</label>
|
|
77
|
+
<input id="people" type="number" min="1" step="1" value="4" inputmode="numeric" />
|
|
78
|
+
|
|
79
|
+
<div class="result">
|
|
80
|
+
<div class="line">
|
|
81
|
+
<span class="label">Tip amount</span>
|
|
82
|
+
<span class="value" id="tipOut">0.00</span>
|
|
83
|
+
</div>
|
|
84
|
+
<div class="line total">
|
|
85
|
+
<span class="label">Each person pays</span>
|
|
86
|
+
<span class="value" id="perOut">0.00</span>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</main>
|
|
90
|
+
|
|
91
|
+
<script>
|
|
92
|
+
(function () {
|
|
93
|
+
var bill = document.getElementById("bill");
|
|
94
|
+
var people = document.getElementById("people");
|
|
95
|
+
var tips = document.getElementById("tips");
|
|
96
|
+
var tipOut = document.getElementById("tipOut");
|
|
97
|
+
var perOut = document.getElementById("perOut");
|
|
98
|
+
var tipPct = 15;
|
|
99
|
+
|
|
100
|
+
function render() {
|
|
101
|
+
var amount = parseFloat(bill.value) || 0;
|
|
102
|
+
var n = Math.max(1, parseInt(people.value, 10) || 1);
|
|
103
|
+
var tip = amount * (tipPct / 100);
|
|
104
|
+
var perPerson = (amount + tip) / n;
|
|
105
|
+
tipOut.textContent = tip.toFixed(2);
|
|
106
|
+
perOut.textContent = perPerson.toFixed(2);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
tips.addEventListener("click", function (e) {
|
|
110
|
+
var btn = e.target.closest("button");
|
|
111
|
+
if (!btn) return;
|
|
112
|
+
tipPct = parseFloat(btn.getAttribute("data-tip"));
|
|
113
|
+
Array.prototype.forEach.call(tips.children, function (b) {
|
|
114
|
+
b.classList.toggle("active", b === btn);
|
|
115
|
+
});
|
|
116
|
+
render();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
bill.addEventListener("input", render);
|
|
120
|
+
people.addEventListener("input", render);
|
|
121
|
+
render();
|
|
122
|
+
})();
|
|
123
|
+
</script>
|
|
124
|
+
</body>
|
|
125
|
+
</html>
|
package/src/corpus/install.md
CHANGED
|
@@ -86,7 +86,8 @@ Then point your agent at the cloned directory.
|
|
|
86
86
|
|
|
87
87
|
## MCP server
|
|
88
88
|
|
|
89
|
-
The
|
|
89
|
+
The MCP server is published separately as
|
|
90
|
+
[`@cloudgrid-io/mcp`](https://github.com/cloudgrid-io/mcp):
|
|
90
91
|
|
|
91
92
|
```
|
|
92
93
|
npx -y @cloudgrid-io/mcp
|
|
@@ -82,8 +82,9 @@ walks through it end to end.
|
|
|
82
82
|
|
|
83
83
|
## MCP server
|
|
84
84
|
|
|
85
|
-
The
|
|
86
|
-
|
|
85
|
+
The MCP server is published separately as
|
|
86
|
+
[`@cloudgrid-io/mcp`](https://github.com/cloudgrid-io/mcp). It exposes the same
|
|
87
|
+
nine actions as MCP tools, for agents that speak the Model Context Protocol.
|
|
87
88
|
Install it with `npx -y @cloudgrid-io/mcp`, or point a remote-capable client at
|
|
88
89
|
`https://mcp.cloudgrid.io/mcp`. See [USAGE.md](USAGE.md) for per-client setup.
|
|
89
90
|
|