The PMA MCP server supports two equivalent authentication paths:
Both paths ultimately resolve to the same underlying API token; OAuth is provided to satisfy the browser-based connector flow used by Claude.ai, ChatGPT, and similar tools. For a custom backend service, the API-token path is simpler and is the supported pattern.
Before you begin, confirm the following on both sides of the connection.
On your server:
Authorization header. The official @modelcontextprotocol/sdk package ships with a compatible StreamableHTTPClientTransport; equivalent libraries exist in other languages.https://pma-mcp.web.app.On the Power My Analytics side:
Your PMA API token is the same token used to authenticate any server-side request to PMA, and it is the credential the MCP server expects in headless mode.
PMA_API_TOKEN in Fly.io secrets, AWS Secrets Manager, GitHub Actions secrets, or equivalent).
Point your MCP client at the PMA MCP endpoint and pass your API token in the Authorization header:
https://pma-mcp.web.app/mcpAuthorization: Bearer <your-pma-api-token>@modelcontextprotocol/sdk)The example below uses the official Model Context Protocol SDK for TypeScript and JavaScript. It connects to the PMA MCP server, lists the available tools, and calls pma_list_data_sources as a sanity check.
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const PMA_API_TOKEN = process.env.PMA_API_TOKEN;
if (!PMA_API_TOKEN) {
throw new Error("PMA_API_TOKEN is not set in the environment.");
}
const transport = new StreamableHTTPClientTransport(
new URL("https://pma-mcp.web.app/mcp"),
{
requestInit: {
headers: {
Authorization: `Bearer ${PMA_API_TOKEN}`,
},
},
}
);
const client = new Client(
{ name: "my-pma-headless-service", version: "1.0.0" },
{ capabilities: {} }
);
await client.connect(transport);
// List tools (sanity check)
const { tools } = await client.listTools();
console.log("Available PMA MCP tools:", tools.map((t) => t.name));
// Call a tool
const sources = await client.callTool({
name: "pma_list_data_sources",
arguments: {},
});
console.log(sources);
await client.close();Any MCP client library that supports Streamable HTTP transport plus a static Bearer token will work. The general requirements are:
https://pma-mcp.web.app/mcp.Authorization: Bearer <token> on every request.For background on the Streamable HTTP transport itself, see the Model Context Protocol specification.
Once connected, run a low-cost diagnostic call to confirm everything is wired up correctly. We recommend pma_list_data_sources for the first verification: it returns the same list you would see under Sources in your Hub, including each platform's has_data flag and last_sync timestamp. If the call succeeds and returns the expected platforms, your headless integration is working.
For a complete tools inventory, see the PMA MCP Tools Reference.
PMA API tokens issued for MCP alpha access are long-lived: they do not expire on their own. You should rotate the token whenever you would rotate any other production secret, including:
To rotate your PMA API token, follow How to Generate a New API Key. After rotating, update the token value wherever it is stored (secrets manager, environment variables, deployment configuration) and restart your service so the new token takes effect.
Cause: The Authorization header is missing or malformed, or the token is invalid or has been rotated. Solution: Confirm that the header is exactly Authorization: Bearer <token> (the literal word Bearer, a single space, then the token). Confirm the token value in your secrets manager matches the most recent token PMA issued. If the token was rotated, replace the old value and restart your service.
Cause: Your PMA organization is not yet on the Alpha access list, or alpha access has been deactivated. Solution: Open a support ticket with the subject line "MCP Early Access" at support.powermyanalytics.com to confirm or restore your access.
Cause: The MCP server enforces a hard limit of 30 requests per minute per organization. Agentic loops, fan-out queries across many platforms, or aggressive retries can hit this limit. Solution: Slow your call cadence, batch requests where possible, and add exponential backoff to your retry logic. For more on this and other limitations, see Troubleshooting and Important Considerations for PMA MCP Server.
Cause: Either the initial sync has not completed for that platform, the wrong report type is being queried, or the connector name passed to the tool does not exactly match a connected source. Solution: Call pma_list_data_sources first to confirm canonical connector names and has_data status, then retry. Use pma_inspect_org_data for a deeper diagnostic if a specific connector still returns nothing.
Cause: Your client library may default to the older Server-Sent Events transport, or your network may be closing long-lived HTTP responses. Solution: Confirm your MCP client is using Streamable HTTP transport explicitly. If you are running behind a proxy or a restrictive firewall, allow https://pma-mcp.web.app and confirm long-running responses are not being closed prematurely.