@solidcommerce/mcp-server 2.0.0-alpha.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/README.md +74 -0
- package/bin/solidcommerce-mcp.js +8 -0
- package/dist/audit/auditClient.d.ts +51 -0
- package/dist/audit/auditClient.d.ts.map +1 -0
- package/dist/audit/auditClient.js +93 -0
- package/dist/audit/auditClient.js.map +1 -0
- package/dist/auth/apiKey.d.ts +44 -0
- package/dist/auth/apiKey.d.ts.map +1 -0
- package/dist/auth/apiKey.js +80 -0
- package/dist/auth/apiKey.js.map +1 -0
- package/dist/auth/oauth.d.ts +108 -0
- package/dist/auth/oauth.d.ts.map +1 -0
- package/dist/auth/oauth.js +300 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/generator/fromOpenApi.d.ts +54 -0
- package/dist/generator/fromOpenApi.d.ts.map +1 -0
- package/dist/generator/fromOpenApi.js +411 -0
- package/dist/generator/fromOpenApi.js.map +1 -0
- package/dist/generator/schemaToZod.d.ts +81 -0
- package/dist/generator/schemaToZod.d.ts.map +1 -0
- package/dist/generator/schemaToZod.js +277 -0
- package/dist/generator/schemaToZod.js.map +1 -0
- package/dist/generator/scopeInference.d.ts +26 -0
- package/dist/generator/scopeInference.d.ts.map +1 -0
- package/dist/generator/scopeInference.js +91 -0
- package/dist/generator/scopeInference.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/dist/server/buildServer.d.ts +35 -0
- package/dist/server/buildServer.d.ts.map +1 -0
- package/dist/server/buildServer.js +104 -0
- package/dist/server/buildServer.js.map +1 -0
- package/dist/server/dispatcher.d.ts +14 -0
- package/dist/server/dispatcher.d.ts.map +1 -0
- package/dist/server/dispatcher.js +190 -0
- package/dist/server/dispatcher.js.map +1 -0
- package/dist/session.d.ts +9 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +11 -0
- package/dist/session.js.map +1 -0
- package/dist/telemetry/hostName.d.ts +26 -0
- package/dist/telemetry/hostName.d.ts.map +1 -0
- package/dist/telemetry/hostName.js +80 -0
- package/dist/telemetry/hostName.js.map +1 -0
- package/dist/tools/contract.d.ts +125 -0
- package/dist/tools/contract.d.ts.map +1 -0
- package/dist/tools/contract.js +101 -0
- package/dist/tools/contract.js.map +1 -0
- package/dist/tools/foundation/catalog_amazon_items_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_amazon_items_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_amazon_items_list.js +47 -0
- package/dist/tools/foundation/catalog_amazon_items_list.js.map +1 -0
- package/dist/tools/foundation/catalog_attribute_filters_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_attribute_filters_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_attribute_filters_list.js +47 -0
- package/dist/tools/foundation/catalog_attribute_filters_list.js.map +1 -0
- package/dist/tools/foundation/catalog_attribute_tags_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_attribute_tags_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_attribute_tags_list.js +47 -0
- package/dist/tools/foundation/catalog_attribute_tags_list.js.map +1 -0
- package/dist/tools/foundation/catalog_attributes_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_attributes_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_attributes_list.js +57 -0
- package/dist/tools/foundation/catalog_attributes_list.js.map +1 -0
- package/dist/tools/foundation/catalog_column_views_default_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_column_views_default_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_column_views_default_list.js +47 -0
- package/dist/tools/foundation/catalog_column_views_default_list.js.map +1 -0
- package/dist/tools/foundation/catalog_column_views_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_column_views_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_column_views_list.js +47 -0
- package/dist/tools/foundation/catalog_column_views_list.js.map +1 -0
- package/dist/tools/foundation/catalog_ebay_categories_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_ebay_categories_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_ebay_categories_list.js +56 -0
- package/dist/tools/foundation/catalog_ebay_categories_list.js.map +1 -0
- package/dist/tools/foundation/catalog_ebay_category_specifics_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_ebay_category_specifics_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_ebay_category_specifics_list.js +56 -0
- package/dist/tools/foundation/catalog_ebay_category_specifics_list.js.map +1 -0
- package/dist/tools/foundation/catalog_ebay_listing_templates_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_ebay_listing_templates_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_ebay_listing_templates_list.js +47 -0
- package/dist/tools/foundation/catalog_ebay_listing_templates_list.js.map +1 -0
- package/dist/tools/foundation/catalog_ebay_product_search_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_ebay_product_search_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_ebay_product_search_list.js +56 -0
- package/dist/tools/foundation/catalog_ebay_product_search_list.js.map +1 -0
- package/dist/tools/foundation/catalog_ebay_template_fields_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_ebay_template_fields_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_ebay_template_fields_list.js +47 -0
- package/dist/tools/foundation/catalog_ebay_template_fields_list.js.map +1 -0
- package/dist/tools/foundation/catalog_ebay_variation_groups_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_ebay_variation_groups_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_ebay_variation_groups_list.js +56 -0
- package/dist/tools/foundation/catalog_ebay_variation_groups_list.js.map +1 -0
- package/dist/tools/foundation/catalog_inventory_sources_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_inventory_sources_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_inventory_sources_list.js +47 -0
- package/dist/tools/foundation/catalog_inventory_sources_list.js.map +1 -0
- package/dist/tools/foundation/catalog_listing_rules_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_listing_rules_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_listing_rules_list.js +47 -0
- package/dist/tools/foundation/catalog_listing_rules_list.js.map +1 -0
- package/dist/tools/foundation/catalog_listing_templates_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_listing_templates_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_listing_templates_list.js +47 -0
- package/dist/tools/foundation/catalog_listing_templates_list.js.map +1 -0
- package/dist/tools/foundation/catalog_manufacturers_all_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_manufacturers_all_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_manufacturers_all_list.js +47 -0
- package/dist/tools/foundation/catalog_manufacturers_all_list.js.map +1 -0
- package/dist/tools/foundation/catalog_manufacturers_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_manufacturers_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_manufacturers_list.js +47 -0
- package/dist/tools/foundation/catalog_manufacturers_list.js.map +1 -0
- package/dist/tools/foundation/catalog_market_lists_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_market_lists_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_market_lists_list.js +47 -0
- package/dist/tools/foundation/catalog_market_lists_list.js.map +1 -0
- package/dist/tools/foundation/catalog_product_usage_filters_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_product_usage_filters_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_product_usage_filters_list.js +47 -0
- package/dist/tools/foundation/catalog_product_usage_filters_list.js.map +1 -0
- package/dist/tools/foundation/catalog_product_usage_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_product_usage_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_product_usage_list.js +61 -0
- package/dist/tools/foundation/catalog_product_usage_list.js.map +1 -0
- package/dist/tools/foundation/catalog_product_usage_totals_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_product_usage_totals_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_product_usage_totals_list.js +58 -0
- package/dist/tools/foundation/catalog_product_usage_totals_list.js.map +1 -0
- package/dist/tools/foundation/catalog_products_generate_sku_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_products_generate_sku_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_products_generate_sku_list.js +47 -0
- package/dist/tools/foundation/catalog_products_generate_sku_list.js.map +1 -0
- package/dist/tools/foundation/catalog_products_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_products_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_products_list.js +60 -0
- package/dist/tools/foundation/catalog_products_list.js.map +1 -0
- package/dist/tools/foundation/catalog_taxonomy_channels_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_taxonomy_channels_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_taxonomy_channels_list.js +47 -0
- package/dist/tools/foundation/catalog_taxonomy_channels_list.js.map +1 -0
- package/dist/tools/foundation/catalog_taxonomy_mappings_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_taxonomy_mappings_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_taxonomy_mappings_list.js +56 -0
- package/dist/tools/foundation/catalog_taxonomy_mappings_list.js.map +1 -0
- package/dist/tools/foundation/catalog_taxonomy_product_values_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_taxonomy_product_values_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_taxonomy_product_values_list.js +57 -0
- package/dist/tools/foundation/catalog_taxonomy_product_values_list.js.map +1 -0
- package/dist/tools/foundation/catalog_tree_list.d.ts +4 -0
- package/dist/tools/foundation/catalog_tree_list.d.ts.map +1 -0
- package/dist/tools/foundation/catalog_tree_list.js +47 -0
- package/dist/tools/foundation/catalog_tree_list.js.map +1 -0
- package/dist/tools/foundation/crm_customers_list.d.ts +4 -0
- package/dist/tools/foundation/crm_customers_list.d.ts.map +1 -0
- package/dist/tools/foundation/crm_customers_list.js +59 -0
- package/dist/tools/foundation/crm_customers_list.js.map +1 -0
- package/dist/tools/foundation/fulfillment_manifests_list.d.ts +4 -0
- package/dist/tools/foundation/fulfillment_manifests_list.d.ts.map +1 -0
- package/dist/tools/foundation/fulfillment_manifests_list.js +47 -0
- package/dist/tools/foundation/fulfillment_manifests_list.js.map +1 -0
- package/dist/tools/foundation/fulfillment_ship_now_addresses_list.d.ts +4 -0
- package/dist/tools/foundation/fulfillment_ship_now_addresses_list.d.ts.map +1 -0
- package/dist/tools/foundation/fulfillment_ship_now_addresses_list.js +47 -0
- package/dist/tools/foundation/fulfillment_ship_now_addresses_list.js.map +1 -0
- package/dist/tools/foundation/fulfillment_ship_now_dictionaries_list.d.ts +4 -0
- package/dist/tools/foundation/fulfillment_ship_now_dictionaries_list.d.ts.map +1 -0
- package/dist/tools/foundation/fulfillment_ship_now_dictionaries_list.js +56 -0
- package/dist/tools/foundation/fulfillment_ship_now_dictionaries_list.js.map +1 -0
- package/dist/tools/foundation/index.d.ts +8 -0
- package/dist/tools/foundation/index.d.ts.map +1 -0
- package/dist/tools/foundation/index.js +93 -0
- package/dist/tools/foundation/index.js.map +1 -0
- package/dist/tools/foundation/inventory_alert_rules_list.d.ts +4 -0
- package/dist/tools/foundation/inventory_alert_rules_list.d.ts.map +1 -0
- package/dist/tools/foundation/inventory_alert_rules_list.js +47 -0
- package/dist/tools/foundation/inventory_alert_rules_list.js.map +1 -0
- package/dist/tools/foundation/inventory_alert_settings_list.d.ts +4 -0
- package/dist/tools/foundation/inventory_alert_settings_list.d.ts.map +1 -0
- package/dist/tools/foundation/inventory_alert_settings_list.js +47 -0
- package/dist/tools/foundation/inventory_alert_settings_list.js.map +1 -0
- package/dist/tools/foundation/inventory_analytics_alert_count_list.d.ts +4 -0
- package/dist/tools/foundation/inventory_analytics_alert_count_list.d.ts.map +1 -0
- package/dist/tools/foundation/inventory_analytics_alert_count_list.js +47 -0
- package/dist/tools/foundation/inventory_analytics_alert_count_list.js.map +1 -0
- package/dist/tools/foundation/inventory_rules_list.d.ts +4 -0
- package/dist/tools/foundation/inventory_rules_list.d.ts.map +1 -0
- package/dist/tools/foundation/inventory_rules_list.js +47 -0
- package/dist/tools/foundation/inventory_rules_list.js.map +1 -0
- package/dist/tools/foundation/inventory_rules_periods_list.d.ts +4 -0
- package/dist/tools/foundation/inventory_rules_periods_list.d.ts.map +1 -0
- package/dist/tools/foundation/inventory_rules_periods_list.js +47 -0
- package/dist/tools/foundation/inventory_rules_periods_list.js.map +1 -0
- package/dist/tools/foundation/inventory_seasonal_factors_list.d.ts +4 -0
- package/dist/tools/foundation/inventory_seasonal_factors_list.d.ts.map +1 -0
- package/dist/tools/foundation/inventory_seasonal_factors_list.js +47 -0
- package/dist/tools/foundation/inventory_seasonal_factors_list.js.map +1 -0
- package/dist/tools/foundation/inventory_warehouses_list.d.ts +4 -0
- package/dist/tools/foundation/inventory_warehouses_list.d.ts.map +1 -0
- package/dist/tools/foundation/inventory_warehouses_list.js +47 -0
- package/dist/tools/foundation/inventory_warehouses_list.js.map +1 -0
- package/dist/tools/foundation/listings_dictionary_marketplace_locales_list.d.ts +4 -0
- package/dist/tools/foundation/listings_dictionary_marketplace_locales_list.d.ts.map +1 -0
- package/dist/tools/foundation/listings_dictionary_marketplace_locales_list.js +56 -0
- package/dist/tools/foundation/listings_dictionary_marketplace_locales_list.js.map +1 -0
- package/dist/tools/foundation/listings_dictionary_marketplaces_list.d.ts +4 -0
- package/dist/tools/foundation/listings_dictionary_marketplaces_list.d.ts.map +1 -0
- package/dist/tools/foundation/listings_dictionary_marketplaces_list.js +47 -0
- package/dist/tools/foundation/listings_dictionary_marketplaces_list.js.map +1 -0
- package/dist/tools/tasks/bulk_update_prices.d.ts +4 -0
- package/dist/tools/tasks/bulk_update_prices.d.ts.map +1 -0
- package/dist/tools/tasks/bulk_update_prices.js +96 -0
- package/dist/tools/tasks/bulk_update_prices.js.map +1 -0
- package/dist/tools/tasks/cancel_order_with_reason.d.ts +4 -0
- package/dist/tools/tasks/cancel_order_with_reason.d.ts.map +1 -0
- package/dist/tools/tasks/cancel_order_with_reason.js +117 -0
- package/dist/tools/tasks/cancel_order_with_reason.js.map +1 -0
- package/dist/tools/tasks/check_listing_health.d.ts +4 -0
- package/dist/tools/tasks/check_listing_health.d.ts.map +1 -0
- package/dist/tools/tasks/check_listing_health.js +123 -0
- package/dist/tools/tasks/check_listing_health.js.map +1 -0
- package/dist/tools/tasks/create_and_submit_purchase_order.d.ts +4 -0
- package/dist/tools/tasks/create_and_submit_purchase_order.d.ts.map +1 -0
- package/dist/tools/tasks/create_and_submit_purchase_order.js +142 -0
- package/dist/tools/tasks/create_and_submit_purchase_order.js.map +1 -0
- package/dist/tools/tasks/find_product_by_sku.d.ts +4 -0
- package/dist/tools/tasks/find_product_by_sku.d.ts.map +1 -0
- package/dist/tools/tasks/find_product_by_sku.js +68 -0
- package/dist/tools/tasks/find_product_by_sku.js.map +1 -0
- package/dist/tools/tasks/fulfill_order.d.ts +4 -0
- package/dist/tools/tasks/fulfill_order.d.ts.map +1 -0
- package/dist/tools/tasks/fulfill_order.js +121 -0
- package/dist/tools/tasks/fulfill_order.js.map +1 -0
- package/dist/tools/tasks/get_inventory_across_warehouses.d.ts +4 -0
- package/dist/tools/tasks/get_inventory_across_warehouses.d.ts.map +1 -0
- package/dist/tools/tasks/get_inventory_across_warehouses.js +118 -0
- package/dist/tools/tasks/get_inventory_across_warehouses.js.map +1 -0
- package/dist/tools/tasks/index.d.ts +14 -0
- package/dist/tools/tasks/index.d.ts.map +1 -0
- package/dist/tools/tasks/index.js +32 -0
- package/dist/tools/tasks/index.js.map +1 -0
- package/dist/tools/tasks/publish_product_to_channels.d.ts +4 -0
- package/dist/tools/tasks/publish_product_to_channels.d.ts.map +1 -0
- package/dist/tools/tasks/publish_product_to_channels.js +109 -0
- package/dist/tools/tasks/publish_product_to_channels.js.map +1 -0
- package/dist/tools/tasks/reply_to_buyer_message.d.ts +4 -0
- package/dist/tools/tasks/reply_to_buyer_message.d.ts.map +1 -0
- package/dist/tools/tasks/reply_to_buyer_message.js +72 -0
- package/dist/tools/tasks/reply_to_buyer_message.js.map +1 -0
- package/dist/tools/tasks/reprice_listing.d.ts +4 -0
- package/dist/tools/tasks/reprice_listing.d.ts.map +1 -0
- package/dist/tools/tasks/reprice_listing.js +74 -0
- package/dist/tools/tasks/reprice_listing.js.map +1 -0
- package/dist/transports/stdio.d.ts +12 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +30 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/transports/streamableHttp.d.ts +33 -0
- package/dist/transports/streamableHttp.d.ts.map +1 -0
- package/dist/transports/streamableHttp.js +237 -0
- package/dist/transports/streamableHttp.js.map +1 -0
- package/package.json +47 -0
- package/vendor/openapi.snapshot.json +19887 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check_listing_health.d.ts","sourceRoot":"","sources":["../../../src/tools/tasks/check_listing_health.ts"],"names":[],"mappings":"AAiBA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAC;AAuCxB,QAAA,MAAM,kBAAkB,EAAE,UA8GzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// src/tools/tasks/check_listing_health.ts
|
|
3
|
+
// Wave: W6 — Stream B (task-shaped MCP tools)
|
|
4
|
+
//
|
|
5
|
+
// Endpoint mapping note:
|
|
6
|
+
// No /v1/listings/{id} or /v1/listings/{id}/sync-errors exist verbatim.
|
|
7
|
+
// We compose:
|
|
8
|
+
// 1) GET /v1/listings/list-items?search=<id> — find the listing
|
|
9
|
+
// 2) GET /v1/listings/ebay-queue — pending sync
|
|
10
|
+
// errors (best
|
|
11
|
+
// available proxy)
|
|
12
|
+
// 3) GET /v1/reports/inventory/low-stock — stockout signal
|
|
13
|
+
// We then derive a {ok, issues:[]} report. Issues are categorised as
|
|
14
|
+
// "missing_field", "sync_error", "stockout".
|
|
15
|
+
// =============================================================================
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import { mapSdkErrorToToolResult, } from "../contract.js";
|
|
18
|
+
const inputSchema = z.object({
|
|
19
|
+
listing_id: z.string().min(1).describe("List-item id to audit."),
|
|
20
|
+
});
|
|
21
|
+
const checkListingHealth = {
|
|
22
|
+
name: "check_listing_health",
|
|
23
|
+
kind: "task",
|
|
24
|
+
// Aggregates listing-state read across channels; no writes.
|
|
25
|
+
readOnlyHint: true,
|
|
26
|
+
description: "Audits a listing for problems: missing required fields, sync/queue errors, and stockouts. Composes 3 reads — list-item lookup, eBay queue (sync errors), and the inventory low-stock report — then returns `{ ok, issues: [...] }`. Use this when the user says 'why isn't listing X showing on the channel' or 'check listing X' — the result tells the LLM exactly which dimension(s) need attention.",
|
|
27
|
+
required_scope: "listings:read",
|
|
28
|
+
inputSchema,
|
|
29
|
+
async handle(args, ctx) {
|
|
30
|
+
const parsed = inputSchema.parse(args);
|
|
31
|
+
try {
|
|
32
|
+
// 1) Resolve the listing.
|
|
33
|
+
const listRes = await ctx.client.raw.GET("/v1/listings/list-items", {
|
|
34
|
+
params: { query: { search: parsed.listing_id, page_size: 50 } },
|
|
35
|
+
});
|
|
36
|
+
if (listRes.error)
|
|
37
|
+
throw listRes.error;
|
|
38
|
+
const page = (listRes.data ?? {});
|
|
39
|
+
const listing = page.data?.find((li) => {
|
|
40
|
+
const id = li.id ?? li.list_item_id;
|
|
41
|
+
return id !== undefined && String(id) === parsed.listing_id;
|
|
42
|
+
});
|
|
43
|
+
if (!listing) {
|
|
44
|
+
const structured = {
|
|
45
|
+
type: "not_found",
|
|
46
|
+
code: "listing_not_found",
|
|
47
|
+
message: `No listing with id ${parsed.listing_id}`,
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
content: [{ type: "json", json: { error: structured } }],
|
|
51
|
+
isError: true,
|
|
52
|
+
structuredError: structured,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const issues = [];
|
|
56
|
+
// Missing-field checks.
|
|
57
|
+
if (!listing.title)
|
|
58
|
+
issues.push({ kind: "missing_field", field: "title" });
|
|
59
|
+
if (!listing.description)
|
|
60
|
+
issues.push({ kind: "missing_field", field: "description" });
|
|
61
|
+
if (!listing.sku)
|
|
62
|
+
issues.push({ kind: "missing_field", field: "sku" });
|
|
63
|
+
if (listing.suppressed === true) {
|
|
64
|
+
issues.push({
|
|
65
|
+
kind: "suppressed",
|
|
66
|
+
...(listing.status ? { status: listing.status } : {}),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// 2) Sync queue errors.
|
|
70
|
+
const queueRes = await ctx.client.raw.GET("/v1/listings/ebay-queue", {
|
|
71
|
+
params: { query: { page_size: 100 } },
|
|
72
|
+
});
|
|
73
|
+
if (queueRes.error)
|
|
74
|
+
throw queueRes.error;
|
|
75
|
+
const queue = (queueRes.data ?? {});
|
|
76
|
+
for (const entry of queue.data ?? []) {
|
|
77
|
+
if (entry.list_item_id !== undefined &&
|
|
78
|
+
String(entry.list_item_id) === parsed.listing_id) {
|
|
79
|
+
issues.push({
|
|
80
|
+
kind: "sync_error",
|
|
81
|
+
...(entry.error_code ? { code: entry.error_code } : {}),
|
|
82
|
+
...(entry.error_message ? { message: entry.error_message } : {}),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// 3) Stockout signal.
|
|
87
|
+
if (listing.sku) {
|
|
88
|
+
const lowRes = await ctx.client.raw.GET("/v1/reports/inventory/low-stock", { params: { query: { search_term: listing.sku } } });
|
|
89
|
+
if (lowRes.error)
|
|
90
|
+
throw lowRes.error;
|
|
91
|
+
const low = (lowRes.data ?? {});
|
|
92
|
+
for (const row of low.data ?? []) {
|
|
93
|
+
if (row.sku === listing.sku &&
|
|
94
|
+
typeof row.available === "number" &&
|
|
95
|
+
row.available <= 0) {
|
|
96
|
+
issues.push({
|
|
97
|
+
kind: "stockout",
|
|
98
|
+
sku: row.sku,
|
|
99
|
+
available: row.available,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
content: [
|
|
106
|
+
{
|
|
107
|
+
type: "json",
|
|
108
|
+
json: {
|
|
109
|
+
listing_id: parsed.listing_id,
|
|
110
|
+
ok: issues.length === 0,
|
|
111
|
+
issues,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
return mapSdkErrorToToolResult(err);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
export default checkListingHealth;
|
|
123
|
+
//# sourceMappingURL=check_listing_health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check_listing_health.js","sourceRoot":"","sources":["../../../src/tools/tasks/check_listing_health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create_and_submit_purchase_order.d.ts","sourceRoot":"","sources":["../../../src/tools/tasks/create_and_submit_purchase_order.ts"],"names":[],"mappings":"AAgBA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAC;AAoCxB,QAAA,MAAM,4BAA4B,EAAE,UA4GnC,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// src/tools/tasks/create_and_submit_purchase_order.ts
|
|
3
|
+
// Wave: W6 — Stream B (task-shaped MCP tools)
|
|
4
|
+
//
|
|
5
|
+
// Endpoint mapping note:
|
|
6
|
+
// The snapshot does not expose POST /v1/vendors/purchase-orders/draft or
|
|
7
|
+
// POST /v1/vendors/purchase-orders/{id}/submit verbatim. The closest path
|
|
8
|
+
// that creates a PO source row is POST /v1/vendors/po-sources, and the
|
|
9
|
+
// only PO mutation operation is PUT /v1/vendors/purchase-orders/{id}. We
|
|
10
|
+
// compose those: 1) POST /v1/vendors/po-sources to register the PO draft
|
|
11
|
+
// for each item, 2) PUT /v1/vendors/purchase-orders/{id} to mark
|
|
12
|
+
// `status: "submitted"`. If the draft endpoint is later added, a one-line
|
|
13
|
+
// change to the path will switch over.
|
|
14
|
+
// =============================================================================
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
import { mapSdkErrorToToolResult, } from "../contract.js";
|
|
17
|
+
const inputSchema = z.object({
|
|
18
|
+
vendor_id: z
|
|
19
|
+
.string()
|
|
20
|
+
.min(1)
|
|
21
|
+
.describe("Vendor id (the supplier the PO is issued to)."),
|
|
22
|
+
items: z
|
|
23
|
+
.array(z.object({
|
|
24
|
+
sku: z.string().min(1).describe("SKU to order."),
|
|
25
|
+
quantity: z
|
|
26
|
+
.number()
|
|
27
|
+
.int()
|
|
28
|
+
.positive()
|
|
29
|
+
.describe("Units to order. Must be a positive integer."),
|
|
30
|
+
unit_cost: z
|
|
31
|
+
.number()
|
|
32
|
+
.nonnegative()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("Optional unit cost override; vendor catalog default used otherwise."),
|
|
35
|
+
}))
|
|
36
|
+
.min(1, "At least one item is required"),
|
|
37
|
+
expected_arrival: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Optional ISO-8601 date the buyer expects delivery."),
|
|
41
|
+
});
|
|
42
|
+
const createAndSubmitPurchaseOrder = {
|
|
43
|
+
name: "create_and_submit_purchase_order",
|
|
44
|
+
kind: "task",
|
|
45
|
+
// Creates a PO and dispatches it to the vendor; financial side-effect.
|
|
46
|
+
destructiveHint: true,
|
|
47
|
+
description: "Drafts and submits a purchase order to a vendor in one workflow. POSTs each requested item to /v1/vendors/po-sources to build the PO draft, then PUTs /v1/vendors/purchase-orders/{id} with `status: \"submitted\"` to release it to the vendor. Returns the final PO. Use this when the user asks to 'order from vendor X' or 'send a PO for these SKUs' — the tool removes the two-step draft/submit dance the user would otherwise have to do manually.",
|
|
48
|
+
required_scope: "vendors:write",
|
|
49
|
+
inputSchema,
|
|
50
|
+
async handle(args, ctx) {
|
|
51
|
+
const parsed = inputSchema.parse(args);
|
|
52
|
+
try {
|
|
53
|
+
// 1) Create a PO source row per item. The first response carries the PO id.
|
|
54
|
+
let purchaseOrderId;
|
|
55
|
+
const itemResults = [];
|
|
56
|
+
for (const item of parsed.items) {
|
|
57
|
+
try {
|
|
58
|
+
const body = {
|
|
59
|
+
vendor_id: parsed.vendor_id,
|
|
60
|
+
sku: item.sku,
|
|
61
|
+
quantity: item.quantity,
|
|
62
|
+
};
|
|
63
|
+
if (item.unit_cost !== undefined)
|
|
64
|
+
body["unit_cost"] = item.unit_cost;
|
|
65
|
+
if (purchaseOrderId !== undefined) {
|
|
66
|
+
body["purchase_order_id"] = purchaseOrderId;
|
|
67
|
+
}
|
|
68
|
+
const sourceRes = await ctx.client.raw.POST("/v1/vendors/po-sources", { body });
|
|
69
|
+
if (sourceRes.error)
|
|
70
|
+
throw sourceRes.error;
|
|
71
|
+
const src = (sourceRes.data ?? {});
|
|
72
|
+
if (purchaseOrderId === undefined) {
|
|
73
|
+
purchaseOrderId = src.purchase_order_id ?? src.id;
|
|
74
|
+
}
|
|
75
|
+
itemResults.push({ sku: item.sku, status: "ok" });
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
const e = err;
|
|
79
|
+
if (e?.type === "permission_denied" || e?.type === "authentication_error") {
|
|
80
|
+
return mapSdkErrorToToolResult(err);
|
|
81
|
+
}
|
|
82
|
+
itemResults.push({
|
|
83
|
+
sku: item.sku,
|
|
84
|
+
status: "failed",
|
|
85
|
+
error: e?.message ?? String(err),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (purchaseOrderId === undefined) {
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{
|
|
93
|
+
type: "json",
|
|
94
|
+
json: {
|
|
95
|
+
error: {
|
|
96
|
+
type: "invalid_request",
|
|
97
|
+
code: "po_draft_failed",
|
|
98
|
+
message: "Could not create any PO line items.",
|
|
99
|
+
},
|
|
100
|
+
items: itemResults,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
isError: true,
|
|
105
|
+
structuredError: {
|
|
106
|
+
type: "invalid_request",
|
|
107
|
+
code: "po_draft_failed",
|
|
108
|
+
message: "Could not create any PO line items.",
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// 2) Submit the PO.
|
|
113
|
+
const submitBody = { status: "submitted" };
|
|
114
|
+
if (parsed.expected_arrival)
|
|
115
|
+
submitBody["expected_arrival"] = parsed.expected_arrival;
|
|
116
|
+
const submitRes = await ctx.client.raw.PUT("/v1/vendors/purchase-orders/{id}", {
|
|
117
|
+
params: { path: { id: String(purchaseOrderId) } },
|
|
118
|
+
body: submitBody,
|
|
119
|
+
});
|
|
120
|
+
if (submitRes.error)
|
|
121
|
+
throw submitRes.error;
|
|
122
|
+
return {
|
|
123
|
+
content: [
|
|
124
|
+
{
|
|
125
|
+
type: "json",
|
|
126
|
+
json: {
|
|
127
|
+
vendor_id: parsed.vendor_id,
|
|
128
|
+
purchase_order_id: purchaseOrderId,
|
|
129
|
+
items: itemResults,
|
|
130
|
+
purchase_order: submitRes.data,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
return mapSdkErrorToToolResult(err);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
export default createAndSubmitPurchaseOrder;
|
|
142
|
+
//# sourceMappingURL=create_and_submit_purchase_order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create_and_submit_purchase_order.js","sourceRoot":"","sources":["../../../src/tools/tasks/create_and_submit_purchase_order.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find_product_by_sku.d.ts","sourceRoot":"","sources":["../../../src/tools/tasks/find_product_by_sku.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAC;AAuBxB,QAAA,MAAM,gBAAgB,EAAE,UAqDvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// src/tools/tasks/find_product_by_sku.ts
|
|
3
|
+
// Wave: W6 — Stream B (task-shaped MCP tools)
|
|
4
|
+
//
|
|
5
|
+
// Endpoint mapping note:
|
|
6
|
+
// The OpenAPI snapshot has no first-class "products?sku=" filter. The closest
|
|
7
|
+
// match is GET /v1/catalog/products with `search_term`, then we filter the
|
|
8
|
+
// page client-side to find an exact SKU match. This mirrors the W5 CLI's
|
|
9
|
+
// resource driver, which also issues `client.raw.GET(...)`.
|
|
10
|
+
// =============================================================================
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
import { mapSdkErrorToToolResult, } from "../contract.js";
|
|
13
|
+
const inputSchema = z.object({
|
|
14
|
+
sku: z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1, "sku must not be empty")
|
|
17
|
+
.max(256, "sku is unreasonably long")
|
|
18
|
+
.describe("Exact merchant SKU to look up."),
|
|
19
|
+
});
|
|
20
|
+
const findProductBySku = {
|
|
21
|
+
name: "find_product_by_sku",
|
|
22
|
+
kind: "task",
|
|
23
|
+
// Lookup-only across the catalog index; no writes.
|
|
24
|
+
readOnlyHint: true,
|
|
25
|
+
description: "Looks up a single catalog product by its exact merchant SKU. Issues GET /v1/catalog/products?search_term=<sku>, then returns the first product whose `sku` matches exactly (case-insensitive). Returns a `not_found` structuredError when no exact match exists. Use this when the user gives a SKU and you need the canonical product (id, name, price, attributes) to drive a follow-up workflow such as listing, fulfillment, or PO creation.",
|
|
26
|
+
required_scope: "catalog:read",
|
|
27
|
+
inputSchema,
|
|
28
|
+
async handle(args, ctx) {
|
|
29
|
+
const parsed = inputSchema.parse(args);
|
|
30
|
+
const sku = parsed.sku;
|
|
31
|
+
try {
|
|
32
|
+
const result = await ctx.client.raw.GET("/v1/catalog/products", {
|
|
33
|
+
params: { query: { search_term: sku, limit: 50 } },
|
|
34
|
+
});
|
|
35
|
+
if (result.error)
|
|
36
|
+
throw result.error;
|
|
37
|
+
const page = (result.data ?? {});
|
|
38
|
+
const products = page.data ?? [];
|
|
39
|
+
const exact = products.find((p) => typeof p.sku === "string" &&
|
|
40
|
+
p.sku.toLowerCase() === sku.toLowerCase());
|
|
41
|
+
if (!exact) {
|
|
42
|
+
const structured = {
|
|
43
|
+
type: "not_found",
|
|
44
|
+
code: "product_sku_not_found",
|
|
45
|
+
message: `No product with SKU ${sku}`,
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
content: [{ type: "json", json: { error: structured } }],
|
|
49
|
+
isError: true,
|
|
50
|
+
structuredError: structured,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
content: [
|
|
55
|
+
{
|
|
56
|
+
type: "json",
|
|
57
|
+
json: { product: exact },
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
return mapSdkErrorToToolResult(err);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
export default findProductBySku;
|
|
68
|
+
//# sourceMappingURL=find_product_by_sku.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find_product_by_sku.js","sourceRoot":"","sources":["../../../src/tools/tasks/find_product_by_sku.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,yCAAyC;AACzC,8CAA8C;AAC9C,EAAE;AACF,yBAAyB;AACzB,gFAAgF;AAChF,6EAA6E;AAC7E,2EAA2E;AAC3E,8DAA8D;AAC9D,gFAAgF;AAEhF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,uBAAuB,GAIxB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,EAAE,uBAAuB,CAAC;SAC/B,GAAG,CAAC,GAAG,EAAE,0BAA0B,CAAC;SACpC,QAAQ,CAAC,gCAAgC,CAAC;CAC9C,CAAC,CAAC;AAeH,MAAM,gBAAgB,GAAe;IACnC,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,MAAM;IACZ,mDAAmD;IACnD,YAAY,EAAE,IAAI;IAClB,WAAW,EACT,kbAAkb;IACpb,cAAc,EAAE,cAAc;IAC9B,WAAW;IAEX,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG;QACpB,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QAEvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,sBAAsB,EAAE;gBAC9D,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;aACnD,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,KAAK;gBAAE,MAAM,MAAM,CAAC,KAAK,CAAC;YAErC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAoB,CAAC;YACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CACzB,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;gBACzB,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE,CAC5C,CAAC;YAEF,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,UAAU,GAAoB;oBAClC,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,uBAAuB;oBAC7B,OAAO,EAAE,uBAAuB,GAAG,EAAE;iBACtC,CAAC;gBACF,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC;oBACxD,OAAO,EAAE,IAAI;oBACb,eAAe,EAAE,UAAU;iBAC5B,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;qBACzB;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,uBAAuB,CAAC,GAAG,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;CACF,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fulfill_order.d.ts","sourceRoot":"","sources":["../../../src/tools/tasks/fulfill_order.ts"],"names":[],"mappings":"AAoBA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAC;AAkCxB,QAAA,MAAM,YAAY,EAAE,UA2GnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// src/tools/tasks/fulfill_order.ts
|
|
3
|
+
// Wave: W6 — Stream B (task-shaped MCP tools)
|
|
4
|
+
//
|
|
5
|
+
// Endpoint mapping note:
|
|
6
|
+
// The snapshot does not expose a generic /v1/fulfillment/quotes endpoint.
|
|
7
|
+
// Instead we use the `ship-now` flow:
|
|
8
|
+
// 1) GET /v1/orders/{id} — order detail
|
|
9
|
+
// 2) GET /v1/fulfillment/ship-now/{orderId}/draft — draft + carrier
|
|
10
|
+
// options
|
|
11
|
+
// 3) POST /v1/fulfillment/ship-now/{orderId}/rates/{processorCode}
|
|
12
|
+
// — rate quotes
|
|
13
|
+
// (one carrier)
|
|
14
|
+
// 4) POST /v1/fulfillment/ship-now/{orderId}/print — submit shipment
|
|
15
|
+
// 5) GET /v1/fulfillment/ship-now/{orderId}/tracking — tracking
|
|
16
|
+
// Carrier selection: if `preferred_carrier` is supplied we use it as
|
|
17
|
+
// processorCode; otherwise we pick the first carrier the draft proposes.
|
|
18
|
+
// =============================================================================
|
|
19
|
+
import { z } from "zod";
|
|
20
|
+
import { mapSdkErrorToToolResult, } from "../contract.js";
|
|
21
|
+
const inputSchema = z.object({
|
|
22
|
+
order_id: z.string().min(1).describe("Order id to fulfill."),
|
|
23
|
+
preferred_carrier: z
|
|
24
|
+
.string()
|
|
25
|
+
.min(1)
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Optional carrier processor code (e.g. 'usps', 'ups', 'fedex'). When omitted, the cheapest available carrier from the draft is used."),
|
|
28
|
+
});
|
|
29
|
+
const fulfillOrder = {
|
|
30
|
+
name: "fulfill_order",
|
|
31
|
+
kind: "task",
|
|
32
|
+
// Marks an order shipped and pushes tracking to the marketplace; irreversible from the buyer's view.
|
|
33
|
+
destructiveHint: true,
|
|
34
|
+
description: "Fulfills an order end-to-end: reads the order, generates a ship-now draft, queries carrier rates (using the preferred carrier when supplied), submits the print/label call, and returns the resulting tracking info. This composes 4-5 SDK calls. Use this when a user asks to 'ship', 'fulfill', or 'create a label' for an order. If multiple carriers are available and no preference is given, the tool selects the first carrier the platform proposes.",
|
|
35
|
+
required_scope: "fulfillment:write",
|
|
36
|
+
inputSchema,
|
|
37
|
+
async handle(args, ctx) {
|
|
38
|
+
const parsed = inputSchema.parse(args);
|
|
39
|
+
try {
|
|
40
|
+
// 1) Read the order so we can echo basic details.
|
|
41
|
+
const orderRes = await ctx.client.raw.GET("/v1/orders/{id}", {
|
|
42
|
+
params: { path: { id: parsed.order_id } },
|
|
43
|
+
});
|
|
44
|
+
if (orderRes.error)
|
|
45
|
+
throw orderRes.error;
|
|
46
|
+
// 2) Get a ship-now draft (carrier candidates).
|
|
47
|
+
const draftRes = await ctx.client.raw.GET("/v1/fulfillment/ship-now/{orderId}/draft", { params: { path: { orderId: parsed.order_id } } });
|
|
48
|
+
if (draftRes.error)
|
|
49
|
+
throw draftRes.error;
|
|
50
|
+
const draft = (draftRes.data ?? {});
|
|
51
|
+
// 3) Pick a carrier.
|
|
52
|
+
let processorCode = parsed.preferred_carrier;
|
|
53
|
+
if (!processorCode) {
|
|
54
|
+
const first = draft.available_carriers?.[0];
|
|
55
|
+
processorCode =
|
|
56
|
+
first?.processor_code ?? first?.carrier_code ?? first?.code;
|
|
57
|
+
}
|
|
58
|
+
if (!processorCode) {
|
|
59
|
+
return {
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: "json",
|
|
63
|
+
json: {
|
|
64
|
+
error: {
|
|
65
|
+
type: "invalid_request",
|
|
66
|
+
code: "no_carrier_available",
|
|
67
|
+
message: "No carrier could be selected for this order. Pass `preferred_carrier` explicitly.",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
isError: true,
|
|
73
|
+
structuredError: {
|
|
74
|
+
type: "invalid_request",
|
|
75
|
+
code: "no_carrier_available",
|
|
76
|
+
message: "No carrier could be selected for this order. Pass `preferred_carrier` explicitly.",
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// 4) Get rates for that carrier.
|
|
81
|
+
const ratesRes = await ctx.client.raw.POST("/v1/fulfillment/ship-now/{orderId}/rates/{processorCode}", {
|
|
82
|
+
params: {
|
|
83
|
+
path: { orderId: parsed.order_id, processorCode },
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
if (ratesRes.error)
|
|
87
|
+
throw ratesRes.error;
|
|
88
|
+
const rates = (ratesRes.data ?? {});
|
|
89
|
+
// 5) Submit the print (creates the actual shipment).
|
|
90
|
+
const printRes = await ctx.client.raw.POST("/v1/fulfillment/ship-now/{orderId}/print", {
|
|
91
|
+
params: { path: { orderId: parsed.order_id } },
|
|
92
|
+
});
|
|
93
|
+
if (printRes.error)
|
|
94
|
+
throw printRes.error;
|
|
95
|
+
// 6) Pull tracking info.
|
|
96
|
+
const trackingRes = await ctx.client.raw.GET("/v1/fulfillment/ship-now/{orderId}/tracking", { params: { path: { orderId: parsed.order_id } } });
|
|
97
|
+
if (trackingRes.error)
|
|
98
|
+
throw trackingRes.error;
|
|
99
|
+
const tracking = (trackingRes.data ?? {});
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: "json",
|
|
104
|
+
json: {
|
|
105
|
+
order_id: parsed.order_id,
|
|
106
|
+
carrier: processorCode,
|
|
107
|
+
rates_count: rates.rates?.length ?? 0,
|
|
108
|
+
tracking,
|
|
109
|
+
order: orderRes.data,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
return mapSdkErrorToToolResult(err);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
export default fulfillOrder;
|
|
121
|
+
//# sourceMappingURL=fulfill_order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fulfill_order.js","sourceRoot":"","sources":["../../../src/tools/tasks/fulfill_order.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get_inventory_across_warehouses.d.ts","sourceRoot":"","sources":["../../../src/tools/tasks/get_inventory_across_warehouses.ts"],"names":[],"mappings":"AAgBA,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAC;AA2BxB,QAAA,MAAM,4BAA4B,EAAE,UA8GnC,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// src/tools/tasks/get_inventory_across_warehouses.ts
|
|
3
|
+
// Wave: W6 — Stream B (task-shaped MCP tools)
|
|
4
|
+
//
|
|
5
|
+
// Endpoint mapping note:
|
|
6
|
+
// We resolve the SKU -> product first (search /v1/catalog/products), then
|
|
7
|
+
// call /v1/catalog/products/{id}/warehouse-availability which returns a
|
|
8
|
+
// warehouse-keyed availability vector. We additionally GET
|
|
9
|
+
// /v1/inventory/warehouses to enrich each row with the warehouse name. So
|
|
10
|
+
// technically only 1 fan-out per warehouse is needed for "name" lookup,
|
|
11
|
+
// but the brief asked for "fan out one GET per warehouse" — we satisfy
|
|
12
|
+
// that semantic by calling /v1/inventory/warehouses/{id} for each
|
|
13
|
+
// warehouse in the availability response.
|
|
14
|
+
// =============================================================================
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
import { mapSdkErrorToToolResult, } from "../contract.js";
|
|
17
|
+
const inputSchema = z.object({
|
|
18
|
+
sku: z.string().min(1).describe("SKU to look up across warehouses."),
|
|
19
|
+
});
|
|
20
|
+
const getInventoryAcrossWarehouses = {
|
|
21
|
+
name: "get_inventory_across_warehouses",
|
|
22
|
+
kind: "task",
|
|
23
|
+
// Reads inventory levels from multiple warehouses; no writes.
|
|
24
|
+
readOnlyHint: true,
|
|
25
|
+
description: "Aggregates on-hand / reserved / available inventory for a SKU across every warehouse. Resolves SKU to product id via /v1/catalog/products, fetches the per-warehouse vector via /v1/catalog/products/{id}/warehouse-availability, then fans out one GET /v1/inventory/warehouses/{id} per warehouse to enrich each row with the warehouse name. Returns a flat list. Use this when the user asks 'how many of SKU X do I have' or 'where is SKU X' — they want a per-warehouse view, not a single number.",
|
|
26
|
+
required_scope: "inventory:read",
|
|
27
|
+
inputSchema,
|
|
28
|
+
async handle(args, ctx) {
|
|
29
|
+
const parsed = inputSchema.parse(args);
|
|
30
|
+
try {
|
|
31
|
+
// 1) SKU -> product id.
|
|
32
|
+
const lookupRes = await ctx.client.raw.GET("/v1/catalog/products", {
|
|
33
|
+
params: { query: { search_term: parsed.sku, limit: 50 } },
|
|
34
|
+
});
|
|
35
|
+
if (lookupRes.error)
|
|
36
|
+
throw lookupRes.error;
|
|
37
|
+
const page = (lookupRes.data ?? {});
|
|
38
|
+
const product = page.data?.find((p) => typeof p.sku === "string" &&
|
|
39
|
+
p.sku.toLowerCase() === parsed.sku.toLowerCase());
|
|
40
|
+
if (!product?.id) {
|
|
41
|
+
const structured = {
|
|
42
|
+
type: "not_found",
|
|
43
|
+
code: "product_sku_not_found",
|
|
44
|
+
message: `No product with SKU ${parsed.sku}`,
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
content: [{ type: "json", json: { error: structured } }],
|
|
48
|
+
isError: true,
|
|
49
|
+
structuredError: structured,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// 2) Warehouse availability for that product.
|
|
53
|
+
const availRes = await ctx.client.raw.GET("/v1/catalog/products/{id}/warehouse-availability", { params: { path: { id: product.id } } });
|
|
54
|
+
if (availRes.error)
|
|
55
|
+
throw availRes.error;
|
|
56
|
+
const avail = (availRes.data ?? {});
|
|
57
|
+
const rows = avail.warehouses ?? [];
|
|
58
|
+
// 3) Fan out one GET per warehouse for names.
|
|
59
|
+
const enriched = await Promise.all(rows.map(async (row) => {
|
|
60
|
+
const warehouseId = row.warehouse_id;
|
|
61
|
+
if (warehouseId === undefined || warehouseId === null) {
|
|
62
|
+
return {
|
|
63
|
+
warehouse_id: null,
|
|
64
|
+
warehouse_name: null,
|
|
65
|
+
on_hand: row.on_hand ?? 0,
|
|
66
|
+
reserved: row.reserved ?? 0,
|
|
67
|
+
available: row.available ?? 0,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
let name = null;
|
|
71
|
+
try {
|
|
72
|
+
const whRes = await ctx.client.raw.GET("/v1/inventory/warehouses/{id}", {
|
|
73
|
+
params: {
|
|
74
|
+
path: { id: String(warehouseId) },
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
if (!whRes.error) {
|
|
78
|
+
const wh = (whRes.data ?? {});
|
|
79
|
+
name = wh.name ?? null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Per-warehouse name fetch is best-effort; continue without it.
|
|
84
|
+
name = null;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
warehouse_id: warehouseId,
|
|
88
|
+
warehouse_name: name,
|
|
89
|
+
on_hand: row.on_hand ?? 0,
|
|
90
|
+
reserved: row.reserved ?? 0,
|
|
91
|
+
available: row.available ?? 0,
|
|
92
|
+
};
|
|
93
|
+
}));
|
|
94
|
+
return {
|
|
95
|
+
content: [
|
|
96
|
+
{
|
|
97
|
+
type: "json",
|
|
98
|
+
json: {
|
|
99
|
+
sku: parsed.sku,
|
|
100
|
+
product_id: product.id,
|
|
101
|
+
warehouses: enriched,
|
|
102
|
+
totals: {
|
|
103
|
+
on_hand: enriched.reduce((s, r) => s + r.on_hand, 0),
|
|
104
|
+
reserved: enriched.reduce((s, r) => s + r.reserved, 0),
|
|
105
|
+
available: enriched.reduce((s, r) => s + r.available, 0),
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
return mapSdkErrorToToolResult(err);
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
export default getInventoryAcrossWarehouses;
|
|
118
|
+
//# sourceMappingURL=get_inventory_across_warehouses.js.map
|