{
  "name": "factory-agent-tools",
  "description": "Deterministic agent tools shipped by the Autonomous Product & Software Factory (apps.giniloh.com), one product subpath per tool: Stripe payout -> GL reconciliation (LedgerLink), EU e-invoice EN 16931 / CIUS-FR validation, Factur-X conversion and EU VAT-id checks (FacturGate), carrier invoice DIM-weight / surcharge auditing with billable-weight computation (ParcelProof), and buyer-side warehouse-automation case auditing with multi-bid comparison and after-tax payback (CaseProof). Products retired in the registry are not listed.",
  "version": "1.5.0",
  "endpoint": "https://apps.giniloh.com/api/agent/calculate",
  "tool_selector": {
    "header": "x-webmcp-tool",
    "default": "reconcile_stripe_payout",
    "note": "Name of the tool to invoke; must be one of the tools listed below. Omit for the default."
  },
  "auth": {
    "type": "api_key",
    "header": "x-customer-id",
    "note": "Optional Stripe customer id for $0.25/query metered billing."
  },
  "pricing": {
    "mode": "metered",
    "rate_per_query_usd": 0.25,
    "currency": "USD"
  },
  "tools": [
    {
      "name": "reconcile_stripe_payout",
      "description": "Reconciles a netted Stripe payout into categorized GL journal lines that sum to the payout net exactly (Σ net == payout.amount). Accepts a customer read-only Stripe restricted key or a pasted Stripe JSON export; never uses the factory account.",
      "product": "ledgerlink",
      "inputSchema": {
        "type": "object",
        "properties": {
          "account_id": {
            "type": "string",
            "description": "Stripe account id whose payout is being reconciled."
          },
          "period": {
            "type": "string",
            "description": "Payout period, e.g. '2026-08' or a Stripe created range 'start:end'."
          },
          "payout_id": {
            "type": "string",
            "description": "Optional specific Stripe payout id to reconcile."
          },
          "stripe_restricted_key": {
            "type": "string",
            "description": "Customer read-only Stripe restricted key (rk_…). Required unless export_json is supplied."
          },
          "export_json": {
            "type": "string",
            "description": "Pasted/uploaded Stripe JSON export (payout + balance_transactions). Required unless stripe_restricted_key is supplied."
          }
        },
        "required": [
          "account_id",
          "period"
        ]
      }
    },
    {
      "name": "validate_einvoice",
      "description": "Pre-send compliance gate for EU e-invoices (EN 16931 + CIUS-FR): returns the exact findings (rule id, severity, field path, fix) with blocking vs advisory severity, a 0-100 readiness score, and the totals reconciliation with the drift delta. Accepts a canonical invoice model or an existing CII/UBL 2.1 document. No rule is reported as passing unless it is implemented (see coverage).",
      "product": "facturgate",
      "inputSchema": {
        "type": "object",
        "properties": {
          "xml": {
            "type": "string",
            "description": "An existing CII (CrossIndustryInvoice) or UBL 2.1 Invoice document to validate as-is. Supply this or `invoice`."
          },
          "invoice": {
            "type": "string",
            "description": "Canonical invoice model as a JSON string: { seller, buyer, invoice, targetFormat, targetCountry }."
          },
          "target_country": {
            "type": "string",
            "description": "Rule set / rounding regime to validate against. Defaults to FR (CIUS-FR overlay).",
            "enum": [
              "FR",
              "PL",
              "BE",
              "DE"
            ]
          },
          "target_format": {
            "type": "string",
            "description": "Artifact the document is destined for. Defaults to facturx.",
            "enum": [
              "facturx",
              "cii",
              "ubl"
            ]
          }
        },
        "required": []
      }
    },
    {
      "name": "convert_invoice_to_facturx",
      "description": "Converts a canonical invoice model into a compliant artifact at the EN 16931 profile (CII/Factur-X body or UBL 2.1 with the Peppol BIS 3.0 ProfileID), returning the corrected XML, the change list (every finding with its rule id and fix) and the reconciled totals. Refuses to emit a document that has blocking findings or an unmappable field.",
      "product": "facturgate",
      "inputSchema": {
        "type": "object",
        "properties": {
          "invoice": {
            "type": "string",
            "description": "Canonical invoice model as a JSON string: { seller, buyer, invoice, targetFormat, targetCountry }."
          },
          "target_country": {
            "type": "string",
            "description": "Rule set / rounding regime for the emitted document. Defaults to FR.",
            "enum": [
              "FR",
              "PL",
              "BE",
              "DE"
            ]
          },
          "target_format": {
            "type": "string",
            "description": "facturx (default, CII at EN 16931), cii (standalone CII) or ubl (UBL 2.1).",
            "enum": [
              "facturx",
              "cii",
              "ubl"
            ]
          }
        },
        "required": [
          "invoice"
        ]
      }
    },
    {
      "name": "check_eu_vat_id",
      "description": "Checks an EU VAT identifier offline: national format and (where implemented) the published checksum — FR VAT-key formula, DE MOD 11,10, BE mod 97, PL NIP, NL mod 11, IT Luhn. Reports formatValid/checksumValid explicitly and never claims a VIES status it did not query. An unknown country is a failure, not a pass.",
      "product": "facturgate",
      "inputSchema": {
        "type": "object",
        "properties": {
          "vat_id": {
            "type": "string",
            "description": "The VAT identifier as written, e.g. 'FR83404833048' or 'BE 0123.456.749'."
          },
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code of the identifier (e.g. FR, DE, BE, PL, NL)."
          }
        },
        "required": [
          "vat_id",
          "country"
        ]
      }
    },
    {
      "name": "audit_carrier_invoice",
      "description": "Audits a UPS/FedEx/USPS parcel invoice against the shipment records behind it: recomputes billable weight per line from the carrier × service × ship-date divisor (USPS 166 → 139 on 2026-07-12) with the round-up rule and cubic-inch thresholds, re-evaluates accessorial eligibility (AHS-Dimension, AHS-Weight, oversize, residential, address correction) naming the trigger that failed, checks the service-commitment refund and the per-line dispute window (UPS ≈30 / FedEx ≈21 days), and returns a per-line recovery ledger plus a dispute CSV. A line whose amount cannot be proven is reported unverifiable, never guessed.",
      "product": "parcelproof",
      "inputSchema": {
        "type": "object",
        "properties": {
          "shipment_records": {
            "type": "string",
            "description": "Shipment records as CSV text: order_id,tracking,carrier,service,ship_date,length,width,height,actual_weight_lb,zone,declared_value_usd,residential,address_correction,promised_date,delivered_at"
          },
          "invoice_lines": {
            "type": "string",
            "description": "Carrier invoice lines as CSV text: tracking,invoice_date,carrier,service,billed_weight_lb,zone,base_charge_usd,surcharges,total_usd (surcharges as code:amount pairs separated by ';')."
          },
          "rate_card": {
            "type": "string",
            "description": "Your contract rate card as CSV text: carrier,service,zone,min_weight_lb,max_weight_lb,rate_usd. Omit it and every line is reported unverifiable-rate (the weight proof still holds) instead of being priced from a guessed rate."
          },
          "as_of_date": {
            "type": "string",
            "description": "ISO 8601 date used as 'today' for the dispute clock and money-back windows. Defaults to the server's UTC date."
          },
          "carrier": {
            "type": "string",
            "description": "Optional carrier filter.",
            "enum": [
              "ups",
              "fedex",
              "usps"
            ]
          }
        },
        "required": [
          "shipment_records",
          "invoice_lines"
        ]
      }
    },
    {
      "name": "compute_billable_weight",
      "description": "Computes the billable weight a UPS/FedEx/USPS domestic parcel shipment incurs: max(actual, ceil(L)×ceil(W)×ceil(H)/divisor) with the divisor resolved by carrier × service × ship date (USPS 166 before 2026-07-12, then 139; UPS/FedEx 139) and the carrier's cubic-inch threshold applied (FedEx Ground / USPS: only above 1,728 cu in). Returns the divisor used, whether dimensional weight applied, the rounded dimensions and the billing basis. Use it to quote landed cost correctly; an unmapped service or an out-of-range ship date is an explicit error, never a default divisor.",
      "product": "parcelproof",
      "inputSchema": {
        "type": "object",
        "properties": {
          "carrier": {
            "type": "string",
            "description": "Carrier the parcel ships on.",
            "enum": [
              "ups",
              "fedex",
              "usps"
            ]
          },
          "service": {
            "type": "string",
            "description": "Service level, which selects the divisor table entry.",
            "enum": [
              "ups_ground",
              "ups_air",
              "ups_express_saver",
              "fedex_ground",
              "fedex_home_delivery",
              "fedex_express",
              "usps_ground_advantage",
              "usps_priority_mail",
              "usps_priority_mail_express",
              "usps_parcel_select"
            ]
          },
          "ship_date": {
            "type": "string",
            "description": "ISO 8601 ship date (YYYY-MM-DD): the divisor in force depends on it."
          },
          "length": {
            "type": "number",
            "description": "Package length in inches (fractions round up)."
          },
          "width": {
            "type": "number",
            "description": "Package width in inches (fractions round up)."
          },
          "height": {
            "type": "number",
            "description": "Package height in inches (fractions round up)."
          },
          "actual_weight_lb": {
            "type": "number",
            "description": "Scale weight in pounds."
          }
        },
        "required": [
          "carrier",
          "service",
          "ship_date",
          "length",
          "width",
          "height",
          "actual_weight_lb"
        ]
      }
    },
    {
      "name": "audit_automation_case",
      "description": "Audits a warehouse-automation business case from the buyer's side: re-runs the vendor's own quoted numbers through the same engine as the buyer's, prices labour at the fully loaded rate (payroll burden, benefits, overtime premium, turnover replacement), adds the cost lines a quote omits (integration, facility work, maintenance, training, ramp and downtime at the contracted availability), applies §179 then bonus depreciation by tax year, and returns payback in months, IRR, NPV at the hurdle rate, the break-even of every assumption the case depends on, the inputs that moved the vendor's number, and the ranked list to confirm in writing. A cost line the case does not state is reported unstated and blocks a pass verdict — nothing is defaulted.",
      "product": "caseproof",
      "inputSchema": {
        "type": "object",
        "properties": {
          "case": {
            "type": "string",
            "description": "The case as a JSON string: { baseline: { ordersPerDay, linesPerOrder, operatingDaysPerYear, shifts, staffByFunction[], hourlyWage, paidHoursPerFtePerYear, payrollBurdenPct?, benefitsPct?, overtimeHoursPerWeek?, turnoverPct?, costPerHireCents?, errorRatePct?, costPerErrorCents?, peakFactor?, vendorAssumedHourlyRate? }, finance: { horizonYears, hurdleRatePct, taxRatePct, inServiceTaxYear, section179ElectionCents?, financingRatePct?, financingMonths? }, options: [{ id, vendor, model: capex|lease|raas, capex?, lease?, raas?, integrationCostCents?, facilityCostCents?, trainingCostCents?, softwareAnnualCents?, maintenancePctOfCapex?, maintenanceAnnualCents?, labourImpact: { fteRemoved, disposition: cash_out|redeploy, rampMonths }, errorReductionPct?, throughputClaim?: { picksPerHour, basis, availabilityPct? }, vendorClaim?, quoteCsv? }] }. Money is integer cents; percentages are percentage points."
          }
        },
        "required": [
          "case"
        ]
      }
    },
    {
      "name": "compare_automation_bids",
      "description": "Normalizes 2–3 competing warehouse-automation bids onto one after-tax cash model — a capex purchase, a lease and a per-unit subscription can be ranked side by side — and returns the NPV ranking at the buyer's hurdle rate, the cost per order and per line for each bid, the point at which the ranking flips as the peak-season premium, the maintenance load or the hurdle rate moves, and the sensitivity grid (volume −10/−20/−30%, capex +15%, maintenance +25%). A ranking that flips inside a scenario is reported as such.",
      "product": "caseproof",
      "inputSchema": {
        "type": "object",
        "properties": {
          "case": {
            "type": "string",
            "description": "The case as a JSON string with 2 or 3 bids in `options` (same shape as audit_automation_case). Each bid may carry the vendor's quote line items as CSV in `quoteCsv`."
          }
        },
        "required": [
          "case"
        ]
      }
    },
    {
      "name": "after_tax_payback",
      "description": "The after-tax payback primitive for one automation bid: payback in months measured from the t=0 outlay, NPV at the buyer's hurdle rate, IRR, the upfront outlay, and the depreciation schedule by tax year (§179 with its phase-out, then bonus depreciation, then straight-line). Use it when you only need the tax timing and the payback, not the full assumption audit.",
      "product": "caseproof",
      "inputSchema": {
        "type": "object",
        "properties": {
          "case": {
            "type": "string",
            "description": "The case as a JSON string with exactly one bid in `options`; the first bid is used (same shape as audit_automation_case)."
          }
        },
        "required": [
          "case"
        ]
      }
    }
  ]
}
