Skip to content
Conduit

mcp server

mcp-server

MCP server for Kadam ad network — manage campaigns, creatives, audiences, sites, and analytics via AI agents

kadam-official/mcp-servercommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • Node.js 20 or newer
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "kadam-official-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "@kadam-net/mcp-server"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 17, 2026

@kadam-net/mcp-server

npm version npm downloads license node MCP Registry

MCP server for Kadam ad network — manage campaigns, creatives, audiences, sites, and analytics via AI agents.

Built on the Model Context Protocol (MCP), the open standard for connecting LLMs to external tools and data.

Install (one click)

Cursor

Or add manually to .cursor/mcp.json:

{
  "mcpServers": {
    "kadam": {
      "command": "npx",
      "args": ["-y", "@kadam-net/mcp-server"],
      "env": {
        "KADAM_ADV_API_KEY": "your-advertiser-api-key",
        "KADAM_PUB_API_KEY": "your-publisher-api-key"
      }
    }
  }
}

Claude Code

claude mcp add kadam -- npx -y @kadam-net/mcp-server

Then set the env var: export KADAM_ADV_API_KEY=your-key

Claude Desktop

Download → double-click → Install. Or add manually to claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "kadam": {
      "command": "npx",
      "args": ["-y", "@kadam-net/mcp-server"],
      "env": {
        "KADAM_ADV_API_KEY": "your-advertiser-api-key",
        "KADAM_PUB_API_KEY": "your-publisher-api-key"
      }
    }
  }
}

Any MCP client (universal one-liner)

npx add-mcp @kadam-net/mcp-server

Docker

docker run -i --rm \
  -e KADAM_ADV_API_KEY=your-key \
  kadam/mcp-server:latest

npm global

npm install -g @kadam-net/mcp-server
KADAM_ADV_API_KEY=your-key kadam-mcp-server

Configuration

