dsers.product.import
Import products from AliExpress, Alibaba, or 1688 supplier URLs into DSers for dropshipping. Supports single or batch imports with pricing rules and preview data before store push.
Instructions
Import product(s) from supplier URL(s) into the DSers import list and return a preview bundle with title, prices, images, and variants. Single mode: provide source_url. Batch mode: provide source_urls_json with an array of URLs or objects. Each successful import returns a job_id needed for dsers.product.preview, dsers.product.visibility, and dsers.store.push. Returns: job_id, status, title_before/after, price_range_before/after, images_before/after, variant_count, variant_preview (first 5), warnings.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| source_url | No | Single supplier product URL. Supports AliExpress (aliexpress.com/item/xxx.html), Alibaba (alibaba.com/product-detail/xxx.html), and 1688 (1688.com/offer/xxx.html). | |
| source_urls_json | No | Batch import: JSON array of URL strings or objects with {url, rules?, source_hint?, country?, target_store?, visibility_mode?}. Example: ["https://aliexpress.com/item/123.html", {"url": "https://aliexpress.com/item/456.html", "rules": {"pricing": {"mode": "multiplier", "multiplier": 3}}}] | |
| source_hint | No | Supplier platform hint. Valid values: auto, aliexpress, alibaba, 1688, accio. Default: auto (detected from URL). | auto |
| country | No | Target country code for shipping and pricing lookup. Examples: US, GB, DE, FR, AU. | US |
| target_store | No | Store ID or display name from dsers.store.discover. Required when the account has multiple stores. | |
| visibility_mode | No | Product visibility after push. backend_only: saved as draft, not visible to shoppers. sell_immediately: published and visible on the storefront. | backend_only |
| rules_json | No | Optional rules as JSON string applied to all items. Keys: pricing ({mode, multiplier, fixed_markup, round_digits}), content ({title_override, title_prefix, title_suffix, description_override_html, description_append_html, tags_add}), images ({keep_first_n, drop_indexes}). Example: {"pricing": {"mode": "fixed_markup", "fixed_markup": 5.00}} |
Implementation Reference
- src/service.ts:193-257 (handler)The `prepareSingle` method handles the actual import logic, including rule normalization, supplier URL resolution, and creating a new import job.
private async prepareSingle( payload: Record<string, any>, ): Promise<Record<string, any>> { const sourceUrl = String(payload.source_url ?? "").trim(); if (!sourceUrl) throw new Error( "source_url is required. Provide a supplier product URL (AliExpress, Alibaba, or 1688).", ); const sourceHint = String(payload.source_hint ?? "auto").trim() || "auto"; const country = String(payload.country ?? "US").trim() || "US"; const visibilityMode = String(payload.visibility_mode ?? "backend_only").trim() || "backend_only"; const targetStore = payload.target_store ?? null; const rules = payload.rules ?? {}; const providerCaps = await this.provider.getRuleCapabilities(targetStore); const validatedRules = normalizeRules(rules, providerCaps.rule_families); if (validatedRules.errors?.length) { throw new Error(validatedRules.errors.join("; ")); } const resolved = await resolveSourceUrl(sourceUrl, sourceHint); const prepared = await this.provider.prepareCandidate( resolved.resolved_url, resolved.source_hint, country, ); const originalDraft = structuredClone(prepared.draft); const effectiveRules = validatedRules.effective_rules ?? {}; const ruled = applyRules(prepared.draft, effectiveRules); const finalDraft = ruled.draft; const job: Record<string, any> = { status: "preview_ready", created_at: utcNow(), provider_label: prepared.provider_label ?? this.provider.name, source_url: sourceUrl, resolved_source_url: resolved.resolved_url, source_hint: resolved.source_hint, resolver_mode: resolved.resolver_mode, country, target_store: targetStore, visibility_mode: visibilityMode, requested_rules: validatedRules.requested_rules ?? {}, effective_rules_snapshot: effectiveRules, rules: effectiveRules, provider_state: prepared.provider_state, original_draft: originalDraft, draft: finalDraft, warnings: [ ...(resolved.warnings ?? []), ...(prepared.warnings ?? []), ...(validatedRules.warnings ?? []), ...((ruled.summary?.warnings as string[]) ?? []), ], rule_summary: ruled.summary ?? {}, }; const jobId = this.store.create(job); job.job_id = jobId; this.store.save(jobId, job); return this.preview(job); } - src/tools.ts:111-213 (registration)The MCP tool registration for `dsers.product.import` which parses input arguments and calls the service handler.
server.registerTool( "dsers.product.import", { title: "AliExpress / Alibaba / 1688 Product Import", description: "Import product(s) from supplier URL(s) into the DSers import list and return a preview bundle with title, prices, images, and variants. " + "Single mode: provide source_url. Batch mode: provide source_urls_json with an array of URLs or objects. " + "Each successful import returns a job_id needed for dsers.product.preview, dsers.product.visibility, and dsers.store.push. " + "Returns: job_id, status, title_before/after, price_range_before/after, images_before/after, variant_count, variant_preview (first 5), warnings.", inputSchema: { source_url: z .string() .optional() .describe( "Single supplier product URL. Supports AliExpress (aliexpress.com/item/xxx.html), " + "Alibaba (alibaba.com/product-detail/xxx.html), and 1688 (1688.com/offer/xxx.html).", ), source_urls_json: z .string() .optional() .describe( "Batch import: JSON array of URL strings or objects with {url, rules?, source_hint?, country?, target_store?, visibility_mode?}. " + 'Example: ["https://aliexpress.com/item/123.html", ' + '{"url": "https://aliexpress.com/item/456.html", "rules": {"pricing": {"mode": "multiplier", "multiplier": 3}}}]', ), source_hint: z .string() .default("auto") .describe( "Supplier platform hint. Valid values: auto, aliexpress, alibaba, 1688, accio. Default: auto (detected from URL).", ), country: z .string() .default("US") .describe( "Target country code for shipping and pricing lookup. Examples: US, GB, DE, FR, AU.", ), target_store: z .string() .optional() .describe( "Store ID or display name from dsers.store.discover. Required when the account has multiple stores.", ), visibility_mode: z .string() .default("backend_only") .describe( "Product visibility after push. " + "backend_only: saved as draft, not visible to shoppers. " + "sell_immediately: published and visible on the storefront.", ), rules_json: z .string() .optional() .describe( "Optional rules as JSON string applied to all items. " + "Keys: pricing ({mode, multiplier, fixed_markup, round_digits}), " + "content ({title_override, title_prefix, title_suffix, description_override_html, description_append_html, tags_add}), " + "images ({keep_first_n, drop_indexes}). " + 'Example: {"pricing": {"mode": "fixed_markup", "fixed_markup": 5.00}}', ), }, annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true, }, }, async (args) => { try { const payload: Record<string, any> = {}; if (args.source_urls_json) { const parsed = safeJsonParse( args.source_urls_json, "source_urls_json", 'Expected a JSON array of URL strings or objects. Example: ["https://aliexpress.com/item/123.html"]', ); if (parsed.error) return fail(new Error(parsed.error)); payload.source_urls = parsed.value; } else if (args.source_url) { payload.source_url = args.source_url; } if (args.source_hint) payload.source_hint = args.source_hint; if (args.country) payload.country = args.country; if (args.target_store) payload.target_store = args.target_store; if (args.visibility_mode) payload.visibility_mode = args.visibility_mode; if (args.rules_json) { const parsed = safeJsonParse( args.rules_json, "rules_json", 'Expected a JSON object with optional keys: pricing, content, images. ' + 'Example: {"pricing": {"mode": "multiplier", "multiplier": 2.0}}', ); if (parsed.error) return fail(new Error(parsed.error)); payload.rules = parsed.value; } return ok(await svc().prepareImportCandidate(payload)); } catch (err) { return fail(err); } }, );