@vantageos/mcp-boilerplate 0.2.0 → 0.2.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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/ui/uiResource.d.ts +3 -3
- package/dist/ui/uiResource.js +22 -7
- package/package.json +2 -1
- package/plugin.json +1 -1
- package/scripts/generate-signing-key.mjs +14 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vantage-mcp-boilerplate",
|
|
3
3
|
"displayName": "VantageOS MCP Boilerplate",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "Clonable MCP server template: SDK v2 on protocol 2026-07-28 (stdio + stateless Streamable HTTP), its own OAuth 2.1 authorization server (Clerk person + organisation), MCP Apps UI, FR/EN i18n and a declarative eval harness. Scaffold, extend, publish.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "ElPi Corp / Laurent Perello"
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.1] - 2026-10-10
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- The MCP Apps UI bundle is resolved relative to the module, not to `process.cwd()`: the
|
|
15
|
+
published package failed `resources/read ui://mcp-boilerplate/items-widget.html` whenever it
|
|
16
|
+
was run from any directory other than its own root.
|
|
17
|
+
- A missing UI bundle now answers an MCP error with no filesystem path in its message (the
|
|
18
|
+
detail is logged on stderr only); it used to leak the absolute `ENOENT` path to the client.
|
|
19
|
+
- `scripts/generate-signing-key.mjs`, which the README tells users to run, is now in the
|
|
20
|
+
published `files`.
|
|
21
|
+
|
|
10
22
|
## [0.2.0] - 2026-10-10
|
|
11
23
|
|
|
12
24
|
SDK v2 / protocol 2026-07-28 migration, own authorization server, MCP Apps + ChatGPT
|
package/dist/ui/uiResource.d.ts
CHANGED
|
@@ -3,9 +3,9 @@ import type { ExampleItem } from "../exampleItems.js";
|
|
|
3
3
|
export declare const ITEMS_UI_RESOURCE_URI = "ui://mcp-boilerplate/items-widget.html";
|
|
4
4
|
/**
|
|
5
5
|
* Reads the single-file bundle produced by `npm run build:ui`
|
|
6
|
-
* (vite-plugin-singlefile).
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* (vite-plugin-singlefile). Never silently swallowed: a missing bundle is a build defect, not
|
|
7
|
+
* a runtime fallback case. The error that reaches the MCP client names no filesystem path;
|
|
8
|
+
* the detail goes to stderr (server side) only.
|
|
9
9
|
*/
|
|
10
10
|
export declare function readUiBundle(): string;
|
|
11
11
|
/**
|
package/dist/ui/uiResource.js
CHANGED
|
@@ -11,13 +11,18 @@
|
|
|
11
11
|
* shape written here.
|
|
12
12
|
*/
|
|
13
13
|
import { readFileSync } from "node:fs";
|
|
14
|
-
import
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
15
|
import { RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
|
|
16
16
|
export const ITEMS_UI_RESOURCE_URI = "ui://mcp-boilerplate/items-widget.html";
|
|
17
17
|
// dist/ui-bundle/ — NEVER dist/ui/ (that path is tsc's compiled-server
|
|
18
18
|
// output for this very module; see vite.config.ts for the collision this
|
|
19
|
-
// avoids).
|
|
20
|
-
|
|
19
|
+
// avoids). Resolved relative to THIS module, never to the working directory: an installed
|
|
20
|
+
// package runs from any cwd. Compiled (dist/ui/uiResource.js) the bundle is `../ui-bundle`;
|
|
21
|
+
// from source (src/ui/uiResource.ts, under vitest) it is the repository's built `dist/`.
|
|
22
|
+
const BUNDLE_CANDIDATES = [
|
|
23
|
+
fileURLToPath(new URL("../ui-bundle/widget.html", import.meta.url)),
|
|
24
|
+
fileURLToPath(new URL("../../dist/ui-bundle/widget.html", import.meta.url)),
|
|
25
|
+
];
|
|
21
26
|
function renderMarkdownFallback(items, locale) {
|
|
22
27
|
const title = locale === "fr" ? "Éléments" : "Items";
|
|
23
28
|
if (items.length === 0) {
|
|
@@ -28,12 +33,22 @@ function renderMarkdownFallback(items, locale) {
|
|
|
28
33
|
}
|
|
29
34
|
/**
|
|
30
35
|
* Reads the single-file bundle produced by `npm run build:ui`
|
|
31
|
-
* (vite-plugin-singlefile).
|
|
32
|
-
*
|
|
33
|
-
*
|
|
36
|
+
* (vite-plugin-singlefile). Never silently swallowed: a missing bundle is a build defect, not
|
|
37
|
+
* a runtime fallback case. The error that reaches the MCP client names no filesystem path;
|
|
38
|
+
* the detail goes to stderr (server side) only.
|
|
34
39
|
*/
|
|
35
40
|
export function readUiBundle() {
|
|
36
|
-
|
|
41
|
+
let lastError;
|
|
42
|
+
for (const candidate of BUNDLE_CANDIDATES) {
|
|
43
|
+
try {
|
|
44
|
+
return readFileSync(candidate, "utf-8");
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
lastError = err;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
console.error(`[ui] UI bundle unreadable (tried ${BUNDLE_CANDIDATES.join(", ")}):`, lastError);
|
|
51
|
+
throw new Error("UI bundle unavailable on this server");
|
|
37
52
|
}
|
|
38
53
|
/**
|
|
39
54
|
* Resource-level `_meta.ui` (MCP Apps spec 2026-01-26). The CSP is derived from what the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vantageos/mcp-boilerplate",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Clonable MCP server skeleton on the official @modelcontextprotocol/server SDK v2 (protocol 2026-07-28 + 2025 legacy, stdio + stateless Streamable HTTP), with its own OAuth 2.1 authorization server (Clerk person + organisation, cloud-identity), MCP Apps UI, tenant scoping, FR/EN i18n and a declarative eval harness.",
|
|
5
5
|
"description_fr": "Squelette de serveur MCP clonable sur le SDK officiel @modelcontextprotocol/server v2 (protocole 2026-07-28 + héritage 2025, stdio + Streamable HTTP sans état), avec son propre serveur d'autorisation OAuth 2.1 (personne + organisation Clerk, cloud-identity), UI MCP Apps, scoping tenant, i18n FR/EN et un harnais d'évaluations déclaratif.",
|
|
6
6
|
"type": "module",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"mcp.json",
|
|
29
29
|
"skills",
|
|
30
30
|
"scripts/plugin-manifest.source.json",
|
|
31
|
+
"scripts/generate-signing-key.mjs",
|
|
31
32
|
"docs",
|
|
32
33
|
"examples/claude-desktop.json",
|
|
33
34
|
"examples/oauth.env.example"
|
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "vantage-mcp-boilerplate",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "Clonable MCP server template: SDK v2 on protocol 2026-07-28 (stdio + stateless Streamable HTTP), its own OAuth 2.1 authorization server (Clerk person + organisation), MCP Apps UI, FR/EN i18n and a declarative eval harness. Scaffold, extend, publish.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "ElPi Corp / Laurent Perello"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Prints a fresh RS256 private JWK on stdout, ready to be stored as the MCP_OAUTH_SIGNING_JWK
|
|
4
|
+
* secret of the authorization server. The key id is the RFC 7638 thumbprint, so it is derived,
|
|
5
|
+
* never typed. Nothing is written to disk; pipe it straight into your secret manager.
|
|
6
|
+
*/
|
|
7
|
+
import { calculateJwkThumbprint, exportJWK, generateKeyPair } from "jose";
|
|
8
|
+
|
|
9
|
+
const { privateKey } = await generateKeyPair("RS256", { modulusLength: 3072, extractable: true });
|
|
10
|
+
const jwk = await exportJWK(privateKey);
|
|
11
|
+
jwk.kid = await calculateJwkThumbprint(jwk);
|
|
12
|
+
jwk.alg = "RS256";
|
|
13
|
+
jwk.use = "sig";
|
|
14
|
+
process.stdout.write(`${JSON.stringify(jwk)}\n`);
|