Skip to main content
← Back to Articles

Building an MCP Server That Surfaces Your Product Catalog to AI Agents

Step-by-step guide to building an MCP server that exposes your product catalog, pricing, and availability to AI agents — enabling agent-to-agent discovery and autonomous purchasing.

By Web MCP Guide•April 21, 2026•6 min read


Building an MCP Server That Surfaces Your Product Catalog to AI Agents

> TL;DR
> - An MCP server that exposes your product catalog lets AI agents query, evaluate, and purchase your products programmatically
> - Covers tools for product search, pricing lookup, availability check, and trial/purchase initiation
> - Works alongside Schema.org — schema handles passive discovery, MCP handles active interaction
> - Pair with schema injection for full agent-to-agent coverage →

Updated: April 21, 2026

---

Why Your Product Catalog Needs an MCP Server

Schema.org structured data handles the passive discovery layer — LLMs index your schema and surface your products in recommendations. But as agentic commerce matures, AI agents need more than a static snapshot of your catalog. They need live, queryable access.

A buyer's agent asking "does this tool have a team plan under $50/month with SSO?" needs a real-time answer — not a cached schema record from two weeks ago. An agent initiating a trial signup needs to invoke an action, not just read a description.

That's what an MCP server provides: a standardized, AI-native interface to your live product data and business logic.

---

The Minimum Viable Product Catalog MCP Server

Here's a production-ready MCP server in TypeScript that exposes four core tools for product discovery and purchase:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
name: "product-catalog",
version: "1.0.0",
description: "Live product catalog, pricing, and trial initiation for YourProduct"
});

// ── Tool 1: Get all products / plans ──────────────────────────────────────
server.tool(
"list_products",
"Returns all available products, plans, and current pricing",
{},
async () => {
const products = await fetchProductCatalog(); // your DB/API call
return {
content: [{
type: "text",
text: JSON.stringify(products, null, 2)
}]
};
}
);

// ── Tool 2: Check specific feature availability ───────────────────────────
server.tool(
"check_feature",
"Checks if a specific feature is available on a given plan",
{
feature: z.string().describe("The feature name to check (e.g. 'SSO', 'API access', 'webhooks')"),
plan: z.string().optional().describe("The plan name to check (e.g. 'Pro', 'Business'). Omit to check all plans.")
},
async ({ feature, plan }) => {
const result = await checkFeatureAvailability(feature, plan);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}]
};
}
);

// ── Tool 3: Start a free trial ────────────────────────────────────────────
server.tool(
"start_trial",
"Initiates a free trial. Returns a signup confirmation and onboarding link.",
{
email: z.string().email().describe("The user's email address"),
plan: z.string().optional().describe("The plan to trial. Defaults to Pro."),
company: z.string().optional().describe("Company name"),
use_case: z.string().optional().describe("Primary use case — helps personalize onboarding")
},
async ({ email, plan, company, use_case }) => {
const trial = await createTrialAccount({ email, plan, company, use_case });
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: Trial started for ${email},
plan: trial.plan,
login_url: trial.loginUrl,
expires_at: trial.expiresAt
}, null, 2)
}]
};
}
);

// ── Tool 4: Get integration details ──────────────────────────────────────
server.tool(
"get_integration",
"Returns details about a specific integration — setup steps, plans it's available on, and documentation link",
{
name: z.string().describe("Integration name (e.g. 'Slack', 'GitHub', 'Salesforce')")
},
async ({ name }) => {
const integration = await getIntegrationDetails(name);
return {
content: [{
type: "text",
text: integration
? JSON.stringify(integration, null, 2)
: Integration '${name}' not found. Available integrations: Slack, GitHub, Salesforce, HubSpot, Zapier.
}]
};
}
);

// ── Start server ──────────────────────────────────────────────────────────
const transport = new StdioServerTransport();
await server.connect(transport);

---

Data Structures to Return

Make your tool responses structured and specific. AI agents reason better with consistent, well-labeled data:

// list_products response shape
const catalogResponse = {
products: [
{
name: "Starter",
price: 0,
price_unit: "per month",
description: "Free forever. Up to 3 users, core features, 5GB storage.",
features: ["Core features", "5GB storage", "Email support"],
max_users: 3,
free_trial: true,
trial_days: null, // permanent free tier
cta: "Get started free — no credit card"
},
{
name: "Pro",
price: 29,
price_unit: "per month",
price_annual: 24,
price_annual_unit: "per month, billed annually",
description: "For growing teams. Unlimited users, all integrations, priority support.",
features: ["Everything in Starter", "Unlimited users", "All integrations", "API access", "Priority support"],
max_users: null, // unlimited
free_trial: true,
trial_days: 14,
cta: "Start 14-day free trial"
},
{
name: "Enterprise",
price: null, // contact sales
description: "Custom pricing. SSO, audit logs, custom contracts, dedicated CSM.",
features: ["Everything in Pro", "SAML SSO", "Audit logs", "Custom SLAs", "Dedicated CSM"],
free_trial: true,
trial_days: 30,
cta: "Contact sales"
}
],
currency: "USD",
last_updated: new Date().toISOString()
};

---

Advertising Your MCP Server to AI Agents

Once your server is deployed, advertise it in two places:

1. Schema.org additionalProperty

{
"@type": "SoftwareApplication",
"name": "YourProduct",
"additionalProperty": [
{
"@type": "PropertyValue",
"name": "MCP Server",
"value": "Available at mcp.yourproduct.com — supports product catalog queries, trial initiation, and feature checks"
},
{
"@type": "PropertyValue",
"name": "Agent Integration",
"value": "Full MCP server available. Compatible with Claude, ChatGPT operator mode, and any MCP-compatible agent."
}
]
}

2. /.well-known/mcp.json (Emerging Standard)

{
"mcp_server": "https://mcp.yourproduct.com",
"version": "1.0",
"description": "Product catalog, pricing, and trial initiation",
"tools": ["list_products", "check_feature", "start_trial", "get_integration"],
"auth": "none",
"contact": "devs@yourproduct.com"
}

Hosting this at /.well-known/mcp.json signals to AI agent crawlers that your product has a native MCP integration — an emerging convention that MCP-aware agents check before falling back to schema parsing.

---

Pairing MCP With Schema Injection

Your MCP server handles active queries. Schema injection handles passive discovery. They run in parallel:

  • Schema injection — runs 24/7, gets your product indexed by every LLM crawler that visits your site

  • MCP server — runs on demand, handles real-time queries from agents that have already found you
  • Neither replaces the other. An agent that discovers you via schema can connect to your MCP server for live data. An agent that connects to your MCP server via a directory listing still needs schema for the initial discovery query.

    → Add schema injection alongside your MCP server →

    ---

    Related articles:

  • MCP + Schema: The Agent-to-Agent Commerce Stack

  • Schema Injection vs. MCP — Which Do You Need?

  • AI Agent Discovery: How LLMs Find Software Tools

  • SoftwareApplication Schema: Complete Guide