Ad Campaign MCP
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Ad Campaign MCPWhat are my active ad campaigns?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Ad Campaign MCP
An MCP (Model Context Protocol) client/server integration built with TypeScript/Node.js. It connects an AI assistant to a small REST API over structured, typed tools — with real error handling for a down API or a missing record — rather than the assistant calling the API directly.
Architecture
MCP client (AI assistant)
│ stdio, JSON-RPC
▼
MCP server (src/index.ts)
│ HTTP
▼
Campaign REST API (src/api.ts, Express)
│ SQL
▼
Postgres (docker-compose.yml)Postgres —
advertisers,campaigns,impressions, andclickstables, created on API startup bysrc/db.ts.REST API (
src/api.ts) —GET /campaigns(optionally filtered by?status=) andGET /campaigns/:id, backed by Postgres.MCP server (
src/index.ts) — exposes two tools that call the REST API and translate its responses (including non-2xx statuses and connection failures) into MCP tool results.
Related MCP server: Ads Analytics MCP
Getting started
docker compose up -d # start Postgres
npm install
npm run api # start the REST API on :3000
npm run build # compile the MCP server to dist/Run the MCP server directly during development with npm run dev (uses
tsx, no build step needed), or run the compiled version with
node dist/index.js. The compiled version starts noticeably faster,
since it skips on-the-fly TypeScript transpilation — worth using for an
MCP client that spawns the server, since Client.connect() has a
default 60s handshake timeout.
The API URL defaults to http://localhost:3000; override it with the
API_BASE_URL environment variable if the REST API runs elsewhere.
Sample API calls
There's no POST /campaigns endpoint yet, so the table starts empty —
seed a row directly via SQL first, or the calls below just return []
/ 404.
Seed a campaign (direct SQL)
docker exec -it ad-campaign-postgres psql -U postgres -d adplatform -c "
INSERT INTO advertisers (name) VALUES ('Acme Corp') RETURNING id;
-- suppose that returns id = 1
INSERT INTO campaigns (id, advertiser_id, name, status, budget, start_date, end_date)
VALUES ('camp_001', 1, 'Summer Launch', 'active', 5000.00, '2026-06-01', '2026-08-31');
"GET /campaigns — list all
curl http://localhost:3000/campaigns[
{
"id": "camp_001",
"advertiser_id": 1,
"name": "Summer Launch",
"status": "active",
"budget": "5000.00",
"start_date": "2026-06-01T00:00:00.000Z",
"end_date": "2026-08-31T00:00:00.000Z",
"created_at": "2026-08-29T10:00:00.000Z",
"updated_at": "2026-08-29T10:00:00.000Z"
}
]GET /campaigns?status=active — filtered by status
curl "http://localhost:3000/campaigns?status=active"GET /campaigns/:id — single campaign
curl http://localhost:3000/campaigns/camp_001Returns the same object as above, unwrapped from the array.
GET /campaigns/:id — not found
curl -i http://localhost:3000/campaigns/does-not-existHTTP/1.1 404 Not Found
{"error":"Campaign not found"}Tools exposed
list_campaigns— list campaigns, optionally filtered bystatus(active|paused|draft).get_campaign— fetch a single campaign byid; returns an error result (not a thrown exception) for a 404 or an unreachable API.
Trying it end-to-end
npm run build
node demo-mcp-client.mjsThis spawns the compiled MCP server, performs the MCP handshake, lists its tools, and calls each one — including the 404 case — printing the results.
Known limitations
The REST API has no authentication — anything reaching
:3000can read campaign data.No
POST/PUTendpoints yet — campaigns can only be seeded directly via SQL, not created through the API or the MCP tools.
License
MIT
Available Tools
2 toolsget_campaignB
Get a single advertising campaign by id
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The campaign id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden for behavioral context. It only says 'Get', which implies a read operation, but it does not disclose return shape, behavior for nonexistent ids, error handling, or whether any side effects occur.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one short, front-loaded sentence with no filler. It clearly communicates the action, resource, and required parameter in minimal words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple get-by-id tool with one documented parameter, the description is mostly adequate. However, there is no output schema and the description does not state return values or error behavior, nor does it provide usage guidance versus list_campaigns, leaving some gaps in completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully describes the single parameter with 100% coverage. The description’s 'by id' adds no new semantics beyond what the schema provides, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (Get), a specific resource (advertising campaign), and the selection mechanism (by id). The word 'single' differentiates it from the sibling tool list_campaigns, making the tool's scope unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance is given about when to use get_campaign versus list_campaigns. The distinction is implied by the word 'single', but the description does not name the alternative or state conditions like 'use list_campaigns to fetch multiple campaigns'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_campaignsC
List advertising campaigns
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter campaigns by status |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must communicate behavioral aspects itself. It only states that campaigns are listed, revealing a read-like operation, but it does not mention pagination, return format, filtering behavior beyond the status parameter, authentication needs, or whether results are limited.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single short phrase with no filler or redundancy. It is front-loaded and easy to parse, though it is extremely brief.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, but with no output schema and no annotations, the description leaves important context unstated, such as what fields are returned, whether results are paginated, and what the default behavior is when no status filter is provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers both parameters: 'status' has an enum and a description. The tool description adds no additional parameter meaning, but with 100% schema coverage, the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a clear verb ('List') and resource ('advertising campaigns'), which tells the agent what the tool does. It is naturally distinguishable from the sibling 'get_campaign' by pluralization (list of campaigns vs single campaign), though it does not explicitly state that distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance about when to use this tool versus 'get_campaign'. The plural form implies it returns multiple campaigns and the sibling returns one, but no explicit usage context, exclusions, or alternative criteria are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v1.0.0- First observed
get_campaign - First observed
list_campaigns
TDQS
Scored across 2 tools
The two tools have clearly distinct purposes: one lists all campaigns and the other retrieves a single campaign by id. There is no ambiguity or overlap between them.
Both tool names follow the consistent verb_noun pattern (list_campaigns, get_campaign), making the naming predictable and easy to understand.
With only two tools, the server feels thin for a domain like ad campaigns, which typically involves more than just reading. However, the count is acceptable if the server is intentionally scoped to read-only operations.
The tool surface only covers listing and retrieving campaigns; there is no create, update, or delete functionality. This is a significant gap for an ad campaign management server, leaving agents unable to perform any lifecycle actions.
Maintenance
Related MCP Connectors
Marketing intelligence API for AI agents. Real campaign data, not LLM guesses.
Build, edit and sync Google, Microsoft, Reddit and Meta ad campaigns from your assistant.
- MorphedOAuthapp.morphed
Create AI images and videos, manage projects and credits, and use workspace campaign context.
Manage AI assistants, history, calls, campaigns, contacts, knowledge, messaging, and automations.
Related MCP Servers
- FlicenseBqualityDmaintenanceEnables users to manage Uber advertising campaigns through natural language by providing access to Uber's External Ads API. Supports campaign creation, retrieval, updating, and deletion with comprehensive filtering and configuration options.5-
- AlicenseAqualityDmaintenanceProvides read access to campaign performance data from Google Ads, Meta Ads, and TikTok Ads via live API calls, enabling AI assistants to analyze and audit advertising campaigns.161MIT
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with the Amazon Advertising API to manage campaigns, keywords, product ads, and retrieve performance metrics.934 npm3MIT

ictcontact-mcpofficial
AlicenseAqualityBmaintenanceEnables AI assistants to monitor outbound campaigns in ICTContact/ICTDialer, including listing campaigns, checking status, reading summaries and per-call results, and optionally starting and stopping campaigns when write access is enabled.437 npm16MIT