MCP is an open standard. Any conforming client connects with the details below: another editor, an agent framework, or code you wrote yourself.
https://mcp.glitchads.ai/mcp
| Transport | Streamable HTTP: POST and GET on the single /mcp endpoint. The deprecated HTTP and SSE transport is not offered. |
| Sessions | Stateless. No Mcp-Session-Id is required: every request authenticates with its own bearer token. |
| Auth, interactive | OAuth 2.1 with PKCE (S256). Discovery through /.well-known/oauth-protected-resource/mcp, which names the authorization server https://api.glitchads.ai. Public clients only: token_endpoint_auth_method is none. Dynamic Client Registration and Client ID Metadata Documents are both supported, and the authorization server metadata advertises client_id_metadata_document_supported. The authorization request must send resource (RFC 8707) with the value https://mcp.glitchads.ai/mcp. |
| Auth, headless | Authorization: Bearer glads_live_… with an API key. Test keys (glads_test_) are not available yet. |
| Instructions | The initialize response carries instructions that tell the assistant to ask which organization to use and to show a preview before making a change. |
| Tools | Twenty-one, all annotated. List tools paginate. |
| Arguments | Unknown arguments are dropped without an error. A misspelled dry_run is ignored, so the call returns a preview instead of making the change. |
| Errors | Tool errors return isError: true with a structured envelope. |
Most MCP capable applications take one of these shapes. Only the key name varies between them: url, serverUrl, or a type of http.
{ "mcpServers": { "glitch": { "url": "https://mcp.glitchads.ai/mcp" } } }
// headless: add the header, and reference the key from the environment
{
"mcpServers": {
"glitch": {
"url": "https://mcp.glitchads.ai/mcp",
"headers": { "Authorization": "Bearer ${GLITCH_API_KEY}" }
}
}
}
# pip install "mcp>=2"
import asyncio
import os
import httpx2
from mcp import Client
from mcp.client.streamable_http import streamable_http_client
async def main():
headers = {"Authorization": f"Bearer {os.environ['GLITCH_API_KEY']}"}
async with httpx2.AsyncClient(headers=headers, timeout=httpx2.Timeout(30, read=300)) as http:
transport = streamable_http_client("https://mcp.glitchads.ai/mcp", http_client=http)
async with Client(transport) as client:
tools = await client.list_tools() # 21 glitch_* tools
result = await client.call_tool(
"glitch_get_performance",
{"organization": "acme", "from": "2026-07-01", "to": "2026-07-07"},
)
print(result.content[0].text)
asyncio.run(main())
// npm install @modelcontextprotocol/sdk zod
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const transport = new StreamableHTTPClientTransport(
new URL("https://mcp.glitchads.ai/mcp"),
{ requestInit: { headers: { Authorization: `Bearer ${process.env.GLITCH_API_KEY}` } } }
);
const client = new Client({ name: "my-agent", version: "1.0.0" });
await client.connect(transport);
const res = await client.callTool({
name: "glitch_run_detector",
arguments: { organization: "acme", campaign: "acme-prospecting", detector: "no_conversion_keywords" },
});
Frameworks with MCP support take the same URL plus the Authorization header. One rule for anyone building a loop that runs on its own:
readOnlyHint: false can change things, and destructiveHint: true marks the four that change a running campaign. Gate those behind human confirmation, or run them with dry_run: true and read the preview in code. The server side guardrails hold regardless, but your users will thank you.Test keys (glads_test_) are not available yet, so there is no sandbox organization to build against. Until there is, use dry_run previews to check what a write would do.
If you do not need MCP semantics at all, the REST API exposes the same operations directly.
tools/list returns the tools.glitch_list_organizations returns the organizations the connection covers, with your role in each; every other tool that takes organization requires it.401 with a WWW-Authenticate header pointing at the resource metadata, which means discovery is working.glitch_*.Ask: "List my Glitch organizations." You should get back the organizations your connection covers, with your role in each.
| Symptom | Fix |
|---|---|
401 with a key set |
The server answers 401 only when the header is missing or malformed. Check it is exactly Authorization: Bearer glads_live_…, with the Bearer prefix and the whole key. |
Tools list, but every call returns unauthorized |
The server does not validate API keys when you connect: it passes them to the API with each tool call. A revoked or expired key still connects and lists the tools, and every tool call returns isError: true with unauthorized. Check the key is active and unexpired, and that the user who created it still belongs to the organization. |
insufficient_scope |
The error names the scope that is missing. Create a key carrying it, or reconnect and approve it. If your Glitch role does not allow it, ask an organization Admin or Owner. |
org_access_denied |
The organization slug is wrong, your Glitch user is not a member of that organization, or the membership ended. glitch_list_organizations shows the slugs you can use. |
| Revoking access | Revoke the key or the connection in Glitch under Account, API Keys, where connections are listed under Connected apps. Either stops access on the next request. |
| OAuth fails at discovery | Your client has to fetch /.well-known/oauth-protected-resource/mcp, follow it to the authorization server at https://api.glitchads.ai, and support PKCE S256. It must register or identify itself as a public client (token_endpoint_auth_method none), through Dynamic Client Registration or a Client ID Metadata Document, and send resource set to https://mcp.glitchads.ai/mcp on the authorization request. Without resource the request fails with invalid_target. A client without OAuth support should use an API key. |
| It works locally and fails from a server | The endpoint is public, so check your egress rules. Tokens are audience bound: one minted for another service will be refused. |