kadam — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited kadam (Plugin) and scored it 45/100 (orange). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 1 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
A base64 string of 128+ characters appears in a documentation file. Encoded prompt injection hides the hostile instruction in base64 — invisible to keyword filters — and relies on the agent's ability to decode it at runtime. There is no normal authoring reason to embed a multi-hundred-byte base64 blob in skill docs.
*.sig, SIGNATURES) outside the documentation.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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.
<a href="https://kadam-official.github.io/mcp-server/install.html"><img alt="Install in Cursor" src="https://cursor.com/deeplink/mcp-install-dark.png" height="32" /></a>
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 mcp add kadam -- npx -y @kadam-net/mcp-serverThen set the env var: export KADAM_ADV_API_KEY=your-key
<a href="https://github.com/kadam-official/mcp-server/releases/latest/download/kadam-mcp-server.mcpb"><img alt="Download for Claude Desktop" src="https://img.shields.io/badge/Claude_Desktop-Download_.mcpb-orange?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiAyQzYuNDggMiAyIDYuNDggMiAxMnM0LjQ4IDEwIDEwIDEwIDEwLTQuNDggMTAtMTBTMTcuNTIgMiAxMiAyem0tMSAxNXYtNEg4bDQtNiA0IDZoLTN2NGgtMnoiLz48L3N2Zz4=" height="32" /></a>
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"
}
}
}
}npx add-mcp @kadam-net/mcp-serverdocker run -i --rm \
-e KADAM_ADV_API_KEY=your-key \
kadam/mcp-server:latestnpm install -g @kadam-net/mcp-server
KADAM_ADV_API_KEY=your-key kadam-mcp-server| Variable | Required | Description |
|---|---|---|
KADAM_ADV_API_KEY | One of two | Advertiser API key from partners.kadam.net -> Profile -> API |
KADAM_PUB_API_KEY | One of two | Publisher API key from pub.kadam.net -> Profile -> API |
KADAM_ADV_API_BASE | No | Advertiser API URL (default: https://partners.kadam.net/api/v1) |
KADAM_PUB_API_BASE | No | Publisher API URL (default: https://pub.kadam.net/api) |
LOG_LEVEL | No | Log 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.
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 }:
| Bearer | impersonation | Catalog |
|---|---|---|
Advertiser API key, or a cabinet JWT with sub only | false | 75 tools; create_campaign / update_campaign have no manager-only fields |
Cabinet JWT with act.sub (a Kadam manager acting for the client) | true | 80 tools (adds the five marked "manager-only" below); campaign writes accept hasCorrectPostback, isDirectTrafficPriority, allowMultiAds |
| Publisher API key | n/a | 17 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.
For server-side deployment serving multiple users:
| Variable | Required | Description |
|---|---|---|
MCP_TRANSPORT | No | "stdio" (default) or "http" |
MCP_HTTP_PORT | No | HTTP port (default: 8080) |
MCP_HTTP_HOST | No | Bind address (default: 0.0.0.0) |
KADAM_ADV_DOMAIN | No | Advertiser domain for PRM (default: https://partners.kadam.net) |
KADAM_PUB_DOMAIN | No | Publisher 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{
"mcpServers": {
"kadam-adv": {
"url": "https://partners.kadam.net/mcp",
"headers": {
"Authorization": "Bearer YOUR_ADV_API_KEY"
}
}
}
}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.
Requires KADAM_ADV_API_KEY.
#### Dictionaries
| Tool | Description | Annotations |
|---|---|---|
kadam_adv_get_dictionary | Reference dictionary: campaign types, browsers, platforms, devices, connections, categories, isps, conversion templates, countries, regions, cities | readOnly |
#### Campaigns
| Tool | Description | Annotations |
|---|---|---|
kadam_adv_list_campaigns | List campaigns with filters (folder, status, type, date, search) and pagination | readOnly |
kadam_adv_get_campaign | Get full campaign configuration by ID: landing page URL, bids per country, budgets, targeting, frequency caps, schedule, conversion settings | readOnly |
kadam_adv_create_campaign | Create campaign with full targeting (countries, devices, OS, browsers, age, gender, audiences); dryRun: true validates only | — |
kadam_adv_update_campaign | Update any campaign fields by ID | — |
kadam_adv_set_campaign_status | Bulk status change (active/paused/archived/restored) for comma-separated IDs; reports per-ID result | idempotent |
kadam_adv_delete_campaigns | Bulk delete of archived campaigns by comma-separated IDs; requires confirm: true, reports per-ID result | destructive |
kadam_adv_move_campaigns | Move campaigns to a campaign group by comma-separated campaign IDs and target group ID | idempotent |
kadam_adv_copy_campaign | Copy 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_urls | Find and replace a landing-URL fragment across campaigns and their creatives. Manager-only (impersonation sessions); supports dryRun | destructive |
kadam_adv_set_campaign_rss | Point a native campaign at an RSS feed to import creatives, or stop the import with an empty link | idempotent |
kadam_adv_set_easy_start | Turn Easy Start (curated site set) on or off for a campaign. Manager-only (impersonation sessions) | idempotent |
kadam_adv_get_blocked_traffic_sources | Traffic sources rejecting a campaign, split into category blocks and moderation-tag blocks. Manager-only (impersonation sessions) | readOnly |
kadam_adv_get_traffic_forecast | Bid-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 zero | readOnly |
#### Bid Management
| Tool | Description | Annotations |
|---|---|---|
kadam_adv_update_campaign_bid | Update bid for a single campaign (lightweight, no full payload). Falls back to current countries if omitted | idempotent |
kadam_adv_bulk_update_bids | Update bids for multiple campaigns at once (all must share the same pricing model) | idempotent |
kadam_adv_block_sites | Stop or resume buying sites (zones) in campaigns | — |
kadam_adv_update_site_bids | Set per-site (zone) bids: static (0.05), multiplier (x1.5), or remove (0) | idempotent |
#### Campaign Folders
| Tool | Description | Annotations |
|---|---|---|
kadam_adv_list_campaign_folders | List folders with campaign counts and budgets | readOnly |
kadam_adv_get_campaign_folder | Get a single folder: name, archived state, budgets | readOnly |
kadam_adv_create_campaign_folder | Create a new folder (name 1-50 chars) | — |
kadam_adv_update_campaign_folder | Partial update: rename and/or change budgets and distribution | — |
kadam_adv_set_campaign_folder_status | Bulk action for comma-separated IDs: activate/pause campaigns, archive or restore folders with their campaigns; returns per-folder result | idempotent |
#### Creatives
| Tool | Description | Annotations |
|---|---|---|
kadam_adv_list_creatives | List creatives by campaign, status, or search query | readOnly |
kadam_adv_create_creative | Create creative for a campaign: image, HTML5 archive, iframe, HTML tag, video file or VAST tag (goes through moderation) | — |
kadam_adv_update_creative | Update creative fields | — |
kadam_adv_set_creative_status | Bulk status change for creatives: active/paused/archived/restored; returns per-creative result | idempotent |
kadam_adv_get_creative_test_conversion | Signed links to test a creative's conversion tracking (test click + frame preview) | — |
kadam_adv_upload_bulk_images | Stage images for a bulk creative batch (async, returns a job) | — |
kadam_adv_create_bulk_creatives | Turn staged images into creatives in several campaigns at once (async, returns a job) | — |
kadam_adv_get_bulk_job | State of a bulk batch: staged images, refusals, per-row outcome | — |
kadam_adv_copy_creatives | Copy creatives into other campaigns (creatives × targets copies), originals untouched | — |
kadam_adv_move_creatives | Move 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_sources | Traffic sources that reject one creative, split by category and moderation tag. Manager-only (impersonation sessions) | — |
kadam_adv_set_creative_bids | Replace the creatives' own per-country bids; countries left out fall back to the campaign bid | — |
kadam_adv_delete_creatives | Bulk delete of archived creatives by comma-separated IDs; requires confirm: true, reports per-ID result | destructive |
#### Audiences
| Tool | Description | Annotations |
|---|---|---|
kadam_adv_list_audiences | List audiences with search and sorting | readOnly |
kadam_adv_get_audience | Get detailed audience info by ID | readOnly |
kadam_adv_create_audience | Create audience (pixel, code, fingerprint, or S2S) | — |
kadam_adv_update_audience | Update audience settings | — |
kadam_adv_get_filtered_audience_sources | Audiences usable as sources of a filtered audience. Manager-only (impersonation sessions) | — |
kadam_adv_get_audience_params | Hardcoded parameters a pixel/S2S audience substitutes into its code | — |
kadam_adv_set_audience_params | Replace the hardcoded parameters of a pixel/S2S audience | — |
kadam_adv_delete_audience | Delete audience permanently (requires confirm: true) | destructive |
#### Finance & Statistics
| Tool | Description | Annotations |
|---|---|---|
kadam_adv_list_finance_operations | Transaction history (deposits, charges, refunds) | readOnly |
kadam_adv_get_stats | Unified statistics — 3 report types via reportType param: custom (report builder with dimension/metric mapping), sites (per-site breakdown), postbacks (conversion logs) | readOnly |
Requires KADAM_PUB_API_KEY.
#### Sites (Sources)
| Tool | Description | Annotations |
|---|---|---|
kadam_pub_list_sources | List publisher sites with stats | readOnly |
kadam_pub_create_source | Add a new site (starts verification flow) | — |
kadam_pub_get_source | Get detailed site info | readOnly |
kadam_pub_update_source | Update site name | — |
kadam_pub_set_source_status | Change site status (active/paused/archived/unarchived) | idempotent |
#### Ad Units
| Tool | Description | Annotations |
|---|---|---|
kadam_pub_list_ad_units | List ad units for a site, filter by format (native/banner/push/popunder/inpagepush) | readOnly |
kadam_pub_set_ad_unit_status | Change ad unit status (active/paused/archived/restored) | idempotent |
#### User & Statistics
| Tool | Description | Annotations |
|---|---|---|
kadam_pub_get_user_info | Get publisher account info and balance | readOnly |
kadam_pub_get_stats | Publisher statistics with human-readable dimension/metric mapping | readOnly |
#### 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.
| Tool | Description | Annotations |
|---|---|---|
kadam_pub_list_mediation_networks | Catalog of networks, which have an account, and what an ad unit already runs | readOnly |
kadam_pub_connect_mediation_network | Attach a network to an ad unit (resolves account and placement itself) | — |
kadam_pub_update_mediation_network | Change geo, unique cap, proxy policy, tag template, placement or account | — |
kadam_pub_set_mediation_network_status | active / paused for a connection | idempotent |
kadam_pub_retest_mediation_network | Restart the forced test share (1-50%); starts a new measurement epoch | — |
kadam_pub_disconnect_mediation_network | Remove a connection (requires confirm) | destructive |
kadam_pub_update_mediation_network_account | Rotate the network API key, rename or disable the account | — |
kadam_pub_delete_mediation_network_account | Remove a network account (requires confirm) | destructive |
Static reference data the agent can read before calling tools:
| URI | Description |
|---|---|
kadam://reference/campaign-types | All ad format types with IDs, features, pricing, and creative specs |
kadam://reference/pricing-models | CPC, CPM, CPV, CPA Target with IDs and descriptions |
kadam://reference/creative-formats | Creative requirements per campaign type |
kadam://reference/ad-unit-types | Publisher ad unit formats with IDs |
kadam://reference/site-states | Publisher site lifecycle states |
kadam://reference/mediation | Outside ad networks: accounts, placements, connections, test share, income split |
kadam://reference/report-dimensions | Available dimensions and metrics for statistics tools |
kadam://reference/api-overview | General Kadam API capabilities overview |
Pre-built workflow templates that guide the agent through multi-step operations:
| Prompt | Description | Arguments |
|---|---|---|
kadam_launch_campaign | Step-by-step campaign creation (check types -> create folder -> create campaign -> add creatives) | type, name, url, budget |
kadam_campaign_performance | Campaign performance analysis with optimization recommendations | campaignId, period |
kadam_optimize_sites | Analyze site performance and suggest blacklist/whitelist changes | campaignId, minClicks, maxCPA |
kadam_account_overview | Full account overview — campaigns, spend, top performers | — |
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 promptsHttpClient instance per product, created on first usemaxResults (default 25, max 100) to prevent LLM context overflowreadOnlyHint, destructiveHint, idempotentHint to guide agent behaviorGET /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 unreachablegit clone https://github.com/kadam-official/mcp-server.git
cd mcp-server
npm install
cp .env.example .env # Fill in your API keysnpm 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)202 tests across 23 files using Vitest + MCP SDK InMemoryTransport:
npm test
# Test Files 23 passed (23)
# Tests 202 passed (202)The MCP Inspector provides a visual interface for testing:
npm run build
npm run inspectdocker build -t kadam-mcp-server .
docker run -i --rm -e KADAM_ADV_API_KEY=... kadam-mcp-serverThe .gitlab-ci.yml pipeline includes:
MIT
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.