Skip to main content
Glama
xar

bing-ads-mcp

by xar
README.md
# bing-ads-mcp

An MCP (Model Context Protocol) server that lets AI assistants manage your Microsoft Advertising (Bing Ads) campaigns. Built with [Bun](https://bun.sh) and the [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk).

Works with Claude Code, Claude Desktop, Cursor, and any MCP-compatible client.

## Why

The Microsoft Advertising web interface is painful for bulk operations. This MCP server gives AI assistants direct access to your Bing Ads account through clean, typed tools -- so you can manage campaigns, ad groups, keywords, and extensions conversationally.

## Features

- **24 tools** covering campaigns, ad groups, ads, keywords, negative keywords, and ad extensions
- **OAuth2 with auto-refresh** -- built-in browser-based setup flow, tokens auto-refresh
- **Auto-discovers Customer ID** -- no need to hunt for it in the UI
- **Streamable HTTP transport** -- works as a remote MCP server
- **Zero config** -- just add credentials and go

## Quick Start

### Prerequisites

- [Bun](https://bun.sh) v1.0+
- A Microsoft Advertising account
- An Azure App Registration ([setup guide below](#azure-app-registration))

### Install & Run

```bash
git clone https://github.com/user/bing-ads-mcp.git
cd bing-ads-mcp
bun install
```

Create a `.env` file with your credentials:

```env
BING_CLIENT_ID=your-azure-app-client-id
BING_CLIENT_SECRET=your-azure-app-client-secret
BING_DEVELOPER_TOKEN=your-developer-token
BING_ACCOUNT_ID=your-account-id
```

Authenticate via OAuth (opens browser):

```bash
bun run setup
```

Start the server:

```bash
bun run start
```

The MCP server runs at `http://localhost:3100/mcp`.

### Connect to Your AI Client

**Claude Code** -- add to `~/.claude.json` or project `.mcp.json`:

```json
{
  "mcpServers": {
    "bing-ads": {
      "url": "http://localhost:3100/mcp"
    }
  }
}
```

**Claude Desktop** -- add to your MCP settings:

```json
{
  "mcpServers": {
    "bing-ads": {
      "url": "http://localhost:3100/mcp"
    }
  }
}
```

## Available Tools

### Campaigns

| Tool | Description |
|------|-------------|
| `list_campaigns` | List all campaigns, optionally filter by type |
| `get_campaign` | Get detailed campaign info by IDs |
| `create_campaign` | Create campaigns with name, budget, type, status |
| `update_campaign` | Update campaign name, status, budget |
| `delete_campaigns` | Delete campaigns by ID |

### Ad Groups

| Tool | Description |
|------|-------------|
| `list_ad_groups` | List ad groups in a campaign |
| `create_ad_group` | Create ad groups with CPC bid, network targeting |
| `update_ad_group` | Update ad group name, status, bid |
| `delete_ad_groups` | Delete ad groups by ID |

### Ads

| Tool | Description |
|------|-------------|
| `list_ads` | List ads in an ad group |
| `create_responsive_search_ad` | Create RSAs with headlines, descriptions, URLs |
| `update_ad` | Update ad content, status, URLs |
| `delete_ads` | Delete ads by ID |

### Keywords

| Tool | Description |
|------|-------------|
| `list_keywords` | List keywords in an ad group |
| `create_keywords` | Add keywords with match type and bid |
| `update_keywords` | Update keyword text, bid, match type, status |
| `delete_keywords` | Delete keywords by ID |

### Negative Keywords

| Tool | Description |
|------|-------------|
| `list_negative_keywords` | List negatives for a campaign or ad group |
| `add_negative_keywords` | Add negative keywords (Exact or Phrase match) |
| `delete_negative_keywords` | Delete negative keywords by ID |

### Ad Extensions

| Tool | Description |
|------|-------------|
| `list_ad_extensions` | List extensions by type |
| `get_ad_extensions` | Get extension details by IDs |
| `create_sitelink_extension` | Create sitelink extensions |
| `create_callout_extension` | Create callout extensions |
| `create_structured_snippet_extension` | Create structured snippets |
| `associate_ad_extensions` | Link extensions to campaigns or ad groups |
| `delete_ad_extensions` | Delete extensions by ID |

## Setup Guide

You need 4 values for your `.env` file. Here's how to get each one step by step.

### Step 1: Create an Azure App Registration (`BING_CLIENT_ID` + `BING_CLIENT_SECRET`)

This creates the OAuth app that lets the MCP server authenticate with Microsoft on your behalf.

1. Go to [Azure Portal > App registrations](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)
   - Sign in with the same Microsoft account you use for Microsoft Advertising
2. Click **+ New registration** at the top
3. Fill in the form:
   - **Name**: `Bing Ads MCP` (or anything you like)
   - **Supported account types**: Select **"Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)"**
   - **Redirect URI**: Select **Web** from the dropdown, then enter: `http://localhost:3456/callback`
4. Click **Register**
5. You'll land on the app's **Overview** page. Copy the **Application (client) ID** -- this is your `BING_CLIENT_ID`
6. In the left sidebar, click **Certificates & secrets**
7. Click **+ New client secret**
   - **Description**: `MCP server` (or anything)
   - **Expires**: Pick an expiry (e.g. 24 months)
8. Click **Add**
9. Copy the **Value** column immediately (it won't be shown again) -- this is your `BING_CLIENT_SECRET`

> **Important**: You do NOT need to add any API permissions in the Azure Portal. The `msads.manage` scope is requested automatically at runtime during the OAuth consent flow.

### Step 2: Get Your Developer Token (`BING_DEVELOPER_TOKEN`)

The developer token authorizes your app to use the Bing Ads API.

1. Go to [Microsoft Advertising](https://ads.microsoft.com) and sign in
2. Navigate to **Tools** > **Developer Portal** (or go directly to [developers.ads.microsoft.com](https://developers.ads.microsoft.com/Account))
3. If you don't have a developer token yet, request one -- for personal use it's typically approved instantly
4. Go to the **Account** tab
5. Copy your **Developer Token** -- this is your `BING_DEVELOPER_TOKEN`

> **Note**: For sandbox/testing, you can use the universal sandbox token `BBD37VB98`.

### Step 3: Get Your Account ID (`BING_ACCOUNT_ID`)

1. Go to [Microsoft Advertising](https://ads.microsoft.com) and sign in
2. Click **Settings** (gear icon) in the left sidebar
3. Click **Account settings**
4. Find **Account ID** (a numeric value like `138954571`) -- this is your `BING_ACCOUNT_ID`
   - This is NOT the "Account number" (which looks like `F107MTKS`) -- you need the numeric ID

### Step 4: Create Your `.env` File

Create a `.env` file in the project root with your 4 values:

```env
BING_CLIENT_ID=your-client-id-from-step-1
BING_CLIENT_SECRET=your-client-secret-from-step-1
BING_DEVELOPER_TOKEN=your-developer-token-from-step-2
BING_ACCOUNT_ID=your-account-id-from-step-3
```

You can leave `BING_CUSTOMER_ID` and `BING_REFRESH_TOKEN` empty -- both are filled automatically:
- **Customer ID** is auto-discovered via the API on first request
- **Refresh Token** is saved when you run `bun run setup`

### Step 5: Authenticate

Run the OAuth setup to get your refresh token:

```bash
bun run setup
```

This opens your browser to Microsoft's login page. Sign in, grant consent, and the refresh token is automatically saved to your `.env` file. You'll see "Setup complete!" in the terminal when done.

### Step 6: Verify

Test that everything works:

```bash
bun run test-api
```

This will authenticate, auto-discover your Customer ID, and list your campaigns. If you see your campaigns printed, you're all set.

## Commands

| Command | Description |
|---------|-------------|
| `bun run start` | Start the MCP server on port 3100 |
| `bun run setup` | Run OAuth flow (opens browser for consent) |
| `bun run refresh` | Re-authenticate when token expires |
| `bun run test-api` | Test API connectivity by listing campaigns |
| `bun run inspect` | Open MCP Inspector for interactive testing |

## Architecture

```
index.ts                 Entry point -- MCP server + Streamable HTTP via Bun.serve()
setup.ts                 OAuth setup CLI -- opens browser, saves tokens to .env
test-api.ts              API connection test script

src/
  auth.ts                OAuth2 token management (auto-refresh, caching, persistence)
  client.ts              Bing Ads REST API client (auto-discovers Customer ID)
  types.ts               TypeScript types for API objects
  tools/
    campaigns.ts         Campaign CRUD
    adgroups.ts          Ad Group CRUD
    ads.ts               Ad CRUD (Responsive Search Ads)
    keywords.ts          Keyword CRUD
    negative-keywords.ts Negative keyword management
    extensions.ts        Ad extensions (sitelinks, callouts, snippets, associations)
```

## How It Works

1. **Auth**: OAuth2 authorization code flow with Microsoft identity platform. Refresh tokens are stored in `.env` and auto-refreshed on expiry.
2. **API**: Thin wrapper over the [Bing Ads REST API v13](https://learn.microsoft.com/en-us/advertising/campaign-management-service/campaign-management-service-reference?view=bingads-13) using native `fetch()`.
3. **Transport**: Streamable HTTP transport via `Bun.serve()` -- each MCP client session gets its own server instance with full state isolation.
4. **Customer ID**: Automatically discovered via the `GetUser` API on first request and cached to `.env`.

## Troubleshooting

| Problem | Solution |
|---------|----------|
| "No refresh token available" | Run `bun run setup` to authenticate |
| Token expired / 401 errors | Run `bun run refresh` to re-authenticate |
| Port 3100 in use | `lsof -ti:3100 \| xargs kill -9` |
| Customer ID errors | Auto-discovered on first call. Check Microsoft Advertising Settings if issues persist |
| API errors with TrackingId | Use the TrackingId when contacting Microsoft support |

## Tech Stack

- **[Bun](https://bun.sh)** -- runtime, HTTP server, env loading, file I/O
- **[MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)** -- Model Context Protocol server
- **[Zod](https://zod.dev)** -- tool parameter validation
- **[Microsoft Advertising REST API v13](https://learn.microsoft.com/en-us/advertising/guides/?view=bingads-13)** -- campaign management

## License

MIT