@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.
- package/CLAUDE.md +1 -1
- package/README.md +1 -1
- package/changelog/0.6.x/0.6.9.md +21 -0
- package/dist/core/serverManifest.d.ts +12 -0
- package/dist/core/serverManifest.d.ts.map +1 -1
- package/dist/core/serverManifest.js +25 -0
- package/dist/core/serverManifest.js.map +1 -1
- package/dist/linter/rules/landing-rules.d.ts.map +1 -1
- package/dist/linter/rules/landing-rules.js +1 -20
- package/dist/linter/rules/landing-rules.js.map +1 -1
- package/dist/mcp-server/transports/http/httpTransport.js +1 -1
- package/dist/mcp-server/transports/http/httpTransport.js.map +1 -1
- package/dist/mcp-server/transports/http/landing-page/assets/copy-script.d.ts +11 -0
- package/dist/mcp-server/transports/http/landing-page/assets/copy-script.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/assets/copy-script.js +36 -0
- package/dist/mcp-server/transports/http/landing-page/assets/copy-script.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/assets/styles.d.ts +21 -0
- package/dist/mcp-server/transports/http/landing-page/assets/styles.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/assets/styles.js +921 -0
- package/dist/mcp-server/transports/http/landing-page/assets/styles.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/handler.d.ts +32 -0
- package/dist/mcp-server/transports/http/landing-page/handler.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/handler.js +92 -0
- package/dist/mcp-server/transports/http/landing-page/handler.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/index.d.ts +27 -0
- package/dist/mcp-server/transports/http/landing-page/index.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/index.js +27 -0
- package/dist/mcp-server/transports/http/landing-page/index.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/primitives.d.ts +19 -0
- package/dist/mcp-server/transports/http/landing-page/primitives.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/primitives.js +38 -0
- package/dist/mcp-server/transports/http/landing-page/primitives.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/render.d.ts +16 -0
- package/dist/mcp-server/transports/http/landing-page/render.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/render.js +57 -0
- package/dist/mcp-server/transports/http/landing-page/render.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/connect.d.ts +19 -0
- package/dist/mcp-server/transports/http/landing-page/sections/connect.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/connect.js +130 -0
- package/dist/mcp-server/transports/http/landing-page/sections/connect.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/extensions.d.ts +10 -0
- package/dist/mcp-server/transports/http/landing-page/sections/extensions.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/extensions.js +30 -0
- package/dist/mcp-server/transports/http/landing-page/sections/extensions.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/footer.d.ts +12 -0
- package/dist/mcp-server/transports/http/landing-page/sections/footer.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/footer.js +49 -0
- package/dist/mcp-server/transports/http/landing-page/sections/footer.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/head.d.ts +11 -0
- package/dist/mcp-server/transports/http/landing-page/sections/head.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/head.js +68 -0
- package/dist/mcp-server/transports/http/landing-page/sections/head.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/hero.d.ts +12 -0
- package/dist/mcp-server/transports/http/landing-page/sections/hero.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/hero.js +48 -0
- package/dist/mcp-server/transports/http/landing-page/sections/hero.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/prompts.d.ts +11 -0
- package/dist/mcp-server/transports/http/landing-page/sections/prompts.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/prompts.js +48 -0
- package/dist/mcp-server/transports/http/landing-page/sections/prompts.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/resources.d.ts +10 -0
- package/dist/mcp-server/transports/http/landing-page/sections/resources.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/resources.js +44 -0
- package/dist/mcp-server/transports/http/landing-page/sections/resources.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/status-strip.d.ts +18 -0
- package/dist/mcp-server/transports/http/landing-page/sections/status-strip.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/status-strip.js +71 -0
- package/dist/mcp-server/transports/http/landing-page/sections/status-strip.js.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/tools.d.ts +13 -0
- package/dist/mcp-server/transports/http/landing-page/sections/tools.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/landing-page/sections/tools.js +130 -0
- package/dist/mcp-server/transports/http/landing-page/sections/tools.js.map +1 -0
- package/package.json +1 -1
- package/dist/mcp-server/transports/http/landing-page.d.ts +0 -48
- package/dist/mcp-server/transports/http/landing-page.d.ts.map +0 -1
- package/dist/mcp-server/transports/http/landing-page.js +0 -1621
- package/dist/mcp-server/transports/http/landing-page.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/assets/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAiB,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEtE,2EAA2E;AAC3E,MAAM,cAAc,GAAG,SAAS,CAAC;AAEjC;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC;IACpE,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;cAoBA,UAAU;wCACgB,UAAU;uCACX,UAAU;uCACV,UAAU;yCACR,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAq2BlD,CAAC;IACA,OAAO,SAAS,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Hono handler factory for `GET /` — serves the HTML landing
|
|
3
|
+
* page. Cache and body shape depend on `manifest.landing.requireAuth` and
|
|
4
|
+
* whether the caller presents an Authorization header.
|
|
5
|
+
*
|
|
6
|
+
* @module src/mcp-server/transports/http/landing-page/handler
|
|
7
|
+
*/
|
|
8
|
+
import type { Context } from 'hono';
|
|
9
|
+
import type { ServerManifest } from '../../../../core/serverManifest.js';
|
|
10
|
+
/**
|
|
11
|
+
* Factory for the `GET /` route handler.
|
|
12
|
+
*
|
|
13
|
+
* Cache behavior and body shape depend on `manifest.landing.requireAuth`:
|
|
14
|
+
*
|
|
15
|
+
* | `requireAuth` | Authenticated | Unauthenticated |
|
|
16
|
+
* |:---|:---|:---|
|
|
17
|
+
* | `false` (default) | full page · `Cache-Control: public, max-age=60` | full page · same |
|
|
18
|
+
* | `true` | full page · `Cache-Control: private, max-age=60` · `Vary: Authorization` | reduced hero-only page · same cache headers |
|
|
19
|
+
*
|
|
20
|
+
* The check is header-presence based — we don't validate the bearer token
|
|
21
|
+
* here (that's the MCP endpoint's job). If a caller presents any Authorization
|
|
22
|
+
* header, the full inventory renders; if not, they see a stub and a pointer
|
|
23
|
+
* to the docs link when available.
|
|
24
|
+
*
|
|
25
|
+
* When `manifest.transport.publicUrl` is set, the base URL is deterministic,
|
|
26
|
+
* so both page variants (full and degraded) are rendered once at factory
|
|
27
|
+
* time and served from memory on each request — the render pipeline then
|
|
28
|
+
* only runs when the origin must be derived per-request from
|
|
29
|
+
* `new URL(c.req.url).origin`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createLandingPageHandler(manifest: ServerManifest): (c: Context) => Response;
|
|
32
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../../src/mcp-server/transports/http/landing-page/handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAwB/D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,cAAc,IASvD,GAAG,OAAO,KAAG,QAAQ,CAqC9B"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Hono handler factory for `GET /` — serves the HTML landing
|
|
3
|
+
* page. Cache and body shape depend on `manifest.landing.requireAuth` and
|
|
4
|
+
* whether the caller presents an Authorization header.
|
|
5
|
+
*
|
|
6
|
+
* @module src/mcp-server/transports/http/landing-page/handler
|
|
7
|
+
*/
|
|
8
|
+
import { logger } from '../../../../utils/internal/logger.js';
|
|
9
|
+
import { requestContextService } from '../../../../utils/internal/requestContext.js';
|
|
10
|
+
import { renderLandingPage } from './render.js';
|
|
11
|
+
/**
|
|
12
|
+
* Content-Security-Policy for the landing page. The page is fully
|
|
13
|
+
* self-contained: a single inlined `<style>` block, a single inlined
|
|
14
|
+
* copy-to-clipboard `<script>`, and a JSON-LD structured data block. Logos
|
|
15
|
+
* are the only element with a variable source and are always either a
|
|
16
|
+
* data URI or an `https://` URL. Nothing else is fetched, framed, or
|
|
17
|
+
* submitted — the policy reflects that reality.
|
|
18
|
+
*/
|
|
19
|
+
const CONTENT_SECURITY_POLICY = [
|
|
20
|
+
"default-src 'none'",
|
|
21
|
+
"style-src 'unsafe-inline'",
|
|
22
|
+
"script-src 'unsafe-inline'",
|
|
23
|
+
"img-src 'self' data: https:",
|
|
24
|
+
"form-action 'none'",
|
|
25
|
+
"frame-ancestors 'none'",
|
|
26
|
+
"base-uri 'none'",
|
|
27
|
+
].join('; ');
|
|
28
|
+
/**
|
|
29
|
+
* Factory for the `GET /` route handler.
|
|
30
|
+
*
|
|
31
|
+
* Cache behavior and body shape depend on `manifest.landing.requireAuth`:
|
|
32
|
+
*
|
|
33
|
+
* | `requireAuth` | Authenticated | Unauthenticated |
|
|
34
|
+
* |:---|:---|:---|
|
|
35
|
+
* | `false` (default) | full page · `Cache-Control: public, max-age=60` | full page · same |
|
|
36
|
+
* | `true` | full page · `Cache-Control: private, max-age=60` · `Vary: Authorization` | reduced hero-only page · same cache headers |
|
|
37
|
+
*
|
|
38
|
+
* The check is header-presence based — we don't validate the bearer token
|
|
39
|
+
* here (that's the MCP endpoint's job). If a caller presents any Authorization
|
|
40
|
+
* header, the full inventory renders; if not, they see a stub and a pointer
|
|
41
|
+
* to the docs link when available.
|
|
42
|
+
*
|
|
43
|
+
* When `manifest.transport.publicUrl` is set, the base URL is deterministic,
|
|
44
|
+
* so both page variants (full and degraded) are rendered once at factory
|
|
45
|
+
* time and served from memory on each request — the render pipeline then
|
|
46
|
+
* only runs when the origin must be derived per-request from
|
|
47
|
+
* `new URL(c.req.url).origin`.
|
|
48
|
+
*/
|
|
49
|
+
export function createLandingPageHandler(manifest) {
|
|
50
|
+
const { publicUrl } = manifest.transport;
|
|
51
|
+
const precomputed = publicUrl
|
|
52
|
+
? {
|
|
53
|
+
full: renderLandingPage(manifest, publicUrl, false),
|
|
54
|
+
degraded: renderLandingPage(manifest, publicUrl, true),
|
|
55
|
+
}
|
|
56
|
+
: null;
|
|
57
|
+
return (c) => {
|
|
58
|
+
const context = requestContextService.createRequestContext({
|
|
59
|
+
operation: 'landingPageHandler',
|
|
60
|
+
});
|
|
61
|
+
const baseUrl = publicUrl ?? new URL(c.req.url).origin;
|
|
62
|
+
const requireAuth = manifest.landing.requireAuth;
|
|
63
|
+
const authHeader = c.req.header('authorization');
|
|
64
|
+
const isAuthenticated = Boolean(authHeader && authHeader.trim().length > 0);
|
|
65
|
+
const degraded = requireAuth && !isAuthenticated;
|
|
66
|
+
const html = precomputed
|
|
67
|
+
? degraded
|
|
68
|
+
? precomputed.degraded
|
|
69
|
+
: precomputed.full
|
|
70
|
+
: renderLandingPage(manifest, baseUrl, degraded);
|
|
71
|
+
logger.debug('Serving landing page.', {
|
|
72
|
+
...context,
|
|
73
|
+
accept: c.req.header('accept'),
|
|
74
|
+
bytes: html.length,
|
|
75
|
+
requireAuth,
|
|
76
|
+
degraded,
|
|
77
|
+
cached: precomputed !== null,
|
|
78
|
+
});
|
|
79
|
+
c.header('Content-Type', 'text/html; charset=utf-8');
|
|
80
|
+
c.header('X-Content-Type-Options', 'nosniff');
|
|
81
|
+
c.header('Content-Security-Policy', CONTENT_SECURITY_POLICY);
|
|
82
|
+
if (requireAuth) {
|
|
83
|
+
c.header('Cache-Control', 'private, max-age=60');
|
|
84
|
+
c.header('Vary', 'Authorization');
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
c.header('Cache-Control', 'public, max-age=60');
|
|
88
|
+
}
|
|
89
|
+
return c.body(html);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../../src/mcp-server/transports/http/landing-page/handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAE3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,uBAAuB,GAAG;IAC9B,oBAAoB;IACpB,2BAA2B;IAC3B,4BAA4B;IAC5B,6BAA6B;IAC7B,oBAAoB;IACpB,wBAAwB;IACxB,iBAAiB;CAClB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAwB;IAC/D,MAAM,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC;IACzC,MAAM,WAAW,GAAG,SAAS;QAC3B,CAAC,CAAC;YACE,IAAI,EAAE,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC;YACnD,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC;SACvD;QACH,CAAC,CAAC,IAAI,CAAC;IAET,OAAO,CAAC,CAAU,EAAY,EAAE;QAC9B,MAAM,OAAO,GAAG,qBAAqB,CAAC,oBAAoB,CAAC;YACzD,SAAS,EAAE,oBAAoB;SAChC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;QAEvD,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC;QACjD,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACjD,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,WAAW,IAAI,CAAC,eAAe,CAAC;QAEjD,MAAM,IAAI,GAAG,WAAW;YACtB,CAAC,CAAC,QAAQ;gBACR,CAAC,CAAC,WAAW,CAAC,QAAQ;gBACtB,CAAC,CAAC,WAAW,CAAC,IAAI;YACpB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAEnD,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE;YACpC,GAAG,OAAO;YACV,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC9B,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,WAAW;YACX,QAAQ;YACR,MAAM,EAAE,WAAW,KAAK,IAAI;SAC7B,CAAC,CAAC;QAEH,CAAC,CAAC,MAAM,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;QACrD,CAAC,CAAC,MAAM,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;QAC9C,CAAC,CAAC,MAAM,CAAC,yBAAyB,EAAE,uBAAuB,CAAC,CAAC;QAC7D,IAAI,WAAW,EAAE,CAAC;YAChB,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;YACjD,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,oBAAoB,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Public barrel for the HTML landing page served at `GET /`.
|
|
3
|
+
* Self-contained, zero-dependency renderer producing a branded,
|
|
4
|
+
* a11y-conscious, `prefers-color-scheme`-aware page from the shared
|
|
5
|
+
* `ServerManifest`.
|
|
6
|
+
*
|
|
7
|
+
* The page is the human-facing sibling of `/mcp` (bespoke JSON) and
|
|
8
|
+
* `/.well-known/mcp.json` (SEP-1649 Server Card). Framework owns the design
|
|
9
|
+
* system; servers supply content through `LandingConfig`.
|
|
10
|
+
*
|
|
11
|
+
* ## Surfaces
|
|
12
|
+
*
|
|
13
|
+
* - Hero — eyebrow, display-size server name, version + pre-release chips,
|
|
14
|
+
* tagline, single-line status strip, terminal-chrome connection card,
|
|
15
|
+
* framework attribution pill
|
|
16
|
+
* - Tools section — responsive 2-column card grid; prefix-grouped; per-card
|
|
17
|
+
* annotation chips, invocation snippet, view-source link, schema preview
|
|
18
|
+
* - Resources section — URI template, mime type, description, view-source link
|
|
19
|
+
* - Prompts section — args list, view-source link
|
|
20
|
+
* - Extensions section — rendered when SEP-2133 extensions are present
|
|
21
|
+
* - Footer — single-row, dim, separator-dot delimited
|
|
22
|
+
*
|
|
23
|
+
* @module src/mcp-server/transports/http/landing-page/index
|
|
24
|
+
*/
|
|
25
|
+
export { createLandingPageHandler } from './handler.js';
|
|
26
|
+
export { renderLandingPage } from './render.js';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/mcp-server/transports/http/landing-page/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Public barrel for the HTML landing page served at `GET /`.
|
|
3
|
+
* Self-contained, zero-dependency renderer producing a branded,
|
|
4
|
+
* a11y-conscious, `prefers-color-scheme`-aware page from the shared
|
|
5
|
+
* `ServerManifest`.
|
|
6
|
+
*
|
|
7
|
+
* The page is the human-facing sibling of `/mcp` (bespoke JSON) and
|
|
8
|
+
* `/.well-known/mcp.json` (SEP-1649 Server Card). Framework owns the design
|
|
9
|
+
* system; servers supply content through `LandingConfig`.
|
|
10
|
+
*
|
|
11
|
+
* ## Surfaces
|
|
12
|
+
*
|
|
13
|
+
* - Hero — eyebrow, display-size server name, version + pre-release chips,
|
|
14
|
+
* tagline, single-line status strip, terminal-chrome connection card,
|
|
15
|
+
* framework attribution pill
|
|
16
|
+
* - Tools section — responsive 2-column card grid; prefix-grouped; per-card
|
|
17
|
+
* annotation chips, invocation snippet, view-source link, schema preview
|
|
18
|
+
* - Resources section — URI template, mime type, description, view-source link
|
|
19
|
+
* - Prompts section — args list, view-source link
|
|
20
|
+
* - Extensions section — rendered when SEP-2133 extensions are present
|
|
21
|
+
* - Footer — single-row, dim, separator-dot delimited
|
|
22
|
+
*
|
|
23
|
+
* @module src/mcp-server/transports/http/landing-page/index
|
|
24
|
+
*/
|
|
25
|
+
export { createLandingPageHandler } from './handler.js';
|
|
26
|
+
export { renderLandingPage } from './render.js';
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/mcp-server/transports/http/landing-page/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Reusable render primitives shared across landing page sections —
|
|
3
|
+
* annotation pills, section headings, copy-enabled code snippets, and the
|
|
4
|
+
* framework attribution badge.
|
|
5
|
+
*
|
|
6
|
+
* @module src/mcp-server/transports/http/landing-page/primitives
|
|
7
|
+
*/
|
|
8
|
+
import type { ServerManifest } from '../../../../core/serverManifest.js';
|
|
9
|
+
import { type SafeHtml } from '../../../../utils/formatting/html.js';
|
|
10
|
+
/**
|
|
11
|
+
* shields.io-style bi-part badge: "Built on" label + framework name. Links to
|
|
12
|
+
* the framework's npm page. Lives in the hero when `landing.attribution` is
|
|
13
|
+
* enabled.
|
|
14
|
+
*/
|
|
15
|
+
export declare function renderFrameworkBadge(framework: ServerManifest['framework']): SafeHtml;
|
|
16
|
+
export declare function renderPill(text: string, variant: string): SafeHtml;
|
|
17
|
+
export declare function renderSectionHeading(id: string, label: string, count: number): SafeHtml;
|
|
18
|
+
export declare function renderSnippet(id: string, text: string): SafeHtml;
|
|
19
|
+
//# sourceMappingURL=primitives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../../../src/mcp-server/transports/http/landing-page/primitives.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEjE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,cAAc,CAAC,WAAW,CAAC,GAAG,QAAQ,CAGrF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAElE;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAOvF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAQhE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Reusable render primitives shared across landing page sections —
|
|
3
|
+
* annotation pills, section headings, copy-enabled code snippets, and the
|
|
4
|
+
* framework attribution badge.
|
|
5
|
+
*
|
|
6
|
+
* @module src/mcp-server/transports/http/landing-page/primitives
|
|
7
|
+
*/
|
|
8
|
+
import { html } from '../../../../utils/formatting/html.js';
|
|
9
|
+
/**
|
|
10
|
+
* shields.io-style bi-part badge: "Built on" label + framework name. Links to
|
|
11
|
+
* the framework's npm page. Lives in the hero when `landing.attribution` is
|
|
12
|
+
* enabled.
|
|
13
|
+
*/
|
|
14
|
+
export function renderFrameworkBadge(framework) {
|
|
15
|
+
const npmUrl = `https://www.npmjs.com/package/${encodeURIComponent(framework.name)}`;
|
|
16
|
+
return html `<a class="badge-shield" href="${npmUrl}" rel="noopener" aria-label="Built on ${framework.name} v${framework.version}"><span class="badge-shield-label">Built on</span><span class="badge-shield-value">${framework.name} v${framework.version}</span></a>`;
|
|
17
|
+
}
|
|
18
|
+
export function renderPill(text, variant) {
|
|
19
|
+
return html `<span class="pill pill-${variant}">${text}</span>`;
|
|
20
|
+
}
|
|
21
|
+
export function renderSectionHeading(id, label, count) {
|
|
22
|
+
return html `
|
|
23
|
+
<div class="section-heading">
|
|
24
|
+
<h2 id="${id}">${label}</h2>
|
|
25
|
+
<span class="section-count" aria-label="${String(count)} ${label}">${String(count)}</span>
|
|
26
|
+
</div>
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
export function renderSnippet(id, text) {
|
|
30
|
+
const targetId = `snippet-${id}`;
|
|
31
|
+
return html `
|
|
32
|
+
<div class="snippet">
|
|
33
|
+
<pre id="${targetId}"><code>${text}</code></pre>
|
|
34
|
+
<button type="button" class="snippet-copy" data-copy data-copy-target="#${targetId}" aria-label="Copy">Copy</button>
|
|
35
|
+
</div>
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=primitives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"primitives.js","sourceRoot":"","sources":["../../../../../src/mcp-server/transports/http/landing-page/primitives.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,IAAI,EAAiB,MAAM,4BAA4B,CAAC;AAEjE;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAsC;IACzE,MAAM,MAAM,GAAG,iCAAiC,kBAAkB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;IACrF,OAAO,IAAI,CAAA,iCAAiC,MAAM,yCAAyC,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,sFAAsF,SAAS,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,aAAa,CAAC;AACzQ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,OAAe;IACtD,OAAO,IAAI,CAAA,0BAA0B,OAAO,KAAK,IAAI,SAAS,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,EAAU,EAAE,KAAa,EAAE,KAAa;IAC3E,OAAO,IAAI,CAAA;;gBAEG,EAAE,KAAK,KAAK;gDACoB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC;;GAErF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAU,EAAE,IAAY;IACpD,MAAM,QAAQ,GAAG,WAAW,EAAE,EAAE,CAAC;IACjC,OAAO,IAAI,CAAA;;iBAEI,QAAQ,WAAW,IAAI;gFACwC,QAAQ;;GAErF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Top-level landing page composition. Stitches `<head>`,
|
|
3
|
+
* hero, capability sections, and footer into a single HTML document string.
|
|
4
|
+
* `degraded` collapses the body to the hero + an empty-state note when the
|
|
5
|
+
* caller is unauthenticated and `landing.requireAuth` is enabled.
|
|
6
|
+
*
|
|
7
|
+
* @module src/mcp-server/transports/http/landing-page/render
|
|
8
|
+
*/
|
|
9
|
+
import type { ServerManifest } from '../../../../core/serverManifest.js';
|
|
10
|
+
/**
|
|
11
|
+
* Render the full landing page. `baseUrl` is the request origin
|
|
12
|
+
* (e.g. `https://pubmed.example.com`) — used in connect snippets and OG meta.
|
|
13
|
+
* `degraded` reduces the body when `requireAuth` gates unauth callers.
|
|
14
|
+
*/
|
|
15
|
+
export declare function renderLandingPage(manifest: ServerManifest, baseUrl: string, degraded?: boolean): string;
|
|
16
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../../../src/mcp-server/transports/http/landing-page/render.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAa/D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,MAAM,EACf,QAAQ,UAAQ,GACf,MAAM,CAmCR"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Top-level landing page composition. Stitches `<head>`,
|
|
3
|
+
* hero, capability sections, and footer into a single HTML document string.
|
|
4
|
+
* `degraded` collapses the body to the hero + an empty-state note when the
|
|
5
|
+
* caller is unauthenticated and `landing.requireAuth` is enabled.
|
|
6
|
+
*
|
|
7
|
+
* @module src/mcp-server/transports/http/landing-page/render
|
|
8
|
+
*/
|
|
9
|
+
import { html } from '../../../../utils/formatting/html.js';
|
|
10
|
+
import { renderCopyScript } from './assets/copy-script.js';
|
|
11
|
+
import { renderTokens } from './assets/styles.js';
|
|
12
|
+
import { renderExtensionsSection } from './sections/extensions.js';
|
|
13
|
+
import { renderFooter } from './sections/footer.js';
|
|
14
|
+
import { renderHead } from './sections/head.js';
|
|
15
|
+
import { renderHero } from './sections/hero.js';
|
|
16
|
+
import { renderPromptsSection } from './sections/prompts.js';
|
|
17
|
+
import { renderResourcesSection } from './sections/resources.js';
|
|
18
|
+
import { renderToolsSection } from './sections/tools.js';
|
|
19
|
+
/**
|
|
20
|
+
* Render the full landing page. `baseUrl` is the request origin
|
|
21
|
+
* (e.g. `https://pubmed.example.com`) — used in connect snippets and OG meta.
|
|
22
|
+
* `degraded` reduces the body when `requireAuth` gates unauth callers.
|
|
23
|
+
*/
|
|
24
|
+
export function renderLandingPage(manifest, baseUrl, degraded = false) {
|
|
25
|
+
const pageUrl = `${baseUrl.replace(/\/$/, '')}/`;
|
|
26
|
+
const body = degraded
|
|
27
|
+
? html `
|
|
28
|
+
${renderHero(manifest, baseUrl, true)}
|
|
29
|
+
<section>
|
|
30
|
+
<p class="empty-state">
|
|
31
|
+
Full server inventory is available to authenticated callers.
|
|
32
|
+
</p>
|
|
33
|
+
</section>
|
|
34
|
+
${renderFooter(manifest)}
|
|
35
|
+
`
|
|
36
|
+
: html `
|
|
37
|
+
${renderHero(manifest, baseUrl, false)}
|
|
38
|
+
${renderToolsSection(manifest.definitions.tools)}
|
|
39
|
+
${renderResourcesSection(manifest.definitions.resources)}
|
|
40
|
+
${renderPromptsSection(manifest.definitions.prompts)}
|
|
41
|
+
${renderExtensionsSection(manifest.extensions)}
|
|
42
|
+
${renderFooter(manifest)}
|
|
43
|
+
`;
|
|
44
|
+
const doc = html `<!DOCTYPE html>
|
|
45
|
+
<html lang="en">
|
|
46
|
+
<head>
|
|
47
|
+
${renderHead(manifest, pageUrl)}
|
|
48
|
+
${renderTokens(manifest.landing.theme.accent)}
|
|
49
|
+
</head>
|
|
50
|
+
<body>
|
|
51
|
+
<main>${body}</main>
|
|
52
|
+
${renderCopyScript()}
|
|
53
|
+
</body>
|
|
54
|
+
</html>`;
|
|
55
|
+
return doc.toString();
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../../../src/mcp-server/transports/http/landing-page/render.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAwB,EACxB,OAAe,EACf,QAAQ,GAAG,KAAK;IAEhB,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC;IAEjD,MAAM,IAAI,GAAG,QAAQ;QACnB,CAAC,CAAC,IAAI,CAAA;UACA,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC;;;;;;UAMnC,YAAY,CAAC,QAAQ,CAAC;OACzB;QACH,CAAC,CAAC,IAAI,CAAA;UACA,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC;UACpC,kBAAkB,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC;UAC9C,sBAAsB,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC;UACtD,oBAAoB,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC;UAClD,uBAAuB,CAAC,QAAQ,CAAC,UAAU,CAAC;UAC5C,YAAY,CAAC,QAAQ,CAAC;OACzB,CAAC;IAEN,MAAM,GAAG,GAAG,IAAI,CAAA;;;MAGZ,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC;MAC7B,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;;;YAGrC,IAAI;MACV,gBAAgB,EAAE;;QAEhB,CAAC;IAEP,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Terminal-chrome connect card with STDIO / HTTP / Claude / curl
|
|
3
|
+
* tabs. Generates copy-paste-ready client configs and commands from the
|
|
4
|
+
* server manifest. Radio-input + `:has()` CSS hack drives tab switching with
|
|
5
|
+
* no JS.
|
|
6
|
+
*
|
|
7
|
+
* Accessibility: the ARIA tab pattern (`role="tablist"`/`"tab"`/`"tabpanel"`
|
|
8
|
+
* + `aria-selected`/`aria-controls`) is a poor fit for a radio-input-driven
|
|
9
|
+
* widget — the radios already communicate a mutually-exclusive selection to
|
|
10
|
+
* assistive tech. We don't add ARIA tab roles because they'd be incomplete
|
|
11
|
+
* (no `aria-selected` state, no `aria-controls` wiring) and a partial ARIA
|
|
12
|
+
* pattern is worse than none.
|
|
13
|
+
*
|
|
14
|
+
* @module src/mcp-server/transports/http/landing-page/sections/connect
|
|
15
|
+
*/
|
|
16
|
+
import type { ServerManifest } from '../../../../../core/serverManifest.js';
|
|
17
|
+
import { type SafeHtml } from '../../../../../utils/formatting/html.js';
|
|
18
|
+
export declare function renderConnectSnippets(manifest: ServerManifest, baseUrl: string): SafeHtml;
|
|
19
|
+
//# sourceMappingURL=connect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEjE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CA0GzF"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Terminal-chrome connect card with STDIO / HTTP / Claude / curl
|
|
3
|
+
* tabs. Generates copy-paste-ready client configs and commands from the
|
|
4
|
+
* server manifest. Radio-input + `:has()` CSS hack drives tab switching with
|
|
5
|
+
* no JS.
|
|
6
|
+
*
|
|
7
|
+
* Accessibility: the ARIA tab pattern (`role="tablist"`/`"tab"`/`"tabpanel"`
|
|
8
|
+
* + `aria-selected`/`aria-controls`) is a poor fit for a radio-input-driven
|
|
9
|
+
* widget — the radios already communicate a mutually-exclusive selection to
|
|
10
|
+
* assistive tech. We don't add ARIA tab roles because they'd be incomplete
|
|
11
|
+
* (no `aria-selected` state, no `aria-controls` wiring) and a partial ARIA
|
|
12
|
+
* pattern is worse than none.
|
|
13
|
+
*
|
|
14
|
+
* @module src/mcp-server/transports/http/landing-page/sections/connect
|
|
15
|
+
*/
|
|
16
|
+
import { html } from '../../../../../utils/formatting/html.js';
|
|
17
|
+
export function renderConnectSnippets(manifest, baseUrl) {
|
|
18
|
+
const endpoint = `${baseUrl.replace(/\/$/, '')}${manifest.transport.endpointPath}`;
|
|
19
|
+
const npmPackage = manifest.landing.npmPackage?.name;
|
|
20
|
+
// `@cyanheads/mcp-ts-core` → `mcp-ts-core`. Short aliases match the convention
|
|
21
|
+
// used in real Claude Desktop / Cursor configs and make the `claude mcp add`
|
|
22
|
+
// command more ergonomic.
|
|
23
|
+
const shortName = deriveShortName(manifest.server.name);
|
|
24
|
+
const envExample = manifest.landing.envExample;
|
|
25
|
+
const stdioEnv = envExample.length > 0 ? envFromEntries(envExample) : undefined;
|
|
26
|
+
// STDIO: prefer native `bunx <pkg>@latest` when the server is published;
|
|
27
|
+
// fall back to `mcp-remote` as a stdio → HTTP bridge so the tab is always
|
|
28
|
+
// useful even for unpublished servers. Env vars belong here — this is the
|
|
29
|
+
// only transport where the client spawns the server process and can pass
|
|
30
|
+
// them through.
|
|
31
|
+
const stdioConfig = JSON.stringify({
|
|
32
|
+
mcpServers: {
|
|
33
|
+
[shortName]: {
|
|
34
|
+
command: 'bunx',
|
|
35
|
+
args: npmPackage ? [`${npmPackage}@latest`] : ['mcp-remote', endpoint],
|
|
36
|
+
...(stdioEnv && { env: stdioEnv }),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}, null, 2);
|
|
40
|
+
// HTTP: no `env` block. MCP clients only forward env vars to spawned stdio
|
|
41
|
+
// child processes; for `type: 'http'` there's no process, so including env
|
|
42
|
+
// is a silent no-op that misleads visitors of a hosted instance into
|
|
43
|
+
// thinking they need to supply credentials the server already owns.
|
|
44
|
+
const httpConfig = JSON.stringify({
|
|
45
|
+
mcpServers: {
|
|
46
|
+
[shortName]: {
|
|
47
|
+
type: 'http',
|
|
48
|
+
url: endpoint,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
}, null, 2);
|
|
52
|
+
// `claude mcp add` — always target the HTTP endpoint. The landing page is
|
|
53
|
+
// served over HTTP, so a visitor is already interacting with this
|
|
54
|
+
// instance; a stdio/bunx command here would install a different (local)
|
|
55
|
+
// copy and carry env placeholders that HTTP wouldn't forward anyway. The
|
|
56
|
+
// STDIO tab still carries the JSON for anyone who wants to run locally.
|
|
57
|
+
const claudeCmd = buildClaudeHttpCmd(shortName, endpoint);
|
|
58
|
+
const curl = [
|
|
59
|
+
`curl -X POST ${endpoint} \\`,
|
|
60
|
+
` -H "Content-Type: application/json" \\`,
|
|
61
|
+
` -H "MCP-Protocol-Version: ${manifest.protocol.latestVersion}" \\`,
|
|
62
|
+
` -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"${manifest.protocol.latestVersion}","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'`,
|
|
63
|
+
].join('\n');
|
|
64
|
+
// Chrome label — npm package when published, else the HTTP endpoint (trimmed).
|
|
65
|
+
const chromeLabel = npmPackage ?? endpoint.replace(/^https?:\/\//, '');
|
|
66
|
+
const panels = [
|
|
67
|
+
{ id: 'stdio', label: 'STDIO', content: stdioConfig, copyAriaLabel: 'Copy stdio config' },
|
|
68
|
+
{
|
|
69
|
+
id: 'http',
|
|
70
|
+
label: 'Streamable HTTP',
|
|
71
|
+
content: httpConfig,
|
|
72
|
+
copyAriaLabel: 'Copy HTTP config',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: 'claude',
|
|
76
|
+
label: 'Claude',
|
|
77
|
+
content: claudeCmd,
|
|
78
|
+
copyAriaLabel: 'Copy claude mcp add command',
|
|
79
|
+
},
|
|
80
|
+
{ id: 'curl', label: 'curl', content: curl, copyAriaLabel: 'Copy curl command' },
|
|
81
|
+
];
|
|
82
|
+
return html `
|
|
83
|
+
<div class="connect" aria-label="Connection snippets">
|
|
84
|
+
<div class="connect-chrome">
|
|
85
|
+
<span class="connect-chrome-dots" aria-hidden="true">
|
|
86
|
+
<span class="connect-chrome-dot"></span>
|
|
87
|
+
<span class="connect-chrome-dot"></span>
|
|
88
|
+
<span class="connect-chrome-dot"></span>
|
|
89
|
+
</span>
|
|
90
|
+
<span class="connect-chrome-endpoint" title="${endpoint}">${chromeLabel}</span>
|
|
91
|
+
</div>
|
|
92
|
+
${panels.map((p, i) => i === 0
|
|
93
|
+
? html `<input type="radio" class="connect-tab-input" name="connect" id="connect-tab-${p.id}" checked />`
|
|
94
|
+
: html `<input type="radio" class="connect-tab-input" name="connect" id="connect-tab-${p.id}" />`)}
|
|
95
|
+
<div class="connect-tabs">
|
|
96
|
+
${panels.map((p) => html `<label for="connect-tab-${p.id}" class="connect-tab-label">${p.label}</label>`)}
|
|
97
|
+
</div>
|
|
98
|
+
<div class="connect-panels">
|
|
99
|
+
${panels.map((p) => renderConnectPanel(p.id, p.content, p.copyAriaLabel))}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
/** Single panel inside the connect card — pre/code + copy button. */
|
|
105
|
+
function renderConnectPanel(id, content, copyAriaLabel) {
|
|
106
|
+
const snippetId = `connect-snippet-${id}`;
|
|
107
|
+
return html `
|
|
108
|
+
<div class="connect-panel panel-${id}">
|
|
109
|
+
<pre id="${snippetId}"><code>${content}</code></pre>
|
|
110
|
+
<button type="button" class="connect-copy" data-copy data-copy-target="#${snippetId}" aria-label="${copyAriaLabel}">Copy</button>
|
|
111
|
+
</div>
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* `@scope/pkg-name` → `pkg-name`. Fall through for bare names.
|
|
116
|
+
* Used as the `mcpServers` key and the Claude CLI server alias.
|
|
117
|
+
*/
|
|
118
|
+
function deriveShortName(serverName) {
|
|
119
|
+
const slash = serverName.lastIndexOf('/');
|
|
120
|
+
return slash >= 0 ? serverName.slice(slash + 1) : serverName;
|
|
121
|
+
}
|
|
122
|
+
/** Convert ordered env entries to the `{ KEY: value }` shape MCP clients expect. */
|
|
123
|
+
function envFromEntries(entries) {
|
|
124
|
+
return Object.fromEntries(entries.map(({ key, value }) => [key, value]));
|
|
125
|
+
}
|
|
126
|
+
/** `claude mcp add --transport http <name> <url>` */
|
|
127
|
+
function buildClaudeHttpCmd(shortName, endpoint) {
|
|
128
|
+
return `claude mcp add --transport http ${shortName} ${endpoint}`;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/connect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Extensions section — rendered when SEP-2133 extensions are
|
|
3
|
+
* advertised in `serverInfo.capabilities`. Each extension key gets a card
|
|
4
|
+
* with a JSON preview of its config.
|
|
5
|
+
*
|
|
6
|
+
* @module src/mcp-server/transports/http/landing-page/sections/extensions
|
|
7
|
+
*/
|
|
8
|
+
import { type SafeHtml } from '../../../../../utils/formatting/html.js';
|
|
9
|
+
export declare function renderExtensionsSection(extensions: Record<string, object> | undefined): SafeHtml;
|
|
10
|
+
//# sourceMappingURL=extensions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/extensions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAIjE,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,QAAQ,CAoBhG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Extensions section — rendered when SEP-2133 extensions are
|
|
3
|
+
* advertised in `serverInfo.capabilities`. Each extension key gets a card
|
|
4
|
+
* with a JSON preview of its config.
|
|
5
|
+
*
|
|
6
|
+
* @module src/mcp-server/transports/http/landing-page/sections/extensions
|
|
7
|
+
*/
|
|
8
|
+
import { html } from '../../../../../utils/formatting/html.js';
|
|
9
|
+
import { renderSectionHeading } from '../primitives.js';
|
|
10
|
+
export function renderExtensionsSection(extensions) {
|
|
11
|
+
if (!extensions || Object.keys(extensions).length === 0)
|
|
12
|
+
return html ``;
|
|
13
|
+
const entries = Object.entries(extensions);
|
|
14
|
+
return html `
|
|
15
|
+
<section aria-labelledby="section-extensions">
|
|
16
|
+
${renderSectionHeading('section-extensions', 'Extensions', entries.length)}
|
|
17
|
+
<div class="card-grid">
|
|
18
|
+
${entries.map(([key, value]) => html `
|
|
19
|
+
<article class="card ext-card">
|
|
20
|
+
<div class="card-head">
|
|
21
|
+
<h3 class="card-title ext-key">${key}</h3>
|
|
22
|
+
</div>
|
|
23
|
+
<pre class="ext-preview"><code>${JSON.stringify(value, null, 2)}</code></pre>
|
|
24
|
+
</article>
|
|
25
|
+
`)}
|
|
26
|
+
</div>
|
|
27
|
+
</section>
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=extensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/extensions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAiB,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,UAAU,uBAAuB,CAAC,UAA8C;IACpF,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA,EAAE,CAAC;IACvE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,OAAO,IAAI,CAAA;;QAEL,oBAAoB,CAAC,oBAAoB,EAAE,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC;;UAEtE,OAAO,CAAC,GAAG,CACX,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,CAAA;;;iDAGiB,GAAG;;+CAEL,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;;WAElE,CACF;;;GAGN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
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 type { ServerManifest } from '../../../../../core/serverManifest.js';
|
|
10
|
+
import { type SafeHtml } from '../../../../../utils/formatting/html.js';
|
|
11
|
+
export declare function renderFooter(manifest: ServerManifest): SafeHtml;
|
|
12
|
+
//# sourceMappingURL=footer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../../../src/mcp-server/transports/http/landing-page/sections/footer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEjE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,QAAQ,CAgD/D"}
|