@emseepea/create-react-ui-server 0.0.31 → 0.0.33
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/initializer-dist/template/package.json +5 -5
- package/initializer-dist/template/src/capabilities/resource.pea-planting-plan-app.ts +3 -37
- package/initializer-dist/template/src/capabilities/tool.preview-planting-plan.ts +2 -1
- package/initializer-dist/template/src/pea-planting-plan-app-resource.ts +28 -0
- package/initializer-dist/template/src/ui-shared.tsx +2 -5
- package/initializer-dist/template/test/server.test.mjs +6 -0
- package/package.json +6 -6
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"container:build": "docker build --tag emseepea-server:local ."
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@emseepea/feedback": "0.2.
|
|
18
|
+
"@emseepea/feedback": "0.2.14",
|
|
19
19
|
"playwright": "1.62.1",
|
|
20
20
|
"axe-core": "4.13.0",
|
|
21
|
-
"@emseepea/testing": "0.11.
|
|
21
|
+
"@emseepea/testing": "0.11.4",
|
|
22
22
|
"@types/node": "24.13.3",
|
|
23
23
|
"@types/react": "19.2.18",
|
|
24
24
|
"@types/react-dom": "19.2.5",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
},
|
|
32
32
|
"private": true,
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@emseepea/react": "0.2.
|
|
35
|
-
"@emseepea/server": "0.12.
|
|
36
|
-
"@emseepea/tailwind": "0.0
|
|
34
|
+
"@emseepea/react": "0.2.4",
|
|
35
|
+
"@emseepea/server": "0.12.1",
|
|
36
|
+
"@emseepea/tailwind": "0.1.0",
|
|
37
37
|
"react": "19.2.8",
|
|
38
38
|
"react-dom": "19.2.8"
|
|
39
39
|
}
|
|
@@ -1,38 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { createElement } from "react";
|
|
5
|
-
import { renderToString } from "react-dom/server";
|
|
6
|
-
import { ResultApp } from "../mcp-app.js";
|
|
1
|
+
import type { AccessPolicy, CapabilityModuleFactory } from "@emseepea/server";
|
|
2
|
+
import { plantingPlanAppResource } from "../pea-planting-plan-app-resource.js";
|
|
7
3
|
|
|
8
|
-
|
|
9
|
-
const legacyCsp = { connect_domains: [], resource_domains: [] };
|
|
10
|
-
|
|
11
|
-
export default ((access) => defineResource({
|
|
12
|
-
name: "pea-planting-plan-app",
|
|
13
|
-
...access,
|
|
14
|
-
uri: plantingPlanAppResourceUri,
|
|
15
|
-
title: "Pea planting plan result",
|
|
16
|
-
description: "An accessible result card for the pea planting-plan preview tool.",
|
|
17
|
-
mimeType: "text/html;profile=mcp-app",
|
|
18
|
-
handler: () => ({
|
|
19
|
-
contents: [{
|
|
20
|
-
uri: plantingPlanAppResourceUri,
|
|
21
|
-
mimeType: "text/html;profile=mcp-app",
|
|
22
|
-
text: appHtml,
|
|
23
|
-
_meta: {
|
|
24
|
-
ui: { prefersBorder: true, csp },
|
|
25
|
-
"openai/widgetPrefersBorder": true,
|
|
26
|
-
"openai/widgetCSP": legacyCsp,
|
|
27
|
-
},
|
|
28
|
-
}],
|
|
29
|
-
}),
|
|
30
|
-
})) satisfies CapabilityModuleFactory<AccessPolicy>;
|
|
31
|
-
|
|
32
|
-
const appScript = readFileSync(new URL("../mcp-app-client.js", import.meta.url), "utf8").replaceAll("</script", "<\\/script");
|
|
33
|
-
const appHtml = `<!doctype html><html lang="en"><head><meta charset="utf-8">` +
|
|
34
|
-
`<meta name="viewport" content="width=device-width, initial-scale=1">` +
|
|
35
|
-
`<title>Pea planting plan result</title><style>` +
|
|
36
|
-
`button{min-block-size:24px} :focus-visible{outline:2px solid currentColor;outline-offset:2px}` +
|
|
37
|
-
`</style></head><body><main id="app">` +
|
|
38
|
-
`${renderToString(createElement(ResultApp))}</main><script type="module">${appScript}</script></body></html>`;
|
|
4
|
+
export default ((access) => plantingPlanAppResource(access).resource) satisfies CapabilityModuleFactory<AccessPolicy>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createPreviewPlantingPlanTool } from "../ui-shared.js";
|
|
2
2
|
import type { AccessPolicy, CapabilityModuleFactory } from "@emseepea/server";
|
|
3
|
+
import { plantingPlanAppResource } from "../pea-planting-plan-app-resource.js";
|
|
3
4
|
|
|
4
|
-
export default ((access) => createPreviewPlantingPlanTool(access,
|
|
5
|
+
export default ((access) => createPreviewPlantingPlanTool(access, plantingPlanAppResource(access).toolMetadata)) satisfies CapabilityModuleFactory<AccessPolicy>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { plantingPlanAppResourceUri } from "./ui-shared.js";
|
|
2
|
+
import { defineMcpAppResource, type AccessPolicy, type McpAppResource } from "@emseepea/server";
|
|
3
|
+
import { createElement } from "react";
|
|
4
|
+
import { renderToString } from "react-dom/server";
|
|
5
|
+
import { ResultApp } from "./mcp-app.js";
|
|
6
|
+
|
|
7
|
+
const definitions = new WeakMap<AccessPolicy, McpAppResource>();
|
|
8
|
+
|
|
9
|
+
export function plantingPlanAppResource(access: AccessPolicy): McpAppResource {
|
|
10
|
+
let definition = definitions.get(access);
|
|
11
|
+
if (!definition) {
|
|
12
|
+
definition = defineMcpAppResource({
|
|
13
|
+
name: "pea-planting-plan-app",
|
|
14
|
+
...access,
|
|
15
|
+
uri: plantingPlanAppResourceUri,
|
|
16
|
+
title: "Pea planting plan result",
|
|
17
|
+
description: "An accessible result card for the pea planting-plan preview tool.",
|
|
18
|
+
language: "en",
|
|
19
|
+
bodyMarkup: `<main id="app">${renderToString(createElement(ResultApp))}</main>`,
|
|
20
|
+
styles: "button{min-block-size:24px} :focus-visible{outline:2px solid currentColor;outline-offset:2px}",
|
|
21
|
+
bundleUrl: new URL("./mcp-app-client.js", import.meta.url),
|
|
22
|
+
csp: { connectDomains: [], resourceDomains: [] },
|
|
23
|
+
prefersBorder: true,
|
|
24
|
+
});
|
|
25
|
+
definitions.set(access, definition);
|
|
26
|
+
}
|
|
27
|
+
return definition;
|
|
28
|
+
}
|
|
@@ -49,17 +49,14 @@ export function previewPlantingPlan(input: z.output<typeof inputSchema>) {
|
|
|
49
49
|
|
|
50
50
|
export function createPreviewPlantingPlanTool(
|
|
51
51
|
access: AccessPolicy = { access: "public" },
|
|
52
|
-
|
|
52
|
+
appResourceMetadata?: Readonly<Record<string, unknown>>,
|
|
53
53
|
) {
|
|
54
54
|
return defineTool({
|
|
55
55
|
name: "preview-planting-plan",
|
|
56
56
|
...access,
|
|
57
57
|
title: "Preview a Pea Planting Plan",
|
|
58
58
|
description: "Preview a sample pea planting plan without sending, storing, or changing anything.",
|
|
59
|
-
...(
|
|
60
|
-
ui: { resourceUri: plantingPlanAppResourceUri },
|
|
61
|
-
"openai/outputTemplate": plantingPlanAppResourceUri,
|
|
62
|
-
} } : {}),
|
|
59
|
+
...(appResourceMetadata ? { _meta: appResourceMetadata } : {}),
|
|
63
60
|
inputSchema,
|
|
64
61
|
outputSchema,
|
|
65
62
|
handler: (input) => ({ data: previewPlantingPlan(input) }),
|
|
@@ -51,6 +51,7 @@ test("publishes the standards-first MCP Apps resource contract", async (t) => {
|
|
|
51
51
|
assert.equal(resource.mimeType, "text/html;profile=mcp-app");
|
|
52
52
|
const [content] = (await client.readResource({ uri: resource.uri })).contents;
|
|
53
53
|
assert.equal(content.mimeType, "text/html;profile=mcp-app");
|
|
54
|
+
assert.deepEqual(resource._meta.ui, content._meta.ui);
|
|
54
55
|
assert.deepEqual(content._meta.ui, {
|
|
55
56
|
prefersBorder: true,
|
|
56
57
|
csp: { connectDomains: [], resourceDomains: [] },
|
|
@@ -63,6 +64,11 @@ test("publishes the standards-first MCP Apps resource contract", async (t) => {
|
|
|
63
64
|
assert.match(content.text, /ui\/notifications\/initialized/);
|
|
64
65
|
assert.match(content.text, /ui\/notifications\/tool-result/);
|
|
65
66
|
assert.match(content.text, /ui\/notifications\/tool-cancelled/);
|
|
67
|
+
assert.match(content.text, /<html lang="en">/);
|
|
68
|
+
assert.match(content.text, /<title>Pea planting plan result<\/title>/);
|
|
69
|
+
assert.match(content.text, /<meta name="viewport"/);
|
|
70
|
+
assert.match(content.text, /<main id="app">/);
|
|
71
|
+
assert.match(content.text, /<h1>/);
|
|
66
72
|
});
|
|
67
73
|
|
|
68
74
|
test("the MCP Apps card completes initialization before rendering a result", async (t) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emseepea/create-react-ui-server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.33",
|
|
4
4
|
"description": "Create an Em See Pea server with an accessible React form.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -18,16 +18,16 @@
|
|
|
18
18
|
"prepack": "npm run build:initializer"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@emseepea/feedback": "0.2.
|
|
22
|
-
"@emseepea/react": "0.2.
|
|
23
|
-
"@emseepea/server": "0.12.
|
|
24
|
-
"@emseepea/tailwind": "0.0
|
|
21
|
+
"@emseepea/feedback": "0.2.14",
|
|
22
|
+
"@emseepea/react": "0.2.4",
|
|
23
|
+
"@emseepea/server": "0.12.1",
|
|
24
|
+
"@emseepea/tailwind": "0.1.0",
|
|
25
25
|
"react": "19.2.8",
|
|
26
26
|
"react-dom": "19.2.8",
|
|
27
27
|
"@emseepea/example-ui-shared": "0.0.0",
|
|
28
28
|
"playwright": "1.62.1",
|
|
29
29
|
"axe-core": "4.13.0",
|
|
30
|
-
"@emseepea/testing": "0.11.
|
|
30
|
+
"@emseepea/testing": "0.11.4",
|
|
31
31
|
"@types/node": "24.13.3",
|
|
32
32
|
"@types/react": "19.2.18",
|
|
33
33
|
"@types/react-dom": "19.2.5",
|