VariableRequiredDescription
KADAM_ADV_API_KEYOne of twoAdvertiser API key from partners.kadam.net -> Profile -> API
KADAM_PUB_API_KEYOne of twoPublisher API key from pub.kadam.net -> Profile -> API
KADAM_ADV_API_BASENoAdvertiser API URL (default: https://partners.kadam.net/api/v1)
KADAM_PUB_API_BASENoPublisher API URL (default: https://pub.kadam.net/api)
LOG_LEVELNoLog level: trace, debug, info, warn, error, fatal (default: info)

At least one API key must be provided in stdio mode. In HTTP mode, tokens are passed per-request via Bearer authentication.

Role-based catalog

The tool catalog matches the role of the bearer. Once per session (and once per process in stdio mode) the server calls GET /api/v1/access on the advertiser API, which answers { impersonation: bool }:

BearerimpersonationCatalog
Advertiser API key, or a cabinet JWT with sub onlyfalse75 tools; create_campaign / update_campaign have no manager-only fields
Cabinet JWT with act.sub (a Kadam manager acting for the client)true80 tools (adds the five marked "manager-only" below); campaign writes accept hasCorrectPostback, isDirectTrafficPriority, allowMultiAds
Publisher API keyn/a17 publisher tools; the publisher API has no impersonation

This is a catalog hint, not a gate: the Kadam API enforces the same rule on every call (403 / 422 for a client token). If /access cannot be reached, the session gets the client catalog — the smaller one is always safe to show.

HTTP Transport (multi-tenant deployment)

For server-side deployment serving multiple users:

VariableRequiredDescription
MCP_TRANSPORTNo"stdio" (default) or "http"
MCP_HTTP_PORTNoHTTP port (default: 8080)
MCP_HTTP_HOSTNoBind address (default: 0.0.0.0)
KADAM_ADV_DOMAINNoAdvertiser domain for PRM (default: https://partners.kadam.net)
KADAM_PUB_DOMAINNoPublisher domain for PRM (default: https://pub.kadam.net)
docker run -d --name kadam-mcp \
  -e MCP_TRANSPORT=http \
  -p 8080:8080 \
  kadam/mcp-server:latest

Connecting via HTTP (Cursor / Claude)

{
  "mcpServers": {
    "kadam-adv": {
      "url": "https://partners.kadam.net/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_ADV_API_KEY"
      }
    }
  }
}

Connecting via OAuth (ChatGPT)

Add https://partners.kadam.net/mcp (advertiser) or https://pub.kadam.net/mcp (publisher) as Server URL in ChatGPT settings. OAuth discovery, registration, and login happen automatically.

Tools (80)

Advertiser Tools (63)

Requires KADAM_ADV_API_KEY.

Dictionaries

ToolDescriptionAnnotations
kadam_adv_get_dictionaryReference dictionary: campaign types, browsers, platforms, devices, connections, categories, isps, conversion templates, countries, regions, citiesreadOnly

Campaigns

ToolDescriptionAnnotations
kadam_adv_list_campaignsList campaigns with filters (folder, status, type, date, search) and paginationreadOnly
kadam_adv_get_campaignGet full campaign configuration by ID: landing page URL, bids per country, budgets, targeting, frequency caps, schedule, conversion settingsreadOnly
kadam_adv_create_campaignCreate campaign with full targeting (countries, devices, OS, browsers, age, gender, audiences); dryRun: true validates only—
kadam_adv_update_campaignUpdate any campaign fields by ID—
kadam_adv_set_campaign_statusBulk status change (active/paused/archived/restored) for comma-separated IDs; reports per-ID resultidempotent
kadam_adv_delete_campaignsBulk delete of archived campaigns by comma-separated IDs; requires confirm: true, reports per-ID resultdestructive
kadam_adv_move_campaignsMove campaigns to a campaign group by comma-separated campaign IDs and target group IDidempotent
kadam_adv_copy_campaignCopy a campaign into a campaign group: settings and bids are cloned, the copy starts paused and re-enters moderation. Optional pricing-model switch, push <-> in-page push cross-format copy, autorules and per-site bids—
kadam_adv_bulk_replace_urlsFind and replace a landing-URL fragment across campaigns and their creatives. Manager-only (impersonation sessions); supports dryRundestructive
kadam_adv_set_campaign_rssPoint a native campaign at an RSS feed to import creatives, or stop the import with an empty linkidempotent
kadam_adv_set_easy_startTurn Easy Start (curated site set) on or off for a campaign. Manager-only (impersonation sessions)idempotent
kadam_adv_get_blocked_traffic_sourcesTraffic sources rejecting a campaign, split into category blocks and moderation-tag blocks. Manager-only (impersonation sessions)readOnly
kadam_adv_get_traffic_forecastBid-to-traffic curve for a targeting set from yesterday's auction. An empty curve means the forecast could not be built, not that traffic is zeroreadOnly

Bid Management

ToolDescriptionAnnotations
kadam_adv_update_campaign_bidUpdate bid for a single campaign (lightweight, no full payload). Falls back to current countries if omittedidempotent
kadam_adv_bulk_update_bidsUpdate bids for multiple campaigns at once (all must share the same pricing model)idempotent
kadam_adv_block_sitesStop or resume buying sites (zones) in campaigns—
kadam_adv_update_site_bidsSet per-site (zone) bids: static (0.05), multiplier (x1.5), or remove (0)idempotent

Campaign Folders

ToolDescriptionAnnotations
kadam_adv_list_campaign_foldersList folders with campaign counts and budgetsreadOnly
kadam_adv_get_campaign_folderGet a single folder: name, archived state, budgetsreadOnly
kadam_adv_create_campaign_folderCreate a new folder (name 1-50 chars)—
kadam_adv_update_campaign_folderPartial update: rename and/or change budgets and distribution—
kadam_adv_set_campaign_folder_statusBulk action for comma-separated IDs: activate/pause campaigns, archive or restore folders with their campaigns; returns per-folder resultidempotent

Creatives

ToolDescriptionAnnotations
kadam_adv_list_creativesList creatives by campaign, status, or search queryreadOnly
kadam_adv_create_creativeCreate creative for a campaign: image, HTML5 archive, video file or VAST tag (goes through moderation)—
kadam_adv_update_creativeUpdate creative fields—
kadam_adv_set_creative_statusBulk status change for creatives: active/paused/archived/restored; returns per-creative resultidempotent
kadam_adv_get_creative_test_conversionSigned links to test a creative's conversion tracking (test click + frame preview)—
kadam_adv_upload_bulk_imagesStage images for a bulk creative batch (async, returns a job)—
kadam_adv_create_bulk_creativesTurn staged images into creatives in several campaigns at once (async, returns a job)—
kadam_adv_get_bulk_jobState of a bulk batch: staged images, refusals, per-row outcome—
kadam_adv_copy_creativesCopy creatives into other campaigns (creatives × targets copies), originals untouched—
kadam_adv_move_creativesMove creatives to another campaign of the same format and pricing model; they lose per-geo bids and return to moderation—
kadam_adv_get_creative_blocked_sourcesTraffic sources that reject one creative, split by category and moderation tag. Manager-only (impersonation sessions)—
kadam_adv_set_creative_bidsReplace the creatives' own per-country bids; countries left out fall back to the campaign bid—
kadam_adv_delete_creativesBulk delete of archived creatives by comma-separated IDs; requires confirm: true, reports per-ID resultdestructive

Audiences

ToolDescriptionAnnotations
kadam_adv_list_audiencesList audiences with search and sortingreadOnly
kadam_adv_get_audienceGet detailed audience info by IDreadOnly
kadam_adv_create_audienceCreate audience (pixel, code, fingerprint, or S2S)—
kadam_adv_update_audienceUpdate audience settings—
kadam_adv_get_filtered_audience_sourcesAudiences usable as sources of a filtered audience. Manager-only (impersonation sessions)—
kadam_adv_get_audience_paramsHardcoded parameters a pixel/S2S audience substitutes into its code—
kadam_adv_set_audience_paramsReplace the hardcoded parameters of a pixel/S2S audience—
kadam_adv_delete_audienceDelete audience permanently (requires confirm: true)destructive

Finance & Statistics

ToolDescriptionAnnotations
kadam_adv_list_finance_operationsTransaction history (deposits, charges, refunds)readOnly
kadam_adv_get_statsUnified statistics — 3 report types via reportType param: custom (report builder with dimension/metric mapping), sites (per-site breakdown), postbacks (conversion logs)readOnly

Publisher Tools (17)

Requires KADAM_PUB_API_KEY.

Sites (Sources)

ToolDescriptionAnnotations
kadam_pub_list_sourcesList publisher sites with statsreadOnly
kadam_pub_create_sourceAdd a new site (starts verification flow)—
kadam_pub_get_sourceGet detailed site inforeadOnly
kadam_pub_update_sourceUpdate site name—
kadam_pub_set_source_statusChange site status (active/paused/archived/unarchived)idempotent

Ad Units

ToolDescriptionAnnotations
kadam_pub_list_ad_unitsList ad units for a site, filter by format (native/banner/push/popunder/inpagepush)readOnly
kadam_pub_set_ad_unit_statusChange ad unit status (active/paused/archived/restored)idempotent

User & Statistics

ToolDescriptionAnnotations
kadam_pub_get_user_infoGet publisher account info and balancereadOnly
kadam_pub_get_statsPublisher statistics with human-readable dimension/metric mappingreadOnly

Kadam Smart Mediation

Selling an ad unit's traffic through outside ad networks alongside Kadam demand. The API, the code and the report dimensions call it plain mediation. Read kadam://reference/mediation first; split the income in kadam_pub_get_stats with groupBy=network and the kadam_revenue / mediation_revenue metrics.

ToolDescriptionAnnotations
kadam_pub_list_mediation_networksCatalog of networks, which have an account, and what an ad unit already runsreadOnly
kadam_pub_connect_mediation_networkAttach a network to an ad unit (resolves account and placement itself)—
kadam_pub_update_mediation_networkChange geo, unique cap, proxy policy, tag template, placement or account—
kadam_pub_set_mediation_network_statusactive / paused for a connectionidempotent
kadam_pub_retest_mediation_networkRestart the forced test share (1-50%); starts a new measurement epoch—
kadam_pub_disconnect_mediation_networkRemove a connection (requires confirm)destructive
kadam_pub_update_mediation_network_accountRotate the network API key, rename or disable the account—
kadam_pub_delete_mediation_network_accountRemove a network account (requires confirm)destructive

Resources (9)

Static reference data the agent can read before calling tools:

URIDescription
kadam://reference/campaign-typesAll ad format types with IDs, features, pricing, and creative specs
kadam://reference/pricing-modelsCPC, CPM, CPV, CPA Target with IDs and descriptions
kadam://reference/creative-formatsCreative requirements per campaign type
kadam://reference/ad-unit-typesPublisher ad unit formats with IDs
kadam://reference/site-statesPublisher site lifecycle states
kadam://reference/mediationOutside ad networks: accounts, placements, connections, test share, income split
kadam://reference/report-dimensionsAvailable dimensions and metrics for statistics tools
kadam://reference/api-overviewGeneral Kadam API capabilities overview

Prompts (4)

Pre-built workflow templates that guide the agent through multi-step operations:

PromptDescriptionArguments
kadam_launch_campaignStep-by-step campaign creation (check types -> create folder -> create campaign -> add creatives)type, name, url, budget
kadam_campaign_performanceCampaign performance analysis with optimization recommendationscampaignId, period
kadam_optimize_sitesAnalyze site performance and suggest blacklist/whitelist changescampaignId, minClicks, maxCPA
kadam_account_overviewFull account overview — campaigns, spend, top performers—

Architecture

src/
├── index.ts                  # Entry point, server instructions, transport
├── config.ts                 # Zod-validated env config with cache
├── errors.ts                 # AuthError class
├── logger.ts                 # Pino structured logging (stderr)
├── output-formatter.ts       # Text formatting + 50KB truncation
├── middleware/
│   └── tool-wrapper.ts       # Auth, error handling, logging middleware
├── api/
│   ├── http-client.ts        # Generic HTTP client with retry/429/timeout
│   ├── partners-client.ts    # Advertiser API (lazy singleton)
│   └── pub-client.ts         # Publisher API (lazy singleton)
├── utils/
│   ├── pagination.ts         # Shared pagination extraction
│   ├── cache-once.ts         # Generic async cache-once utility
│   └── dimension-mapper.ts   # Stats dimension name→ID resolution
├── types/
│   ├── common.ts             # Shared types (ApiListResponse, ReportConfig)
│   ├── advertiser.ts         # Campaign, Creative, Audience types + maps
│   ├── publisher.ts          # Source, AdUnit, PubUser types + maps
│   └── tool-module.ts        # ToolModule interface
├── tools/
│   ├── advertiser/           # 63 tools across 14 modules
│   └── publisher/            # 17 tools across 6 modules
├── resources/                # 9 reference resources
└── prompts/                  # 4 workflow prompts

Key Design Decisions

  • ToolWrapper middleware — centralized auth validation, error formatting, and logging for all 80 tools
  • Lazy singleton API clients — one HttpClient instance per product, created on first use
  • Output truncation — hard 50KB limit per response with maxResults (default 25, max 100) to prevent LLM context overflow
  • Human-readable output — formatted tables, aligned entities, pagination metadata instead of raw JSON
  • Tool annotations — readOnlyHint, destructiveHint, idempotentHint to guide agent behavior
  • Server instructions — usage patterns and constraints sent to the LLM on connection
  • Dimension mapping — stats tools accept human-readable names ("clicks", "spend") and resolve them to API IDs internally
  • Role-shaped catalog — the bearer is forwarded untouched, and its role is read once per session from GET /access (see "Role-based catalog"). Tools declare requires: "impersonation" and ToolWrapper skips them for client sessions; campaigns.ts adds the manager-only campaign fields to its schemas only under impersonation. Nothing is enforced here — the API still answers 403 / 422 to a client token — so the catalog can never be wider than the key's real rights, only narrower when /access is unreachable

Development

Prerequisites

  • Node.js >= 18
  • npm

Setup

git clone https://github.com/kadam-official/mcp-server.git
cd mcp-server
npm install
cp .env.example .env  # Fill in your API keys

Commands

npm run dev             # Watch mode with tsx
npm run build           # Production build with Vite
npm run start           # Run built server
npm run typecheck       # TypeScript check
npm run lint            # ESLint
npm run format          # Prettier
npm test                # Run 82 tests
npm run test:coverage   # Tests with V8 coverage
npm run inspect         # MCP Inspector (visual debugger)

Testing

202 tests across 23 files using Vitest + MCP SDK InMemoryTransport:

  • Unit tests — output formatter, config, HTTP client (mocked fetch)
  • Middleware tests — ToolWrapper auth, error formatting, logging
  • Integration tests — full server with all 72 tools, 8 resources, 4 prompts via in-memory MCP client
  • Tool handler tests — each tool module with mocked API clients
npm test
# Test Files  23 passed (23)
#      Tests  202 passed (202)

MCP Inspector

The MCP Inspector provides a visual interface for testing:

npm run build
npm run inspect

Deployment

Docker

docker build -t kadam-mcp-server .
docker run -i --rm -e KADAM_ADV_API_KEY=... kadam-mcp-server

CI/CD

The .gitlab-ci.yml pipeline includes:

  • lint — ESLint + TypeScript check
  • test — Vitest with coverage
  • build — Vite production build
  • publish — npm publish + Docker push (manual trigger)

License

MIT

↑↓ navigate openesc close