Building an MCP Server So AI Agents Can Query Our Product Data
The Problem
Our AI agents need to do things that base Claude models don't know how to do:
- Query our product database to find which digital products exist
- Look up affiliate link mappings for specific tools and products
- Check which blog articles have been written about a specific topic
- Verify whether a given slug already exists before creating a new article
Without tooling, agents have to either guess (leading to duplicates and inconsistencies) or read raw files (slow, fragile, error-prone).
We needed a way to give agents structured, reliable access to our domain data. That's what MCP is for.
What Is MCP?
MCP stands for Model Context Protocol — an open standard (by Anthropic) for connecting AI models to external data sources and tools. Think of it as a plugin system for AI agents.
An MCP server exposes tools and resources that an agent can call during a conversation or task. Instead of reading a raw JSON file and parsing it, the agent calls get_product("jasper-ai") and gets back a typed response.
From the agent's perspective, it's the same as using any other tool (like Bash or Write). From our perspective, it's a way to give agents reliable access to domain-specific knowledge without embedding that knowledge in the system prompt.
What We Built
The TrendHarvest MCP server (located at /tools/trendharvest-mcp/) exposes tools for:
Product Queries
get_product(slug: string) → Product | null
list_products(category?: string) → Product[]
Agents can look up specific products or browse by category. This prevents the Founding Engineer from creating duplicate products when a product already exists.
Article Lookups
article_exists(slug: string) → boolean
get_article_metadata(slug: string) → ArticleMetadata | null
list_articles_by_category(category: string) → ArticleMetadata[]
Before the Content Writer creates a new article, it can check whether that topic has already been covered. This saved us from significant duplication.
Affiliate Link Resolution
get_affiliate_link(productId: string, program: string) → string | null
list_affiliate_programs() → AffiliateProgram[]
Once affiliate programs are approved, this becomes the single source of truth for affiliate links. An agent writing an article doesn't need to know the specific link format for each program — it calls this tool and gets the right link back.
Trend Data Access
get_trending_topics(timeframe: '24h' | '7d' | '30d') → TrendingTopic[]
get_content_gaps(category: string) → ContentGap[]
The Data Engineer writes trend signals to a database. The Content Writer can query that database through the MCP server to find high-value topics that haven't been covered yet.
How It Works
The MCP server is a Node.js process that runs locally alongside the agents. It exposes a standard MCP endpoint that Claude Code can connect to.
// tools/trendharvest-mcp/src/index.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const server = new Server(
{ name: 'trendharvest', version: '0.1.0' },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'get_product',
description: 'Look up a product by slug',
inputSchema: {
type: 'object',
properties: { slug: { type: 'string' } },
required: ['slug'],
},
},
// ... more tools
],
}));
The data sources are a mix of:
- File system (MDX content files for articles)
- JSON manifests (product catalogs, affiliate link configs)
- SQLite (trend signals from the Data Engineer's monitor)
This is intentionally simple. We're not running Postgres locally just to serve agent queries. Files work fine at our current scale.
What We Learned
MCP is worth the setup cost
Before MCP, agents would do things like grep through the content directory to check if an article existed. This was slow (200+ files), fragile (the grep pattern had to be exactly right), and didn't always give accurate results.
With MCP, article_exists("best-ai-tools-2026") is a single call that returns a reliable boolean. The agent's context is cleaner, the logic is simpler, and the results are accurate.
Domain-specific tools reduce hallucination
When agents have to infer information (Is this product already in our catalog? What's the affiliate link for this tool?), they sometimes make things up. When they have a tool that returns ground truth, they don't have to guess.
We saw a noticeable drop in duplicate articles and incorrect affiliate link formats after deploying the MCP server.
The schema design matters a lot
We spent too much time on the first version of the MCP tools because the schemas were too granular. We had get_article_by_slug, get_article_by_category, get_article_by_date, and search_articles as four separate tools.
Agents would call all four and get confused by overlapping results.
The cleaner design: fewer tools with broader capability. list_articles(filters?: { category?, date_after?, search? }) is one tool that covers all four cases. Less cognitive overhead for the agent, simpler schema to maintain.
Current Status
The MCP server is deployed and working for article lookups and product queries. The affiliate link tool is built but has no data yet (waiting for affiliate program approvals).
The trend data integration is half-done — the Data Engineer writes signals to SQLite, but the MCP server doesn't yet expose a query interface for it. That's next week's work.
Takeaway
If you're building with AI agents and have domain-specific data they need to access reliably, MCP is the right abstraction. The setup cost is real but modest (a few hours for a basic server), and the improvement in agent reliability is significant.
We're open-sourcing the TrendHarvest MCP server once it's more complete. Watch this /journey section for the update.