@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.
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
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;AA+B3B;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;kBAwElC,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"}
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;AAsFxB;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;oBAwB7B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwH/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"}
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"}
@@ -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
@@ -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;AAMnB,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"}
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.6.3",
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.6.3"
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",