Skip to main content
Glama

Recommend a stack from requirements

plan_stack
Read-only

Given confirmed requirements as capability ids, recommend a vendor per category with a runner-up, requirement fit, cost now, cost at forecast scale, year-one cost after perks, cost cliffs, trade-offs and blockers. Use recommend_stack instead when you only have a plain-language description. Example: {"mau_now":5000,"mau_forecast":20000,"profile_id":"booking_marketplace","requirements":[{"capability":"auth.google"},{"capability":"payments.merchant_of_record"}],"founder":{"gateways":["mercury"]}}. How to present the result: show the stack table (pick and runner-up per category, monthly cost now and at forecast) and the totals. For each price give its source's verified date, or say it is unverified seed data. Show every caveat word for word; never round, merge or drop one. Mention requirement gaps, blockers and trade-offs, and each pick's "weighed" note when a cheaper vendor lost on lock-in, setup work or seed prices. Offer the alternatives (cheapest, fewest vendors) with what each changes, its cost and its share_url. List not_planned as needed but not in the totals. Ask the questions (most expensive first) and re-plan with the answers in the argument each names (per_user, revenue_per_mau_usd, builder_profile); when the user says an assumption is right, add the question id to confirmed so it isn't asked again. On a saved stack, keep answers with update_saved_stack (answers). Link share_url so the user can open the full result on kongreviews.com. Do not add vendors or prices that are not in the result.

Input Schema

NameRequiredDescriptionDefault
needsNoNeeds the plan should list even though they are not priced (directory category ids such as maps, vector_db, speech), from recommend_stack's requirements_read.needs.
seatsNoTeam members on per-seat plans. Default 1.
answersNoInterview answers by question id, each an option id from compare_architectures, e.g. {"server":"dynamic","logins":"consumers","threat":"public","ops":"managed"}.
founderNoOptional company details used only to find startup perks.
mau_nowNoMonthly active users now. Without it, a new product of the app type at launch.
rankingNobalanced (default): monthly cost plus a small monthly weight for lock-in, setup work before first use and unverified seed prices, so a slightly cheaper vendor that is hard to leave or slow to set up can lose. cost: price alone. simplest: fewest vendors and least setup (one vendor covering several categories wins unless the others are much cheaper). Each plan lists the other two as alternatives when their picks differ.
accountsNoFor a business product counted in customers ("50 clinics now, 500 next year"): customers now and at the forecast, and people using it at each (default 10). Users are worked out from these when mau_now is not given.
app_typeNoKind of app, from Product Hunt's categories: productivity, engineering_development, design_creative, finance, marketing_sales, data_analysis, platforms, no_code, product_addons, llms, ai_agents, voice_ai, social_community, health_fitness, family, lifestyle, web3, ecommerce, travel, physical_products, booking_marketplace, content_site, ios_on_device. Sets the usage profile and, when users are not given, typical users at launch and after the forecast period.
per_userNoUsage per active user a month, e.g. {"sms": 2, "file_storage_gb": 0.2, "ai_input_ktok": 30}. Replaces the profile and the filled-in defaults for those units; a plan's questions say which unit each answer sets. Units: mau, seat, request_million, bandwidth_gb, db_storage_gb, egress_gb, email, event, error_event, compute_hour, revenue_usd, transaction, ai_input_ktok, ai_output_ktok, kv_read, kv_write, ci_hour, file_storage_gb, file_egress_gb, file_write, file_read, video_min_stored, video_min_delivered, sms, job_run, search_request, search_record.
confirmedNoIds of questions whose assumption the user confirmed as right (e.g. ["region", "builder"]), so the plan stops asking them. A question answered with a figure goes in its own argument instead (per_user, revenue_per_mau_usd…).
platformsNoWhere the app runs; with architecture, a phone-only app leaves out web hosting.
build_toolNoThe build tool the user named, as a coding vendor id (lovable, bolt, replit, base44, v0, cursor, claude-code, github-copilot…): the plan uses it. An app builder that hosts the app and runs its database and sign-in (Lovable, Bolt, Replit, Base44) covers those, so they are not planned separately.
categoriesNo
per_1k_mauNoOverride usage per 1,000 MAU. Units: mau, seat, request_million, bandwidth_gb, db_storage_gb, egress_gb, email, event, error_event, compute_hour, revenue_usd, transaction, ai_input_ktok, ai_output_ktok, kv_read, kv_write, ci_hour, file_storage_gb, file_egress_gb, file_write, file_read, video_min_stored, video_min_delivered, sms, job_run, search_request, search_record.
profile_idNoUsage profile: b2b_saas (default), consumer_app, booking_marketplace, content_site, ios_on_device. Defaults to the app type's profile.
apply_perksNo
task_intentNoWhat the user is trying to do, in a few words, e.g. "pick a stack for an MVP" or "cost section for an investor deck". No names or contact details.
architectureNoPlan with only this architecture's vendors, from compare_architectures (e.g. serverless_nextjs, cloudflare_edge, vps_cloudflare).
mau_forecastNo
requirementsNo
builder_profileNoWho builds it. developer picks an AI coding agent, non_developer an app builder (and counts setup work double). Given without categories, the plan adds the build tool (coding).
exclude_vendorsNo
forecast_monthsNo
budget_monthly_usdNo
output_destinationNoWhere the answer goes. chat (default): summary for the conversation. document: a section ready to paste into a PRD. code: adds npm packages and environment variable names for each pick.
revenue_per_mau_usdNoAverage monthly revenue per active user (for payment fees).
transactions_per_mauNoPayments per active user per month.

