@cyanheads/mcp-ts-core 0.6.8 → 0.6.9

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.
Files changed (77) hide show
  1. package/CLAUDE.md +1 -1
  2. package/README.md +1 -1
  3. package/changelog/0.6.x/0.6.9.md +21 -0
  4. package/dist/core/serverManifest.d.ts +12 -0
  5. package/dist/core/serverManifest.d.ts.map +1 -1
  6. package/dist/core/serverManifest.js +25 -0
  7. package/dist/core/serverManifest.js.map +1 -1
  8. package/dist/linter/rules/landing-rules.d.ts.map +1 -1
  9. package/dist/linter/rules/landing-rules.js +1 -20
  10. package/dist/linter/rules/landing-rules.js.map +1 -1
  11. package/dist/mcp-server/transports/http/httpTransport.js +1 -1
  12. package/dist/mcp-server/transports/http/httpTransport.js.map +1 -1
  13. package/dist/mcp-server/transports/http/landing-page/assets/copy-script.d.ts +11 -0
  14. package/dist/mcp-server/transports/http/landing-page/assets/copy-script.d.ts.map +1 -0
  15. package/dist/mcp-server/transports/http/landing-page/assets/copy-script.js +36 -0
  16. package/dist/mcp-server/transports/http/landing-page/assets/copy-script.js.map +1 -0
  17. package/dist/mcp-server/transports/http/landing-page/assets/styles.d.ts +21 -0
  18. package/dist/mcp-server/transports/http/landing-page/assets/styles.d.ts.map +1 -0
  19. package/dist/mcp-server/transports/http/landing-page/assets/styles.js +921 -0
  20. package/dist/mcp-server/transports/http/landing-page/assets/styles.js.map +1 -0
  21. package/dist/mcp-server/transports/http/landing-page/handler.d.ts +32 -0
  22. package/dist/mcp-server/transports/http/landing-page/handler.d.ts.map +1 -0
  23. package/dist/mcp-server/transports/http/landing-page/handler.js +92 -0
  24. package/dist/mcp-server/transports/http/landing-page/handler.js.map +1 -0
  25. package/dist/mcp-server/transports/http/landing-page/index.d.ts +27 -0
  26. package/dist/mcp-server/transports/http/landing-page/index.d.ts.map +1 -0
  27. package/dist/mcp-server/transports/http/landing-page/index.js +27 -0
  28. package/dist/mcp-server/transports/http/landing-page/index.js.map +1 -0
  29. package/dist/mcp-server/transports/http/landing-page/primitives.d.ts +19 -0
  30. package/dist/mcp-server/transports/http/landing-page/primitives.d.ts.map +1 -0
  31. package/dist/mcp-server/transports/http/landing-page/primitives.js +38 -0
  32. package/dist/mcp-server/transports/http/landing-page/primitives.js.map +1 -0
  33. package/dist/mcp-server/transports/http/landing-page/render.d.ts +16 -0
  34. package/dist/mcp-server/transports/http/landing-page/render.d.ts.map +1 -0
  35. package/dist/mcp-server/transports/http/landing-page/render.js +57 -0
  36. package/dist/mcp-server/transports/http/landing-page/render.js.map +1 -0
  37. package/dist/mcp-server/transports/http/landing-page/sections/connect.d.ts +19 -0
  38. package/dist/mcp-server/transports/http/landing-page/sections/connect.d.ts.map +1 -0
  39. package/dist/mcp-server/transports/http/landing-page/sections/connect.js +130 -0
  40. package/dist/mcp-server/transports/http/landing-page/sections/connect.js.map +1 -0
  41. package/dist/mcp-server/transports/http/landing-page/sections/extensions.d.ts +10 -0
  42. package/dist/mcp-server/transports/http/landing-page/sections/extensions.d.ts.map +1 -0
  43. package/dist/mcp-server/transports/http/landing-page/sections/extensions.js +30 -0
  44. package/dist/mcp-server/transports/http/landing-page/sections/extensions.js.map +1 -0
  45. package/dist/mcp-server/transports/http/landing-page/sections/footer.d.ts +12 -0
  46. package/dist/mcp-server/transports/http/landing-page/sections/footer.d.ts.map +1 -0
  47. package/dist/mcp-server/transports/http/landing-page/sections/footer.js +49 -0
  48. package/dist/mcp-server/transports/http/landing-page/sections/footer.js.map +1 -0
  49. package/dist/mcp-server/transports/http/landing-page/sections/head.d.ts +11 -0
  50. package/dist/mcp-server/transports/http/landing-page/sections/head.d.ts.map +1 -0
  51. package/dist/mcp-server/transports/http/landing-page/sections/head.js +68 -0
  52. package/dist/mcp-server/transports/http/landing-page/sections/head.js.map +1 -0
  53. package/dist/mcp-server/transports/http/landing-page/sections/hero.d.ts +12 -0
  54. package/dist/mcp-server/transports/http/landing-page/sections/hero.d.ts.map +1 -0
  55. package/dist/mcp-server/transports/http/landing-page/sections/hero.js +48 -0
  56. package/dist/mcp-server/transports/http/landing-page/sections/hero.js.map +1 -0
  57. package/dist/mcp-server/transports/http/landing-page/sections/prompts.d.ts +11 -0
  58. package/dist/mcp-server/transports/http/landing-page/sections/prompts.d.ts.map +1 -0
  59. package/dist/mcp-server/transports/http/landing-page/sections/prompts.js +48 -0
  60. package/dist/mcp-server/transports/http/landing-page/sections/prompts.js.map +1 -0
  61. package/dist/mcp-server/transports/http/landing-page/sections/resources.d.ts +10 -0
  62. package/dist/mcp-server/transports/http/landing-page/sections/resources.d.ts.map +1 -0
  63. package/dist/mcp-server/transports/http/landing-page/sections/resources.js +44 -0
  64. package/dist/mcp-server/transports/http/landing-page/sections/resources.js.map +1 -0
  65. package/dist/mcp-server/transports/http/landing-page/sections/status-strip.d.ts +18 -0
  66. package/dist/mcp-server/transports/http/landing-page/sections/status-strip.d.ts.map +1 -0
  67. package/dist/mcp-server/transports/http/landing-page/sections/status-strip.js +71 -0
  68. package/dist/mcp-server/transports/http/landing-page/sections/status-strip.js.map +1 -0
  69. package/dist/mcp-server/transports/http/landing-page/sections/tools.d.ts +13 -0
  70. package/dist/mcp-server/transports/http/landing-page/sections/tools.d.ts.map +1 -0
  71. package/dist/mcp-server/transports/http/landing-page/sections/tools.js +130 -0
  72. package/dist/mcp-server/transports/http/landing-page/sections/tools.js.map +1 -0
  73. package/package.json +1 -1
  74. package/dist/mcp-server/transports/http/landing-page.d.ts +0 -48
  75. package/dist/mcp-server/transports/http/landing-page.d.ts.map +0 -1
  76. package/dist/mcp-server/transports/http/landing-page.js +0 -1621
  77. package/dist/mcp-server/transports/http/landing-page.js.map +0 -1
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @fileoverview Single-row dim footer with separator-dot-delimited links.
3
+ * Merges user-supplied `landing.links` with an auto-derived GitHub cluster
4
+ * (changelog, release tag, issues, source), an npm link when published, and
5
+ * the framework attribution when `landing.attribution` is enabled.
6
+ *
7
+ * @module src/mcp-server/transports/http/landing-page/sections/footer
8
+ */
9
+ import { html } from '../../../../../utils/formatting/html.js';
10
+ export function renderFooter(manifest) {
11
+ const { landing, framework } = manifest;
12
+ const links = [];
13
+ // User-supplied links
14
+ for (const link of landing.links) {
15
+ links.push({ href: link.href, label: link.label });
16
+ }
17
+ // Auto-derived GitHub cluster
18
+ if (landing.repoRoot) {
19
+ const repo = landing.repoRoot;
20
+ const version = manifest.server.version;
21
+ links.push({
22
+ href: landing.changelogUrl ?? `${repo.url}/blob/main/CHANGELOG.md`,
23
+ label: 'Changelog',
24
+ });
25
+ links.push({
26
+ href: `${repo.url}/releases/tag/v${version}`,
27
+ label: `v${version}`,
28
+ });
29
+ links.push({ href: `${repo.url}/issues`, label: 'Issues' });
30
+ links.push({ href: repo.url, label: 'Source' });
31
+ }
32
+ // Package / registry
33
+ if (landing.npmPackage) {
34
+ links.push({ href: landing.npmPackage.url, label: 'npm' });
35
+ }
36
+ const frameworkNpm = `https://www.npmjs.com/package/${encodeURIComponent(framework.name)}`;
37
+ const linkEls = links.map((l, i) => html `${i > 0 ? html `<span class="footer-sep">·</span>` : html ``}<a href="${l.href}" rel="noopener">${l.label}</a>`);
38
+ const attribution = landing.attribution
39
+ ? html `<span class="footer-attrib">built on <a href="${framework.homepage}">${framework.name}</a> v${framework.version} · <a href="${frameworkNpm}" rel="noopener">npm</a></span>`
40
+ : html ``;
41
+ return html `
42
+ <footer>
43
+ ${linkEls}
44
+ <span class="footer-spacer"></span>
45
+ ${attribution}
46
+ </footer>
47
+ `;
48
+ }
49
+ //# sourceMappingURL=footer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/footer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,IAAI,EAAiB,MAAM,4BAA4B,CAAC;AAEjE,MAAM,UAAU,YAAY,CAAC,QAAwB;IACnD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;IACxC,MAAM,KAAK,GAA2C,EAAE,CAAC;IAEzD,sBAAsB;IACtB,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,8BAA8B;IAC9B,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC9B,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,OAAO,CAAC,YAAY,IAAI,GAAG,IAAI,CAAC,GAAG,yBAAyB;YAClE,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,kBAAkB,OAAO,EAAE;YAC5C,KAAK,EAAE,IAAI,OAAO,EAAE;SACrB,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,qBAAqB;IACrB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,YAAY,GAAG,iCAAiC,kBAAkB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;IAE3F,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CACvB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,IAAI,CAAA,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,mCAAmC,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE,YAAY,CAAC,CAAC,IAAI,oBAAoB,CAAC,CAAC,KAAK,MAAM,CACrH,CAAC;IAEF,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW;QACrC,CAAC,CAAC,IAAI,CAAA,iDAAiD,SAAS,CAAC,QAAQ,KAAK,SAAS,CAAC,IAAI,SAAS,SAAS,CAAC,OAAO,eAAe,YAAY,iCAAiC;QAClL,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IAEX,OAAO,IAAI,CAAA;;QAEL,OAAO;;QAEP,WAAW;;GAEhB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @fileoverview `<head>` metadata renderer — title, description, Open Graph
3
+ * tags, theme color, JSON-LD structured data, favicon (when a data URI logo
4
+ * is available), and the `mcp-endpoint` / server-card alternate links.
5
+ *
6
+ * @module src/mcp-server/transports/http/landing-page/sections/head
7
+ */
8
+ import type { ServerManifest } from '../../../../../core/serverManifest.js';
9
+ import { type SafeHtml } from '../../../../../utils/formatting/html.js';
10
+ export declare function renderHead(manifest: ServerManifest, pageUrl: string): SafeHtml;
11
+ //# sourceMappingURL=head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/head.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAQ,KAAK,QAAQ,EAAa,MAAM,4BAA4B,CAAC;AAE5E,wBAAgB,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CA0C9E"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @fileoverview `<head>` metadata renderer — title, description, Open Graph
3
+ * tags, theme color, JSON-LD structured data, favicon (when a data URI logo
4
+ * is available), and the `mcp-endpoint` / server-card alternate links.
5
+ *
6
+ * @module src/mcp-server/transports/http/landing-page/sections/head
7
+ */
8
+ import { html, unsafeRaw } from '../../../../../utils/formatting/html.js';
9
+ export function renderHead(manifest, pageUrl) {
10
+ const { server, landing } = manifest;
11
+ const title = `${server.name} · MCP server`;
12
+ const description = landing.tagline ?? server.description ?? `MCP server: ${server.name}`;
13
+ const ogImage = landing.logo?.startsWith('http')
14
+ ? html `<meta property="og:image" content="${landing.logo}" />`
15
+ : html ``;
16
+ const favicon = landing.logo && isImageDataUri(landing.logo)
17
+ ? html `<link rel="icon" href="${landing.logo}" />`
18
+ : html ``;
19
+ const themeColor = html `<meta name="theme-color" content="${landing.theme.accent}" />`;
20
+ const jsonLd = JSON.stringify({
21
+ '@context': 'https://schema.org',
22
+ '@type': 'SoftwareApplication',
23
+ name: server.name,
24
+ description,
25
+ applicationCategory: 'DeveloperApplication',
26
+ softwareVersion: server.version,
27
+ ...(server.homepage && { url: server.homepage }),
28
+ });
29
+ return html `
30
+ <meta charset="utf-8" />
31
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
32
+ <title>${title}</title>
33
+ <meta name="description" content="${description}" />
34
+ ${themeColor}
35
+ <meta property="og:title" content="${title}" />
36
+ <meta property="og:description" content="${description}" />
37
+ <meta property="og:type" content="website" />
38
+ <meta property="og:url" content="${pageUrl}" />
39
+ ${ogImage}
40
+ <meta name="twitter:card" content="summary" />
41
+ <meta name="twitter:title" content="${title}" />
42
+ <meta name="twitter:description" content="${description}" />
43
+ ${favicon}
44
+ <link rel="mcp-endpoint" href="${manifest.transport.endpointPath}" />
45
+ <link rel="alternate" type="application/json" href="/.well-known/mcp.json" title="MCP Server Card" />
46
+ <script type="application/ld+json">${unsafeRaw(escapeLdJson(jsonLd))}</script>
47
+ `;
48
+ }
49
+ function isImageDataUri(value) {
50
+ if (!value)
51
+ return false;
52
+ return /^data:image\/(png|svg\+xml|jpeg|gif|webp|x-icon|vnd\.microsoft\.icon)/i.test(value);
53
+ }
54
+ /**
55
+ * Escape a JSON string for safe embedding inside `<script type="application/ld+json">`.
56
+ * Replaces HTML-sensitive characters with Unicode escapes — `<` → `<`,
57
+ * `>` → `>`, `&` → `&`, U+2028/U+2029 line terminators → escaped.
58
+ * Matches the hardening recommendation in https://html.spec.whatwg.org/#script-data-state.
59
+ */
60
+ function escapeLdJson(json) {
61
+ return json
62
+ .replace(/</g, '\\u003c')
63
+ .replace(/>/g, '\\u003e')
64
+ .replace(/&/g, '\\u0026')
65
+ .replace(/\u2028/g, '\\u2028')
66
+ .replace(/\u2029/g, '\\u2029');
67
+ }
68
+ //# sourceMappingURL=head.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/head.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,IAAI,EAAiB,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5E,MAAM,UAAU,UAAU,CAAC,QAAwB,EAAE,OAAe;IAClE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IACrC,MAAM,KAAK,GAAG,GAAG,MAAM,CAAC,IAAI,eAAe,CAAC;IAC5C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,WAAW,IAAI,eAAe,MAAM,CAAC,IAAI,EAAE,CAAC;IAC1F,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC;QAC9C,CAAC,CAAC,IAAI,CAAA,sCAAsC,OAAO,CAAC,IAAI,MAAM;QAC9D,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IACX,MAAM,OAAO,GACX,OAAO,CAAC,IAAI,IAAI,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC;QAC1C,CAAC,CAAC,IAAI,CAAA,0BAA0B,OAAO,CAAC,IAAI,MAAM;QAClD,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IACb,MAAM,UAAU,GAAG,IAAI,CAAA,qCAAqC,OAAO,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC;IAEvF,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;QAC5B,UAAU,EAAE,oBAAoB;QAChC,OAAO,EAAE,qBAAqB;QAC9B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW;QACX,mBAAmB,EAAE,sBAAsB;QAC3C,eAAe,EAAE,MAAM,CAAC,OAAO;QAC/B,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;KACjD,CAAC,CAAC;IAEH,OAAO,IAAI,CAAA;;;aAGA,KAAK;wCACsB,WAAW;MAC7C,UAAU;yCACyB,KAAK;+CACC,WAAW;;uCAEnB,OAAO;MACxC,OAAO;;0CAE6B,KAAK;gDACC,WAAW;MACrD,OAAO;qCACwB,QAAQ,CAAC,SAAS,CAAC,YAAY;;yCAE3B,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;GACrE,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,wEAAwE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9F,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI;SACR,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;SACxB,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;SACxB,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;SACxB,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;SAC7B,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @fileoverview Hero section — eyebrow, optional logo, display-size server
3
+ * name, version + pre-release chips, tagline, status strip, terminal-chrome
4
+ * connect card, and framework attribution pill. The connect card is omitted
5
+ * in degraded (unauth) mode.
6
+ *
7
+ * @module src/mcp-server/transports/http/landing-page/sections/hero
8
+ */
9
+ import type { ServerManifest } from '../../../../../core/serverManifest.js';
10
+ import { type SafeHtml } from '../../../../../utils/formatting/html.js';
11
+ export declare function renderHero(manifest: ServerManifest, baseUrl: string, degraded: boolean): SafeHtml;
12
+ //# sourceMappingURL=hero.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hero.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/hero.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAMjE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAwCjG"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @fileoverview Hero section — eyebrow, optional logo, display-size server
3
+ * name, version + pre-release chips, tagline, status strip, terminal-chrome
4
+ * connect card, and framework attribution pill. The connect card is omitted
5
+ * in degraded (unauth) mode.
6
+ *
7
+ * @module src/mcp-server/transports/http/landing-page/sections/hero
8
+ */
9
+ import { html } from '../../../../../utils/formatting/html.js';
10
+ import { renderFrameworkBadge } from '../primitives.js';
11
+ import { renderConnectSnippets } from './connect.js';
12
+ import { renderStatusStrip } from './status-strip.js';
13
+ export function renderHero(manifest, baseUrl, degraded) {
14
+ const { server, landing } = manifest;
15
+ const releaseUrl = landing.repoRoot
16
+ ? `${landing.repoRoot.url}/releases/tag/v${server.version}`
17
+ : undefined;
18
+ const versionBadge = releaseUrl
19
+ ? html `<a class="badge-version" href="${releaseUrl}" aria-label="v${server.version} release notes">v${server.version}</a>`
20
+ : html `<span class="badge-version">v${server.version}</span>`;
21
+ const preReleaseBadge = landing.preRelease.isPreRelease
22
+ ? html `<span class="badge-pre">${landing.preRelease.label ?? 'pre-release'}</span>`
23
+ : html ``;
24
+ const tagline = landing.tagline ?? server.description ?? '';
25
+ const logo = landing.logo
26
+ ? html `<img class="hero-logo" src="${landing.logo}" alt="" aria-hidden="true" />`
27
+ : html ``;
28
+ const frameworkBadge = landing.attribution
29
+ ? html `<div class="hero-badges">${renderFrameworkBadge(manifest.framework)}</div>`
30
+ : html ``;
31
+ const connect = degraded ? html `` : renderConnectSnippets(manifest, baseUrl);
32
+ return html `
33
+ <header class="hero">
34
+ <span class="hero-eyebrow" aria-hidden="true">MCP Server</span>
35
+ <div class="hero-title-row">
36
+ ${logo}
37
+ <h1 class="hero-heading">${server.name}</h1>
38
+ ${versionBadge}
39
+ ${preReleaseBadge}
40
+ </div>
41
+ ${tagline ? html `<p class="hero-tagline">${tagline}</p>` : html ``}
42
+ ${renderStatusStrip(manifest, degraded)}
43
+ ${connect}
44
+ ${frameworkBadge}
45
+ </header>
46
+ `;
47
+ }
48
+ //# sourceMappingURL=hero.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hero.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/hero.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,IAAI,EAAiB,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,UAAU,UAAU,CAAC,QAAwB,EAAE,OAAe,EAAE,QAAiB;IACrF,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IACrC,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ;QACjC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,kBAAkB,MAAM,CAAC,OAAO,EAAE;QAC3D,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,YAAY,GAAG,UAAU;QAC7B,CAAC,CAAC,IAAI,CAAA,kCAAkC,UAAU,kBAAkB,MAAM,CAAC,OAAO,oBAAoB,MAAM,CAAC,OAAO,MAAM;QAC1H,CAAC,CAAC,IAAI,CAAA,gCAAgC,MAAM,CAAC,OAAO,SAAS,CAAC;IAEhE,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY;QACrD,CAAC,CAAC,IAAI,CAAA,2BAA2B,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,aAAa,SAAS;QACnF,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IAEX,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAC5D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI;QACvB,CAAC,CAAC,IAAI,CAAA,+BAA+B,OAAO,CAAC,IAAI,gCAAgC;QACjF,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IAEX,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW;QACxC,CAAC,CAAC,IAAI,CAAA,4BAA4B,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ;QAClF,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IAEX,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE7E,OAAO,IAAI,CAAA;;;;UAIH,IAAI;mCACqB,MAAM,CAAC,IAAI;UACpC,YAAY;UACZ,eAAe;;QAEjB,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,2BAA2B,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;QAC/D,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACrC,OAAO;QACP,cAAc;;GAEnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @fileoverview Prompts section — responsive card grid showing each prompt's
3
+ * description, args list (with required markers + inline descriptions), and
4
+ * optional source link.
5
+ *
6
+ * @module src/mcp-server/transports/http/landing-page/sections/prompts
7
+ */
8
+ import type { ManifestPrompt } from '../../../../../core/serverManifest.js';
9
+ import { type SafeHtml } from '../../../../../utils/formatting/html.js';
10
+ export declare function renderPromptsSection(prompts: ManifestPrompt[]): SafeHtml;
11
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAIjE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,QAAQ,CAQxE"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @fileoverview Prompts section — responsive card grid showing each prompt's
3
+ * description, args list (with required markers + inline descriptions), and
4
+ * optional source link.
5
+ *
6
+ * @module src/mcp-server/transports/http/landing-page/sections/prompts
7
+ */
8
+ import { html } from '../../../../../utils/formatting/html.js';
9
+ import { renderSectionHeading } from '../primitives.js';
10
+ export function renderPromptsSection(prompts) {
11
+ if (prompts.length === 0)
12
+ return html ``;
13
+ return html `
14
+ <section aria-labelledby="section-prompts">
15
+ ${renderSectionHeading('section-prompts', 'Prompts', prompts.length)}
16
+ <div class="card-grid">${prompts.map(renderPromptCard)}</div>
17
+ </section>
18
+ `;
19
+ }
20
+ function renderPromptCard(prompt) {
21
+ const anchor = `prompt-${prompt.name}`;
22
+ const source = prompt.sourceUrl
23
+ ? html `<a class="source-link" href="${prompt.sourceUrl}" rel="noopener">view source ↗</a>`
24
+ : html ``;
25
+ const argsList = prompt.args.length > 0
26
+ ? html `
27
+ <ul class="args-list">
28
+ ${prompt.args.map((arg) => html `
29
+ <li>
30
+ <code>${arg.name}</code>${arg.required ? html `<span class="args-required">required</span>` : html ``}
31
+ ${arg.description ? html ` — ${arg.description}` : html ``}
32
+ </li>
33
+ `)}
34
+ </ul>
35
+ `
36
+ : html ``;
37
+ return html `
38
+ <article class="card" id="${anchor}">
39
+ <div class="card-head">
40
+ <h3 class="card-title"><a href="#${anchor}">${prompt.name}</a></h3>
41
+ ${source}
42
+ </div>
43
+ <p class="card-desc">${prompt.description}</p>
44
+ ${argsList}
45
+ </article>
46
+ `;
47
+ }
48
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,IAAI,EAAiB,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,UAAU,oBAAoB,CAAC,OAAyB;IAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA,EAAE,CAAC;IACxC,OAAO,IAAI,CAAA;;QAEL,oBAAoB,CAAC,iBAAiB,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC;+BAC3C,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;;GAEzD,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAsB;IAC9C,MAAM,MAAM,GAAG,UAAU,MAAM,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS;QAC7B,CAAC,CAAC,IAAI,CAAA,gCAAgC,MAAM,CAAC,SAAS,oCAAoC;QAC1F,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IAEX,MAAM,QAAQ,GACZ,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QACpB,CAAC,CAAC,IAAI,CAAA;;YAEA,MAAM,CAAC,IAAI,CAAC,GAAG,CACf,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAA;;wBAED,GAAG,CAAC,IAAI,UACd,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,6CAA6C,CAAC,CAAC,CAAC,IAAI,CAAA,EACzE;kBACE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;;aAE3D,CACF;;OAEJ;QACD,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IAEb,OAAO,IAAI,CAAA;gCACmB,MAAM;;2CAEK,MAAM,KAAK,MAAM,CAAC,IAAI;UACvD,MAAM;;6BAEa,MAAM,CAAC,WAAW;QACvC,QAAQ;;GAEb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Resources section — responsive card grid showing each
3
+ * resource's URI template, mime type, description, and optional source link.
4
+ *
5
+ * @module src/mcp-server/transports/http/landing-page/sections/resources
6
+ */
7
+ import type { ManifestResource } from '../../../../../core/serverManifest.js';
8
+ import { type SafeHtml } from '../../../../../utils/formatting/html.js';
9
+ export declare function renderResourcesSection(resources: ManifestResource[]): SafeHtml;
10
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/resources.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAIjE,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,gBAAgB,EAAE,GAAG,QAAQ,CAQ9E"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @fileoverview Resources section — responsive card grid showing each
3
+ * resource's URI template, mime type, description, and optional source link.
4
+ *
5
+ * @module src/mcp-server/transports/http/landing-page/sections/resources
6
+ */
7
+ import { html } from '../../../../../utils/formatting/html.js';
8
+ import { renderSectionHeading } from '../primitives.js';
9
+ export function renderResourcesSection(resources) {
10
+ if (resources.length === 0)
11
+ return html ``;
12
+ return html `
13
+ <section aria-labelledby="section-resources">
14
+ ${renderSectionHeading('section-resources', 'Resources', resources.length)}
15
+ <div class="card-grid">${resources.map(renderResourceCard)}</div>
16
+ </section>
17
+ `;
18
+ }
19
+ function renderResourceCard(resource) {
20
+ const anchor = `resource-${slugifyUri(resource.uriTemplate || resource.name)}`;
21
+ const source = resource.sourceUrl
22
+ ? html `<a class="source-link" href="${resource.sourceUrl}" rel="noopener">view source ↗</a>`
23
+ : html ``;
24
+ return html `
25
+ <article class="card" id="${anchor}">
26
+ <div class="card-head">
27
+ <h3 class="card-title"><a href="#${anchor}">${resource.name}</a></h3>
28
+ ${source}
29
+ </div>
30
+ <p class="card-desc">${resource.description}</p>
31
+ <div class="card-meta">
32
+ <span><span class="card-meta-label">uri</span> <code>${resource.uriTemplate}</code></span>
33
+ ${resource.mimeType ? html `<span><span class="card-meta-label">mime</span> <code>${resource.mimeType}</code></span>` : html ``}
34
+ </div>
35
+ </article>
36
+ `;
37
+ }
38
+ function slugifyUri(template) {
39
+ return template
40
+ .replace(/[^a-z0-9]+/gi, '-')
41
+ .replace(/^-+|-+$/g, '')
42
+ .toLowerCase();
43
+ }
44
+ //# sourceMappingURL=resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/resources.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,IAAI,EAAiB,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,UAAU,sBAAsB,CAAC,SAA6B;IAClE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA,EAAE,CAAC;IAC1C,OAAO,IAAI,CAAA;;QAEL,oBAAoB,CAAC,mBAAmB,EAAE,WAAW,EAAE,SAAS,CAAC,MAAM,CAAC;+BACjD,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC;;GAE7D,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,QAA0B;IACpD,MAAM,MAAM,GAAG,YAAY,UAAU,CAAC,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IAC/E,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS;QAC/B,CAAC,CAAC,IAAI,CAAA,gCAAgC,QAAQ,CAAC,SAAS,oCAAoC;QAC5F,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IAEX,OAAO,IAAI,CAAA;gCACmB,MAAM;;2CAEK,MAAM,KAAK,QAAQ,CAAC,IAAI;UACzD,MAAM;;6BAEa,QAAQ,CAAC,WAAW;;+DAEc,QAAQ,CAAC,WAAW;UACzE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,yDAAyD,QAAQ,CAAC,QAAQ,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;;;GAGlI,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,QAAQ;SACZ,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @fileoverview Single-line status strip under the hero. Communicates auth
3
+ * mode, capability counts, and protocol version in one mono-spaced,
4
+ * dot-separated row.
5
+ *
6
+ * Accessibility: the container carries an `aria-label` with the long-form
7
+ * auth phrase ("Public access", "Requires OAuth", etc.) so assistive tech
8
+ * reads the gated-ness even when the visible label is compact ("public",
9
+ * "oauth"). The strip is static after initial render, so `role="status"`
10
+ * (meant for live regions) would announce on page load as if it were a
11
+ * change — we deliberately omit it.
12
+ *
13
+ * @module src/mcp-server/transports/http/landing-page/sections/status-strip
14
+ */
15
+ import type { ServerManifest } from '../../../../../core/serverManifest.js';
16
+ import { type SafeHtml } from '../../../../../utils/formatting/html.js';
17
+ export declare function renderStatusStrip(manifest: ServerManifest, degraded: boolean): SafeHtml;
18
+ //# sourceMappingURL=status-strip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-strip.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/status-strip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAgB,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEjE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAuCvF"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @fileoverview Single-line status strip under the hero. Communicates auth
3
+ * mode, capability counts, and protocol version in one mono-spaced,
4
+ * dot-separated row.
5
+ *
6
+ * Accessibility: the container carries an `aria-label` with the long-form
7
+ * auth phrase ("Public access", "Requires OAuth", etc.) so assistive tech
8
+ * reads the gated-ness even when the visible label is compact ("public",
9
+ * "oauth"). The strip is static after initial render, so `role="status"`
10
+ * (meant for live regions) would announce on page load as if it were a
11
+ * change — we deliberately omit it.
12
+ *
13
+ * @module src/mcp-server/transports/http/landing-page/sections/status-strip
14
+ */
15
+ import { html } from '../../../../../utils/formatting/html.js';
16
+ export function renderStatusStrip(manifest, degraded) {
17
+ const { auth, definitionCounts, protocol } = manifest;
18
+ const authMeta = describeAuth(auth);
19
+ // Counts hidden in degraded mode to avoid leaking inventory shape.
20
+ const counts = degraded
21
+ ? []
22
+ : [
23
+ { n: definitionCounts.tools, label: 'tools' },
24
+ { n: definitionCounts.resources, label: 'resources' },
25
+ { n: definitionCounts.prompts, label: 'prompts' },
26
+ ].filter((c) => c.n > 0);
27
+ const signin = auth.mode === 'oauth' && auth.oauthIssuer
28
+ ? html ` <a class="status-signin" href="${auth.oauthIssuer}" rel="noopener">sign in ↗</a>`
29
+ : html ``;
30
+ return html `
31
+ <div class="status-strip" aria-label="${authMeta.ariaLabel}">
32
+ <span class="status-item" title="${authMeta.ariaLabel}">
33
+ <span class="status-dot ${authMeta.dotClass}" aria-hidden="true"></span>
34
+ <span class="status-value">${authMeta.label}</span>${signin}
35
+ </span>
36
+ ${counts.map((c) => html `
37
+ <a class="status-item status-link" href="#section-${c.label}">
38
+ <span class="status-value">${String(c.n)}</span>
39
+ <span>${c.label}</span>
40
+ </a>
41
+ `)}
42
+ <span class="status-item" title="MCP protocol version ${protocol.latestVersion}">
43
+ <span>protocol</span>
44
+ <span class="status-value status-value-accent">${protocol.latestVersion}</span>
45
+ </span>
46
+ </div>
47
+ `;
48
+ }
49
+ /** Visible label, dot class, and long-form aria phrase for the auth strip item. */
50
+ function describeAuth(auth) {
51
+ if (auth.mode === 'none') {
52
+ return {
53
+ label: 'public',
54
+ dotClass: 'status-dot-public',
55
+ ariaLabel: 'Public access — no authentication required',
56
+ };
57
+ }
58
+ if (auth.mode === 'jwt') {
59
+ return {
60
+ label: 'bearer',
61
+ dotClass: 'status-dot-gated',
62
+ ariaLabel: 'Requires a bearer token',
63
+ };
64
+ }
65
+ return {
66
+ label: 'oauth',
67
+ dotClass: 'status-dot-gated',
68
+ ariaLabel: 'Requires OAuth',
69
+ };
70
+ }
71
+ //# sourceMappingURL=status-strip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-strip.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/status-strip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,IAAI,EAAiB,MAAM,4BAA4B,CAAC;AAEjE,MAAM,UAAU,iBAAiB,CAAC,QAAwB,EAAE,QAAiB;IAC3E,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAEtD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAEpC,mEAAmE;IACnE,MAAM,MAAM,GAAG,QAAQ;QACrB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC;YACE,EAAE,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE;YAC7C,EAAE,CAAC,EAAE,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE;YACrD,EAAE,CAAC,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE;SAClD,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAE7B,MAAM,MAAM,GACV,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,WAAW;QACvC,CAAC,CAAC,IAAI,CAAA,mCAAmC,IAAI,CAAC,WAAW,gCAAgC;QACzF,CAAC,CAAC,IAAI,CAAA,EAAE,CAAC;IAEb,OAAO,IAAI,CAAA;4CAC+B,QAAQ,CAAC,SAAS;yCACrB,QAAQ,CAAC,SAAS;kCACzB,QAAQ,CAAC,QAAQ;qCACd,QAAQ,CAAC,KAAK,UAAU,MAAM;;QAE3D,MAAM,CAAC,GAAG,CACV,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAA;8DAC2C,CAAC,CAAC,KAAK;yCAC5B,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;oBAChC,CAAC,CAAC,KAAK;;SAElB,CACF;8DACuD,QAAQ,CAAC,aAAa;;yDAE3B,QAAQ,CAAC,aAAa;;;GAG5E,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,SAAS,YAAY,CAAC,IAAkB;IAKtC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO;YACL,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,mBAAmB;YAC7B,SAAS,EAAE,4CAA4C;SACxD,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACxB,OAAO;YACL,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,kBAAkB;YAC5B,SAAS,EAAE,yBAAyB;SACrC,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE,kBAAkB;QAC5B,SAAS,EAAE,gBAAgB;KAC5B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @fileoverview Tools section — responsive 2-column card grid, optionally
3
+ * prefix-grouped when ≥2 tools share a common `snake_case` prefix. Each card
4
+ * carries annotation pills (read-only / destructive / open-world / task /
5
+ * app), auth scope chips, a JSON-RPC invocation snippet, and a collapsible
6
+ * input-schema preview.
7
+ *
8
+ * @module src/mcp-server/transports/http/landing-page/sections/tools
9
+ */
10
+ import type { ManifestTool } from '../../../../../core/serverManifest.js';
11
+ import { type SafeHtml } from '../../../../../utils/formatting/html.js';
12
+ export declare function renderToolsSection(tools: ManifestTool[]): SafeHtml;
13
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAIjE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,QAAQ,CAkBlE"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * @fileoverview Tools section — responsive 2-column card grid, optionally
3
+ * prefix-grouped when ≥2 tools share a common `snake_case` prefix. Each card
4
+ * carries annotation pills (read-only / destructive / open-world / task /
5
+ * app), auth scope chips, a JSON-RPC invocation snippet, and a collapsible
6
+ * input-schema preview.
7
+ *
8
+ * @module src/mcp-server/transports/http/landing-page/sections/tools
9
+ */
10
+ import { html } from '../../../../../utils/formatting/html.js';
11
+ import { renderPill, renderSectionHeading, renderSnippet } from '../primitives.js';
12
+ export function renderToolsSection(tools) {
13
+ if (tools.length === 0)
14
+ return html ``;
15
+ const groups = groupToolsByPrefix(tools);
16
+ // A single group — whether labeled or not — would render as redundant with
17
+ // the section header. Skip the sub-heading; render a flat grid.
18
+ const showHeadings = groups.length > 1;
19
+ const body = groups.map((group) => {
20
+ const heading = showHeadings && group.label ? html `<h4 class="group-heading">${group.label}</h4>` : html ``;
21
+ return html `${heading}<div class="card-grid">${group.tools.map(renderToolCard)}</div>`;
22
+ });
23
+ return html `
24
+ <section aria-labelledby="section-tools">
25
+ ${renderSectionHeading('section-tools', 'Tools', tools.length)}
26
+ ${body}
27
+ </section>
28
+ `;
29
+ }
30
+ function renderToolCard(tool) {
31
+ const anchor = `tool-${tool.name}`;
32
+ const annotations = tool.annotations;
33
+ const pills = [];
34
+ if (annotations?.readOnlyHint)
35
+ pills.push(renderPill('read-only', 'readonly'));
36
+ if (annotations?.destructiveHint === true)
37
+ pills.push(renderPill('destructive', 'destructive'));
38
+ if (annotations?.openWorldHint)
39
+ pills.push(renderPill('open-world', 'openworld'));
40
+ if (tool.isTask)
41
+ pills.push(renderPill('task', 'task'));
42
+ if (tool.isApp)
43
+ pills.push(renderPill('app', 'app'));
44
+ const source = tool.sourceUrl
45
+ ? html `<a class="source-link" href="${tool.sourceUrl}" rel="noopener">view source ↗</a>`
46
+ : html ``;
47
+ const schemaPreview = tool.inputSchema
48
+ ? html `
49
+ <details>
50
+ <summary>Input schema</summary>
51
+ <pre><code>${JSON.stringify(tool.inputSchema, null, 2)}</code></pre>
52
+ </details>
53
+ `
54
+ : html ``;
55
+ const invocation = html `
56
+ <details>
57
+ <summary>Invocation</summary>
58
+ ${renderSnippet(`tool-${tool.name}`, buildInvocationSnippet(tool))}
59
+ </details>
60
+ `;
61
+ const authBadges = tool.auth && tool.auth.length > 0
62
+ ? html `<div class="card-meta"><span class="card-meta-label">scopes</span>${tool.auth.map((scope) => html ` <span class="pill pill-auth">${scope}</span>`)}</div>`
63
+ : html ``;
64
+ return html `
65
+ <article class="card" id="${anchor}">
66
+ <div class="card-head">
67
+ <h3 class="card-title"><a href="#${anchor}">${tool.name}</a></h3>
68
+ <div class="pill-row" role="list">${pills}</div>
69
+ ${source}
70
+ </div>
71
+ <p class="card-desc">${tool.description}</p>
72
+ ${authBadges}
73
+ ${invocation}
74
+ ${schemaPreview}
75
+ </article>
76
+ `;
77
+ }
78
+ function groupToolsByPrefix(tools) {
79
+ if (tools.length < 3)
80
+ return [{ label: null, tools }];
81
+ const prefixCounts = new Map();
82
+ for (const tool of tools) {
83
+ const prefix = tool.name.split('_', 1)[0];
84
+ if (!prefix)
85
+ continue;
86
+ prefixCounts.set(prefix, (prefixCounts.get(prefix) ?? 0) + 1);
87
+ }
88
+ const groupablePrefixes = new Set([...prefixCounts.entries()].filter(([, count]) => count >= 2).map(([p]) => p));
89
+ if (groupablePrefixes.size === 0)
90
+ return [{ label: null, tools }];
91
+ const groups = new Map();
92
+ const other = [];
93
+ for (const tool of tools) {
94
+ const prefix = tool.name.split('_', 1)[0];
95
+ if (prefix && groupablePrefixes.has(prefix)) {
96
+ const list = groups.get(prefix) ?? [];
97
+ list.push(tool);
98
+ groups.set(prefix, list);
99
+ }
100
+ else {
101
+ other.push(tool);
102
+ }
103
+ }
104
+ const out = [];
105
+ for (const [prefix, list] of groups) {
106
+ out.push({ label: titleCase(prefix), tools: list });
107
+ }
108
+ if (other.length > 0)
109
+ out.push({ label: 'Other', tools: other });
110
+ return out;
111
+ }
112
+ function titleCase(s) {
113
+ return s.charAt(0).toUpperCase() + s.slice(1);
114
+ }
115
+ function buildInvocationSnippet(tool) {
116
+ const args = {};
117
+ for (const field of tool.requiredFields) {
118
+ args[field] = `<${field}>`;
119
+ }
120
+ return JSON.stringify({
121
+ jsonrpc: '2.0',
122
+ id: 1,
123
+ method: 'tools/call',
124
+ params: {
125
+ name: tool.name,
126
+ arguments: args,
127
+ },
128
+ }, null, 2);
129
+ }
130
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/tools.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/mcp-ts-core",
3
- "version": "0.6.8",
3
+ "version": "0.6.9",
4
4
  "mcpName": "io.github.cyanheads/mcp-ts-core",
5
5
  "description": "Agent-native TypeScript framework for building MCP servers. Declarative definitions with auth, multi-backend storage, OpenTelemetry, and first-class support for Bun/Node/Cloudflare Workers.",
6
6
  "main": "dist/core/index.js",