@ggui-ai/artifact-manifest 0.6.3 → 0.8.0
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/dist/artifact-manifest.d.ts +8 -0
- package/dist/artifact-manifest.d.ts.map +1 -1
- package/dist/blueprint-manifest.d.ts +4 -0
- package/dist/blueprint-manifest.d.ts.map +1 -1
- package/dist/blueprint-manifest.js +5 -0
- package/dist/gadget-manifest.d.ts +4 -0
- package/dist/gadget-manifest.d.ts.map +1 -1
- package/dist/gadget-manifest.js +6 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/mcp-tool-bindings.d.ts +95 -0
- package/dist/mcp-tool-bindings.d.ts.map +1 -0
- package/dist/mcp-tool-bindings.js +137 -0
- package/package.json +4 -3
|
@@ -32,6 +32,10 @@ import { z } from 'zod';
|
|
|
32
32
|
*/
|
|
33
33
|
export declare const artifactManifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
34
34
|
connect: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
35
|
+
mcpTools: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
36
|
+
server: z.ZodOptional<z.ZodString>;
|
|
37
|
+
tool: z.ZodString;
|
|
38
|
+
}, z.core.$strict>>>>;
|
|
35
39
|
tags: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
36
40
|
author: z.ZodOptional<z.ZodObject<{
|
|
37
41
|
name: z.ZodString;
|
|
@@ -92,6 +96,10 @@ export declare const artifactManifestSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
|
|
|
92
96
|
intent: z.ZodOptional<z.ZodString>;
|
|
93
97
|
generatorProtocolVersion: z.ZodOptional<z.ZodString>;
|
|
94
98
|
toolIdentityCatalogHash: z.ZodOptional<z.ZodString>;
|
|
99
|
+
mcpTools: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
100
|
+
server: z.ZodOptional<z.ZodString>;
|
|
101
|
+
tool: z.ZodString;
|
|
102
|
+
}, z.core.$strict>>>>;
|
|
95
103
|
}, z.core.$strict>], "kind">;
|
|
96
104
|
/**
|
|
97
105
|
* Static TypeScript type derived from {@link artifactManifestSchema}.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-manifest.d.ts","sourceRoot":"","sources":["../src/artifact-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"artifact-manifest.d.ts","sourceRoot":"","sources":["../src/artifact-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAGjC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAatE;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,sBAAsB,CAAC,SAAS,CAAC,CAErD"}
|
|
@@ -94,6 +94,10 @@ export declare const blueprintManifestSchema: z.ZodObject<{
|
|
|
94
94
|
intent: z.ZodOptional<z.ZodString>;
|
|
95
95
|
generatorProtocolVersion: z.ZodOptional<z.ZodString>;
|
|
96
96
|
toolIdentityCatalogHash: z.ZodOptional<z.ZodString>;
|
|
97
|
+
mcpTools: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
98
|
+
server: z.ZodOptional<z.ZodString>;
|
|
99
|
+
tool: z.ZodString;
|
|
100
|
+
}, z.core.$strict>>>>;
|
|
97
101
|
}, z.core.$strict>;
|
|
98
102
|
/**
|
|
99
103
|
* Static TypeScript type derived from {@link blueprintManifestSchema}.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-manifest.d.ts","sourceRoot":"","sources":["../src/blueprint-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAGlB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"blueprint-manifest.d.ts","sourceRoot":"","sources":["../src/blueprint-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAGlB,MAAM,mBAAmB,CAAC;AAgC3B;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+ElC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAmBxE;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,wBAAwB,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAEtE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,uBAAuB,CAAC,SAAS,CAAC,CAEtD"}
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
import { z } from 'zod';
|
|
62
62
|
import { blueprintVarianceSchema, dataContractSchema, } from '@ggui-ai/protocol';
|
|
63
63
|
import { ArtifactScopeSchema, ArtifactVersionSchema, ArtifactVisibilitySchema, BLUEPRINT_NAME_RE, sharedMetadataShape, } from './base.js';
|
|
64
|
+
import { mcpToolsSchema } from './mcp-tool-bindings.js';
|
|
64
65
|
/**
|
|
65
66
|
* Blueprint name regex — the same kebab-case rule as gadgets. See
|
|
66
67
|
* {@link BLUEPRINT_NAME_RE} for the rationale.
|
|
@@ -130,6 +131,10 @@ export const blueprintManifestSchema = z.strictObject({
|
|
|
130
131
|
.min(1)
|
|
131
132
|
.optional()
|
|
132
133
|
.describe('SHA256(16) of the tool-identity catalog used to canonicalize `contract` at authoring time. Importers re-canonicalize against their own catalog and recompute the key; a divergence means the same intent would mis-key and silently cold-gen, so it is rejected. Optional — most marketplace blueprints are authored without a live tool catalog, which leaves the import gate’s re-key check inert.'),
|
|
134
|
+
// ---- Optional MCP tool bindings (search metadata only) ----
|
|
135
|
+
mcpTools: mcpToolsSchema
|
|
136
|
+
.optional()
|
|
137
|
+
.describe('MCP tool bindings this blueprint renders — surfaced in registry search results and matched by the `tool` / `server` search filters. When absent, registry publish derives bare tool-name bindings from the contract (`propsSpec.properties[*].sourceTool` plus `streamSpec[*].source.tool`); declaring this field disables derivation entirely (declared wins, no merge). Bindings are publisher claims, not an endorsement by the named server. Search metadata only — never part of `blueprintKey` or any cache identity. Max 16 entries, charset `[A-Za-z0-9_.-]`, case-sensitive; exact-duplicate `(server, tool)` pairs rejected.'),
|
|
133
138
|
// ---- Shared metadata ----
|
|
134
139
|
...sharedMetadataShape,
|
|
135
140
|
});
|
|
@@ -81,6 +81,10 @@ export declare const gadgetExportSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
81
81
|
*/
|
|
82
82
|
export declare const gadgetManifestSchema: z.ZodObject<{
|
|
83
83
|
connect: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
84
|
+
mcpTools: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
85
|
+
server: z.ZodOptional<z.ZodString>;
|
|
86
|
+
tool: z.ZodString;
|
|
87
|
+
}, z.core.$strict>>>>;
|
|
84
88
|
tags: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
85
89
|
author: z.ZodOptional<z.ZodObject<{
|
|
86
90
|
name: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gadget-manifest.d.ts","sourceRoot":"","sources":["../src/gadget-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"gadget-manifest.d.ts","sourceRoot":"","sources":["../src/gadget-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAuFxB;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;oBAwB7B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+H/B,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAE5D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,oBAAoB,CAAC,SAAS,CAAC,CAEnD"}
|
package/dist/gadget-manifest.js
CHANGED
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
import { z } from 'zod';
|
|
56
56
|
import { BUNDLE_HOST_RE, gadgetRequiresSchema, jsonValueSchema, } from '@ggui-ai/protocol';
|
|
57
57
|
import { ArtifactScopeSchema, ArtifactVersionSchema, ArtifactVisibilitySchema, GADGET_NAME_RE, sharedMetadataShape, } from './base.js';
|
|
58
|
+
import { mcpToolsSchema } from './mcp-tool-bindings.js';
|
|
58
59
|
/**
|
|
59
60
|
* Gadget name — kebab-case identifier without scope prefix. The
|
|
60
61
|
* scope lives on its own field. Examples: `weather-card`, `leaflet`,
|
|
@@ -220,7 +221,7 @@ export const gadgetManifestSchema = z.strictObject({
|
|
|
220
221
|
.string()
|
|
221
222
|
.regex(BUNDLE_HOST_RE)
|
|
222
223
|
.optional()
|
|
223
|
-
.describe("Optional author-default registry hostname (no scheme, no path). The server prepends `https://` and appends `/bundles/<scope>/<name>/<version>/{bundle.js,style.css}` at push time. Omit to inherit the spec default (`registry.ggui.ai`). Operators can override per-gadget via `ggui.json#app.gadgets[*].bundleHost`."),
|
|
224
|
+
.describe("Optional author-default registry hostname (no scheme, no path). The server prepends `https://` and appends `/bundles/public/<scope>/<name>/<version>/{bundle.js,style.css}` at push time (the public prefix of the registry's visibility-split bundle layout). Omit to inherit the spec default (`registry.ggui.ai`). Operators can override per-gadget via `ggui.json#app.gadgets[*].bundleHost`."),
|
|
224
225
|
// ---- Shared metadata ----
|
|
225
226
|
// `description` is intentionally NOT spread from here — gadgets
|
|
226
227
|
// require it (declared above) while blueprints inherit the
|
|
@@ -233,6 +234,10 @@ export const gadgetManifestSchema = z.strictObject({
|
|
|
233
234
|
})(),
|
|
234
235
|
// ---- Optional wire allowlist (mirrors gadgetEntry.connect) ----
|
|
235
236
|
connect: GadgetConnectSchema.optional().describe("URLs the wrapper's runtime may speak to. Merged into the iframe CSP `connect-src` at boot. Shape mirrors `gadgetDescriptorSchema.connect` in `@ggui-ai/protocol` — a flat readonly string list."),
|
|
237
|
+
// ---- Optional MCP tool bindings (search metadata only) ----
|
|
238
|
+
mcpTools: mcpToolsSchema
|
|
239
|
+
.optional()
|
|
240
|
+
.describe('MCP tool bindings this gadget renders — surfaced in registry search results and matched by the `tool` / `server` search filters (`tool` matches any entry with that tool name; `server` matches entries declaring that server; both together match the exact pair). Bindings are publisher claims, not an endorsement by the named server. Search metadata only — never part of any cache identity. Max 16 entries, charset `[A-Za-z0-9_.-]`, case-sensitive; exact-duplicate `(server, tool)` pairs rejected.'),
|
|
236
241
|
});
|
|
237
242
|
/**
|
|
238
243
|
* Canonical filename — always at the gadget repo root, always this
|
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export type { BlueprintManifest } from './blueprint-manifest.js';
|
|
|
24
24
|
export { artifactManifestSchema, parseArtifactManifest, safeParseArtifactManifest, } from './artifact-manifest.js';
|
|
25
25
|
export type { ArtifactManifest } from './artifact-manifest.js';
|
|
26
26
|
export { GADGET_NAME_RE, BLUEPRINT_NAME_RE, ArtifactScopeSchema, ArtifactVersionSchema, } from './base.js';
|
|
27
|
+
export { MCP_TOOL_BINDING_NAME_RE, mcpToolBindingSchema, mcpToolsSchema, resolveMcpToolBindings, } from './mcp-tool-bindings.js';
|
|
28
|
+
export type { McpToolBinding, McpToolBindingSource } from './mcp-tool-bindings.js';
|
|
27
29
|
export { manifestToRegistryEntry, type ManifestToRegistryEntryFields, } from './manifest-to-registry-entry.js';
|
|
28
30
|
export { POOL_ARTIFACT_CODES_DIR, POOL_ARTIFACT_CODE_REF_PATTERN, POOL_ARTIFACT_MANIFEST_FILENAME, POOL_ARTIFACT_SCHEMA_VERSION, POOL_ARTIFACT_V1_REJECTION, buildPoolArtifactManifest, parsePoolArtifactManifest, poolArtifactCodeRef, serializePoolArtifactManifest, type ParsePoolArtifactManifestResult, type PoolArtifactManifest, type PoolArtifactManifestEntry, } from './pool-artifact.js';
|
|
29
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAS/D,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAS/D,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAQnB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAMnF,OAAO,EACL,uBAAuB,EACvB,KAAK,6BAA6B,GACnC,MAAM,iCAAiC,CAAC;AAMzC,OAAO,EACL,uBAAuB,EACvB,8BAA8B,EAC9B,+BAA+B,EAC/B,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,mBAAmB,EACnB,6BAA6B,EAC7B,KAAK,+BAA+B,EACpC,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,GAC/B,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,13 @@ export { artifactManifestSchema, parseArtifactManifest, safeParseArtifactManifes
|
|
|
31
31
|
// validation; reuse keeps the CLI and registry-side validation on a
|
|
32
32
|
// single regex source.
|
|
33
33
|
export { GADGET_NAME_RE, BLUEPRINT_NAME_RE, ArtifactScopeSchema, ArtifactVersionSchema, } from './base.js';
|
|
34
|
+
// MCP tool bindings — the `mcpTools` search-metadata field shared by
|
|
35
|
+
// both manifest kinds, plus the declared-vs-derived resolver registry
|
|
36
|
+
// publish flows use to compute the effective binding set. Registry
|
|
37
|
+
// search input validation (`tool=` / `server=` filters) imports
|
|
38
|
+
// `MCP_TOOL_BINDING_NAME_RE` from here so the wire filters and the
|
|
39
|
+
// manifest field stay on a single charset rule.
|
|
40
|
+
export { MCP_TOOL_BINDING_NAME_RE, mcpToolBindingSchema, mcpToolsSchema, resolveMcpToolBindings, } from './mcp-tool-bindings.js';
|
|
34
41
|
// Manifest → registry-entry translator. The install CLI, programmatic
|
|
35
42
|
// publish flows, and any future register-by-manifest tool all go
|
|
36
43
|
// through this one function. Round-trip validated in the companion
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool bindings — the `mcpTools` search-metadata field shared by
|
|
3
|
+
* both artifact-manifest kinds, plus the declared-vs-derived resolver
|
|
4
|
+
* registry publish flows use to compute the effective binding set.
|
|
5
|
+
*
|
|
6
|
+
* A binding names an MCP tool (optionally scoped to an MCP server,
|
|
7
|
+
* `serverInfo.name` semantics) that the artifact renders a UI for.
|
|
8
|
+
* Bindings are search metadata ONLY:
|
|
9
|
+
*
|
|
10
|
+
* - They MUST NOT enter contract canonicalization, `blueprintKey`,
|
|
11
|
+
* or any cache identity — declaring or removing bindings never
|
|
12
|
+
* re-keys an artifact.
|
|
13
|
+
* - They are publisher claims. A binding MUST NOT be presented as
|
|
14
|
+
* an endorsement by the named server or its authors.
|
|
15
|
+
*
|
|
16
|
+
* Precedence ({@link resolveMcpToolBindings}): a declared `mcpTools`
|
|
17
|
+
* field wins entirely — derivation never runs, no merge. Blueprints
|
|
18
|
+
* without the field derive bare tool-name bindings from their
|
|
19
|
+
* contract (`propsSpec.properties[*].sourceTool` union
|
|
20
|
+
* `streamSpec[*].source.tool`). Gadgets never derive (they carry no
|
|
21
|
+
* contract).
|
|
22
|
+
*/
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
import type { BlueprintManifest } from "./blueprint-manifest.js";
|
|
25
|
+
import type { GadgetManifest } from "./gadget-manifest.js";
|
|
26
|
+
/**
|
|
27
|
+
* Charset for both `server` and `tool` binding names — 1-128 chars
|
|
28
|
+
* of `[A-Za-z0-9_.-]`, the practical MCP tool-name grammar.
|
|
29
|
+
* Case-sensitive throughout (MCP tool names are). Registry search
|
|
30
|
+
* input validation (`tool=` / `server=` filters) imports this via
|
|
31
|
+
* the package barrel so the wire filters and the manifest field
|
|
32
|
+
* stay on a single charset rule.
|
|
33
|
+
*/
|
|
34
|
+
export declare const MCP_TOOL_BINDING_NAME_RE: RegExp;
|
|
35
|
+
/**
|
|
36
|
+
* One MCP tool binding. `server` optional — omit for a
|
|
37
|
+
* server-agnostic tool-name binding.
|
|
38
|
+
*/
|
|
39
|
+
export declare const mcpToolBindingSchema: z.ZodObject<{
|
|
40
|
+
server: z.ZodOptional<z.ZodString>;
|
|
41
|
+
tool: z.ZodString;
|
|
42
|
+
}, z.core.$strict>;
|
|
43
|
+
/** Static TS type for one binding entry. */
|
|
44
|
+
export type McpToolBinding = z.infer<typeof mcpToolBindingSchema>;
|
|
45
|
+
/**
|
|
46
|
+
* Bounded binding list. Caps protect the index and wire payload
|
|
47
|
+
* size — 16 entries covers every realistic multi-tool artifact
|
|
48
|
+
* while bounding worst-case spam (same rationale as the 20-tag
|
|
49
|
+
* cap on `tags`). Exact-duplicate `(server, tool)` pairs are
|
|
50
|
+
* rejected; the same tool under different servers (or bare +
|
|
51
|
+
* server-scoped) is legal.
|
|
52
|
+
*/
|
|
53
|
+
export declare const mcpToolsSchema: z.ZodReadonly<z.ZodArray<z.ZodObject<{
|
|
54
|
+
server: z.ZodOptional<z.ZodString>;
|
|
55
|
+
tool: z.ZodString;
|
|
56
|
+
}, z.core.$strict>>>;
|
|
57
|
+
/**
|
|
58
|
+
* Provenance of a resolved binding set — declared verbatim on the
|
|
59
|
+
* manifest, or derived from a blueprint contract's tool names.
|
|
60
|
+
*/
|
|
61
|
+
export type McpToolBindingSource = "declared" | "derived";
|
|
62
|
+
/**
|
|
63
|
+
* Compute the effective binding set for a manifest. Pure.
|
|
64
|
+
*
|
|
65
|
+
* Precedence: a declared `mcpTools` field wins entirely (result
|
|
66
|
+
* marked `declared`; derivation never runs, no merge). Otherwise,
|
|
67
|
+
* blueprint manifests with a contract derive bare `{tool}` entries
|
|
68
|
+
* from the union of `contract.propsSpec.properties[*].sourceTool`
|
|
69
|
+
* and `contract.streamSpec[*].source.tool` (contracts carry no
|
|
70
|
+
* server identity), marked `derived`. Derivation stays INSIDE the
|
|
71
|
+
* same envelope a declared list is validated against — it composes
|
|
72
|
+
* the envelope, it does not relax it:
|
|
73
|
+
*
|
|
74
|
+
* - Every candidate tool name is filtered through
|
|
75
|
+
* {@link MCP_TOOL_BINDING_NAME_RE}; a name failing the charset
|
|
76
|
+
* (including the empty string — just one case of the charset
|
|
77
|
+
* filter) is dropped silently rather than rejected. Contract
|
|
78
|
+
* lineage is agent/tool-authored data, not an author
|
|
79
|
+
* declaration, so malformed lineage is noise to filter, not a
|
|
80
|
+
* manifest error.
|
|
81
|
+
* - Survivors are deduped first-seen — props entries in
|
|
82
|
+
* declaration order, then stream channels in declaration order —
|
|
83
|
+
* then capped at {@link MCP_TOOL_BINDING_MAX_ENTRIES} in that
|
|
84
|
+
* same first-appearance order, matching the bound a declared
|
|
85
|
+
* list is schema-capped at.
|
|
86
|
+
*
|
|
87
|
+
* Returns `undefined` when nothing declares or derives (gadgets
|
|
88
|
+
* without `mcpTools`, contract-less blueprints, contracts naming no
|
|
89
|
+
* valid tools) — such artifacts are simply not findable by tool.
|
|
90
|
+
*/
|
|
91
|
+
export declare function resolveMcpToolBindings(manifest: GadgetManifest | BlueprintManifest): {
|
|
92
|
+
source: McpToolBindingSource;
|
|
93
|
+
bindings: ReadonlyArray<McpToolBinding>;
|
|
94
|
+
} | undefined;
|
|
95
|
+
//# sourceMappingURL=mcp-tool-bindings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tool-bindings.d.ts","sourceRoot":"","sources":["../src/mcp-tool-bindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,QAA4B,CAAC;AASlE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;kBAkB/B,CAAC;AAEH,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc;;;oBAkBxB,CAAC;AAEJ;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,cAAc,GAAG,iBAAiB,GAC3C;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;CAAE,GAAG,SAAS,CAuBvF"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool bindings — the `mcpTools` search-metadata field shared by
|
|
3
|
+
* both artifact-manifest kinds, plus the declared-vs-derived resolver
|
|
4
|
+
* registry publish flows use to compute the effective binding set.
|
|
5
|
+
*
|
|
6
|
+
* A binding names an MCP tool (optionally scoped to an MCP server,
|
|
7
|
+
* `serverInfo.name` semantics) that the artifact renders a UI for.
|
|
8
|
+
* Bindings are search metadata ONLY:
|
|
9
|
+
*
|
|
10
|
+
* - They MUST NOT enter contract canonicalization, `blueprintKey`,
|
|
11
|
+
* or any cache identity — declaring or removing bindings never
|
|
12
|
+
* re-keys an artifact.
|
|
13
|
+
* - They are publisher claims. A binding MUST NOT be presented as
|
|
14
|
+
* an endorsement by the named server or its authors.
|
|
15
|
+
*
|
|
16
|
+
* Precedence ({@link resolveMcpToolBindings}): a declared `mcpTools`
|
|
17
|
+
* field wins entirely — derivation never runs, no merge. Blueprints
|
|
18
|
+
* without the field derive bare tool-name bindings from their
|
|
19
|
+
* contract (`propsSpec.properties[*].sourceTool` union
|
|
20
|
+
* `streamSpec[*].source.tool`). Gadgets never derive (they carry no
|
|
21
|
+
* contract).
|
|
22
|
+
*/
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
/**
|
|
25
|
+
* Charset for both `server` and `tool` binding names — 1-128 chars
|
|
26
|
+
* of `[A-Za-z0-9_.-]`, the practical MCP tool-name grammar.
|
|
27
|
+
* Case-sensitive throughout (MCP tool names are). Registry search
|
|
28
|
+
* input validation (`tool=` / `server=` filters) imports this via
|
|
29
|
+
* the package barrel so the wire filters and the manifest field
|
|
30
|
+
* stay on a single charset rule.
|
|
31
|
+
*/
|
|
32
|
+
export const MCP_TOOL_BINDING_NAME_RE = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
33
|
+
/**
|
|
34
|
+
* Shared entry-count bound for a binding list, declared OR derived —
|
|
35
|
+
* one envelope, referenced everywhere a cap applies rather than a
|
|
36
|
+
* second magic `16` drifting from this one.
|
|
37
|
+
*/
|
|
38
|
+
const MCP_TOOL_BINDING_MAX_ENTRIES = 16;
|
|
39
|
+
/**
|
|
40
|
+
* One MCP tool binding. `server` optional — omit for a
|
|
41
|
+
* server-agnostic tool-name binding.
|
|
42
|
+
*/
|
|
43
|
+
export const mcpToolBindingSchema = z.strictObject({
|
|
44
|
+
server: z
|
|
45
|
+
.string()
|
|
46
|
+
.regex(MCP_TOOL_BINDING_NAME_RE, {
|
|
47
|
+
message: "server must be 1-128 chars of `[A-Za-z0-9_.-]` (MCP server name charset).",
|
|
48
|
+
})
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("MCP server identity this binding targets — `serverInfo.name` semantics, matched case-sensitively. Omit for a server-agnostic binding that matches the tool name on any server. 1-128 chars, charset `[A-Za-z0-9_.-]`."),
|
|
51
|
+
tool: z
|
|
52
|
+
.string()
|
|
53
|
+
.regex(MCP_TOOL_BINDING_NAME_RE, {
|
|
54
|
+
message: "tool must be 1-128 chars of `[A-Za-z0-9_.-]` (MCP tool name charset).",
|
|
55
|
+
})
|
|
56
|
+
.describe("MCP tool name this artifact renders. Matched case-sensitively by the registry search `tool` filter. 1-128 chars, charset `[A-Za-z0-9_.-]`."),
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* Bounded binding list. Caps protect the index and wire payload
|
|
60
|
+
* size — 16 entries covers every realistic multi-tool artifact
|
|
61
|
+
* while bounding worst-case spam (same rationale as the 20-tag
|
|
62
|
+
* cap on `tags`). Exact-duplicate `(server, tool)` pairs are
|
|
63
|
+
* rejected; the same tool under different servers (or bare +
|
|
64
|
+
* server-scoped) is legal.
|
|
65
|
+
*/
|
|
66
|
+
export const mcpToolsSchema = z
|
|
67
|
+
.array(mcpToolBindingSchema)
|
|
68
|
+
.min(1, { message: "mcpTools must declare at least one binding." })
|
|
69
|
+
.max(MCP_TOOL_BINDING_MAX_ENTRIES, {
|
|
70
|
+
message: `at most ${MCP_TOOL_BINDING_MAX_ENTRIES} MCP tool bindings per artifact.`,
|
|
71
|
+
})
|
|
72
|
+
.readonly()
|
|
73
|
+
.refine((bindings) => {
|
|
74
|
+
const seen = new Set();
|
|
75
|
+
for (const binding of bindings) {
|
|
76
|
+
const key = JSON.stringify([binding.server ?? null, binding.tool]);
|
|
77
|
+
if (seen.has(key))
|
|
78
|
+
return false;
|
|
79
|
+
seen.add(key);
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}, { message: "duplicate `(server, tool)` binding pairs are not allowed." });
|
|
83
|
+
/**
|
|
84
|
+
* Compute the effective binding set for a manifest. Pure.
|
|
85
|
+
*
|
|
86
|
+
* Precedence: a declared `mcpTools` field wins entirely (result
|
|
87
|
+
* marked `declared`; derivation never runs, no merge). Otherwise,
|
|
88
|
+
* blueprint manifests with a contract derive bare `{tool}` entries
|
|
89
|
+
* from the union of `contract.propsSpec.properties[*].sourceTool`
|
|
90
|
+
* and `contract.streamSpec[*].source.tool` (contracts carry no
|
|
91
|
+
* server identity), marked `derived`. Derivation stays INSIDE the
|
|
92
|
+
* same envelope a declared list is validated against — it composes
|
|
93
|
+
* the envelope, it does not relax it:
|
|
94
|
+
*
|
|
95
|
+
* - Every candidate tool name is filtered through
|
|
96
|
+
* {@link MCP_TOOL_BINDING_NAME_RE}; a name failing the charset
|
|
97
|
+
* (including the empty string — just one case of the charset
|
|
98
|
+
* filter) is dropped silently rather than rejected. Contract
|
|
99
|
+
* lineage is agent/tool-authored data, not an author
|
|
100
|
+
* declaration, so malformed lineage is noise to filter, not a
|
|
101
|
+
* manifest error.
|
|
102
|
+
* - Survivors are deduped first-seen — props entries in
|
|
103
|
+
* declaration order, then stream channels in declaration order —
|
|
104
|
+
* then capped at {@link MCP_TOOL_BINDING_MAX_ENTRIES} in that
|
|
105
|
+
* same first-appearance order, matching the bound a declared
|
|
106
|
+
* list is schema-capped at.
|
|
107
|
+
*
|
|
108
|
+
* Returns `undefined` when nothing declares or derives (gadgets
|
|
109
|
+
* without `mcpTools`, contract-less blueprints, contracts naming no
|
|
110
|
+
* valid tools) — such artifacts are simply not findable by tool.
|
|
111
|
+
*/
|
|
112
|
+
export function resolveMcpToolBindings(manifest) {
|
|
113
|
+
if (manifest.mcpTools !== undefined) {
|
|
114
|
+
return { source: "declared", bindings: manifest.mcpTools };
|
|
115
|
+
}
|
|
116
|
+
if (manifest.kind !== "blueprint" || manifest.contract === undefined) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
const seen = new Set();
|
|
120
|
+
const tools = [];
|
|
121
|
+
const add = (tool) => {
|
|
122
|
+
if (tool === undefined || !MCP_TOOL_BINDING_NAME_RE.test(tool) || seen.has(tool))
|
|
123
|
+
return;
|
|
124
|
+
seen.add(tool);
|
|
125
|
+
tools.push(tool);
|
|
126
|
+
};
|
|
127
|
+
for (const entry of Object.values(manifest.contract.propsSpec?.properties ?? {})) {
|
|
128
|
+
add(entry.sourceTool);
|
|
129
|
+
}
|
|
130
|
+
for (const entry of Object.values(manifest.contract.streamSpec ?? {})) {
|
|
131
|
+
add(entry.source?.tool);
|
|
132
|
+
}
|
|
133
|
+
if (tools.length === 0)
|
|
134
|
+
return undefined;
|
|
135
|
+
const capped = tools.slice(0, MCP_TOOL_BINDING_MAX_ENTRIES);
|
|
136
|
+
return { source: "derived", bindings: capped.map((tool) => ({ tool })) };
|
|
137
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/artifact-manifest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Strict zod schemas + parsers for ggui marketplace artifact manifests — ggui.gadget.json (gadget bundles) and ggui.blueprint.json (cached UI blueprints).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -27,11 +27,12 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"zod": "^4.3.6",
|
|
30
|
-
"@ggui-ai/protocol": "0.
|
|
30
|
+
"@ggui-ai/protocol": "0.8.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"typescript": "^5.0.0",
|
|
34
|
-
"vitest": "^3.2.6"
|
|
34
|
+
"vitest": "^3.2.6",
|
|
35
|
+
"@ggui-ai/protocol-conformance": "0.8.0"
|
|
35
36
|
},
|
|
36
37
|
"repository": {
|
|
37
38
|
"type": "git",
|