mcp-bing-ads 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/config.example.json +16 -0
- package/dist/build-info.json +1 -0
- package/dist/errors.d.ts +17 -0
- package/dist/errors.js +60 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +755 -0
- package/dist/resilience.d.ts +3 -0
- package/dist/resilience.js +80 -0
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +143 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 drak-marketing
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Bing Ads MCP Server
|
|
2
|
+
|
|
3
|
+
Production-grade MCP server for Microsoft Advertising (Bing Ads) API. Enables Claude to manage Bing/Microsoft Ads accounts with full campaign, ad group, keyword, and performance analysis capabilities.
|
|
4
|
+
|
|
5
|
+
**Features:**
|
|
6
|
+
- 30+ production-tested tools
|
|
7
|
+
- Campaign, ad group, and keyword management
|
|
8
|
+
- Keyword performance analysis with quality scores
|
|
9
|
+
- Search term reporting & bid automation
|
|
10
|
+
- Budget & bid strategy optimization
|
|
11
|
+
- Campaign-level budget updates
|
|
12
|
+
- Negative keyword management (shared + campaign-level)
|
|
13
|
+
|
|
14
|
+
**Note:** ⚠️ First open-source Bing Ads MCP with comprehensive tooling
|
|
15
|
+
- No serious alternatives exist in the ecosystem
|
|
16
|
+
- Battle-tested across multiple accounts
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install mcp-bing-ads
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
1. **Get OAuth credentials:**
|
|
27
|
+
- Go to [Microsoft Azure Portal](https://portal.azure.com/)
|
|
28
|
+
- Create an Azure AD app registration
|
|
29
|
+
- Grant API permissions: `Microsoft Advertising API`
|
|
30
|
+
- Scopes: `https://ads.microsoft.com/msads.manage offline_access`
|
|
31
|
+
|
|
32
|
+
2. **Create `config.json`:**
|
|
33
|
+
```bash
|
|
34
|
+
cp config.example.json config.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
3. **Fill in your credentials:**
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"oauth": {
|
|
41
|
+
"client_id": "YOUR_AZURE_CLIENT_ID",
|
|
42
|
+
"client_secret": "YOUR_AZURE_CLIENT_SECRET"
|
|
43
|
+
},
|
|
44
|
+
"clients": {
|
|
45
|
+
"default": {
|
|
46
|
+
"customer_id": "YOUR_CUSTOMER_ID",
|
|
47
|
+
"account_id": "YOUR_ACCOUNT_ID",
|
|
48
|
+
"name": "My Account"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
4. **Set environment variables (recommended):**
|
|
55
|
+
```bash
|
|
56
|
+
export BING_ADS_CLIENT_ID="your_client_id"
|
|
57
|
+
export BING_ADS_CLIENT_SECRET="your_client_secret"
|
|
58
|
+
export BING_CUSTOMER_ID="your_customer_id"
|
|
59
|
+
export BING_ACCOUNT_ID="your_account_id"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Start the server
|
|
65
|
+
```bash
|
|
66
|
+
npm start
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Use with Claude Code
|
|
70
|
+
Add to `~/.claude.json`:
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"bing-ads": {
|
|
75
|
+
"type": "http",
|
|
76
|
+
"url": "http://localhost:3002"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Example API Calls
|
|
83
|
+
```typescript
|
|
84
|
+
// Get client context
|
|
85
|
+
bing_ads_get_client_context({ working_directory: "/path/to/project" })
|
|
86
|
+
|
|
87
|
+
// List campaigns
|
|
88
|
+
bing_ads_list_campaigns()
|
|
89
|
+
|
|
90
|
+
// Get campaign performance
|
|
91
|
+
bing_ads_get_campaign_performance({
|
|
92
|
+
start_date: "2026-01-01",
|
|
93
|
+
end_date: "2026-03-01"
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// Get keyword performance
|
|
97
|
+
bing_ads_keyword_performance({
|
|
98
|
+
start_date: "2026-02-01",
|
|
99
|
+
end_date: "2026-03-01"
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// Create negative keywords
|
|
103
|
+
bing_ads_add_shared_negatives({
|
|
104
|
+
shared_list_id: "list_123",
|
|
105
|
+
keywords: [
|
|
106
|
+
{ text: "cheap", match_type: "Phrase" },
|
|
107
|
+
{ text: "discount", match_type: "Exact" }
|
|
108
|
+
]
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## API Reference
|
|
113
|
+
|
|
114
|
+
### Campaigns
|
|
115
|
+
- `bing_ads_list_campaigns()` — List all campaigns
|
|
116
|
+
- `bing_ads_get_campaign_performance(start_date, end_date)` — Campaign metrics
|
|
117
|
+
- `bing_ads_update_campaign_budget(campaign_id, daily_budget)` — Update daily spend
|
|
118
|
+
|
|
119
|
+
### Ad Groups
|
|
120
|
+
- `bing_ads_list_ad_groups(campaign_id)` — List ad groups in campaign
|
|
121
|
+
|
|
122
|
+
### Keywords
|
|
123
|
+
- `bing_ads_keyword_performance(start_date, end_date, [campaign_ids])` — Keyword metrics & QS
|
|
124
|
+
- `bing_ads_search_term_report(start_date, end_date)` — Search terms that triggered ads
|
|
125
|
+
- `bing_ads_pause_keywords(ad_group_id, keyword_ids)` — Pause keywords
|
|
126
|
+
|
|
127
|
+
### Negative Keywords
|
|
128
|
+
- `bing_ads_list_shared_entities([type])` — List shared negative lists
|
|
129
|
+
- `bing_ads_add_shared_negatives(list_id, keywords)` — Add to shared list
|
|
130
|
+
- `bing_ads_add_campaign_negatives(campaign_id, keywords)` — Campaign-level negatives
|
|
131
|
+
|
|
132
|
+
### Performance Reports
|
|
133
|
+
- Campaign performance (ROI, conversions, CTR, CPC)
|
|
134
|
+
- Keyword performance (QS, expected CTR, ad relevance, landing page experience)
|
|
135
|
+
- Search term insights (which queries are converting)
|
|
136
|
+
|
|
137
|
+
## Key Metrics & Definitions
|
|
138
|
+
|
|
139
|
+
**Quality Score (QS):** 1-10 rating of keyword quality
|
|
140
|
+
- 1-3: Poor
|
|
141
|
+
- 4-6: Average
|
|
142
|
+
- 7-10: Excellent
|
|
143
|
+
|
|
144
|
+
**Expected CTR:** 1-9 rating of expected click-through rate
|
|
145
|
+
**Ad Relevance:** 1-9 rating of relevance to search query
|
|
146
|
+
**Landing Page Experience:** 1-9 rating of landing page quality
|
|
147
|
+
|
|
148
|
+
## CLI Tools
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npm run dev # Run in dev mode (tsx)
|
|
152
|
+
npm run build # Compile TypeScript
|
|
153
|
+
npm test # Run contract tests
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Architecture
|
|
157
|
+
|
|
158
|
+
**Files:**
|
|
159
|
+
- `src/index.ts` — MCP server, OAuth flow, tool handlers
|
|
160
|
+
- `src/tools.ts` — Tool schema definitions
|
|
161
|
+
- `src/errors.ts` — Error handling & classification
|
|
162
|
+
- `config.json` — Credentials & client mapping
|
|
163
|
+
|
|
164
|
+
**Error Classification:**
|
|
165
|
+
- Authentication errors (token expired)
|
|
166
|
+
- Rate limit errors (retry with backoff)
|
|
167
|
+
- Service errors (API temporarily unavailable)
|
|
168
|
+
- Validation errors (bad input)
|
|
169
|
+
|
|
170
|
+
## Development
|
|
171
|
+
|
|
172
|
+
### Adding a New Tool
|
|
173
|
+
1. Define schema in `src/tools.ts`
|
|
174
|
+
2. Add handler in `src/index.ts` tool dispatch
|
|
175
|
+
3. Add contract test in `.contract.test.ts`
|
|
176
|
+
4. Test with `npm test`
|
|
177
|
+
|
|
178
|
+
### Testing
|
|
179
|
+
```bash
|
|
180
|
+
npm test -- --run # Single run
|
|
181
|
+
npm test -- --watch # Watch mode
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Troubleshooting
|
|
185
|
+
|
|
186
|
+
### `Config file not found`
|
|
187
|
+
```bash
|
|
188
|
+
cp config.example.json config.json
|
|
189
|
+
# Fill in your Azure credentials and Bing Ads IDs
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### `Missing required credentials`
|
|
193
|
+
Check that:
|
|
194
|
+
- `BING_ADS_CLIENT_ID` and `BING_ADS_CLIENT_SECRET` are set (or in config.json)
|
|
195
|
+
- `BING_CUSTOMER_ID` and `BING_ACCOUNT_ID` are provided
|
|
196
|
+
- OAuth token is valid (expires, may need refresh)
|
|
197
|
+
|
|
198
|
+
### `Rate limit exceeded`
|
|
199
|
+
Bing Ads applies rate limits. The server handles common retries automatically. If you hit limits frequently:
|
|
200
|
+
- Batch operations when possible
|
|
201
|
+
- Reduce query frequency
|
|
202
|
+
- Wait before retrying
|
|
203
|
+
|
|
204
|
+
### `Quality Score is 0`
|
|
205
|
+
QS = 0 means keyword hasn't been shown enough times yet. Increase impressions or wait for more data.
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|
|
210
|
+
|
|
211
|
+
## Contributing
|
|
212
|
+
|
|
213
|
+
Contributions welcome! Please:
|
|
214
|
+
1. Add tests for new features
|
|
215
|
+
2. Update README
|
|
216
|
+
3. Follow existing code style
|
|
217
|
+
4. Tag releases
|
|
218
|
+
|
|
219
|
+
## Support
|
|
220
|
+
|
|
221
|
+
- **Issues:** GitHub issues for bugs/feature requests
|
|
222
|
+
- **Docs:** See `docs/` folder for detailed API reference
|
|
223
|
+
- **Community:** GitHub Discussions
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
**Maintained by:** VS Code AI team & community contributors
|
|
228
|
+
|
|
229
|
+
**Last Updated:** 2026-03-13
|
|
230
|
+
|
|
231
|
+
**Stability:** Production-ready
|
|
232
|
+
|
|
233
|
+
**Note:** This is the first comprehensive open-source Bing Ads MCP. No other serious alternatives exist.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"oauth": {
|
|
3
|
+
"client_id": "YOUR_MICROSOFT_CLIENT_ID",
|
|
4
|
+
"client_secret": "YOUR_MICROSOFT_CLIENT_SECRET",
|
|
5
|
+
"token_url": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
6
|
+
"scope": "https://ads.microsoft.com/msads.manage offline_access"
|
|
7
|
+
},
|
|
8
|
+
"clients": {
|
|
9
|
+
"default": {
|
|
10
|
+
"customer_id": "YOUR_BING_CUSTOMER_ID",
|
|
11
|
+
"account_id": "YOUR_BING_ACCOUNT_ID",
|
|
12
|
+
"name": "Primary Account",
|
|
13
|
+
"folder": "/path/to/working/directory"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"sha":"57a49a1","builtAt":"2026-03-13T17:44:14.321Z"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class BingAdsAuthError extends Error {
|
|
2
|
+
readonly cause?: unknown | undefined;
|
|
3
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
4
|
+
}
|
|
5
|
+
export declare class BingAdsRateLimitError extends Error {
|
|
6
|
+
readonly retryAfterMs: number;
|
|
7
|
+
constructor(retryAfterMs: number, cause?: unknown);
|
|
8
|
+
}
|
|
9
|
+
export declare class BingAdsServiceError extends Error {
|
|
10
|
+
readonly cause?: unknown | undefined;
|
|
11
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
12
|
+
}
|
|
13
|
+
export declare function validateCredentials(): {
|
|
14
|
+
valid: boolean;
|
|
15
|
+
missing: string[];
|
|
16
|
+
};
|
|
17
|
+
export declare function classifyError(error: any): Error;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// TYPED ERRORS (mirrors motion-mcp pattern)
|
|
3
|
+
// ============================================
|
|
4
|
+
export class BingAdsAuthError extends Error {
|
|
5
|
+
cause;
|
|
6
|
+
constructor(message, cause) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.cause = cause;
|
|
9
|
+
this.name = "BingAdsAuthError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class BingAdsRateLimitError extends Error {
|
|
13
|
+
retryAfterMs;
|
|
14
|
+
constructor(retryAfterMs, cause) {
|
|
15
|
+
super(`Rate limited, retry after ${retryAfterMs}ms`);
|
|
16
|
+
this.retryAfterMs = retryAfterMs;
|
|
17
|
+
this.name = "BingAdsRateLimitError";
|
|
18
|
+
this.cause = cause;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class BingAdsServiceError extends Error {
|
|
22
|
+
cause;
|
|
23
|
+
constructor(message, cause) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.cause = cause;
|
|
26
|
+
this.name = "BingAdsServiceError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// ============================================
|
|
30
|
+
// STARTUP CREDENTIAL VALIDATION
|
|
31
|
+
// ============================================
|
|
32
|
+
export function validateCredentials() {
|
|
33
|
+
const required = [
|
|
34
|
+
"BING_ADS_DEVELOPER_TOKEN",
|
|
35
|
+
"BING_ADS_CLIENT_ID",
|
|
36
|
+
"BING_ADS_REFRESH_TOKEN",
|
|
37
|
+
];
|
|
38
|
+
const missing = required.filter((key) => !process.env[key] || process.env[key].trim() === "");
|
|
39
|
+
return { valid: missing.length === 0, missing };
|
|
40
|
+
}
|
|
41
|
+
export function classifyError(error) {
|
|
42
|
+
const message = error?.message || String(error);
|
|
43
|
+
const status = error?.status;
|
|
44
|
+
if (status === 401 ||
|
|
45
|
+
status === 403 ||
|
|
46
|
+
message.includes("invalid_grant") ||
|
|
47
|
+
message.includes("OAuth token refresh failed") ||
|
|
48
|
+
message.includes("AuthenticationTokenExpired") ||
|
|
49
|
+
message.includes("InvalidCredentials")) {
|
|
50
|
+
return new BingAdsAuthError(`Auth failed: ${message}. Refresh token may be expired. Re-authenticate and update Keychain.`, error);
|
|
51
|
+
}
|
|
52
|
+
if (status === 429 || message.includes("RateLimit") || message.includes("CallRateExceeded")) {
|
|
53
|
+
const retryMs = 60_000;
|
|
54
|
+
return new BingAdsRateLimitError(retryMs, error);
|
|
55
|
+
}
|
|
56
|
+
if (status >= 500 || message.includes("InternalError")) {
|
|
57
|
+
return new BingAdsServiceError(`Bing Ads API server error: ${message}`, error);
|
|
58
|
+
}
|
|
59
|
+
return error;
|
|
60
|
+
}
|
package/dist/index.d.ts
ADDED