@aotter/mantle-web 0.1.0-alpha.11 → 0.1.0-alpha.13
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/README.md +23 -0
- package/dist/webmcp.d.ts +32 -0
- package/dist/webmcp.d.ts.map +1 -0
- package/dist/webmcp.js +69 -0
- package/dist/webmcp.js.map +1 -0
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -23,3 +23,26 @@ const html = await web.renderEntryLive.execute({
|
|
|
23
23
|
|
|
24
24
|
Omit this package when an application only needs Mantle parsing, planning, or
|
|
25
25
|
headless runtime operations.
|
|
26
|
+
|
|
27
|
+
## WebMCP (opt in)
|
|
28
|
+
|
|
29
|
+
Browsers implementing the draft imperative WebMCP API can expose public Views
|
|
30
|
+
as read-only tools. Importing the subpath has no registration side effect;
|
|
31
|
+
registration begins only when `bindWebMcp` is called.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { projectCallableCapabilities } from "@aotter/mantle-runtime";
|
|
35
|
+
import { bindWebMcp } from "@aotter/mantle-web/webmcp";
|
|
36
|
+
|
|
37
|
+
const binding = await bindWebMcp(
|
|
38
|
+
projectCallableCapabilities(plan, { surface: "public" }),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// Unregister when the page/app scope ends.
|
|
42
|
+
binding.dispose();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Unsupported browsers return `{ supported: false }`. Only public View
|
|
46
|
+
capabilities are registered; staff Views and Procedure mutations are excluded.
|
|
47
|
+
Calls use the same-origin `/api/views/<name>` route, forward browser
|
|
48
|
+
cancellation, and declare both `readOnlyHint` and `untrustedContentHint`.
|
package/dist/webmcp.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { RuntimeCallableCapability } from "@aotter/mantle-runtime";
|
|
2
|
+
export interface WebMcpTool {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly title?: string;
|
|
5
|
+
readonly description: string;
|
|
6
|
+
readonly inputSchema: Record<string, unknown>;
|
|
7
|
+
readonly annotations: {
|
|
8
|
+
readonly readOnlyHint: true;
|
|
9
|
+
readonly untrustedContentHint: true;
|
|
10
|
+
};
|
|
11
|
+
execute(input: Record<string, unknown>, context: {
|
|
12
|
+
readonly signal?: AbortSignal;
|
|
13
|
+
}): Promise<unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface WebMcpModelContext {
|
|
16
|
+
registerTool(tool: WebMcpTool, options: {
|
|
17
|
+
readonly signal: AbortSignal;
|
|
18
|
+
}): void | Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export interface WebMcpBinding {
|
|
21
|
+
readonly supported: boolean;
|
|
22
|
+
readonly registered: readonly string[];
|
|
23
|
+
dispose(): void;
|
|
24
|
+
}
|
|
25
|
+
export interface BindWebMcpOptions {
|
|
26
|
+
readonly modelContext?: WebMcpModelContext;
|
|
27
|
+
readonly fetch?: typeof fetch;
|
|
28
|
+
readonly endpointPrefix?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Opt-in browser binding for public, read-only View capabilities. */
|
|
31
|
+
export declare function bindWebMcp(capabilities: readonly RuntimeCallableCapability[], options?: BindWebMcpOptions): Promise<WebMcpBinding>;
|
|
32
|
+
//# sourceMappingURL=webmcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webmcp.d.ts","sourceRoot":"","sources":["../src/webmcp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,QAAQ,CAAC,WAAW,EAAE;QACpB,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;QAC5B,QAAQ,CAAC,oBAAoB,EAAE,IAAI,CAAC;KACrC,CAAC;IACF,OAAO,CACL,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GACzC,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,CACV,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GACxC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,sEAAsE;AACtE,wBAAsB,UAAU,CAC9B,YAAY,EAAE,SAAS,yBAAyB,EAAE,EAClD,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,aAAa,CAAC,CAkCxB"}
|
package/dist/webmcp.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Opt-in browser binding for public, read-only View capabilities. */
|
|
2
|
+
export async function bindWebMcp(capabilities, options = {}) {
|
|
3
|
+
const modelContext = options.modelContext ?? browserModelContext();
|
|
4
|
+
if (!modelContext)
|
|
5
|
+
return unsupportedBinding();
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const views = capabilities.filter((capability) => capability.kind === "view" && capability.surface === "public");
|
|
8
|
+
try {
|
|
9
|
+
await Promise.all(views.map((capability) => modelContext.registerTool({
|
|
10
|
+
name: capability.name,
|
|
11
|
+
...(capability.title ? { title: capability.title } : {}),
|
|
12
|
+
description: capability.description,
|
|
13
|
+
inputSchema: capability.inputSchema,
|
|
14
|
+
annotations: { readOnlyHint: true, untrustedContentHint: true },
|
|
15
|
+
execute: (input, context) => queryView(capability, input, context.signal
|
|
16
|
+
? AbortSignal.any([context.signal, controller.signal])
|
|
17
|
+
: controller.signal, options),
|
|
18
|
+
}, { signal: controller.signal })));
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
controller.abort();
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
return Object.freeze({
|
|
25
|
+
supported: true,
|
|
26
|
+
registered: Object.freeze(views.map((view) => view.name)),
|
|
27
|
+
dispose: () => controller.abort(),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function browserModelContext() {
|
|
31
|
+
const modelContext = globalThis
|
|
32
|
+
.document?.modelContext;
|
|
33
|
+
return modelContext && typeof modelContext.registerTool === "function"
|
|
34
|
+
? modelContext
|
|
35
|
+
: undefined;
|
|
36
|
+
}
|
|
37
|
+
function unsupportedBinding() {
|
|
38
|
+
return Object.freeze({
|
|
39
|
+
supported: false,
|
|
40
|
+
registered: Object.freeze([]),
|
|
41
|
+
dispose: () => { },
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async function queryView(capability, input, signal, options) {
|
|
45
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
46
|
+
throw new TypeError("WebMCP View input must be an object.");
|
|
47
|
+
}
|
|
48
|
+
const query = Object.entries(input)
|
|
49
|
+
.filter((entry) => ["string", "number", "boolean"].includes(typeof entry[1]))
|
|
50
|
+
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
|
|
51
|
+
.join("&");
|
|
52
|
+
const prefix = (options.endpointPrefix ?? "/api/views").replace(/\/$/u, "");
|
|
53
|
+
if (!/^\/(?!\/)[^\\?#]*$/u.test(prefix)) {
|
|
54
|
+
throw new TypeError("WebMCP endpointPrefix must be a same-origin absolute path.");
|
|
55
|
+
}
|
|
56
|
+
const response = await (options.fetch ?? fetch)(`${prefix}/${encodeURIComponent(capability.ownerName)}${query ? `?${query}` : ""}`, {
|
|
57
|
+
method: "GET",
|
|
58
|
+
credentials: "same-origin",
|
|
59
|
+
headers: { accept: "application/json" },
|
|
60
|
+
signal,
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok)
|
|
63
|
+
throw new Error(`Mantle View '${capability.ownerName}' failed (${response.status}).`);
|
|
64
|
+
const body = await response.json();
|
|
65
|
+
return body && typeof body === "object" && body.ok === true
|
|
66
|
+
? body.data
|
|
67
|
+
: body;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=webmcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webmcp.js","sourceRoot":"","sources":["../src/webmcp.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aotter/mantle-web",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.13",
|
|
4
4
|
"description": "Optional public document composition for Mantle: HTML, Markdown, llms.txt, sitemap, SEO, and preview.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://mantle.tools/",
|
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
".": {
|
|
23
23
|
"types": "./dist/index.d.ts",
|
|
24
24
|
"import": "./dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./webmcp": {
|
|
27
|
+
"types": "./dist/webmcp.d.ts",
|
|
28
|
+
"import": "./dist/webmcp.js"
|
|
25
29
|
}
|
|
26
30
|
},
|
|
27
31
|
"files": [
|
|
@@ -29,8 +33,8 @@
|
|
|
29
33
|
"README.md"
|
|
30
34
|
],
|
|
31
35
|
"dependencies": {
|
|
32
|
-
"@aotter/mantle-
|
|
33
|
-
"@aotter/mantle-
|
|
36
|
+
"@aotter/mantle-spec": "0.1.0-alpha.13",
|
|
37
|
+
"@aotter/mantle-runtime": "0.1.0-alpha.13"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
36
40
|
"@types/node": "^26",
|