Skip to content

Commit cbe4c63

Browse files
authored
feat(auth)!: drop PIPEBOARD_API_TOKEN auth from the self-hosted package (#157)
* feat(auth)!: drop PIPEBOARD_API_TOKEN auth from the self-hosted package The PIPEBOARD_API_TOKEN path exchanged a Pipeboard API token for the underlying Meta access token, which defeated the account/permission scoping on that API token; the endpoint behind it has been removed. Self-hosted users now authenticate with META_ACCESS_TOKEN from their own Meta app, or with the local OAuth flow via META_APP_ID. Anyone who wants to keep using a Pipeboard API token should use the hosted MCP at https://meta-ads.mcp.pipeboard.co/, where Pipeboard resolves the Meta credential server-side and enforces scoping. Deletes pipeboard_auth.py and meta_ads_auth.sh, and startup now warns on stderr (not stdout, which is the JSON-RPC channel on stdio) when PIPEBOARD_API_TOKEN is still set. Docs, smithery.yaml, and tests updated. * chore(release): bump to 1.0.120
1 parent ef2592d commit cbe4c63

17 files changed

Lines changed: 229 additions & 890 deletions

‎STREAMABLE_HTTP_SETUP.md‎

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,25 @@ python -m meta_ads_mcp --transport streamable-http --host 0.0.0.0 --port 9000
1818

1919
### 2. Set Authentication
2020

21-
Set your Pipeboard token as an environment variable. This is optional for HTTP transport if you provide the token in the header, but it can be useful for command-line use.
21+
When you run this server yourself, the credential is a **Meta access token** from
22+
your own Meta app — create one at
23+
[developers.facebook.com](https://developers.facebook.com/apps/). A Pipeboard API
24+
token will not work here: the server passes whatever you give it straight to the
25+
Meta Graph API.
2226

2327
```bash
24-
export PIPEBOARD_API_TOKEN=your_pipeboard_token
28+
export META_ACCESS_TOKEN=your_meta_access_token
2529
```
2630

31+
Setting this is optional for the HTTP transport if you pass the token per request
32+
in a header (see [Security Model](#security-model-read-before-exposing-the-port)),
33+
but it is convenient for command-line use.
34+
35+
> Want to authenticate with a Pipeboard API token instead, and never handle a Meta
36+
> token? Use the hosted MCP at `https://meta-ads.mcp.pipeboard.co/` rather than
37+
> running this server. (`PIPEBOARD_API_TOKEN` is no longer supported by this
38+
> package — see [Migration](#migration-from-stdio).)
39+
2740
### 3. Make HTTP Requests
2841

2942
The server accepts JSON-RPC 2.0 requests at the `/mcp` endpoint. Use the `Authorization` header to provide your token.
@@ -32,7 +45,7 @@ The server accepts JSON-RPC 2.0 requests at the `/mcp` endpoint. Use the `Author
3245
curl -X POST http://localhost:8080/mcp \
3346
-H "Content-Type: application/json" \
3447
-H "Accept: application/json, text/event-stream" \
35-
-H "Authorization: Bearer your_pipeboard_token" \
48+
-H "Authorization: Bearer your_meta_access_token" \
3649
-d '{
3750
"jsonrpc": "2.0",
3851
"method": "tools/call",
@@ -75,7 +88,7 @@ deliberately different from stdio. Understanding it is the difference between a
7588
safe deployment and leaking your Meta account to the internet.
7689

7790
- **stdio (local):** the server acts as whatever credential is configured in its
78-
environment — `META_ACCESS_TOKEN`, `PIPEBOARD_API_TOKEN`, or a stored login.
91+
environment — `META_ACCESS_TOKEN` or a stored login from the local OAuth flow.
7992
Only the local process that launched it can talk to it, so this is expected
8093
and safe. *If all you want is to use the MCP locally, prefer stdio.*
8194

@@ -106,33 +119,23 @@ safe deployment and leaking your Meta account to the internet.
106119

107120
## Authentication
108121

109-
### Primary Method: Bearer Token (Recommended)
122+
Which credential you use depends on **who runs the server**.
110123

111-
1. Sign up at [Pipeboard.co](https://pipeboard.co)
112-
2. Generate an API token at [pipeboard.co/api-tokens](https://pipeboard.co/api-tokens)
113-
3. Include the token in the `Authorization` HTTP header:
124+
### Self-hosted: Meta access token
125+
126+
When you run this package yourself, supply a Meta access token from your own Meta
127+
app. Create one at [developers.facebook.com](https://developers.facebook.com/apps/),
128+
then pass it in the `Authorization` header:
114129

115130
```bash
116-
curl -H "Authorization: Bearer your_pipeboard_token" \
131+
curl -H "Authorization: Bearer your_meta_access_token" \
117132
-X POST http://localhost:8080/mcp \
118133
-H "Content-Type: application/json" \
119134
-H "Accept: application/json, text/event-stream" \
120135
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
121136
```
122137

123-
#### Remote MCP: Token in URL
124-
125-
When using the hosted Remote MCP at `https://mcp.pipeboard.co/meta-ads-mcp`, you can alternatively authenticate by including the token as a URL parameter:
126-
127-
```
128-
https://mcp.pipeboard.co/meta-ads-mcp?token=YOUR_PIPEBOARD_TOKEN
129-
```
130-
131-
This is particularly useful for MCP clients that don't support interactive authentication flows.
132-
133-
### Alternative Method: Direct Meta Token
134-
135-
If you have a Meta Developer App, you can use a direct access token via the `X-META-ACCESS-TOKEN` header. This is less common.
138+
The `X-META-ACCESS-TOKEN` header is equivalent:
136139

137140
```bash
138141
curl -H "X-META-ACCESS-TOKEN: your_meta_access_token" \
@@ -142,6 +145,28 @@ curl -H "X-META-ACCESS-TOKEN: your_meta_access_token" \
142145
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
143146
```
144147

148+
### Hosted: Pipeboard API token
149+
150+
The hosted Remote MCP at `https://meta-ads.mcp.pipeboard.co/` accepts a **Pipeboard
151+
API token** instead, so you never handle a Meta token yourself. Pipeboard resolves
152+
the Meta credential server-side and enforces the API token's account and permission
153+
scoping on every call.
154+
155+
1. Sign up at [Pipeboard.co](https://pipeboard.co)
156+
2. Generate an API token at [pipeboard.co/api-tokens](https://pipeboard.co/api-tokens)
157+
3. Point your MCP client at `https://meta-ads.mcp.pipeboard.co/` with
158+
`Authorization: Bearer <your_pipeboard_token>`
159+
160+
For clients that cannot send headers, the token may be passed as a URL parameter:
161+
162+
```
163+
https://meta-ads.mcp.pipeboard.co/?token=YOUR_PIPEBOARD_TOKEN
164+
```
165+
166+
> A Pipeboard API token only works against the hosted endpoint. Passing one to a
167+
> server you run yourself will fail, because that server forwards the token
168+
> directly to the Meta Graph API.
169+
145170
## Available Endpoints
146171

147172
### Server URL Structure
@@ -279,7 +304,7 @@ class MetaAdsMCPClient:
279304
return response.json()
280305

281306
# Usage
282-
client = MetaAdsMCPClient(token="your_pipeboard_token")
307+
client = MetaAdsMCPClient(token="your_meta_access_token")
283308
result = client.call_tool("get_ad_accounts", {"limit": 5})
284309
print(json.dumps(result, indent=2))
285310
```
@@ -323,7 +348,7 @@ class MetaAdsMCPClient {
323348
}
324349

325350
// Usage
326-
const client = new MetaAdsMCPClient('http://localhost:8080', 'your_pipeboard_token');
351+
const client = new MetaAdsMCPClient('http://localhost:8080', 'your_meta_access_token');
327352
client.callTool('get_ad_accounts', { limit: 5 })
328353
.then(result => console.log(JSON.stringify(result, null, 2)));
329354
```
@@ -362,11 +387,11 @@ CMD ["python", "-m", "meta_ads_mcp", "--transport", "streamable-http", "--host",
362387
### Environment Variables
363388

364389
```bash
365-
# For Pipeboard-based authentication. The token will be used for stdio,
366-
# but for HTTP it should be passed in the Authorization header.
367-
export PIPEBOARD_API_TOKEN=your_pipeboard_token
390+
# Meta access token from your own Meta app. Used for stdio; for HTTP it can
391+
# also be passed per request in the Authorization header.
392+
export META_ACCESS_TOKEN=your_meta_access_token
368393

369-
# Optional (for custom Meta apps)
394+
# Optional (for the local OAuth flow instead of a direct token)
370395
export META_APP_ID=your_app_id
371396
export META_APP_SECRET=your_app_secret
372397

@@ -410,7 +435,13 @@ If you're currently using stdio transport with MCP clients, you can support both
410435
1. **Keep existing MCP client setup** (Claude Desktop, Cursor, etc.) using stdio.
411436
2. **Add HTTP transport** for web applications and custom integrations by running a separate server instance with the `--transport streamable-http` flag.
412437
3. **Use the same authentication method**:
413-
- For stdio, the `PIPEBOARD_API_TOKEN` environment variable is used.
438+
- For stdio, the `META_ACCESS_TOKEN` environment variable is used.
414439
- For HTTP, pass the token in the `Authorization: Bearer <token>` header.
415440

441+
> **Removed:** `PIPEBOARD_API_TOKEN` used to exchange a Pipeboard API token for the
442+
> underlying Meta access token. That exchange has been removed, because the Meta
443+
> token it returned ignored the scoping on the API token that requested it. Either
444+
> set `META_ACCESS_TOKEN` from your own Meta app, or use the hosted MCP at
445+
> `https://meta-ads.mcp.pipeboard.co/`.
446+
416447
Both transports access the same Meta Ads functionality and use the same underlying authentication system.

‎examples/README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This directory contains example scripts and usage demonstrations for the Meta Ad
88
A complete example HTTP client that demonstrates how to interact with the Meta Ads MCP server using the HTTP transport.
99

1010
**Features:**
11-
- Shows how to authenticate with Pipeboard tokens or Meta access tokens
11+
- Shows how to authenticate with a Meta access token
1212
- Demonstrates all basic MCP operations (initialize, list tools, call tools)
1313
- Includes error handling and response formatting
1414
- Ready-to-use client class for integration
@@ -24,8 +24,8 @@ python http_client.py
2424
```
2525

2626
**Authentication:**
27-
- Set `PIPEBOARD_API_TOKEN` environment variable for Pipeboard auth
28-
- Or pass `meta_access_token` parameter for direct Meta API auth
27+
- Set the `META_ACCESS_TOKEN` environment variable, or pass the
28+
`meta_access_token` parameter, using a token from your own Meta app
2929

3030
## Adding New Examples
3131

‎examples/example_http_client.py‎

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,12 @@ class MetaAdsMCPClient:
1919
"""Simple HTTP client for Meta Ads MCP server"""
2020

2121
def __init__(self, base_url: str = "http://localhost:8080",
22-
pipeboard_token: Optional[str] = None,
2322
meta_access_token: Optional[str] = None):
2423
"""Initialize the client
2524
2625
Args:
2726
base_url: Base URL of the MCP server
28-
pipeboard_token: Pipeboard API token (recommended)
29-
meta_access_token: Direct Meta access token (fallback)
27+
meta_access_token: Meta access token from your own Meta app
3028
"""
3129
self.base_url = base_url.rstrip('/')
3230
self.endpoint = f"{self.base_url}/mcp/"
@@ -40,12 +38,9 @@ def __init__(self, base_url: str = "http://localhost:8080",
4038
}
4139

4240
# Add authentication
43-
if pipeboard_token:
44-
self.headers["Authorization"] = f"Bearer {pipeboard_token}"
45-
print(f"✅ Using Pipeboard authentication")
46-
elif meta_access_token:
47-
self.headers["X-META-ACCESS-TOKEN"] = meta_access_token
48-
print(f"✅ Using direct Meta token authentication")
41+
if meta_access_token:
42+
self.headers["Authorization"] = f"Bearer {meta_access_token}"
43+
print(f"✅ Using Meta access token authentication")
4944
else:
5045
print(f"⚠️ No authentication provided - tools will require auth")
5146

@@ -123,20 +118,16 @@ def main():
123118
print("="*60)
124119

125120
# Check for authentication
126-
pipeboard_token = os.environ.get("PIPEBOARD_API_TOKEN")
127121
meta_token = os.environ.get("META_ACCESS_TOKEN")
128-
129-
if not pipeboard_token and not meta_token:
130-
print("⚠️ No authentication tokens found in environment")
131-
print(" Set PIPEBOARD_API_TOKEN or META_ACCESS_TOKEN for full functionality")
122+
123+
if not meta_token:
124+
print("⚠️ No authentication token found in environment")
125+
print(" Set META_ACCESS_TOKEN for full functionality")
132126
print(" Using test token for demonstration...")
133-
pipeboard_token = "demo_token_12345"
134-
127+
meta_token = "demo_token_12345"
128+
135129
# Create client
136-
client = MetaAdsMCPClient(
137-
pipeboard_token=pipeboard_token,
138-
meta_access_token=meta_token
139-
)
130+
client = MetaAdsMCPClient(meta_access_token=meta_token)
140131

141132
# Test the MCP protocol flow
142133
print("\n🔄 Testing MCP Protocol Flow")
@@ -212,7 +203,7 @@ def main():
212203
print(" Tool Call: ✅ SUCCESS")
213204
print("\n🎉 Meta Ads MCP HTTP transport is fully functional!")
214205
print("\n💡 Next steps:")
215-
print(" 1. Set PIPEBOARD_API_TOKEN environment variable")
206+
print(" 1. Set META_ACCESS_TOKEN environment variable")
216207
print(" 2. Call any of the 26 available Meta Ads tools")
217208
print(" 3. Build your web application or automation scripts")
218209

‎meta_ads_auth.sh‎

Lines changed: 0 additions & 54 deletions
This file was deleted.

‎meta_ads_mcp/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from meta_ads_mcp.core.server import main
88

9-
__version__ = "1.0.119"
9+
__version__ = "1.0.120"
1010

1111
__all__ = [
1212
'get_ad_accounts',

0 commit comments

Comments
 (0)