Why a Brand-Owned MCP Server Matters
Model Context Protocol (MCP) is the agent-tool surface most-likely to determine which brands AI assistants pull live information from in 2026. A brand-owned MCP server lets ChatGPT, Claude, Cursor, OpenClaw, and any other MCP-compatible client query your authoritative data (catalogue, pricing, support FAQs, availability) directly instead of relying on stale crawled content. This template gives you a TypeScript scaffold that is production-deployable in 30 minutes.
What This Starter Provides
- A working MCP server in TypeScript using the official MCP SDK.
- Four reference tools:
get_product,search_catalogue,get_faq,get_pricing. - Two reference resources:
brand://about,brand://policies. - Read-only by default (safe for public deployment).
- Comments showing where to add authentication for sensitive operations.
Project Setup
mkdir my-brand-mcp && cd my-brand-mcp
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node tsx
Create tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "node16",
"strict": true,
"esModuleInterop": true,
"outDir": "dist"
},
"include": ["src/**/*"]
}
The Server (src/index.ts)
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// Replace this with your real data source (DB, JSON file, API)
const catalogue = [
{ sku: "ACX5-BLK", name: "Acme Wireless Headphones X5", priceUSD: 299, inStock: true },
{ sku: "ACX5-WHT", name: "Acme Wireless Headphones X5 (White)", priceUSD: 299, inStock: true },
{ sku: "ACM2-BLK", name: "Acme Earbuds Mini 2", priceUSD: 149, inStock: false },
];
const faqs = [
{ q: "What is your return policy?", a: "30 days from purchase, full refund if unopened." },
{ q: "Do you ship internationally?", a: "Yes, to 47 countries via DHL Express." },
];
const server = new McpServer({
name: "acme-brand",
version: "1.0.0",
});
// Tool: get a single product
server.tool(
"get_product",
{ sku: z.string().describe("Product SKU") },
async ({ sku }) => {
const product = catalogue.find((p) => p.sku === sku);
return {
content: [
{
type: "text",
text: product ? JSON.stringify(product) : "Product not found",
},
],
};
}
);
// Tool: keyword search across the catalogue
server.tool(
"search_catalogue",
{ query: z.string().describe("Search keywords") },
async ({ query }) => {
const q = query.toLowerCase();
const matches = catalogue.filter((p) => p.name.toLowerCase().includes(q));
return {
content: [{ type: "text", text: JSON.stringify(matches) }],
};
}
);
// Tool: answer a FAQ
server.tool(
"get_faq",
{ question: z.string().describe("Customer question") },
async ({ question }) => {
const q = question.toLowerCase();
const match = faqs.find((f) => q.includes(f.q.toLowerCase().split(" ").slice(0, 3).join(" ")));
return {
content: [
{
type: "text",
text: match
? `Q: ${match.q}\nA: ${match.a}`
: "No matching FAQ found. Please contact support.",
},
],
};
}
);
// Tool: get pricing for a product
server.tool(
"get_pricing",
{ sku: z.string().describe("Product SKU") },
async ({ sku }) => {
const product = catalogue.find((p) => p.sku === sku);
return {
content: [
{
type: "text",
text: product
? `${product.name}: $${product.priceUSD} USD (${product.inStock ? "in stock" : "out of stock"})`
: "Product not found",
},
],
};
}
);
// Resource: brand about page
server.resource(
"brand://about",
"About the brand",
async () => ({
contents: [
{
uri: "brand://about",
mimeType: "text/plain",
text: "Acme is a consumer audio brand founded in 2014, headquartered in Brooklyn NY.",
},
],
})
);
// Resource: brand policies
server.resource(
"brand://policies",
"Brand policies",
async () => ({
contents: [
{
uri: "brand://policies",
mimeType: "text/plain",
text: "Returns: 30 days. Warranty: 2 years. Privacy: stored at brand-host EU + US regions only.",
},
],
})
);
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Acme MCP server running on stdio.");
Run the Server
npx tsx src/index.ts
Connect from Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the Windows equivalent:
{
"mcpServers": {
"acme-brand": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/my-brand-mcp/src/index.ts"]
}
}
}
Production Considerations
- Move catalogue and FAQ data out of code. Hit your real product database or content API.
- Add authentication. The starter is unauthenticated and read-only. For write tools or sensitive data, add OAuth or bearer-token auth at the transport layer.
- Add observability. Log tool invocations, latencies, and error rates. MCP servers are AI surfaces; you want monitoring data the same way you do for APIs.
- Publish discovery metadata. Expose the server URL and capabilities in your llms.txt and on a public
/mcppage so agents can find it. - Version the tools. Treat tool signatures as public API. Breaking changes need migration guidance.