---
title: Automate Statsig MCP in scheduled and CI jobs
description: "Call the Statsig MCP V3 server from a scheduled job or CI workflow with Python or JavaScript, using discovery to check gate references without an LLM."
product: general
lang: en
token_estimate: 1192
---
# Automate Statsig MCP in scheduled and CI jobs

> For AI agents: a documentation index is available at [/llms.txt](/llms.txt). Append `.md` to any page URL for markdown, or send `Accept: text/markdown`.

Use a scheduled job or CI workflow to retrieve the references for a gate before you plan cleanup. This read-only example discovers the operation, then calls it directly, so it needs no LLM.

## Prerequisites

- A Console API key with access to the project, stored as `STATSIG_API_KEY` in your runner's secret store
- The ID of an existing gate in that project, set as `STATSIG_GATE_ID`
- Python with the `mcp` package, or Node.js 22 or later with the MCP JavaScript SDK

## Check gate references

#### Python

1. Install the SDK:

   ```bash
   python -m pip install mcp==1.30.0
   ```
2. Save the following script as `gate_references.py`:

   ```python
   import asyncio
   import json
   import os
   import httpx
   from mcp import ClientSession
   from mcp.client.streamable_http import streamable_http_client

   URL = "https://api.statsig.com/v3/mcp"

   async def main():
       headers = {"statsig-api-key": os.environ["STATSIG_API_KEY"]}
       async with httpx.AsyncClient(headers=headers) as http:
           async with streamable_http_client(URL, http_client=http) as streams:
               async with ClientSession(streams[0], streams[1]) as session:
                   await session.initialize()
                   discovery = await session.call_tool("discover_tools", {
                       "action": "get",
                       "operationId": "feature_gates.list.list_gate_references",
                   })
                   if discovery.isError:
                       raise RuntimeError("Gate discovery failed")
                   operation = discovery.structuredContent["data"]
                   if operation["lane"] != "api_read":
                       raise RuntimeError("Expected a read-only operation")
                   result = await session.call_tool(operation["lane"], {
                       "operationHandle": operation["handle"],
                       "arguments": {"path": {"id": os.environ["STATSIG_GATE_ID"]}},
                   })
                   if result.isError:
                       raise RuntimeError("Gate reference lookup failed")
                   print(json.dumps(result.structuredContent["data"], indent=2))

   asyncio.run(main())
   ```
3. Run the script:

   ```bash
   python gate_references.py
   ```

#### JavaScript

1. Install the SDK:

   ```bash
   npm install @modelcontextprotocol/sdk@1.30.0
   ```
2. Save the following script as `gate_references.mjs`:

   ```javascript
   import { Client } from "@modelcontextprotocol/sdk/client/index.js";
   import { StreamableHTTPClientTransport }
     from "@modelcontextprotocol/sdk/client/streamableHttp.js";

   const key = process.env.STATSIG_API_KEY;
   const gateId = process.env.STATSIG_GATE_ID;
   if (!key || !gateId) {
     throw new Error("Set STATSIG_API_KEY and STATSIG_GATE_ID");
   }
   const client = new Client({ name: "gate-reference-job", version: "1.0.0" });
   const transport = new StreamableHTTPClientTransport(
     new URL("https://api.statsig.com/v3/mcp"),
     { requestInit: { headers: { "statsig-api-key": key } } }
   );
   try {
     await client.connect(transport);
     const discovery = await client.callTool({
       name: "discover_tools",
       arguments: {
         action: "get",
         operationId: "feature_gates.list.list_gate_references",
       },
     });
     if (discovery.isError) throw new Error("Gate discovery failed");
     const operation = discovery.structuredContent.data;
     if (operation.lane !== "api_read") {
       throw new Error("Expected a read-only operation");
     }
     const result = await client.callTool({
       name: operation.lane,
       arguments: {
         operationHandle: operation.handle,
         arguments: { path: { id: gateId } },
       },
     });
     if (result.isError) throw new Error("Gate reference lookup failed");
     console.log(JSON.stringify(result.structuredContent.data, null, 2));
   } finally {
     await client.close();
   }
   ```
3. Run the script:

   ```bash
   node gate_references.mjs
   ```

The script prints the API response for one page of gate references. To get more pages, follow the returned pagination with `arguments.query.page`.

An empty result doesn't prove that a gate is safe to delete.

## Production practices

- Retrieve a fresh operation handle on every run. Handles expire, so don't store them.
- Check `isError` before you read `structuredContent`.
- Confirm the returned `lane` is the one you expect before you call it, as the examples do with `api_read`.
- Use a read-only API key for jobs that only read.

