@primeuicom/mcp 1.2.3 → 1.2.5

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/service.js CHANGED
@@ -622,6 +622,14 @@ var primeUiComponentExportPageSchema = z3.object({
622
622
  isReadyToExport: z3.boolean(),
623
623
  manifest: primeUiExportPageManifestSchema
624
624
  });
625
+ var primeUiComponentExportSelectedBlockSchema = z3.object({
626
+ blockId: z3.string(),
627
+ componentId: z3.string(),
628
+ contentKey: z3.string(),
629
+ occurrenceIndex: z3.number().int().positive(),
630
+ props: z3.record(z3.unknown()).nullable(),
631
+ slot: z3.string().nullable()
632
+ });
625
633
  var primeUiProjectInfoSchema = z3.object(
626
634
  {
627
635
  projectId: z3.string(),
@@ -739,6 +747,9 @@ var primeUiComponentCandidatesResponseSchema = z3.object({
739
747
  candidates: z3.array(primeUiComponentCandidateSchema)
740
748
  });
741
749
  var primeUiComponentPropsValidateInputSchema = z3.object({
750
+ blockId: z3.string().refine((value) => value.trim().length > 0, {
751
+ message: "blockId must be a non-empty string"
752
+ }),
742
753
  pageSlug: primeUiPageSlugInputSchema,
743
754
  componentId: z3.string(),
744
755
  props: z3.record(z3.unknown())
@@ -755,6 +766,13 @@ var primeUiComponentPropsRenderCheckSchema = z3.object({
755
766
  var primeUiComponentPropsValidateResponseSchema = z3.object({
756
767
  valid: z3.boolean(),
757
768
  normalizedProps: z3.record(z3.unknown()).nullable(),
769
+ propsValidationId: z3.string().nullable(),
770
+ block: z3.object({
771
+ blockId: z3.string(),
772
+ componentId: z3.string(),
773
+ contentKey: z3.string(),
774
+ props: z3.record(z3.unknown())
775
+ }).nullable(),
758
776
  errors: z3.array(primeUiComponentPropsValidationErrorSchema),
759
777
  hints: z3.array(z3.string()),
760
778
  renderCheck: primeUiComponentPropsRenderCheckSchema
@@ -987,6 +1005,7 @@ var primeUiExportManifestSchema = primeUiCreateExportResponseSchema;
987
1005
  var primeUiComponentExportResponseSchema = z3.object({
988
1006
  exportId: z3.string(),
989
1007
  export: primeUiPostExportPayloadExportSchema,
1008
+ block: primeUiComponentExportSelectedBlockSchema.optional(),
990
1009
  component: primeUiComponentExportComponentSchema,
991
1010
  page: primeUiComponentExportPageSchema,
992
1011
  pages: z3.array(primeUiComponentExportPageSchema)
@@ -1083,6 +1102,16 @@ var normalizePrimeUiApiRoot = (rawBaseUrl) => {
1083
1102
  var buildPrimeUiApiUrl = (apiRoot, endpoint) => new URL(endpoint, apiRoot).toString();
1084
1103
  var isJsonContentType = (contentType) => contentType.includes("application/json") || contentType.includes("+json");
1085
1104
  var isZipContentType = (contentType) => ZIP_CONTENT_TYPES.some((allowedType) => contentType.includes(allowedType));
1105
+ function normalizePropsValidationId(propsValidationId) {
1106
+ if (typeof propsValidationId === "undefined") {
1107
+ return void 0;
1108
+ }
1109
+ const trimmed = propsValidationId.trim();
1110
+ if (!trimmed) {
1111
+ throw new Error("propsValidationId must be a non-empty string.");
1112
+ }
1113
+ return trimmed;
1114
+ }
1086
1115
  var looksLikeZipArchive = (buffer) => {
1087
1116
  if (buffer.length < 4) {
1088
1117
  return false;
@@ -1295,11 +1324,14 @@ var ApiProjectDataProvider = class {
1295
1324
  }
1296
1325
  );
1297
1326
  }
1298
- async createComponentExport(componentId) {
1327
+ async createComponentExport(componentId, options = {}) {
1328
+ const propsValidationId = normalizePropsValidationId(
1329
+ options.propsValidationId
1330
+ );
1299
1331
  return this.requestJson(
1300
1332
  `component-registry/components/${encodeURIComponent(componentId)}/exports`,
1301
1333
  primeUiComponentExportResponseSchema,
1302
- {
1334
+ propsValidationId ? this.buildJsonRequestInit({ propsValidationId }) : {
1303
1335
  method: "POST"
1304
1336
  }
1305
1337
  );
@@ -3920,6 +3952,11 @@ function isVirtualRouteFile(relativePath) {
3920
3952
  const segments = relativePath.split("/");
3921
3953
  return segments[0] === "src" && segments[1] === "app" && segments.includes(VIRTUAL_ROUTE_SEGMENT);
3922
3954
  }
3955
+ function isVirtualComponentExportPageFile(relativePath) {
3956
+ const segments = relativePath.split("/");
3957
+ const virtualRouteIndex = segments.indexOf(VIRTUAL_ROUTE_SEGMENT);
3958
+ return isVirtualRouteFile(relativePath) && virtualRouteIndex >= 0 && segments.length === virtualRouteIndex + 3 && segments[virtualRouteIndex + 2] === "page.tsx";
3959
+ }
3923
3960
  function getVirtualComponentRelativePath(relativePath, componentId) {
3924
3961
  const prefix = `${COMPONENT_PAGES_PREFIX}${VIRTUAL_ROUTE_SEGMENT}/${componentId}/`;
3925
3962
  if (!relativePath.startsWith(prefix)) {
@@ -3985,6 +4022,44 @@ function toImportPath(relativePath) {
3985
4022
  const withoutIndex = withoutExtension.replace(/\/index$/u, "");
3986
4023
  return `@/${withoutIndex.replace(/^src\//u, "")}`;
3987
4024
  }
4025
+ function toPascalComponentName(componentId) {
4026
+ return componentId.split(/[^a-zA-Z0-9]+/u).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
4027
+ }
4028
+ function toVariableName(componentName) {
4029
+ if (!componentName) {
4030
+ return "componentProps";
4031
+ }
4032
+ return `${componentName.charAt(0).toLowerCase()}${componentName.slice(1)}Props`;
4033
+ }
4034
+ function toSafeCamelIdentifier(input, fallback) {
4035
+ const parts = input.trim().split(/[^a-zA-Z0-9]+/u).filter(Boolean);
4036
+ if (parts.length === 0) {
4037
+ return fallback;
4038
+ }
4039
+ const pascalName = parts.map((part) => {
4040
+ const normalizedPart = part.toLowerCase();
4041
+ return `${normalizedPart.charAt(0).toUpperCase()}${normalizedPart.slice(1)}`;
4042
+ }).join("");
4043
+ if (!pascalName) {
4044
+ return fallback;
4045
+ }
4046
+ if (/^[0-9]/u.test(pascalName)) {
4047
+ return `block${pascalName}`;
4048
+ }
4049
+ return `${pascalName.charAt(0).toLowerCase()}${pascalName.slice(1)}`;
4050
+ }
4051
+ function isDefaultComponentExportBlock(selectedBlock) {
4052
+ return selectedBlock.blockId === `component-export:${selectedBlock.componentId}:block`;
4053
+ }
4054
+ function toPropsVariableName(input) {
4055
+ if (isDefaultComponentExportBlock(input.selectedBlock)) {
4056
+ return toVariableName(input.componentName);
4057
+ }
4058
+ return `${toSafeCamelIdentifier(
4059
+ input.selectedBlock.blockId,
4060
+ input.componentName ? toVariableName(input.componentName).replace(/Props$/u, "") : "component"
4061
+ )}Props`;
4062
+ }
3988
4063
  function escapeRegExp(value) {
3989
4064
  return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
3990
4065
  }
@@ -4224,6 +4299,113 @@ function buildMessage(input) {
4224
4299
  );
4225
4300
  return parts.join(" ");
4226
4301
  }
4302
+ function getDefaultSelectedBlock(manifest) {
4303
+ const componentId = manifest.component.componentId;
4304
+ return {
4305
+ blockId: `component-export:${componentId}:block`,
4306
+ componentId,
4307
+ contentKey: componentId,
4308
+ occurrenceIndex: 1,
4309
+ props: null,
4310
+ slot: null
4311
+ };
4312
+ }
4313
+ function getSelectedBlock(manifest) {
4314
+ return manifest.block ?? getDefaultSelectedBlock(manifest);
4315
+ }
4316
+ function getVirtualRouteFile(manifestFiles) {
4317
+ return manifestFiles.find(isVirtualComponentExportPageFile) ?? manifestFiles.find(isVirtualRouteFile) ?? null;
4318
+ }
4319
+ function readBalancedObjectLiteral(input, startIndex) {
4320
+ if (input[startIndex] !== "{") {
4321
+ return null;
4322
+ }
4323
+ let depth = 0;
4324
+ let quote = null;
4325
+ let escaped = false;
4326
+ for (let index = startIndex; index < input.length; index += 1) {
4327
+ const char = input[index];
4328
+ if (escaped) {
4329
+ escaped = false;
4330
+ continue;
4331
+ }
4332
+ if (quote) {
4333
+ if (char === "\\") {
4334
+ escaped = true;
4335
+ continue;
4336
+ }
4337
+ if (char === quote) {
4338
+ quote = null;
4339
+ }
4340
+ continue;
4341
+ }
4342
+ if (char === '"' || char === "'" || char === "`") {
4343
+ quote = char;
4344
+ continue;
4345
+ }
4346
+ if (char === "{") {
4347
+ depth += 1;
4348
+ continue;
4349
+ }
4350
+ if (char !== "}") {
4351
+ continue;
4352
+ }
4353
+ depth -= 1;
4354
+ if (depth === 0) {
4355
+ return input.slice(startIndex, index + 1);
4356
+ }
4357
+ }
4358
+ return null;
4359
+ }
4360
+ function extractContentDataPropsCode(input) {
4361
+ const contentDataIndex = input.source.indexOf("const contentData");
4362
+ if (contentDataIndex < 0) {
4363
+ return null;
4364
+ }
4365
+ const keyPattern = new RegExp(
4366
+ `["']${escapeRegExp(input.contentKey)}["']\\s*:`,
4367
+ "u"
4368
+ );
4369
+ const keyMatch = keyPattern.exec(input.source.slice(contentDataIndex));
4370
+ if (!keyMatch) {
4371
+ return null;
4372
+ }
4373
+ const valueStartSearchIndex = contentDataIndex + keyMatch.index + keyMatch[0].length;
4374
+ const objectStartIndex = input.source.indexOf("{", valueStartSearchIndex);
4375
+ if (objectStartIndex < 0) {
4376
+ return null;
4377
+ }
4378
+ return readBalancedObjectLiteral(input.source, objectStartIndex);
4379
+ }
4380
+ async function buildRegistryComponentInsertion(input) {
4381
+ const componentName = toPascalComponentName(input.selectedBlock.componentId);
4382
+ const propsVariableName = toPropsVariableName({
4383
+ componentName,
4384
+ selectedBlock: input.selectedBlock
4385
+ });
4386
+ const virtualRouteFile = getVirtualRouteFile(input.manifestFiles);
4387
+ const referenceFiles = virtualRouteFile ? [virtualRouteFile] : [];
4388
+ let materializedPropsCode = input.selectedBlock.props ? JSON.stringify(input.selectedBlock.props, null, 2) : "{}";
4389
+ if (virtualRouteFile) {
4390
+ try {
4391
+ const virtualRouteSource = await readFile7(
4392
+ path13.join(input.exportPath, virtualRouteFile),
4393
+ "utf-8"
4394
+ );
4395
+ materializedPropsCode = extractContentDataPropsCode({
4396
+ source: virtualRouteSource,
4397
+ contentKey: input.selectedBlock.contentKey
4398
+ }) ?? materializedPropsCode;
4399
+ } catch {
4400
+ }
4401
+ }
4402
+ return {
4403
+ imports: [`import ${componentName} from "${input.componentImportPath}";`],
4404
+ propsCode: `const ${propsVariableName} = ${materializedPropsCode};`,
4405
+ jsx: `<${componentName} {...${propsVariableName}} />`,
4406
+ referenceFiles
4407
+ };
4408
+ }
4227
4409
  async function copyRegistryComponentFromExport(input) {
4228
4410
  const normalizedComponentId = normalizeComponentId(input.componentId);
4229
4411
  const { exportId, exportPath } = await resolveSingleExportDirectory(
@@ -4316,6 +4498,13 @@ async function copyRegistryComponentFromExport(input) {
4316
4498
  componentId: normalizedComponentId,
4317
4499
  copyableFiles: copyableSourceFiles
4318
4500
  });
4501
+ const selectedBlock = getSelectedBlock(manifest);
4502
+ const insertion = await buildRegistryComponentInsertion({
4503
+ componentImportPath,
4504
+ exportPath,
4505
+ manifestFiles,
4506
+ selectedBlock
4507
+ });
4319
4508
  const candidateFiles = await resolveManifestCandidateFiles({
4320
4509
  exportPath,
4321
4510
  manifestOwnerLabel: `registry component "${normalizedComponentId}"`,
@@ -4407,8 +4596,10 @@ async function copyRegistryComponentFromExport(input) {
4407
4596
  exportId,
4408
4597
  componentId: normalizedComponentId,
4409
4598
  componentImportPath,
4599
+ insertion,
4410
4600
  manifestFiles,
4411
4601
  copyableFiles,
4602
+ selectedBlock,
4412
4603
  skippedFiles,
4413
4604
  conflicts: sortedConflictEntries,
4414
4605
  missingManifestFiles: missingManifestFileList
@@ -4445,8 +4636,10 @@ async function copyRegistryComponentFromExport(input) {
4445
4636
  manifestPath,
4446
4637
  component: manifest.component,
4447
4638
  componentImportPath,
4639
+ insertion,
4448
4640
  manifestFiles,
4449
4641
  copyableFiles,
4642
+ selectedBlock,
4450
4643
  newFiles: sortedNewFiles,
4451
4644
  identicalFiles: sortedIdenticalFiles,
4452
4645
  conflictFiles: sortedConflictFiles,
@@ -4674,9 +4867,11 @@ var ProjectSyncService = class {
4674
4867
  }
4675
4868
  };
4676
4869
  }
4677
- async createComponentExport(componentId, _context) {
4870
+ async createComponentExport(componentId, options = {}, _context) {
4678
4871
  await this.ensureTempLayout();
4679
- const result = await this.provider.createComponentExport(componentId);
4872
+ const result = await this.provider.createComponentExport(componentId, {
4873
+ propsValidationId: options.propsValidationId
4874
+ });
4680
4875
  const manifestPath = buildManifestPath(this.exportsRoot, result.export.id);
4681
4876
  await writeUtf8(manifestPath, `${JSON.stringify(result, null, 2)}
4682
4877
  `);
@@ -5131,10 +5326,10 @@ var LazyProjectSyncSource = class {
5131
5326
  (service) => service.createExport(context)
5132
5327
  );
5133
5328
  }
5134
- async createComponentExport(componentId, context) {
5329
+ async createComponentExport(componentId, options, context) {
5135
5330
  return this.withService(
5136
5331
  context,
5137
- (service) => service.createComponentExport(componentId, context)
5332
+ (service) => service.createComponentExport(componentId, options, context)
5138
5333
  );
5139
5334
  }
5140
5335
  async downloadExportById(id, context) {
@@ -5354,6 +5549,16 @@ var copyComponentGuidanceSchema = z4.object({
5354
5549
  requiredActions: z4.array(z4.string()).describe("Concrete next actions for finishing component transfer."),
5355
5550
  notes: z4.array(z4.string()).describe("Important semantics and caveats for this transfer result.")
5356
5551
  });
5552
+ var registryComponentInsertionSchema = z4.object({
5553
+ imports: z4.array(z4.string()).describe("Import statements needed for inserting the copied component."),
5554
+ propsCode: z4.string().describe(
5555
+ "Materialized props source derived from the downloaded virtual component export."
5556
+ ),
5557
+ jsx: z4.string().describe("JSX snippet for rendering the materialized component instance."),
5558
+ referenceFiles: z4.array(z4.string()).describe(
5559
+ "Downloaded export files used as the source of truth for materialized insertion."
5560
+ )
5561
+ });
5357
5562
  var pageDetailsSchema = pageSchema.extend({
5358
5563
  pageInstruction: z4.string().nullable().describe(
5359
5564
  "Current instruction text for the active page variant. Null when no active variant is set."
@@ -5642,6 +5847,7 @@ WHEN TO USE: Use this only for the component-registry import track when the user
5642
5847
  AFTER CALLING:
5643
5848
  - Verify component.componentId matches the requested componentId.
5644
5849
  - Verify component.isReadyToExport is true and page.manifest.files is present.
5850
+ - Pass propsValidationId from component_props_validate when exporting a validated instance. Omit it only for the intentional default-props component export path.
5645
5851
  - Local component sidecar manifest is saved to .primeui/temp/exports/[exportId].manifest.json.
5646
5852
  - Use the returned export ID to call download_component_export.
5647
5853
  - Use copy_registry_component after download_component_export for this component-track manifest. Do not use page copy tools for component-track manifests.
@@ -5650,7 +5856,10 @@ AFTER CALLING:
5650
5856
  ${WORKFLOW_SUMMARY}`,
5651
5857
  inputSchema: {
5652
5858
  projectRoot: projectRootInputSchema,
5653
- componentId: z4.string().min(1).describe("PrimeUI component registry identifier to export.")
5859
+ componentId: z4.string().min(1).describe("PrimeUI component registry identifier to export."),
5860
+ propsValidationId: z4.string().trim().min(1).optional().describe(
5861
+ "Optional props validation handoff id returned by component_props_validate. Omit to export registry defaultProps."
5862
+ )
5654
5863
  },
5655
5864
  outputSchema: z4.object({
5656
5865
  exportId: z4.string().describe(
@@ -5669,6 +5878,9 @@ ${WORKFLOW_SUMMARY}`,
5669
5878
  exportables: z4.array(exportableSchema).describe("Shared exportables included in this export payload.")
5670
5879
  }).describe("Created component export summary."),
5671
5880
  component: componentExportComponentSchema,
5881
+ block: copyComponentSelectedBlockSchema.optional().describe(
5882
+ "Selected virtual component-export block metadata when the export used a propsValidationId handoff."
5883
+ ),
5672
5884
  page: componentExportPageSchema.describe(
5673
5885
  "Virtual page manifest for this component export."
5674
5886
  ),
@@ -5982,6 +6194,7 @@ BEHAVIOR:
5982
6194
  - Copies only the selected registry component import graph, narrowly referenced public assets, and safe support files from the component sidecar manifest/export.
5983
6195
  - Remaps component-local files into src/components/shared/** and returns componentImportPath for manual insertion.
5984
6196
  - Skips virtual route files that include __primeui-component-export, because those are reference/insertion hints and must not be installed as normal app routes.
6197
+ - Returns selectedBlock and insertion artifacts derived from the downloaded virtual component export. Treat insertion.propsCode and insertion.jsx as the materialized instance source of truth.
5985
6198
  - Skips app/search/layout/header/footer/env/project-shell files instead of copying whole exportable buckets.
5986
6199
  - Never copies package.json directly. package.json is used only to add missing dependency entries and report dependency version conflicts.
5987
6200
  - Keeps safe support files on their natural target paths, such as src/components/ui/**, src/lib/**, src/types/**, and src/contexts/**.
@@ -6018,6 +6231,12 @@ ${WORKFLOW_SUMMARY}`,
6018
6231
  componentImportPath: z4.string().describe(
6019
6232
  "Canonical import path for the copied registry component entrypoint, for example @/components/shared/hero--pricing."
6020
6233
  ),
6234
+ selectedBlock: copyComponentSelectedBlockSchema.describe(
6235
+ "Selected virtual component-export block metadata. First-instance contentKey semantics match page export."
6236
+ ),
6237
+ insertion: registryComponentInsertionSchema.describe(
6238
+ "Materialized insertion artifact for adding this component instance to a real local page."
6239
+ ),
6021
6240
  manifestFiles: z4.array(z4.string()).describe(
6022
6241
  "Normalized component sidecar manifest files considered by the copy service."
6023
6242
  ),
@@ -6259,6 +6478,9 @@ var componentPropsValidateInputSchema = z4.object({
6259
6478
  "Stable PrimeUI page slug used for validation diagnostics, for example '/pricing'. Use the same pageSlug as candidate retrieval."
6260
6479
  ),
6261
6480
  componentId: z4.string().describe("PrimeUI component registry identifier selected by the agent."),
6481
+ blockId: z4.string().trim().min(1).describe(
6482
+ "Stable local block identifier for this planned component instance. Required for propsValidationId handoff records."
6483
+ ),
6262
6484
  props: z4.record(z4.unknown()).describe(
6263
6485
  "Agent-authored props payload to validate against PrimeUI's registry schema."
6264
6486
  )
@@ -6321,6 +6543,17 @@ var componentPropsValidateOutputSchema = z4.object({
6321
6543
  normalizedProps: z4.record(z4.unknown()).nullable().describe(
6322
6544
  "Props normalized by PrimeUI when valid; null when validation failed."
6323
6545
  ),
6546
+ propsValidationId: z4.string().nullable().describe(
6547
+ "Durable validation handoff id for create_component_export; null when props are invalid."
6548
+ ),
6549
+ block: z4.object({
6550
+ blockId: z4.string(),
6551
+ componentId: z4.string(),
6552
+ contentKey: z4.string(),
6553
+ props: z4.record(z4.unknown())
6554
+ }).nullable().describe(
6555
+ "Selected validated block identity and normalized props; null when props are invalid."
6556
+ ),
6324
6557
  errors: z4.array(componentPropsValidationErrorSchema).describe("Structured validation errors for invalid props."),
6325
6558
  hints: z4.array(z4.string()).describe("Agent-facing guidance for correcting invalid props."),
6326
6559
  renderCheck: componentPropsRenderCheckSchema.describe(
@@ -6793,15 +7026,15 @@ WHEN TO USE:
6793
7026
  - Treat valid: false as actionable feedback, not a transport failure. Fix the props from errors and hints, then call this tool again.
6794
7027
 
6795
7028
  AFTER CALLING:
6796
- - If valid is true, use normalizedProps for local page edits.
7029
+ - If valid is true, pass propsValidationId to create_component_export so copy_registry_component can return materialized insertion artifacts.
6797
7030
  - If valid is false, correct props using errors[].path, errors[].message, and hints before editing local files.
6798
7031
  - Do not mutate Prime page state from this tool result. This is validation guidance only.`,
6799
7032
  inputSchema: componentPropsValidateInputSchema,
6800
7033
  outputSchema: componentPropsValidateOutputSchema,
6801
7034
  annotations: {
6802
- readOnlyHint: true,
7035
+ readOnlyHint: false,
6803
7036
  destructiveHint: false,
6804
- idempotentHint: true,
7037
+ idempotentHint: false,
6805
7038
  openWorldHint: true
6806
7039
  }
6807
7040
  };
@@ -7274,11 +7507,17 @@ function createPrimeUiMcpServer(source) {
7274
7507
  server.registerTool(
7275
7508
  "create_component_export",
7276
7509
  toolCreateComponentExport,
7277
- async ({ componentId, projectRoot }) => {
7510
+ async ({
7511
+ componentId,
7512
+ projectRoot,
7513
+ propsValidationId
7514
+ }) => {
7278
7515
  try {
7279
- const result = await source.createComponentExport(componentId, {
7280
- projectRoot
7281
- });
7516
+ const result = await source.createComponentExport(
7517
+ componentId,
7518
+ { propsValidationId },
7519
+ { projectRoot }
7520
+ );
7282
7521
  return okResult("create_component_export", result);
7283
7522
  } catch (error) {
7284
7523
  return errorResult(error);