Output Schema

NameRequiredDescriptionDefault
dataYesThe tool result. Its shape depends on the tool.
staleYes
caveatsYesShow to the user word for word.
sourcesYes
confidenceYes
assumptionsYesUsage and pricing assumptions behind the numbers.
disclosuresYesAlways includes the neutrality note: no vendor pays for a place in the answer. Link its url when you mention how Kong Reviews is paid.
generated_atYes
engine_versionYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed21 schema fields changed
    • addedInput schema / properties / accounts
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "For a business product counted in customers (\"50 clinics now, 500 next year\"): customers now and at the forecast, and people using it at each (default 10). Users are worked out from these when mau_now is not given.",
      +  "properties": {
      +    "forecast": {
      +      "maximum": 10000000,
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "now": {
      +      "maximum": 10000000,
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "users_per_account": {
      +      "maximum": 100000,
      +      "minimum": 1,
      +      "type": "number"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / build_tool
      Added value: +{
      +  "description": "The build tool the user named, as a coding vendor id (lovable, bolt, replit, base44, v0, cursor, claude-code, github-copilot…): the plan uses it. An app builder that hosts the app and runs its database and sign-in (Lovable, Bolt, Replit, Base44) covers those, so they are not planned separately.",
      +  "maxLength": 40,
      +  "type": "string"
      +}
    • addedInput schema / properties / builder_profile
      Added value: +{
      +  "description": "Who builds it. developer picks an AI coding agent, non_developer an app builder (and counts setup work double). Given without categories, the plan adds the build tool (coding).",
      +  "enum": [
      +    "developer",
      +    "non_developer",
      +    "unknown"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / categories / items / enum
      Previous value: -[
      -  "hosting",
      -  "database",
      -  "auth",
      -  "email",
      -  "payments",
      -  "observability",
      -  "ai",
      -  "edge",
      -  "app_store",
      -  "coding"
      -]New value: +[
      +  "hosting",
      +  "database",
      +  "auth",
      +  "email",
      +  "payments",
      +  "observability",
      +  "ai",
      +  "edge",
      +  "app_store",
      +  "coding",
      +  "storage",
      +  "video",
      +  "sms",
      +  "push",
      +  "jobs",
      +  "search"
      +]
    • addedInput schema / properties / confirmed
      Added value: +{
      +  "description": "Ids of questions whose assumption the user confirmed as right (e.g. [\"region\", \"builder\"]), so the plan stops asking them. A question answered with a figure goes in its own argument instead (per_user, revenue_per_mau_usd…).",
      +  "items": {
      +    "maxLength": 40,
      +    "type": "string"
      +  },
      +  "maxItems": 20,
      +  "type": "array"
      +}
    • addedInput schema / properties / needs
      Added value: +{
      +  "description": "Needs the plan should list even though they are not priced (directory category ids such as maps, vector_db, speech), from recommend_stack's requirements_read.needs.",
      +  "items": {
      +    "properties": {
      +      "id": {
      +        "maxLength": 40,
      +        "type": "string"
      +      },
      +      "label": {
      +        "maxLength": 80,
      +        "type": "string"
      +      },
      +      "source": {
      +        "maxLength": 500,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  "maxItems": 20,
      +  "type": "array"
      +}
    • changedInput schema / properties / per_1k_mau / description
      Previous value: -"Override usage per 1,000 MAU. Units: mau, seat, request_million, bandwidth_gb, db_storage_gb, egress_gb, email, event, error_event, compute_hour, revenue_usd, transaction, ai_input_ktok, ai_output_ktok, kv_read, kv_write, ci_hour."New value: +"Override usage per 1,000 MAU. Units: mau, seat, request_million, bandwidth_gb, db_storage_gb, egress_gb, email, event, error_event, compute_hour, revenue_usd, transaction, ai_input_ktok, ai_output_ktok, kv_read, kv_write, ci_hour, file_storage_gb, file_egress_gb, file_write, file_read, video_min_stored, video_min_delivered, sms, job_run, search_request, search_record."
    • addedInput schema / properties / per_1k_mau / properties / file_egress_gb
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / file_read
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / file_storage_gb
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / file_write
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / job_run
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / search_record
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / search_request
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / sms
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / video_min_delivered
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_1k_mau / properties / video_min_stored
      Added value: +{
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / per_user
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Usage per active user a month, e.g. {\"sms\": 2, \"file_storage_gb\": 0.2, \"ai_input_ktok\": 30}. Replaces the profile and the filled-in defaults for those units; a plan's questions say which unit each answer sets. Units: mau, seat, request_million, bandwidth_gb, db_storage_gb, egress_gb, email, event, error_event, compute_hour, revenue_usd, transaction, ai_input_ktok, ai_output_ktok, kv_read, kv_write, ci_hour, file_storage_gb, file_egress_gb, file_write, file_read, video_min_stored, video_min_delivered, sms, job_run, search_request, search_record.",
      +  "properties": {
      +    "ai_input_ktok": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "ai_output_ktok": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "bandwidth_gb": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "ci_hour": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "compute_hour": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "db_storage_gb": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "egress_gb": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "email": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "error_event": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "event": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "file_egress_gb": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "file_read": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "file_storage_gb": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "file_write": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "job_run": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "kv_read": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "kv_write": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "mau": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "request_million": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "revenue_usd": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "search_record": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "search_request": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "seat": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "sms": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "transaction": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "video_min_delivered": {
      +      "minimum": 0,
      +      "type": "number"
      +    },
      +    "video_min_stored": {
      +      "minimum": 0,
      +      "type": "number"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / ranking
      Added value: +{
      +  "description": "balanced (default): monthly cost plus a small monthly weight for lock-in, setup work before first use and unverified seed prices, so a slightly cheaper vendor that is hard to leave or slow to set up can lose. cost: price alone. simplest: fewest vendors and least setup (one vendor covering several categories wins unless the others are much cheaper). Each plan lists the other two as alternatives when their picks differ.",
      +  "enum": [
      +    "balanced",
      +    "cost",
      +    "simplest"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / requirements / items / properties / categories / items / enum
      Previous value: -[
      -  "hosting",
      -  "database",
      -  "auth",
      -  "email",
      -  "payments",
      -  "observability",
      -  "ai",
      -  "edge",
      -  "app_store",
      -  "coding"
      -]New value: +[
      +  "hosting",
      +  "database",
      +  "auth",
      +  "email",
      +  "payments",
      +  "observability",
      +  "ai",
      +  "edge",
      +  "app_store",
      +  "coding",
      +  "storage",
      +  "video",
      +  "sms",
      +  "push",
      +  "jobs",
      +  "search"
      +]
    • addedOutput schema / properties / disclosures / description
      Added value: +"Always includes the neutrality note: no vendor pays for a place in the answer. Link its url when you mention how Kong Reviews is paid."
  2. Changed3 schema fields changed
    • addedInput schema / properties / answers
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Interview answers by question id, each an option id from compare_architectures, e.g. {\"server\":\"dynamic\",\"logins\":\"consumers\",\"threat\":\"public\",\"ops\":\"managed\"}.",
      +  "properties": {
      +    "background": {
      +      "enum": [
      +        "none",
      +        "jobs",
      +        "realtime"
      +      ],
      +      "type": "string"
      +    },
      +    "data": {
      +      "enum": [
      +        "little",
      +        "lots"
      +      ],
      +      "type": "string"
      +    },
      +    "logins": {
      +      "enum": [
      +        "none",
      +        "consumers",
      +        "teams",
      +        "enterprise"
      +      ],
      +      "type": "string"
      +    },
      +    "media": {
      +      "enum": [
      +        "none",
      +        "images",
      +        "video"
      +      ],
      +      "type": "string"
      +    },
      +    "ops": {
      +      "enum": [
      +        "managed",
      +        "some",
      +        "admin"
      +      ],
      +      "type": "string"
      +    },
      +    "sensitivity": {
      +      "enum": [
      +        "low",
      +        "eu",
      +        "business",
      +        "health"
      +      ],
      +      "type": "string"
      +    },
      +    "server": {
      +      "enum": [
      +        "static",
      +        "mixed",
      +        "dynamic",
      +        "none",
      +        "proxy",
      +        "full"
      +      ],
      +      "type": "string"
      +    },
      +    "threat": {
      +      "enum": [
      +        "low",
      +        "public",
      +        "target"
      +      ],
      +      "type": "string"
      +    },
      +    "uptime": {
      +      "enum": [
      +        "fine",
      +        "costly",
      +        "critical"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / architecture
      Added value: +{
      +  "description": "Plan with only this architecture's vendors, from compare_architectures (e.g. serverless_nextjs, cloudflare_edge, vps_cloudflare).",
      +  "enum": [
      +    "static_cdn",
      +    "frontend_baas",
      +    "serverless_nextjs",
      +    "cloudflare_edge",
      +    "managed_containers",
      +    "single_vps",
      +    "vps_cloudflare",
      +    "firebase",
      +    "on_device"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / platforms
      Added value: +{
      +  "description": "Where the app runs; with architecture, a phone-only app leaves out web hosting.",
      +  "items": {
      +    "enum": [
      +      "web",
      +      "ios",
      +      "android",
      +      "desktop"
      +    ],
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  3. Changed6 schema fields changed
    • addedInput schema / properties / app_type
      Added value: +{
      +  "description": "Kind of app, from Product Hunt's categories: productivity, engineering_development, design_creative, finance, marketing_sales, data_analysis, platforms, no_code, product_addons, llms, ai_agents, voice_ai, social_community, health_fitness, family, lifestyle, web3, ecommerce, travel, physical_products, booking_marketplace, content_site, ios_on_device. Sets the usage profile and, when users are not given, typical users at launch and after the forecast period.",
      +  "type": "string"
      +}
    • changedInput schema / properties / categories / items / enum
      Previous value: -[
      -  "hosting",
      -  "database",
      -  "auth",
      -  "email",
      -  "payments",
      -  "observability",
      -  "ai",
      -  "edge",
      -  "app_store"
      -]New value: +[
      +  "hosting",
      +  "database",
      +  "auth",
      +  "email",
      +  "payments",
      +  "observability",
      +  "ai",
      +  "edge",
      +  "app_store",
      +  "coding"
      +]
    • addedInput schema / properties / mau_now / description
      Added value: +"Monthly active users now. Without it, a new product of the app type at launch."
    • changedInput schema / properties / profile_id / description
      Previous value: -"Usage profile: b2b_saas (default), consumer_app, booking_marketplace, content_site."New value: +"Usage profile: b2b_saas (default), consumer_app, booking_marketplace, content_site, ios_on_device. Defaults to the app type's profile."
    • changedInput schema / properties / requirements / items / properties / categories / items / enum
      Previous value: -[
      -  "hosting",
      -  "database",
      -  "auth",
      -  "email",
      -  "payments",
      -  "observability",
      -  "ai",
      -  "edge",
      -  "app_store"
      -]New value: +[
      +  "hosting",
      +  "database",
      +  "auth",
      +  "email",
      +  "payments",
      +  "observability",
      +  "ai",
      +  "edge",
      +  "app_store",
      +  "coding"
      +]
    • removedInput schema / required
      Removed value: -[
      -  "mau_now"
      -]
  4. First observed

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a read-only, closed-world planning call, yet the description still adds real behavioral constraints: never invent vendors or prices, reproduce caveats verbatim, flag unverified seed data, and link share_url so results live on kongreviews.com. The one gap is that it doesn't say anything about cost or latency for a 27-parameter computation over pricing data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the sibling exclusion are front-loaded, and nearly every sentence is actionable. It is still a dense single block that mixes invocation guidance with output presentation rules and a raw JSON example, which makes it harder to scan than a short segmented description would be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 27-parameter planning tool with nested usage overrides, an output schema already present, and a multi-turn interview workflow, the description covers what an agent needs: the input contract, the ask-then-re-plan loop, how to record confirmations, and what to surface from the result. Nothing essential to calling it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 74%, so most parameters are self-documenting, but the description adds cross-parameter semantics the schema cannot express: interview answers are re-submitted into 'the argument each names (per_user, revenue_per_mau_usd, builder_profile)' and confirmed question ids go into `confirmed` so they aren't re-asked. The embedded example call anchors the requirements/founder/mau_now combination. It does not touch many of the pricing-override objects, but those are covered in schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource plus the full output shape: 'recommend a vendor per category with a runner-up, requirement fit, cost now, cost at forecast scale, year-one cost after perks, cost cliffs, trade-offs and blockers.' It explicitly separates itself from the closest sibling, recommend_stack, by input type (confirmed capability ids vs. plain-language description).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-not with the alternative named: 'Use recommend_stack instead when you only have a plain-language description.' It also routes downstream work to specific siblings with argument names ('keep answers with update_saved_stack (answers)'), so the agent knows the handoff points as well as the entry condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources