@dropins/mcp 0.1.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.
Files changed (103) hide show
  1. package/LICENSE.md +127 -0
  2. package/README.md +314 -0
  3. package/dist/common/project-reader.d.ts +55 -0
  4. package/dist/common/project-reader.js +173 -0
  5. package/dist/common/registry-loader.d.ts +101 -0
  6. package/dist/common/registry-loader.js +386 -0
  7. package/dist/common/response-handling.d.ts +12 -0
  8. package/dist/common/response-handling.js +21 -0
  9. package/dist/common/sanitize.d.ts +8 -0
  10. package/dist/common/sanitize.js +45 -0
  11. package/dist/common/synonyms.d.ts +9 -0
  12. package/dist/common/synonyms.js +127 -0
  13. package/dist/common/telemetry.d.ts +14 -0
  14. package/dist/common/telemetry.js +54 -0
  15. package/dist/common/types.d.ts +308 -0
  16. package/dist/common/types.js +1 -0
  17. package/dist/common/version.d.ts +2 -0
  18. package/dist/common/version.js +14 -0
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.js +136 -0
  21. package/dist/operations/analyze-project.d.ts +13 -0
  22. package/dist/operations/analyze-project.js +125 -0
  23. package/dist/operations/check-block-health.d.ts +19 -0
  24. package/dist/operations/check-block-health.js +1149 -0
  25. package/dist/operations/check-config.d.ts +13 -0
  26. package/dist/operations/check-config.js +228 -0
  27. package/dist/operations/explain-event-flow.d.ts +16 -0
  28. package/dist/operations/explain-event-flow.js +218 -0
  29. package/dist/operations/get-upgrade-diff.d.ts +13 -0
  30. package/dist/operations/get-upgrade-diff.js +144 -0
  31. package/dist/operations/list-api-functions.d.ts +13 -0
  32. package/dist/operations/list-api-functions.js +53 -0
  33. package/dist/operations/list-containers.d.ts +13 -0
  34. package/dist/operations/list-containers.js +44 -0
  35. package/dist/operations/list-design-tokens.d.ts +13 -0
  36. package/dist/operations/list-design-tokens.js +47 -0
  37. package/dist/operations/list-events.d.ts +16 -0
  38. package/dist/operations/list-events.js +39 -0
  39. package/dist/operations/list-graphql-queries.d.ts +19 -0
  40. package/dist/operations/list-graphql-queries.js +84 -0
  41. package/dist/operations/list-i18n-keys.d.ts +19 -0
  42. package/dist/operations/list-i18n-keys.js +105 -0
  43. package/dist/operations/list-models.d.ts +16 -0
  44. package/dist/operations/list-models.js +80 -0
  45. package/dist/operations/list-slots.d.ts +16 -0
  46. package/dist/operations/list-slots.js +81 -0
  47. package/dist/operations/scaffold-block.d.ts +31 -0
  48. package/dist/operations/scaffold-block.js +331 -0
  49. package/dist/operations/scaffold-extension.d.ts +28 -0
  50. package/dist/operations/scaffold-extension.js +346 -0
  51. package/dist/operations/scaffold-slot.d.ts +22 -0
  52. package/dist/operations/scaffold-slot.js +189 -0
  53. package/dist/operations/search-commerce-docs.d.ts +16 -0
  54. package/dist/operations/search-commerce-docs.js +101 -0
  55. package/dist/operations/search-docs.d.ts +23 -0
  56. package/dist/operations/search-docs.js +298 -0
  57. package/dist/operations/suggest-event-handler.d.ts +16 -0
  58. package/dist/operations/suggest-event-handler.js +175 -0
  59. package/dist/operations/suggest-slot-implementation.d.ts +19 -0
  60. package/dist/operations/suggest-slot-implementation.js +183 -0
  61. package/dist/registry/api-functions.json +3045 -0
  62. package/dist/registry/block-patterns.json +78 -0
  63. package/dist/registry/containers.json +2003 -0
  64. package/dist/registry/design-tokens.json +577 -0
  65. package/dist/registry/docs/boilerplate.json +55 -0
  66. package/dist/registry/docs/dropins-all.json +97 -0
  67. package/dist/registry/docs/dropins-b2b.json +607 -0
  68. package/dist/registry/docs/dropins-cart.json +163 -0
  69. package/dist/registry/docs/dropins-checkout.json +193 -0
  70. package/dist/registry/docs/dropins-order.json +139 -0
  71. package/dist/registry/docs/dropins-payment-services.json +73 -0
  72. package/dist/registry/docs/dropins-personalization.json +67 -0
  73. package/dist/registry/docs/dropins-product-details.json +139 -0
  74. package/dist/registry/docs/dropins-product-discovery.json +85 -0
  75. package/dist/registry/docs/dropins-recommendations.json +67 -0
  76. package/dist/registry/docs/dropins-user-account.json +121 -0
  77. package/dist/registry/docs/dropins-user-auth.json +103 -0
  78. package/dist/registry/docs/dropins-wishlist.json +85 -0
  79. package/dist/registry/docs/get-started.json +85 -0
  80. package/dist/registry/docs/how-tos.json +19 -0
  81. package/dist/registry/docs/index.json +139 -0
  82. package/dist/registry/docs/licensing.json +19 -0
  83. package/dist/registry/docs/merchants.json +523 -0
  84. package/dist/registry/docs/resources.json +13 -0
  85. package/dist/registry/docs/sdk.json +139 -0
  86. package/dist/registry/docs/setup.json +145 -0
  87. package/dist/registry/docs/troubleshooting.json +19 -0
  88. package/dist/registry/events.json +2200 -0
  89. package/dist/registry/examples/index.json +19 -0
  90. package/dist/registry/examples/storefront-checkout.json +377 -0
  91. package/dist/registry/examples/storefront-quote-management.json +49 -0
  92. package/dist/registry/extensions.json +272 -0
  93. package/dist/registry/graphql.json +3469 -0
  94. package/dist/registry/i18n.json +1873 -0
  95. package/dist/registry/models.json +1001 -0
  96. package/dist/registry/sdk.json +2357 -0
  97. package/dist/registry/slots.json +2270 -0
  98. package/dist/registry/tools-components.json +595 -0
  99. package/dist/resources/guides.d.ts +7 -0
  100. package/dist/resources/guides.js +625 -0
  101. package/dist/resources/handlers.d.ts +31 -0
  102. package/dist/resources/handlers.js +322 -0
  103. package/package.json +47 -0
package/dist/index.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { execFile } from "node:child_process";
6
+ import { promisify } from "node:util";
7
+ import { z } from "zod";
8
+ import { zodToJsonSchema } from "zod-to-json-schema";
9
+ import { VERSION } from "./common/version.js";
10
+ import { getResourceHandlers } from "./resources/handlers.js";
11
+ import * as telemetry from "./common/telemetry.js";
12
+ import * as analyzeProject from "./operations/analyze-project.js";
13
+ import * as listSlots from "./operations/list-slots.js";
14
+ import * as listEvents from "./operations/list-events.js";
15
+ import * as listContainers from "./operations/list-containers.js";
16
+ import * as listApiFunctions from "./operations/list-api-functions.js";
17
+ import * as listDesignTokens from "./operations/list-design-tokens.js";
18
+ import * as listI18nKeys from "./operations/list-i18n-keys.js";
19
+ import * as checkConfig from "./operations/check-config.js";
20
+ import * as scaffoldBlock from "./operations/scaffold-block.js";
21
+ import * as scaffoldExtension from "./operations/scaffold-extension.js";
22
+ import * as scaffoldSlot from "./operations/scaffold-slot.js";
23
+ import * as suggestSlot from "./operations/suggest-slot-implementation.js";
24
+ import * as suggestEventHandler from "./operations/suggest-event-handler.js";
25
+ import * as explainEventFlow from "./operations/explain-event-flow.js";
26
+ import * as getUpgradeDiff from "./operations/get-upgrade-diff.js";
27
+ import * as searchDocs from "./operations/search-docs.js";
28
+ import * as searchCommerceDocs from "./operations/search-commerce-docs.js";
29
+ import * as listGraphqlQueries from "./operations/list-graphql-queries.js";
30
+ import * as checkBlockHealth from "./operations/check-block-health.js";
31
+ import * as listModels from "./operations/list-models.js";
32
+ const server = new Server({
33
+ name: "dropins-mcp-server",
34
+ version: VERSION,
35
+ }, {
36
+ capabilities: {
37
+ tools: {},
38
+ resources: {},
39
+ },
40
+ });
41
+ const resourceHandlers = getResourceHandlers();
42
+ server.setRequestHandler(ListResourcesRequestSchema, resourceHandlers.listResources);
43
+ server.setRequestHandler(ListResourceTemplatesRequestSchema, resourceHandlers.listResourceTemplates);
44
+ server.setRequestHandler(ReadResourceRequestSchema, resourceHandlers.readResource);
45
+ function tool(name, description, schema, handler) {
46
+ return {
47
+ name,
48
+ description,
49
+ schema,
50
+ handler: handler,
51
+ };
52
+ }
53
+ const toolRegistry = [
54
+ tool("analyze_project", "Analyze a merchant storefront project: detect installed dropins, blocks, config, and versions", analyzeProject.AnalyzeProjectSchema, analyzeProject.analyzeProject),
55
+ tool("list_slots", "AUTHORITATIVE source for slot data. List available slots for dropin containers with context shapes and examples. Use this instead of search tools for slot questions", listSlots.ListSlotsSchema, listSlots.listSlots),
56
+ tool("list_events", "AUTHORITATIVE source for event data. List events emitted and consumed by dropins with payload shapes. Use this instead of search tools for event questions", listEvents.ListEventsSchema, listEvents.listEvents),
57
+ tool("list_containers", "AUTHORITATIVE source for container data. List available dropin containers with props and slot names. Use this instead of search tools for container questions", listContainers.ListContainersSchema, listContainers.listContainers),
58
+ tool("list_api_functions", "AUTHORITATIVE source for API function data. List available API functions for dropins with signatures. Use this instead of search tools for API questions", listApiFunctions.ListApiFunctionsSchema, listApiFunctions.listApiFunctions),
59
+ tool("list_design_tokens", "List design tokens (CSS custom properties) for theming", listDesignTokens.ListDesignTokensSchema, listDesignTokens.listDesignTokens),
60
+ tool("list_i18n_keys", "List i18n dictionary keys and their default English values, filterable by dropin and substring query on key path or value", listI18nKeys.ListI18nKeysSchema, listI18nKeys.listI18nKeys),
61
+ tool("list_models", "Look up TypeScript interface and type definitions (CartModel, Price, Item, etc.) used in event payloads and slot contexts. Use when a payloadType or contextType references a named model you need to understand.", listModels.ListModelsSchema, listModels.listModels),
62
+ tool("check_config", "Validate a merchant storefront project configuration", checkConfig.CheckConfigSchema, checkConfig.checkConfig),
63
+ tool("scaffold_block", "Generate a new AEM block with dropin containers. Supports single dropin (dropin + containers) or multi-dropin (containersByDropin) with automatic provider aliases.", scaffoldBlock.ScaffoldBlockSchema, scaffoldBlock.scaffoldBlock),
64
+ tool("scaffold_extension", "Generate a checkout extension with selected hooks, extension manager, and index file", scaffoldExtension.ScaffoldExtensionSchema, scaffoldExtension.scaffoldExtension),
65
+ tool("scaffold_slot", "Generate production-ready slot implementation boilerplate for a specific container slot, including imports, context destructuring, and all available slot methods", scaffoldSlot.ScaffoldSlotSchema, scaffoldSlot.scaffoldSlot),
66
+ tool("suggest_slot_implementation", "Suggest slot implementation code for a UI customization request on an existing block", suggestSlot.SuggestSlotSchema, suggestSlot.suggestSlotImplementation),
67
+ tool("suggest_event_handler", "Suggest event handler code for a cross-dropin behavior request", suggestEventHandler.SuggestEventHandlerSchema, suggestEventHandler.suggestEventHandler),
68
+ tool("explain_event_flow", "Trace the full lifecycle of an event: who emits it, who consumes it, payload type, and ready-to-use listen and emit code. Supports exact, prefix, and substring matching.", explainEventFlow.ExplainEventFlowSchema, explainEventFlow.explainEventFlow),
69
+ tool("get_upgrade_diff", "Compare merchant dropin versions against registry and show containers, slots, and migration notes", getUpgradeDiff.GetUpgradeDiffSchema, getUpgradeDiff.getUpgradeDiff),
70
+ tool("search_docs", "Search local documentation snapshots, SDK packages, code examples, and GraphQL operations. For API data, prefer dedicated tools first (list_slots, list_containers, etc). Use this for cross-cutting searches or working code examples", searchDocs.SearchDocsSchema, searchDocs.searchDocsOperation),
71
+ tool("search_commerce_docs", "AI-powered semantic search for conceptual documentation: guides, tutorials, best practices, architecture. Optional enhancement requiring aio CLI authentication. NOT for API definitions (slots, events, containers) — use registry tools instead", searchCommerceDocs.SearchCommerceDocsSchema, searchCommerceDocs.searchCommerceDocs),
72
+ tool("list_graphql_queries", "AUTHORITATIVE source for GraphQL operations. List queries, mutations, and extensible fragments used by dropins with full resolved source and extensibility metadata", listGraphqlQueries.ListGraphqlQueriesSchema, listGraphqlQueries.listGraphqlQueries),
73
+ tool("check_block_health", "Check a merchant's AEM block against the current registry. Detects containers, slots, events, and API functions that no longer exist or have been renamed. Omit the block parameter to scan all dropin blocks and their initializer files at once. Pass fix: true to get a concrete rename or remove hint for every finding.", checkBlockHealth.CheckBlockHealthSchema, checkBlockHealth.checkBlockHealth),
74
+ ];
75
+ const toolHandlers = new Map(toolRegistry.map((t) => [t.name, { schema: t.schema, handler: t.handler }]));
76
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
77
+ return {
78
+ tools: toolRegistry.map((t) => ({
79
+ name: t.name,
80
+ description: t.description,
81
+ inputSchema: zodToJsonSchema(t.schema),
82
+ })),
83
+ };
84
+ });
85
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
86
+ const start = Date.now();
87
+ const toolName = request.params.name;
88
+ try {
89
+ const entry = toolHandlers.get(toolName);
90
+ if (!entry) {
91
+ throw new Error(`Unknown tool: ${toolName}`);
92
+ }
93
+ const parsed = entry.schema.parse(request.params.arguments ?? {});
94
+ const result = await entry.handler(parsed);
95
+ telemetry.record(toolName, parsed, result, Date.now() - start);
96
+ return {
97
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
98
+ };
99
+ }
100
+ catch (error) {
101
+ const errorMsg = error instanceof Error ? error.message : "Unknown error occurred";
102
+ telemetry.record(toolName, (request.params.arguments ?? {}), null, Date.now() - start, errorMsg);
103
+ if (error instanceof z.ZodError) {
104
+ const fieldErrors = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`);
105
+ throw new Error(`Invalid input: ${fieldErrors.join("; ")}`);
106
+ }
107
+ process.stderr.write(`Unexpected error: ${error instanceof Error ? error.stack : error}\n`);
108
+ throw new Error("An unexpected error occurred");
109
+ }
110
+ });
111
+ const execFileAsync = promisify(execFile);
112
+ async function checkForUpdates() {
113
+ if (VERSION.includes("alpha") || VERSION.includes("beta")) {
114
+ return;
115
+ }
116
+ try {
117
+ const { stdout } = await execFileAsync("npm", ["show", "@dropins/mcp", "version"], { timeout: 10000 });
118
+ const latest = stdout.trim();
119
+ if (latest && latest !== VERSION) {
120
+ process.stderr.write(`\n⚠️ Dropins MCP update available: ${VERSION} → ${latest}\n` +
121
+ ` Run: npm update -g @dropins/mcp\n\n`);
122
+ }
123
+ }
124
+ catch {
125
+ }
126
+ }
127
+ async function runServer() {
128
+ const transport = new StdioServerTransport();
129
+ await server.connect(transport);
130
+ process.stderr.write("Dropins MCP Server running on stdio\n");
131
+ checkForUpdates();
132
+ }
133
+ runServer().catch((error) => {
134
+ process.stderr.write(`Fatal error in main(): ${error}\n`);
135
+ process.exit(1);
136
+ });
@@ -0,0 +1,13 @@
1
+ import { z } from "zod";
2
+ export declare const AnalyzeProjectSchema: z.ZodObject<{
3
+ projectDir: z.ZodString;
4
+ }, "strip", z.ZodTypeAny, {
5
+ projectDir: string;
6
+ }, {
7
+ projectDir: string;
8
+ }>;
9
+ export declare function analyzeProject(params: z.infer<typeof AnalyzeProjectSchema>): Promise<{
10
+ success: boolean;
11
+ message: string;
12
+ data: unknown;
13
+ }>;
@@ -0,0 +1,125 @@
1
+ import { z } from "zod";
2
+ import { formatSuccessResponse, formatExceptionResponse, } from "../common/response-handling.js";
3
+ import { readPackageJson, readConfigJson, listBlocks, readBlockFile, listInitializers, projectDirGuard, extractDropinDependencies, extractImportsFromBlock, INITIALIZER_ALIASES, } from "../common/project-reader.js";
4
+ import { getContainerRegistry } from "../common/registry-loader.js";
5
+ export const AnalyzeProjectSchema = z.object({
6
+ projectDir: z
7
+ .string()
8
+ .describe("Absolute path to the merchant storefront project root"),
9
+ });
10
+ export async function analyzeProject(params) {
11
+ try {
12
+ const guard = projectDirGuard(params.projectDir);
13
+ if (guard)
14
+ return guard;
15
+ const pkg = readPackageJson(params.projectDir);
16
+ const config = readConfigJson(params.projectDir);
17
+ const blocks = listBlocks(params.projectDir);
18
+ const initializers = listInitializers(params.projectDir);
19
+ const registry = getContainerRegistry();
20
+ const dropinDeps = pkg ? extractDropinDependencies(pkg) : [];
21
+ const allBlockAnalysis = blocks.map((block) => {
22
+ const jsContent = readBlockFile(params.projectDir, block.name);
23
+ if (!jsContent) {
24
+ return {
25
+ name: block.name,
26
+ hasCss: block.hasCss,
27
+ hasDropinImports: false,
28
+ imports: null,
29
+ note: "No JS file found",
30
+ };
31
+ }
32
+ const imports = extractImportsFromBlock(jsContent);
33
+ const hasDropinImports = imports.dropinImports.some((p) => p.includes("@dropins/storefront-"));
34
+ return {
35
+ name: block.name,
36
+ hasCss: block.hasCss,
37
+ hasDropinImports,
38
+ dropinImports: imports.dropinImports,
39
+ containerImports: imports.containerImports,
40
+ apiImports: imports.apiImports,
41
+ usesEventBus: imports.eventImports,
42
+ };
43
+ });
44
+ const commerceBlocks = allBlockAnalysis.filter((b) => b.hasDropinImports);
45
+ const blockAnalysis = commerceBlocks.map(({ hasDropinImports: _, ...rest }) => rest);
46
+ const issues = [];
47
+ const suggestions = [];
48
+ if (!pkg) {
49
+ issues.push("No package.json found — cannot detect dropin versions");
50
+ }
51
+ if (dropinDeps.length === 0 && pkg) {
52
+ issues.push("No @dropins/* dependencies found in package.json");
53
+ }
54
+ if (!config) {
55
+ issues.push("No config.json or demo-config.json found");
56
+ }
57
+ else {
58
+ const defaultConfig = config.public?.default;
59
+ if (!defaultConfig?.["commerce-endpoint"]) {
60
+ issues.push("Missing commerce-endpoint in config");
61
+ }
62
+ if (!defaultConfig?.["commerce-core-endpoint"]) {
63
+ suggestions.push("Consider adding commerce-core-endpoint for core GraphQL queries");
64
+ }
65
+ }
66
+ if (commerceBlocks.length === 0) {
67
+ issues.push("No blocks using dropin imports found in blocks/ directory");
68
+ }
69
+ if (initializers.length === 0) {
70
+ suggestions.push("No dropin initializers found in scripts/initializers/");
71
+ }
72
+ const registeredDropins = Object.keys(registry.dropins);
73
+ const installedDropinNames = dropinDeps.map((d) => d.name.replace("@dropins/", ""));
74
+ const missingInitializers = installedDropinNames.filter((name) => {
75
+ if (name === "tools" || name === "build-tools")
76
+ return false;
77
+ const alias = INITIALIZER_ALIASES[name];
78
+ return !initializers.some((init) => name.includes(init.name) || (alias && init.name === alias));
79
+ });
80
+ if (missingInitializers.length > 0) {
81
+ suggestions.push(`Dropins installed but missing initializers: ${missingInitializers.join(", ")}`);
82
+ }
83
+ const knownDropins = installedDropinNames.filter((name) => registeredDropins.includes(name));
84
+ const unknownDropins = installedDropinNames.filter((name) => !registeredDropins.includes(name) &&
85
+ name !== "tools" &&
86
+ name !== "build-tools");
87
+ return formatSuccessResponse("Project analysis complete", {
88
+ projectName: pkg?.name ?? "unknown",
89
+ projectVersion: pkg?.version ?? "unknown",
90
+ dropins: {
91
+ installed: dropinDeps.map((d) => ({
92
+ name: d.name,
93
+ version: d.version,
94
+ isDev: d.isDev,
95
+ knownInRegistry: registeredDropins.includes(d.name.replace("@dropins/", "")),
96
+ })),
97
+ count: dropinDeps.length,
98
+ knownDropins,
99
+ unknownDropins,
100
+ },
101
+ config: config
102
+ ? {
103
+ found: true,
104
+ commerceEndpoint: config.public?.default?.["commerce-endpoint"] ?? null,
105
+ commerceCoreEndpoint: config.public?.default?.["commerce-core-endpoint"] ?? null,
106
+ hasHeaders: !!config.public?.default?.headers,
107
+ hasAnalytics: !!config.public?.default?.analytics,
108
+ }
109
+ : { found: false },
110
+ blocks: {
111
+ total: blocks.length,
112
+ commerceBlocks: blockAnalysis,
113
+ nonCommerceBlocks: allBlockAnalysis
114
+ .filter((b) => !b.hasDropinImports)
115
+ .map((b) => b.name),
116
+ },
117
+ initializers: initializers.map((i) => i.name),
118
+ issues,
119
+ suggestions,
120
+ });
121
+ }
122
+ catch (error) {
123
+ return formatExceptionResponse(error, "analyzing project");
124
+ }
125
+ }
@@ -0,0 +1,19 @@
1
+ import { z } from "zod";
2
+ export declare const CheckBlockHealthSchema: z.ZodObject<{
3
+ projectDir: z.ZodString;
4
+ block: z.ZodOptional<z.ZodString>;
5
+ fix: z.ZodOptional<z.ZodBoolean>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ projectDir: string;
8
+ block?: string | undefined;
9
+ fix?: boolean | undefined;
10
+ }, {
11
+ projectDir: string;
12
+ block?: string | undefined;
13
+ fix?: boolean | undefined;
14
+ }>;
15
+ export declare function checkBlockHealth(params: z.infer<typeof CheckBlockHealthSchema>): Promise<{
16
+ success: boolean;
17
+ message: string;
18
+ data: unknown;
19
+ }>;