{
  "tools": [
    {
      "name": "calculate_catalog_profit",
      "title": "Catalog Profit Check",
      "page": "https://profitfirstppc.com/tools/catalog-profit-check/",
      "api": {
        "url": "https://profitfirstppc.com/api/catalog-profit-check",
        "method": "POST",
        "operationId": "checkCatalogProfit",
        "specification": "https://profitfirstppc.com/api/openapi.json",
        "responses": {
          "200": {
            "description": "Per-product results and catalog summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "methodVersion": {
                      "type": "string"
                    },
                    "docs": {
                      "type": "string",
                      "format": "uri"
                    },
                    "openapi": {
                      "type": "string",
                      "format": "uri"
                    },
                    "result": {
                      "type": "object",
                      "properties": {
                        "marginToKeep": {
                          "type": "number"
                        },
                        "products": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "index": {
                                "type": "integer"
                              },
                              "name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "no_room_for_ads",
                                  "losing_money",
                                  "over_target",
                                  "room_to_scale",
                                  "thin_margin",
                                  "workable",
                                  "healthy_margin"
                                ]
                              },
                              "profitBeforeAds": {
                                "type": "number"
                              },
                              "breakEvenAcos": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "Profit before ads ÷ price."
                              },
                              "targetAcos": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "maxCpc": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "Price × target ACoS × conversion rate."
                              },
                              "acosToday": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "adProfitPerMonth": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "Ad sales × (break-even ACoS − ACoS today)."
                              },
                              "errors": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              }
                            }
                          }
                        },
                        "summary": {
                          "type": "object",
                          "properties": {
                            "productsChecked": {
                              "type": "integer"
                            },
                            "breakEvenRange": {
                              "type": [
                                "array",
                                "null"
                              ],
                              "items": {
                                "type": "number"
                              }
                            },
                            "noRoomForAds": {
                              "type": "integer"
                            },
                            "losingMoneyOnAds": {
                              "type": "integer"
                            },
                            "adProfitPerMonth": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "monthlyLossOnLosingProducts": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "blendedAcos": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "blendedBreakEvenAcos": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "blendedAcosHidesLosers": {
                              "type": "boolean",
                              "description": "True when the sales-weighted ACoS is under the sales-weighted break-even while some products lose money."
                            }
                          }
                        },
                        "methodVersion": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "More than 500 products"
          },
          "400": {
            "description": "Invalid input. Each error names the field and says what to send.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "field": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from one address. Wait a minute."
          }
        }
      },
      "description": "Which products lose money on ads? Up to 500 products",
      "limits": "Rates are fractions: 0.30 means 30%. Contribution estimates require complete supplied costs; they are not net business profit. Inspect per-product errors even when the batch call succeeds.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "marginToKeep": {
            "type": "number",
            "description": "Fraction, default 0.10."
          },
          "products": {
            "type": "array",
            "maxItems": 500,
            "items": {
              "type": "object",
              "required": [
                "price",
                "fees",
                "cost"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "price": {
                  "type": "number"
                },
                "fees": {
                  "type": "number",
                  "description": "Amazon referral + FBA fees per unit."
                },
                "cost": {
                  "type": "number",
                  "description": "Landed cost per unit."
                },
                "conversionRate": {
                  "type": "number",
                  "description": "Optional ad conversion rate, fraction (0.12). Adds maxCpc."
                },
                "acos": {
                  "type": "number",
                  "description": "Optional ACoS today, fraction (0.22)."
                },
                "adSales": {
                  "type": "number",
                  "description": "Optional ad sales per month, dollars. With acos, adds adProfitPerMonth."
                }
              }
            }
          }
        },
        "description": "Either { marginToKeep, products: [...] } or one product's fields at the top level."
      },
      "example": {
        "marginToKeep": 0.1,
        "products": [
          {
            "name": "Water bottle 750ml",
            "price": 39.99,
            "fees": 11.2,
            "cost": 9.5,
            "conversionRate": 0.12,
            "acos": 0.22,
            "adSales": 18400
          },
          {
            "name": "Bottle 2-pack",
            "price": 24.99,
            "fees": 9.1,
            "cost": 11.4,
            "conversionRate": 0.1,
            "acos": 0.31,
            "adSales": 9200
          }
        ]
      },
      "webmcp": {
        "page": "https://profitfirstppc.com/ai/",
        "requires": "Browser support for document.modelContext.registerTool",
        "execution": "local pure calculation; inputs are not sent over the network; no storage or account changes",
        "maxInputBytes": 2000000,
        "output": "JSON string: {ok:true,result:<calculator result>} or {ok:false,errors:[{field,message}]}. HTTP server metadata is omitted. Some batch tools return row-level errors inside result even when ok is true. The two term tools accept one term per WebMCP call; their HTTP APIs also support batches."
      }
    },
    {
      "name": "review_search_term_negation",
      "title": "When to Negate",
      "page": "https://profitfirstppc.com/tools/when-to-negate/",
      "api": {
        "url": "https://profitfirstppc.com/api/when-to-negate",
        "method": "POST",
        "operationId": "checkWhenToNegateBatch",
        "specification": "https://profitfirstppc.com/api/openapi.json",
        "responses": {
          "200": {
            "description": "One result, or summary + results for a batch",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "tool": {
                          "type": "string"
                        },
                        "methodVersion": {
                          "type": "string"
                        },
                        "docs": {
                          "type": "string",
                          "format": "uri"
                        },
                        "openapi": {
                          "type": "string",
                          "format": "uri"
                        },
                        "result": {
                          "type": "object",
                          "properties": {
                            "searchTerm": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "verdict": {
                              "type": "string",
                              "enum": [
                                "negate",
                                "watch",
                                "early",
                                "profitable",
                                "no_profit_before_ads",
                                "cpc_above_profit"
                              ]
                            },
                            "headline": {
                              "type": "string"
                            },
                            "probabilityIfBreakEven": {
                              "type": [
                                "number",
                                "null"
                              ],
                              "description": "P(X ≤ orders) for X ~ Binomial(clicks, break-even CVR): how often a term that exactly paid for its clicks would look this bad."
                            },
                            "breakEvenCvr": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "observedCvr": {
                              "type": "number"
                            },
                            "cpc": {
                              "type": "number"
                            },
                            "profitPerOrder": {
                              "type": "number"
                            },
                            "maxProfitableCpcAtObservedCvr": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "clicksToBeSure": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "description": "Click count (or additional clicks) reaching the single-test tail-probability threshold with no additional orders and unchanged CPC. Not a posterior certainty or a historical stopping point."
                            },
                            "moreClicksToBeSure": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "description": "Click count (or additional clicks) reaching the single-test tail-probability threshold with no additional orders and unchanged CPC. Not a posterior certainty or a historical stopping point."
                            },
                            "spendToBeSure": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "confidence": {
                              "type": "number"
                            },
                            "notes": {
                              "type": "string"
                            },
                            "methodVersion": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    {
                      "type": "object",
                      "properties": {
                        "tool": {
                          "type": "string"
                        },
                        "methodVersion": {
                          "type": "string"
                        },
                        "docs": {
                          "type": "string",
                          "format": "uri"
                        },
                        "openapi": {
                          "type": "string",
                          "format": "uri"
                        },
                        "summary": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "integer"
                          },
                          "description": "Count of results per verdict (\"error\" for rows with invalid input)."
                        },
                        "results": {
                          "type": "array",
                          "items": {
                            "allOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "searchTerm": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "verdict": {
                                    "type": "string",
                                    "enum": [
                                      "negate",
                                      "watch",
                                      "early",
                                      "profitable",
                                      "no_profit_before_ads",
                                      "cpc_above_profit"
                                    ]
                                  },
                                  "headline": {
                                    "type": "string"
                                  },
                                  "probabilityIfBreakEven": {
                                    "type": [
                                      "number",
                                      "null"
                                    ],
                                    "description": "P(X ≤ orders) for X ~ Binomial(clicks, break-even CVR): how often a term that exactly paid for its clicks would look this bad."
                                  },
                                  "breakEvenCvr": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "observedCvr": {
                                    "type": "number"
                                  },
                                  "cpc": {
                                    "type": "number"
                                  },
                                  "profitPerOrder": {
                                    "type": "number"
                                  },
                                  "maxProfitableCpcAtObservedCvr": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "clicksToBeSure": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "description": "Click count (or additional clicks) reaching the single-test tail-probability threshold with no additional orders and unchanged CPC. Not a posterior certainty or a historical stopping point."
                                  },
                                  "moreClicksToBeSure": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "description": "Click count (or additional clicks) reaching the single-test tail-probability threshold with no additional orders and unchanged CPC. Not a posterior certainty or a historical stopping point."
                                  },
                                  "spendToBeSure": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "confidence": {
                                    "type": "number"
                                  },
                                  "notes": {
                                    "type": "string"
                                  },
                                  "methodVersion": {
                                    "type": "string"
                                  }
                                }
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "index": {
                                    "type": "integer"
                                  },
                                  "errors": {
                                    "type": "array",
                                    "items": {
                                      "type": "object"
                                    }
                                  }
                                }
                              }
                            ]
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "More than 500 terms"
          },
          "400": {
            "description": "Invalid input. Each error names the field and says what to send.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "field": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from one address. Wait a minute."
          }
        }
      },
      "description": "Check one search term, or up to 500",
      "limits": "Single-term binomial evidence under supplied assumptions. Statistical evidence is not certainty or proof of wasted spend.",
      "inputSchema": {
        "type": "object",
        "description": "camelCase or snake_case keys are both accepted.",
        "properties": {
          "searchTerm": {
            "type": "string"
          },
          "clicks": {
            "type": "integer"
          },
          "orders": {
            "type": "integer"
          },
          "spend": {
            "type": "number"
          },
          "profitPerOrder": {
            "type": "number"
          },
          "price": {
            "type": "number"
          },
          "breakEvenAcos": {
            "type": "number"
          },
          "confidence": {
            "type": "number",
            "enum": [
              0.8,
              0.9,
              0.95
            ]
          }
        }
      },
      "example": {
        "clicks": 24,
        "orders": 0,
        "spend": 28.8,
        "profitPerOrder": 19.29
      },
      "webmcp": {
        "page": "https://profitfirstppc.com/ai/",
        "requires": "Browser support for document.modelContext.registerTool",
        "execution": "local pure calculation; inputs are not sent over the network; no storage or account changes",
        "maxInputBytes": 2000000,
        "output": "JSON string: {ok:true,result:<calculator result>} or {ok:false,errors:[{field,message}]}. HTTP server metadata is omitted. Some batch tools return row-level errors inside result even when ok is true. The two term tools accept one term per WebMCP call; their HTTP APIs also support batches."
      }
    },
    {
      "name": "review_exact_match_readiness",
      "title": "Harvest Readiness",
      "page": "https://profitfirstppc.com/tools/harvest-readiness/",
      "api": {
        "url": "https://profitfirstppc.com/api/harvest-readiness",
        "method": "POST",
        "operationId": "checkHarvestReadinessBatch",
        "specification": "https://profitfirstppc.com/api/openapi.json",
        "responses": {
          "200": {
            "description": "One result, or summary + results for a batch",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "tool": {
                          "type": "string"
                        },
                        "methodVersion": {
                          "type": "string"
                        },
                        "docs": {
                          "type": "string",
                          "format": "uri"
                        },
                        "openapi": {
                          "type": "string",
                          "format": "uri"
                        },
                        "result": {
                          "type": "object",
                          "properties": {
                            "searchTerm": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "verdict": {
                              "type": "string",
                              "enum": [
                                "harvest_now",
                                "wait",
                                "do_not_harvest",
                                "no_evidence"
                              ]
                            },
                            "headline": {
                              "type": "string",
                              "description": "One-sentence plain-English answer."
                            },
                            "probabilityProfitable": {
                              "type": "number",
                              "description": "P(true conversion rate > break-even conversion rate) under the beta posterior."
                            },
                            "observedCvr": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "estimatedCvr": {
                              "type": "number",
                              "description": "Posterior mean conversion rate under the uncalibrated baseline weighting."
                            },
                            "breakEvenCvr": {
                              "type": "number",
                              "description": "CPC ÷ profit per order."
                            },
                            "luckShare": {
                              "type": "number",
                              "description": "Deprecated name for the assumed baseline weight, not a measured share of luck. Use priorWeight.",
                              "deprecated": true
                            },
                            "cpc": {
                              "type": "number"
                            },
                            "spend": {
                              "type": "number"
                            },
                            "profitSoFar": {
                              "type": "number"
                            },
                            "expectedProfitPer100Clicks": {
                              "type": "number"
                            },
                            "maxProfitableBid": {
                              "type": "number",
                              "description": "Deprecated name for estimated break-even CPC, rounded to cents. Not an adjusted Amazon bid cap. Use breakEvenCpcAtEstimate.",
                              "deprecated": true
                            },
                            "suggestedStartingBid": {
                              "type": [
                                "number",
                                "null"
                              ],
                              "description": "Review-only base bid for fixed bidding with no placement or other modifiers. Null if below the minimum economic click value; does not guarantee CPC."
                            },
                            "extraClicksNeeded": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "description": "Conditional scenario adding fractional expected orders at the current posterior mean with unchanged CPC. Not a forecast or guaranteed stopping time. Null when the threshold is not reached in 2,000 extra clicks."
                            },
                            "breakEvenAcos": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "explanation": {
                              "type": "string"
                            },
                            "assumptions": {
                              "type": "object"
                            },
                            "methodVersion": {
                              "type": "string"
                            },
                            "priorWeight": {
                              "type": "number",
                              "description": "priorClicks / (priorClicks + clicks): assumed shrinkage weight."
                            },
                            "breakEvenCpcAtEstimate": {
                              "type": "number",
                              "description": "Posterior mean conversion rate times contribution per purchase, before bid adjustments."
                            },
                            "minimumBidExceedsWorth": {
                              "type": "boolean",
                              "description": "True if estimated click value is below the $0.02 minimum base bid. No starting bid is suggested."
                            }
                          }
                        }
                      }
                    },
                    {
                      "type": "object",
                      "properties": {
                        "tool": {
                          "type": "string"
                        },
                        "methodVersion": {
                          "type": "string"
                        },
                        "docs": {
                          "type": "string",
                          "format": "uri"
                        },
                        "openapi": {
                          "type": "string",
                          "format": "uri"
                        },
                        "summary": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "integer"
                          },
                          "description": "Count of results per verdict (\"error\" for rows with invalid input)."
                        },
                        "results": {
                          "type": "array",
                          "items": {
                            "allOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "searchTerm": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "verdict": {
                                    "type": "string",
                                    "enum": [
                                      "harvest_now",
                                      "wait",
                                      "do_not_harvest",
                                      "no_evidence"
                                    ]
                                  },
                                  "headline": {
                                    "type": "string",
                                    "description": "One-sentence plain-English answer."
                                  },
                                  "probabilityProfitable": {
                                    "type": "number",
                                    "description": "P(true conversion rate > break-even conversion rate) under the beta posterior."
                                  },
                                  "observedCvr": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "estimatedCvr": {
                                    "type": "number",
                                    "description": "Posterior mean conversion rate under the uncalibrated baseline weighting."
                                  },
                                  "breakEvenCvr": {
                                    "type": "number",
                                    "description": "CPC ÷ profit per order."
                                  },
                                  "luckShare": {
                                    "type": "number",
                                    "description": "Deprecated name for the assumed baseline weight, not a measured share of luck. Use priorWeight.",
                                    "deprecated": true
                                  },
                                  "cpc": {
                                    "type": "number"
                                  },
                                  "spend": {
                                    "type": "number"
                                  },
                                  "profitSoFar": {
                                    "type": "number"
                                  },
                                  "expectedProfitPer100Clicks": {
                                    "type": "number"
                                  },
                                  "maxProfitableBid": {
                                    "type": "number",
                                    "description": "Deprecated name for estimated break-even CPC, rounded to cents. Not an adjusted Amazon bid cap. Use breakEvenCpcAtEstimate.",
                                    "deprecated": true
                                  },
                                  "suggestedStartingBid": {
                                    "type": [
                                      "number",
                                      "null"
                                    ],
                                    "description": "Review-only base bid for fixed bidding with no placement or other modifiers. Null if below the minimum economic click value; does not guarantee CPC."
                                  },
                                  "extraClicksNeeded": {
                                    "type": [
                                      "integer",
                                      "null"
                                    ],
                                    "description": "Conditional scenario adding fractional expected orders at the current posterior mean with unchanged CPC. Not a forecast or guaranteed stopping time. Null when the threshold is not reached in 2,000 extra clicks."
                                  },
                                  "breakEvenAcos": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "explanation": {
                                    "type": "string"
                                  },
                                  "assumptions": {
                                    "type": "object"
                                  },
                                  "methodVersion": {
                                    "type": "string"
                                  },
                                  "priorWeight": {
                                    "type": "number",
                                    "description": "priorClicks / (priorClicks + clicks): assumed shrinkage weight."
                                  },
                                  "breakEvenCpcAtEstimate": {
                                    "type": "number",
                                    "description": "Posterior mean conversion rate times contribution per purchase, before bid adjustments."
                                  },
                                  "minimumBidExceedsWorth": {
                                    "type": "boolean",
                                    "description": "True if estimated click value is below the $0.02 minimum base bid. No starting bid is suggested."
                                  }
                                }
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "index": {
                                    "type": "integer"
                                  },
                                  "errors": {
                                    "type": "array",
                                    "items": {
                                      "type": "object"
                                    }
                                  }
                                }
                              }
                            ]
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "413": {
            "description": "More than 500 terms"
          },
          "400": {
            "description": "Invalid input. Each error names the field and says what to send.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "field": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from one address. Wait a minute."
          }
        }
      },
      "description": "Send one term's fields, or { defaults, terms: [...] }. Defaults apply to every term unless the term overrides them.",
      "limits": "Single-term, uncalibrated model. Does not estimate incremental profit from harvesting or guarantee future performance.",
      "inputSchema": {
        "type": "object",
        "description": "camelCase or snake_case keys are both accepted.",
        "properties": {
          "searchTerm": {
            "type": "string"
          },
          "clicks": {
            "type": "integer",
            "minimum": 0
          },
          "orders": {
            "type": "integer",
            "minimum": 0
          },
          "spend": {
            "type": "number",
            "description": "Positive spend with positive clicks. If cpc is also supplied, it must agree with spend / clicks within half a cent."
          },
          "cpc": {
            "type": "number"
          },
          "profitPerOrder": {
            "type": "number"
          },
          "baselineCvr": {
            "type": "number"
          },
          "priorClicks": {
            "type": "number"
          },
          "confidence": {
            "type": "number",
            "description": "Model probability threshold, at least 0.5 and below 1. Not empirically calibrated."
          },
          "price": {
            "type": "number"
          }
        }
      },
      "example": {
        "clicks": 60,
        "orders": 12,
        "spend": 72,
        "profitPerOrder": 12,
        "baselineCvr": 0.1
      },
      "webmcp": {
        "page": "https://profitfirstppc.com/ai/",
        "requires": "Browser support for document.modelContext.registerTool",
        "execution": "local pure calculation; inputs are not sent over the network; no storage or account changes",
        "maxInputBytes": 2000000,
        "output": "JSON string: {ok:true,result:<calculator result>} or {ok:false,errors:[{field,message}]}. HTTP server metadata is omitted. Some batch tools return row-level errors inside result even when ok is true. The two term tools accept one term per WebMCP call; their HTTP APIs also support batches."
      }
    },
    {
      "name": "calculate_placement_bids",
      "title": "Placement Bid Calculator",
      "page": "https://profitfirstppc.com/tools/placement-bid-calculator/",
      "api": {
        "url": "https://profitfirstppc.com/api/placement-bids",
        "method": "POST",
        "operationId": "calculatePlacementBids",
        "specification": "https://profitfirstppc.com/api/openapi.json",
        "responses": {
          "200": {
            "description": "Per-placement values and the two bid options",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "methodVersion": {
                      "type": "string"
                    },
                    "docs": {
                      "type": "string",
                      "format": "uri"
                    },
                    "openapi": {
                      "type": "string",
                      "format": "uri"
                    },
                    "result": {
                      "type": "object",
                      "properties": {
                        "targetAcos": {
                          "type": "number"
                        },
                        "breakEvenAcos": {
                          "type": "number"
                        },
                        "strategy": {
                          "type": "string"
                        },
                        "placements": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "placement": {
                                "type": "string"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "no_data",
                                  "too_few_clicks",
                                  "losing_money",
                                  "over_target",
                                  "under_target"
                                ]
                              },
                              "clicks": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "cpc": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "conversionRate": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "acos": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "salesPerClick": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "clickWorth": {
                                "type": [
                                  "number",
                                  "null"
                                ],
                                "description": "Sales per click × target ACoS: the most a click can cost and stay on target."
                              },
                              "mostYouPayToday": {
                                "type": "number",
                                "description": "Keyword bid × (1 + adjustment), × dynamic uplift for updown."
                              },
                              "bidAboveWorth": {
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "adProfitLost": {
                                "type": "number"
                              }
                            }
                          }
                        },
                        "rebalance": {
                          "type": "object",
                          "properties": {
                            "description": {
                              "type": "string"
                            },
                            "keywordBid": {
                              "type": "number"
                            },
                            "keywordBidChange": {
                              "type": "number"
                            },
                            "adjustments": {
                              "type": "object",
                              "properties": {
                                "topOfSearch": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "restOfSearch": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "productPages": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                }
                              },
                              "description": "Placement adjustments in percent. null = too few clicks (under 30) to set."
                            },
                            "cappedPlacements": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "minimumBidHit": {
                              "type": "boolean"
                            }
                          }
                        },
                        "keepKeywordBid": {
                          "type": "object",
                          "properties": {
                            "description": {
                              "type": "string"
                            },
                            "keywordBid": {
                              "type": "number"
                            },
                            "adjustments": {
                              "type": "object",
                              "properties": {
                                "topOfSearch": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "restOfSearch": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                },
                                "productPages": {
                                  "type": [
                                    "integer",
                                    "null"
                                  ]
                                }
                              },
                              "description": "Placement adjustments in percent. null = too few clicks (under 30) to set."
                            },
                            "stillAboveWorth": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "weakestPlacement": {
                          "type": "string"
                        },
                        "strongestPlacement": {
                          "type": "string"
                        },
                        "usablePlacements": {
                          "type": "integer"
                        },
                        "methodVersion": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input. Each error names the field and says what to send.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "field": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from one address. Wait a minute."
          }
        }
      },
      "description": "A click in each placement is worth (sales ÷ clicks) × target ACoS. Returns two options: rebalance (the weakest placement sets the keyword bid) and keep today's keyword bid. Placements under 30 clicks don't set bids. Docs: https://profitfirstppc.com/tools/placement-bid-calculator/",
      "limits": "Rates are fractions. Low-evidence placements and minimum-bid exceptions need review; no Amazon settings are changed.",
      "inputSchema": {
        "type": "object",
        "required": [
          "breakEvenAcos",
          "keywordBid",
          "placements"
        ],
        "properties": {
          "breakEvenAcos": {
            "type": "number",
            "description": "Fraction (0.482) or percent (48.2)."
          },
          "marginToKeep": {
            "type": "number",
            "description": "Points of margin to keep after ads; fraction (0.10) or percent (10). Default 0.10. Target ACoS = breakEvenAcos − marginToKeep."
          },
          "keywordBid": {
            "type": "number",
            "description": "Typical keyword bid in the campaign, in dollars."
          },
          "strategy": {
            "type": "string",
            "enum": [
              "fixed",
              "down",
              "updown"
            ],
            "default": "fixed",
            "description": "Campaign bidding strategy: fixed bids, dynamic down only, or dynamic up and down."
          },
          "placements": {
            "type": "object",
            "properties": {
              "topOfSearch": {
                "type": "object",
                "properties": {
                  "adjustment": {
                    "type": "number",
                    "description": "Placement adjustment today, in percent as shown in the console (50 = +50%)."
                  },
                  "clicks": {
                    "type": "number"
                  },
                  "spend": {
                    "type": "number"
                  },
                  "orders": {
                    "type": "number"
                  },
                  "sales": {
                    "type": "number"
                  }
                }
              },
              "restOfSearch": {
                "type": "object",
                "properties": {
                  "adjustment": {
                    "type": "number",
                    "description": "Placement adjustment today, in percent as shown in the console (50 = +50%)."
                  },
                  "clicks": {
                    "type": "number"
                  },
                  "spend": {
                    "type": "number"
                  },
                  "orders": {
                    "type": "number"
                  },
                  "sales": {
                    "type": "number"
                  }
                }
              },
              "productPages": {
                "type": "object",
                "properties": {
                  "adjustment": {
                    "type": "number",
                    "description": "Placement adjustment today, in percent as shown in the console (50 = +50%)."
                  },
                  "clicks": {
                    "type": "number"
                  },
                  "spend": {
                    "type": "number"
                  },
                  "orders": {
                    "type": "number"
                  },
                  "sales": {
                    "type": "number"
                  }
                }
              }
            }
          }
        }
      },
      "example": {
        "breakEvenAcos": 0.482,
        "marginToKeep": 0.1,
        "keywordBid": 1.0,
        "strategy": "fixed",
        "placements": {
          "topOfSearch": {
            "adjustment": 50,
            "clicks": 400,
            "spend": 560,
            "orders": 60,
            "sales": 2400
          },
          "restOfSearch": {
            "adjustment": 0,
            "clicks": 300,
            "spend": 300,
            "orders": 24,
            "sales": 960
          },
          "productPages": {
            "adjustment": 0,
            "clicks": 250,
            "spend": 200,
            "orders": 8,
            "sales": 320
          }
        }
      },
      "webmcp": {
        "page": "https://profitfirstppc.com/ai/",
        "requires": "Browser support for document.modelContext.registerTool",
        "execution": "local pure calculation; inputs are not sent over the network; no storage or account changes",
        "maxInputBytes": 2000000,
        "output": "JSON string: {ok:true,result:<calculator result>} or {ok:false,errors:[{field,message}]}. HTTP server metadata is omitted. Some batch tools return row-level errors inside result even when ok is true. The two term tools accept one term per WebMCP call; their HTTP APIs also support batches."
      }
    },
    {
      "name": "review_search_term_report",
      "title": "Search Term Report Checker",
      "page": "https://profitfirstppc.com/tools/search-term-report-checker/",
      "api": {
        "url": "https://profitfirstppc.com/api/search-term-report",
        "method": "POST",
        "operationId": "reviewSearchTermReport",
        "specification": "https://profitfirstppc.com/api/openapi.json",
        "responses": {
          "200": {
            "description": "Analysis with totals, contextual terms, categories, coverage, assumptions and method version"
          },
          "400": {
            "description": "Invalid or inconsistent normalized data or options"
          },
          "413": {
            "description": "Too many rows"
          },
          "429": {
            "description": "Rate limit reached"
          }
        }
      },
      "description": "Pure report analysis. No file upload or storage. Optional sales must use the same purchase attribution window. One currency per request. Orders greater than clicks remain descriptive and skip probability models. Bulk exact-keyword inventory is browser-only. Zero-order spend is not confirmed waste.",
      "limits": "At most 500 normalized rows. Zero-order spend is not confirmed waste. Same report context and attribution definitions are caller prerequisites.",
      "inputSchema": {
        "type": "object",
        "required": [
          "rows"
        ],
        "properties": {
          "rows": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "items": {
              "type": "object",
              "required": [
                "term",
                "clicks",
                "orders",
                "spend"
              ],
              "properties": {
                "term": {
                  "type": "string",
                  "maxLength": 2000
                },
                "campaign": {
                  "type": "string",
                  "maxLength": 2000
                },
                "campaignId": {
                  "type": "string",
                  "maxLength": 2000
                },
                "adGroup": {
                  "type": "string",
                  "maxLength": 2000
                },
                "adGroupId": {
                  "type": "string",
                  "maxLength": 2000
                },
                "product": {
                  "type": "string",
                  "maxLength": 2000
                },
                "matchType": {
                  "type": "string",
                  "maxLength": 2000
                },
                "targeting": {
                  "type": "string",
                  "maxLength": 2000
                },
                "currency": {
                  "type": "string",
                  "maxLength": 2000
                },
                "start": {
                  "type": "string",
                  "maxLength": 2000
                },
                "end": {
                  "type": "string",
                  "maxLength": 2000
                },
                "clicks": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 1000000000
                },
                "orders": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 1000000000
                },
                "spend": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000000000000
                },
                "sales": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 1000000000000
                }
              }
            }
          },
          "options": {
            "type": "object",
            "properties": {
              "profitPerOrder": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "targetAcos": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "minClicks": {
                "type": "integer",
                "minimum": 1
              },
              "minOrders": {
                "type": "integer",
                "minimum": 1
              },
              "minSpend": {
                "type": "number",
                "minimum": 0
              },
              "globalComparable": {
                "type": "boolean",
                "description": "Explicitly confirm comparable profit per purchase across groups."
              },
              "protectedPhrases": {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "type": "string",
                  "maxLength": 2000
                }
              },
              "contexts": {
                "type": "object",
                "additionalProperties": {
                  "type": "number",
                  "exclusiveMinimum": 0
                },
                "description": "Profit per purchase by contextual group key returned in result.groups."
              }
            },
            "additionalProperties": false
          }
        }
      },
      "example": {
        "rows": [
          {
            "term": "water bottle",
            "clicks": 20,
            "orders": 0,
            "spend": 24,
            "sales": 0,
            "campaign": "Discovery",
            "adGroup": "Bottle",
            "matchType": "BROAD"
          }
        ]
      },
      "webmcp": {
        "page": "https://profitfirstppc.com/ai/",
        "requires": "Browser support for document.modelContext.registerTool",
        "execution": "local pure calculation; inputs are not sent over the network; no storage or account changes",
        "maxInputBytes": 2000000,
        "output": "JSON string: {ok:true,result:<calculator result>} or {ok:false,errors:[{field,message}]}. HTTP server metadata is omitted. Some batch tools return row-level errors inside result even when ok is true. The two term tools accept one term per WebMCP call; their HTTP APIs also support batches."
      }
    },
    {
      "name": "explain_acos_change",
      "title": "ACoS Change Explainer",
      "page": "https://profitfirstppc.com/tools/acos-change-explainer/",
      "api": {
        "url": "https://profitfirstppc.com/api/acos-change-explainer",
        "method": "POST",
        "operationId": "acoschangeexplainerReview",
        "specification": "https://profitfirstppc.com/api/openapi.json",
        "responses": {
          "200": {
            "description": "Tool result or usage metadata",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "description": "Unsupported method"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      },
      "description": "Six-order averaged arithmetic bridge for ACoS change. Same scope and attribution definitions must be checked by the caller. Not a causal diagnosis.",
      "limits": "An arithmetic allocation, not a causal diagnosis. Compare consistent scope, currency and attribution definitions.",
      "inputSchema": {
        "type": "object",
        "required": [
          "before",
          "after"
        ],
        "properties": {
          "before": {
            "type": "object",
            "required": [
              "clicks",
              "spend",
              "orders",
              "sales"
            ],
            "additionalProperties": false,
            "properties": {
              "clicks": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1000000000.0
              },
              "spend": {
                "type": "number",
                "minimum": 0,
                "maximum": 1000000000000.0
              },
              "orders": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1000000000.0
              },
              "sales": {
                "type": "number",
                "minimum": 0,
                "maximum": 1000000000000.0
              }
            }
          },
          "after": {
            "type": "object",
            "required": [
              "clicks",
              "spend",
              "orders",
              "sales"
            ],
            "additionalProperties": false,
            "properties": {
              "clicks": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1000000000.0
              },
              "spend": {
                "type": "number",
                "minimum": 0,
                "maximum": 1000000000000.0
              },
              "orders": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1000000000.0
              },
              "sales": {
                "type": "number",
                "minimum": 0,
                "maximum": 1000000000000.0
              }
            }
          }
        }
      },
      "example": {
        "before": {
          "clicks": 1000,
          "spend": 1000,
          "orders": 100,
          "sales": 5000
        },
        "after": {
          "clicks": 1000,
          "spend": 1200,
          "orders": 80,
          "sales": 3600
        }
      },
      "webmcp": {
        "page": "https://profitfirstppc.com/ai/",
        "requires": "Browser support for document.modelContext.registerTool",
        "execution": "local pure calculation; inputs are not sent over the network; no storage or account changes",
        "maxInputBytes": 2000000,
        "output": "JSON string: {ok:true,result:<calculator result>} or {ok:false,errors:[{field,message}]}. HTTP server metadata is omitted. Some batch tools return row-level errors inside result even when ok is true. The two term tools accept one term per WebMCP call; their HTTP APIs also support batches."
      }
    },
    {
      "name": "review_report_comparability",
      "title": "Amazon Report Mismatch Checker",
      "page": "https://profitfirstppc.com/tools/amazon-report-mismatch-checker/",
      "api": {
        "url": "https://profitfirstppc.com/api/amazon-report-mismatch-checker",
        "method": "POST",
        "operationId": "amazonreportmismatchcheckerReview",
        "specification": "https://profitfirstppc.com/api/openapi.json",
        "responses": {
          "200": {
            "description": "Tool result or usage metadata",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "405": {
            "description": "Unsupported method"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      },
      "description": "Comparison-basis checklist and currency-compatible numeric gap. Not order-level reconciliation or an exact organic revenue calculation.",
      "limits": "A comparison-basis checklist, not order-level reconciliation or exact organic revenue.",
      "inputSchema": {
        "type": "object",
        "required": [
          "adsSales",
          "retailSales"
        ],
        "properties": {
          "adsSales": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "retailSales": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000000000.0
          },
          "adsCurrency": {
            "type": "string",
            "pattern": "^[A-Za-z]{3}$"
          },
          "retailCurrency": {
            "type": "string",
            "pattern": "^[A-Za-z]{3}$"
          },
          "adsStart": {
            "type": "string",
            "format": "date"
          },
          "adsEnd": {
            "type": "string",
            "format": "date"
          },
          "retailStart": {
            "type": "string",
            "format": "date"
          },
          "retailEnd": {
            "type": "string",
            "format": "date"
          },
          "dateBasis": {
            "type": "string",
            "enum": [
              "unknown",
              "interaction",
              "conversion"
            ]
          },
          "scope": {
            "type": "string",
            "enum": [
              "unknown",
              "same",
              "different"
            ]
          },
          "settled": {
            "type": "string",
            "enum": [
              "unknown",
              "yes",
              "no"
            ]
          }
        }
      },
      "example": {
        "adsSales": 12000,
        "retailSales": 10000,
        "adsCurrency": "USD",
        "retailCurrency": "USD",
        "adsStart": "2026-08-01",
        "adsEnd": "2026-08-14",
        "retailStart": "2026-08-01",
        "retailEnd": "2026-08-14",
        "dateBasis": "interaction",
        "scope": "unknown",
        "settled": "yes"
      },
      "webmcp": {
        "page": "https://profitfirstppc.com/ai/",
        "requires": "Browser support for document.modelContext.registerTool",
        "execution": "local pure calculation; inputs are not sent over the network; no storage or account changes",
        "maxInputBytes": 2000000,
        "output": "JSON string: {ok:true,result:<calculator result>} or {ok:false,errors:[{field,message}]}. HTTP server metadata is omitted. Some batch tools return row-level errors inside result even when ok is true. The two term tools accept one term per WebMCP call; their HTTP APIs also support batches."
      }
    }
  ]
}
