How to Build an MCP Server for Marketing: Tutorial with Code [2026]

An MCP (Model Context Protocol) server connects Claude, ChatGPT, or other AI models to your marketing tools. Build one that queries your Attio CRM, pulls analytics from Google Analytics, or executes campaigns in HubSpot—all from within Claude. This tutorial covers architecture, a complete code example, and deployment.

"MCP servers are how marketing technologists give AI access to their marketing stack. The server becomes your command center for automation, analysis, and decision-making."

What Is an MCP Server?

An MCP (Model Context Protocol) server is a lightweight application that sits between an AI model (Claude, ChatGPT, etc.) and your APIs or data sources. It defines "tools" that the AI can call. When you ask Claude "Query our top 10 deals from Attio," the MCP server receives that request, calls the Attio API, and returns the result to Claude.

Think of it as a translator: Your AI model speaks in natural language. Your API expects structured requests. The MCP server does the translation—and handles authentication, error handling, rate limiting, and logging.

MCP servers are not new (they've existed for 10+ years as "custom actions" or "API integrations"), but they're newly popular because AI models got smarter at using them. Claude can now call 5-10 tools in sequence, chain results together, and reason about them—which makes a well-designed MCP server incredibly powerful.

Why Marketing Technologists Should Build MCP Servers

1. Automate decision-making. Instead of manually querying your CRM to check a prospect's engagement level, ask Claude "What's the sales engagement score for Acme Corp?" Claude calls your MCP server, which queries Attio, and returns the answer with context.

2. Chain operations together. "Pull top 10 deals from Attio, get their company data from Crunchbase, and draft outreach emails." This requires 3 API calls and integration logic. Your MCP server handles it.

3. Scale your team's capabilities. Every marketer on your team gets access to a personal AI that knows your entire marketing stack. No API documentation needed. No command-line tools. Just natural language.

4. Build custom marketing agents. A marketing agent is an AI that runs autonomously, using your MCP server to make decisions, execute campaigns, and report results. This is the future of marketing operations.

MCP Server Architecture (High Level)

Host (Claude, ChatGPT, etc.)

↓ (natural language request)

MCP Client (handles transport, serialization)

↓ (JSON-RPC protocol)

MCP Server (your application)

↓ (executes tool, calls API)

External API (Attio, Google Analytics, HubSpot, etc.)

↓ (returns data)

MCP Server (formats response)

↓ (JSON-RPC response)

MCP Client

↓ (Claude reads result)

Host (generates answer)

The key: Your MCP server doesn't know about Claude directly. It just listens for RPC requests and responds with results. The MCP client handles the Claude integration.

Prerequisites

Technical: Node.js 18+ or Python 3.8+, basic REST API knowledge, API credentials for your target platform (Attio, Google Analytics, HubSpot).

Knowledge: Understand how your target API works (read its docs for 30 minutes). Understand JSON and REST. You don't need to be a professional developer—marketing technologists with Python/JavaScript experience can build MCP servers.

Step-by-Step Tutorial: Build a Marketing MCP Server (TypeScript)

Step 1: Set Up Your Project

mkdir marketing-mcp-server cd marketing-mcp-server npm init -y npm install @modelcontextprotocol/sdk typescript node-fetch dotenv

Create a `.env` file for your API credentials:

ATTIO_API_KEY=your_attio_api_key ATTIO_WORKSPACE=your_workspace_id GOOGLE_ANALYTICS_KEY=your_ga_service_account_key HUBSPOT_API_KEY=your_hubspot_api_key

Step 2: Define Your Tools

An MCP server exposes "tools" that Claude can call. Example tools for a marketing MCP:

// src/tools.ts export const tools = [ { name: "get_deals_from_attio", description: "Query top 10 deals from Attio CRM, sorted by value", inputSchema: { type: "object", properties: { limit: { type: "number", description: "Number of deals to return (default 10)" } } } }, { name: "get_company_info", description: "Get company info from Crunchbase (company name, funding, employees)", inputSchema: { type: "object", properties: { company_name: { type: "string", description: "Company name" } } } }, { name: "draft_email", description: "Draft an outreach email given context about the prospect", inputSchema: { type: "object", properties: { prospect_name: { type: "string" }, prospect_company: { type: "string" }, key_context: { type: "string", description: "Key selling point or pain point" } } } } ];

Step 3: Implement Tool Handlers

// src/handlers.ts import fetch from 'node-fetch'; import { config } from 'dotenv'; config(); export async function getDealsFromAttio(limit = 10) { const response = await fetch( 'https://api.attio.com/v2/records/deals?limit=' + limit, { headers: { 'Authorization': `Bearer ${process.env.ATTIO_API_KEY}`, 'Content-Type': 'application/json' } } ); if (!response.ok) { throw new Error(`Attio API error: ${response.statusText}`); } const data = await response.json(); return data.records.map(deal => ({ name: deal.title, value: deal.deal_value, stage: deal.stage, owner: deal.owner_name })); } export async function getCompanyInfo(companyName) { // Call Crunchbase API const response = await fetch( `https://api.crunchbase.com/v4/entities/companies/collection?name=${companyName}`, { headers: { 'X-Cb-User-Key': process.env.CRUNCHBASE_API_KEY } } ); const data = await response.json(); const company = data.entities[0]; return { name: company.name, founded: company.founded_on, employees: company.num_employees_enum, funding: company.funding_total, website: company.website }; } export async function draftEmail(prospectName, prospectCompany, keyContext) { // Use Claude API to draft email (or a template + simple formatting) return `Subject: Quick thought about ${prospectCompany} Hi ${prospectName}, I was thinking about ${prospectCompany} and how you could ${keyContext}. Would love to chat briefly about this approach. Best, [Your name]`; }

Step 4: Create the MCP Server

// src/server.ts import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { CallToolRequestSchema, ListToolsRequestSchema, TextContent, ToolResultBlockParam } from '@modelcontextprotocol/sdk/types.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { tools } from './tools.js'; import * as handlers from './handlers.js'; const server = new Server({ name: 'marketing-mcp-server', version: '1.0.0' }); // Handle tool listing server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { let result; if (name === 'get_deals_from_attio') { result = await handlers.getDealsFromAttio(args.limit); } else if (name === 'get_company_info') { result = await handlers.getCompanyInfo(args.company_name); } else if (name === 'draft_email') { result = await handlers.draftEmail( args.prospect_name, args.prospect_company, args.key_context ); } else { throw new Error(`Unknown tool: ${name}`); } return { content: [ { type: 'text' as const, text: JSON.stringify(result, null, 2) } ] }; } catch (error) { return { content: [ { type: 'text' as const, text: `Error: ${error.message}` } ], isError: true }; } }); // Start server const transport = new StdioServerTransport(); server.connect(transport);

Step 5: Compile and Run

npx tsc node dist/server.js

Your MCP server is now running. It listens on stdin for RPC requests.

Step 6: Connect to Claude

In your Claude prompt or Claude desktop app, point to your MCP server:

You have access to a marketing MCP server with tools: - get_deals_from_attio: Query top deals - get_company_info: Look up company info - draft_email: Draft outreach Use these tools to answer questions about our sales pipeline.

Claude will now be able to call your tools directly.

Deployment Options

Local (simplest): Run on your machine. Claude desktop app connects to localhost. Good for personal use or small teams.

Docker (recommended for teams): Containerize your MCP server. Deploy to AWS ECS, Google Cloud Run, or Heroku. All team members connect to the same endpoint. Scales automatically.

AWS Lambda: Serverless deployment. Good for occasional use (low cost). Cold starts can be slow (2-5 seconds).

Vercel Functions: Similar to Lambda, but easier to deploy from Git. Good for SaaS/web-based use cases.

Security Considerations

API key management. Never hardcode API keys. Use environment variables or secrets management (AWS Secrets Manager, HashiCorp Vault). Rotate keys regularly.

Rate limiting. If Claude makes 100 API calls in 1 minute, you'll hit rate limits. Implement queuing and backoff logic in your handlers.

Audit logging. Log all tool calls (user, timestamp, action, result). This is critical for compliance and debugging.

Permission scoping. Grant your MCP server the minimum API permissions it needs. If it only reads deals, don't give it write access to the entire CRM.

From One Tool to a Full Marketing Stack

Start with one tool (e.g., get_deals_from_attio). Get it working. Then add more tools incrementally: get_company_info, analyze_engagement, draft_email, send_email, log_to_crm.

Once you have 5+ tools working together, you've effectively built a marketing agent—an AI that can autonomously query your stack, make decisions, and take actions.

From there, you can build workflow automations: "Every morning, pull deals at risk, analyze why they're stalling, and draft win-back emails."

Real Example: Marketing Enigma's MCP Server

Tools: get_aeo_insights (queries our analytics), check_ai_visibility (pings ChatGPT/Claude to see if we're cited), get_client_status (queries Attio), draft_audit_report (uses Claude's native capabilities + our data).

Use case: When a prospect books an audit call, our team runs: "Generate audit brief for [company name]." The MCP server pulls their website, queries AI visibility, checks our CRM for prior notes, and drafts a 1-page briefing document.

Result: Sales team has context in 30 seconds instead of 15 minutes of manual research. Proposals are more personalized. Close rate improved 24%.

FAQ

Do I need to be a professional developer to build an MCP server?

No. If you can read API documentation and understand JSON, you can build a basic MCP server in 2-4 hours. The TypeScript/Python knowledge required is minimal.

Can I build an MCP server that connects multiple APIs?

Yes. Your server can call Attio, Google Analytics, HubSpot, Crunchbase, and any other API simultaneously. That's the whole point.

What's the difference between an MCP server and a Zapier/Make automation?

MCP servers are AI-native. Claude orchestrates them naturally ("pull deals and draft emails"). Zapier/Make require explicit workflow setup. MCP servers are better for knowledge work; Zapier is better for simple, repeating workflows.

Can I monetize an MCP server I build?

Yes. You can build a commercial MCP server and sell it to marketing teams (e.g., "MCP server for HubSpot users"). This is an emerging market.

What if my API doesn't have good documentation?

Ask Claude to help. Paste your API docs (or lack thereof) into Claude and ask "How would I query X?" Claude often reverse-engineers APIs faster than you can read docs.

Want to build a custom MCP server for your marketing stack? Book a free consultation with our MCP specialists.