Content
# LINE Ads MCP Server
> Built by **Praphat Srisuma (Ong)** · [Spark Factor Co., Ltd.](https://sparkth.io) · LINE Certified Coach
> Licensed under [Apache 2.0](LICENSE) — attribution required, see [NOTICE](NOTICE)
MCP server for Claude to call LINE Ads API v3 directly, instead of controlling the browser for tasks that the API can do, such as reporting, campaign/adset/ad management, and audience management.
## ⚡ Installation with Claude Cowork (Easiest Method)
No need to type commands yourself — just copy and paste the prompt below into **Claude Desktop (Cowork mode)** and let Claude do everything:
```
Help me set up LINE Ads MCP Server.
Steps to follow:
1. Clone repo: https://github.com/ongkub/line-ads-mcp.git
- Recommended path: ~/line-ads-mcp or ~/Desktop/line-ads-mcp
- If the folder already exists, use git pull instead.
2. Install dependencies:
cd <path cloned to>
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
3. Create .env file from .env.example:
cp .env.example .env
- Then ask me for LINE_ADS_ACCESS_KEY, LINE_ADS_SECRET_KEY, LINE_ADS_AD_ACCOUNT_ID
- (Found in LINE Ads Manager → Settings → API Management)
- Fill those values into .env.
4. Update claude_desktop_config.json to add this MCP server block:
{
"mcpServers": {
"line-ads": {
"command": "<absolute path of .venv/bin/python>",
"args": ["-m", "line_ads_mcp.server"],
"cwd": "<absolute path of repo>",
"env": {
"LINE_ADS_ACCESS_KEY": "<from .env>",
"LINE_ADS_SECRET_KEY": "<from .env>",
"LINE_ADS_AD_ACCOUNT_ID": "<from .env>"
}
}
}
}
- macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
- Windows: %APPDATA%\Claude\claude_desktop_config.json
- If the file already has mcpServers, add "line-ads" to it, don't overwrite the existing content.
5. Let me know if it's successful, and tell me to quit and reopen Claude Desktop to load the MCP.
If any information is missing during the process, feel free to ask me step by step.
```
> **Note:** After Claude Cowork is successful, you need to **quit and reopen Claude Desktop** (not just close the window) to load the new MCP server.
### Final Step — Set System Prompt
After restarting, create a new **Project** in Claude Desktop → **Project Instructions** → copy and paste the content from [`CLAUDE_PROJECT_PROMPT.md`](CLAUDE_PROJECT_PROMPT.md) entirely.
That's it, you're ready to use it.
### Update to New Version with Claude Cowork
When there's an update on GitHub, use this prompt:
```
Help me update LINE Ads MCP Server.
Repo is at: https://github.com/ongkub/line-ads-mcp.git
Folder on the machine is: (tell the path).
Follow the steps:
1. cd into that folder
2. git pull --rebase origin main
3. source .venv/bin/activate && pip install -e .
4. python -m pytest (if tests fail, let me know)
5. Let me know to quit and reopen Claude Desktop
```
## For Marketers — Usage through AI
No coding required, no need to open LINE Ads Manager every time — just talk to AI and let it pull data and manage campaigns.
### Usage with Claude Desktop (Recommended)
Claude Desktop supports MCP directly, so you can use it right after a one-time setup.
**Steps:**
1. **Install Python and this repo**
```bash
git clone https://github.com/ongkub/line-ads-mcp.git
cd line-ads-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e .
```
2. **Set credentials in `.env`**
```bash
cp .env.example .env
# Edit .env file and fill in Access Key / Secret Key from LINE Ads Manager
# (Settings → API Management)
LINE_ADS_ACCESS_KEY=your_access_key
LINE_ADS_SECRET_KEY=your_secret_key
LINE_ADS_AD_ACCOUNT_ID=A_xxxxxxxxxxxx
```
3. **Add MCP server in Claude Desktop**
Open Claude Desktop config file:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
Add this block:
```json
{
"mcpServers": {
"line-ads": {
"command": "/absolute/path/to/.venv/bin/python",
"args": ["-m", "line_ads_mcp.server"],
"cwd": "/absolute/path/to/line-ads-mcp",
"env": {
"LINE_ADS_ACCESS_KEY": "your_key",
"LINE_ADS_SECRET_KEY": "your_secret",
"LINE_ADS_AD_ACCOUNT_ID": "A_xxxxxxxxxxxx"
}
}
}
}
```
4. **Restart Claude Desktop and you're good to go**
5. **Set System Prompt (important)** — so Claude knows the role and security rules automatically
Go to Claude Desktop → create a new **Project** → **Project Instructions** → copy and paste from [`CLAUDE_PROJECT_PROMPT.md`](CLAUDE_PROJECT_PROMPT.md)
**Example prompts in Claude after setup:**
```
Show me all running campaigns.
```
```
Summarize the performance of the last 7 days for me, which campaign has the lowest CPF.
```
```
Pause campaign "Add friends: ..." temporarily.
```
### Usage with Gemini CLI
Gemini CLI supports MCP server through `settings.json` file or `gemini mcp add` command.
**Basic Steps:**
1. **Install repo and dependencies**
```bash
git clone https://github.com/ongkub/line-ads-mcp.git
cd line-ads-mcp
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
```
2. **Fill credentials in `.env`**
```bash
LINE_ADS_ACCESS_KEY=your_access_key
LINE_ADS_SECRET_KEY=your_secret_key
LINE_ADS_BASE_URL=https://ads.line.me/api/v3
LINE_ADS_AD_ACCOUNT_ID=A_xxxxxxxxxxxx
```
3. **Add MCP server to Gemini CLI**
Using command:
```bash
gemini mcp add line-ads \
-e LINE_ADS_ACCESS_KEY=your_access_key \
-e LINE_ADS_SECRET_KEY=your_secret_key \
-e LINE_ADS_BASE_URL=https://ads.line.me/api/v3 \
-e LINE_ADS_AD_ACCOUNT_ID=A_xxxxxxxxxxxx \
/absolute/path/to/line-ads-mcp/.venv/bin/python \
-m line_ads_mcp.server
```
After using this command, check `settings.json` to ensure `cwd` points to this repo correctly. If not, add it manually as per the JSON example below.
Or edit `~/.gemini/settings.json` / `.gemini/settings.json` file:
```json
{
"mcpServers": {
"line-ads": {
"command": "/absolute/path/to/line-ads-mcp/.venv/bin/python",
"args": ["-m", "line_ads_mcp.server"],
"cwd": "/absolute/path/to/line-ads-mcp",
"env": {
"LINE_ADS_ACCESS_KEY": "your_access_key",
"LINE_ADS_SECRET_KEY": "your_secret_key",
"LINE_ADS_BASE_URL": "https://ads.line.me/api/v3",
"LINE_ADS_AD_ACCOUNT_ID": "A_xxxxxxxxxxxx"
},
"timeout": 600000,
"trust": false
}
}
}
```
4. **Check if Gemini sees MCP tools**
```bash
gemini
/mcp
```
You should see a server named `line-ads` and tools like `list_campaigns`, `get_report`, `create_campaign`
5. **Set instruction for Gemini to read before usage**
At the start of the session, paste:
```text
Read CLAUDE_PROJECT_PROMPT.md, AGENTS.md, and relevant workflow/knowledge before calling LINE Ads MCP tools.
Every write action must have dry_run=True initially, and wait for "ยืนยัน" before dry_run=False.
Don't assume currency values like budget, bid cap, CPF, CPC, CPA.
```
**Example prompts in Gemini CLI:**
```text
Use LINE Ads MCP to pull all active campaigns and summarize their performance over the last 7 days.
```
```text
I want to create a campaign to add LINE OA friends using MCP Manual/API-first.
Read workflow/02-campaign.md first and ask for missing information step by step.
```
Reference: [Gemini CLI MCP server docs](https://google-gemini.github.io/gemini-cli/docs/tools/mcp-server.html)
### Usage with OpenAI Codex (for technical/system operator teams)
[Codex](https://codex.com) is an AI coding agent from OpenAI that can run Python code directly.
No need to go through the MCP protocol — Codex imports tools and calls them directly.
**Steps:**
1. **Open Codex and clone this repo into the environment**
```bash
git clone https://github.com/ongkub/line-ads-mcp.git
cd line-ads-mcp
pip install -e .
```
2. **Set `.env`** like Claude Desktop (step 2 above)
3. **Tell Codex what you want to do**, e.g.:
```
Pull all campaigns and summarize their performance over the last 7 days.
```
```
Create a campaign to add friends with a budget of 300 THB/day and show the payload for confirmation.
```
Codex will import tools from `src/line_ads_mcp/tools/` and call them directly.
The `dry_run=True` security rule still applies.
### Security for Marketers
- **Every action related to money** (create campaign, set budget, create ad) will **show a preview first** — AI must confirm before sending.
- **No delete button** — no tool for deleting campaigns/ad/adset in this set.
- Credentials are stored in `.env` on your machine, not through an external server.
## Setup
```bash
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
```
Configure `.env`:
```bash
LINE_ADS_ACCESS_KEY=your_access_key
LINE_ADS_SECRET_KEY=your_secret_key
LINE_ADS_BASE_URL=https://ads.line.me/api/v3
LINE_ADS_AD_ACCOUNT_ID=A_xxxxxxxxxxxx
```
## Update From Git
Use when there's a new version update on GitHub and you want to pull it down to your machine.
### No Local File Modifications
```bash
cd /path/to/line-ads-mcp
git status
git pull --rebase origin main
source .venv/bin/activate
pip install -e ".[dev]"
python -m pytest
```
If using this machine path:
```bash
cd "/Users/ongkub/Desktop/lineads-ai/LINE Ads V0.1.3 - MCP Layer"
git pull --rebase origin main
source .venv/bin/activate
pip install -e ".[dev]"
python -m pytest
```
### Existing Local File Modifications
Check first:
```bash
git status
```
If there are local modifications not yet committed:
```bash
git stash push -m "local work before update"
git pull --rebase origin main
git stash pop
python -m pytest
```
If there are conflicts after `git stash pop`, resolve the conflicting files and run:
```bash
git status
python -m pytest
```
### Files That Should Not Be Overwritten
- `.env` should not be committed and should not be overwritten from Git.
- Credentials such as Access Key / Secret Key should be stored in `.env` or AI client config only.
- If there is a `.env.example`, compare and add new keys to `.env` manually.
## Run
```bash
python -m line_ads_mcp.server
```
or use the console script:
```bash
line-ads-mcp
```
## Claude Desktop Config
```json
{
"mcpServers": {
"line-ads": {
"command": "python",
"args": ["-m", "line_ads_mcp.server"],
"cwd": "/Users/ongkub/Desktop/lineads-ai/LINE Ads V0.1.3 - MCP Layer",
"env": {
"LINE_ADS_ACCESS_KEY": "your_key",
"LINE_ADS_SECRET_KEY": "your_secret",
"LINE_ADS_AD_ACCOUNT_ID": "A_xxxxxxxxxxxx"
}
}
}
}
```
## Safety
- No delete tools.
- Write tools set `dry_run=true` by default.
- Budget/bid changes require assistant to confirm with the user before calling `dry_run=false`.
- Credentials are read from environment variables only, not hardcoded in the code.
- Error messages are returned in Thai for the assistant to forward to the user immediately.
## Tool Status
### ✅ Read-ready (smoke test passed with real API)
| Tool | Notes |
|---|---|
| `list_campaigns` | ✅ |
| `list_adsets` | ✅ |
| `list_ads` | ✅ |
| `get_ad_status` | ✅ |
| `get_report` / `get_daily_report` / `get_weekly_report` | ✅ |
| `list_audiences` | ✅ |
| `list_advanced_targeting_codes` | ✅ Used to find official interest/behavior/status codes |
### ✅ Write-ready (payload matches spec + tests passed — still dry_run=true by default)
| Tool | Budget/Bid | Objective/Status | Notes |
|---|---|---|---|
| `create_campaign` | `dailyBudgetMicro` / `totalBudgetMicro` (THB × 1M) | `campaignObjective: GAIN_FRIENDS` | Must specify `start_date` always, e.g., `2026-05-14T09:00:00+07:00` |
| `update_campaign` | `dailyBudgetMicro` | `configuredStatus` | |
| `pause_campaign` / `resume_campaign` | — | `configuredStatus: PAUSED/ACTIVE` | |
| `create_adset` | `dailyBudgetMicro` / `bidAmountMicro` (THB × 1M) | `bidType`, `bidStrategy` required | If `interest_codes` are provided, use `targetingMode=MANUAL` + `includeAdvancedTargetings` |
| `update_adset` | `dailyBudgetMicro` / `bidAmountMicro` | `configuredStatus` | |
| `pause_adset` / `resume_adset` | — | `configuredStatus: PAUSED/ACTIVE` | |
### ✅ Write-ready — payload verified from real API response + error probing
| Tool | Notes |
|---|---|
| `create_ad` | Creative is a nested object; uses `imageHash` (from `upload_media`), `title`, `callToAction.type`; `title`/`description` ≤ 20 characters |
| `upload_media` | Endpoint `/media/upload`; must send `mediaType: IMAGE\|VIDEO`; signing uses `"multipart/form-data"` |
### ⚠️ Dry-run only (403 permissions — code is correct, but account feature not enabled)
| Tool | Status |
|---|---|
| `create_audience` | API returns 403 for all types — must enable Custom Audience feature in LINE Ads Manager first |
## Budget & Bid Units
LINE Ads API v3 uses **micro** units for all currency values:
```
1 THB = 1,000,000 micro
Example from real adset:
dailyBudgetMicro: 300_000_000 → 300 THB/day
bidAmountMicro: 10_000_000 → 10 THB/friend
```
Tools accept normal THB values (float) and convert to micro automatically via `to_micro()` in `common.py`.
## Interest Targeting
LINE Ads API does not accept direct interest names like `Marketing`, `Branding`, `Advertising`, `Business`; only official codes are accepted.
Use [knowledge/interest-catalog-INDEX.md](knowledge/interest-catalog-INDEX.md) as a local cache first to save tokens/API calls, then load `knowledge/interest-detail-*.md` for specific categories or call `list_advanced_targeting_codes` when necessary.
For `TH + GAIN_FRIENDS` tested in real scenarios:
```
อาชีพและธุรกิจ = code "4"
```
Broad interest targeting uses `interest_codes`:
```json
{
"targeting": {
"targetingMode": "MANUAL",
"ageMin": 25,
"ageMax": 44,
"country": "TH",
"excludedCustomAudienceIds": ["5343822743474"],
"includeAdvancedTargetings": [
{ "interests": ["4"] }
]
}
}
```
To narrow the audience, use `interest_groups` like `[[ "4" ], [ "12" ]]` to create multiple objects in `includeAdvancedTargetings`:
```json
"includeAdvancedTargetings": [
{ "interests": ["4"] },
{ "interests": ["12"] }
]
```
If `targetingMode=AUTO`, interest/custom advanced targeting will not be used.
## Valid Campaign Objectives
```
GAIN_FRIENDS ← Gain LINE OA friends (confirmed from real API)
WEBSITE_TRAFFIC ← Website traffic
CONVERSIONS
REACH
APP_INSTALL
VIDEO_VIEW
```
> ⚠️ `FRIEND_ADDED`, `VISIT_MY_WEBSITE`, `APP_INSTALLS`, `VIDEO_VIEWS` are outdated enums — tools will reject them immediately.
## Acknowledgements
This project was developed using AI coding agents as part of the development process:
- **OpenAI Codex (o3)** — main scaffolding, auth layer, tool architecture
- **Anthropic Claude** — payload verification, API probing, test suite
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available