ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Build Automatic API Key Rotation for MCP Configs
Tutorial

How to Build Automatic API Key Rotation for MCP Configs

Build an automatic API key rotation system for MCP server configurations. Rotate keys on schedule, validate them, and update configs without downtime.

Get Free API KeyAPI Docs

MCP server configurations store API keys in plain JSON files like .mcp.json or claude_desktop_config.json. When a key expires, gets compromised, or hits rate limits, every agent using that MCP server breaks. Manually editing config files across machines is error-prone and slow. This tutorial builds a Python utility that reads MCP configs, rotates API keys from a secure store, validates the new key against the target API, and writes the updated config atomically. The approach works for any MCP server that passes credentials via environment variables or command-line arguments.

Prerequisites

  • Python 3.8 or higher installed
  • requests library installed
  • An existing MCP config file (.mcp.json or equivalent)
  • A Scavio API key for validation testing

Walkthrough

Step 1: Read the current MCP config

Load the MCP config file and identify all servers that use API key environment variables. The script looks for env keys containing API_KEY or TOKEN.

Python
import json
import os

def load_mcp_config(path: str) -> dict:
    with open(path, "r") as f:
        return json.load(f)

config_path = os.path.expanduser("~/.mcp.json")
config = load_mcp_config(config_path)
for name, server in config.get("mcpServers", {}).items():
    env = server.get("env", {})
    key_vars = [k for k in env if "API_KEY" in k or "TOKEN" in k]
    print(f"{name}: {key_vars}")

Step 2: Fetch the rotated key from your secret store

Pull the new API key from an environment variable, a secrets manager, or a local encrypted file. This example reads from environment variables with a _NEW suffix convention.

Python
def get_rotated_key(var_name: str) -> str | None:
    new_var = f"{var_name}_NEW"
    rotated = os.environ.get(new_var)
    if rotated:
        print(f"Rotation candidate found: {new_var}")
    return rotated

Step 3: Validate the new key before writing

Make a lightweight API call with the new key to confirm it works. For Scavio keys, POST a minimal search query. If validation fails, skip rotation for that key.

Python
import requests

def validate_scavio_key(api_key: str) -> bool:
    try:
        r = requests.post(
            "https://api.scavio.dev/api/v1/search",
            headers={"x-api-key": api_key},
            json={"query": "test", "country_code": "us"},
            timeout=10
        )
        return r.status_code == 200
    except Exception:
        return False

new_key = get_rotated_key("SCAVIO_API_KEY")
if new_key and validate_scavio_key(new_key):
    print("New key validated successfully")
else:
    print("Validation failed, skipping rotation")

Step 4: Write the updated config atomically

Write to a temporary file first, then rename it over the original. This prevents partial writes from corrupting the config if the process is interrupted.

Python
import tempfile
import shutil

def rotate_config(config_path: str, config: dict, server_name: str, var_name: str, new_key: str) -> None:
    config["mcpServers"][server_name]["env"][var_name] = new_key
    tmp = tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False)
    json.dump(config, tmp, indent=2)
    tmp.close()
    shutil.move(tmp.name, config_path)
    print(f"Rotated {var_name} for {server_name}")

Python Example

Python
import json
import os
import tempfile
import shutil
import requests

def load_config(path: str) -> dict:
    with open(path, "r") as f:
        return json.load(f)

def validate_key(api_key: str) -> bool:
    try:
        r = requests.post(
            "https://api.scavio.dev/api/v1/search",
            headers={"x-api-key": api_key},
            json={"query": "test", "country_code": "us"},
            timeout=10
        )
        return r.status_code == 200
    except Exception:
        return False

def atomic_write(path: str, data: dict) -> None:
    tmp = tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False)
    json.dump(data, tmp, indent=2)
    tmp.close()
    shutil.move(tmp.name, path)

def rotate_all(config_path: str) -> None:
    config = load_config(config_path)
    rotated = 0
    for name, server in config.get("mcpServers", {}).items():
        env = server.get("env", {})
        for var in list(env.keys()):
            if "API_KEY" not in var and "TOKEN" not in var:
                continue
            new_key = os.environ.get(f"{var}_NEW")
            if not new_key:
                continue
            if validate_key(new_key):
                env[var] = new_key
                rotated += 1
                print(f"Rotated {var} for {name}")
            else:
                print(f"Validation failed for {var}, skipping")
    if rotated > 0:
        atomic_write(config_path, config)
        print(f"Config updated with {rotated} rotated keys")
    else:
        print("No keys rotated")

if __name__ == "__main__":
    rotate_all(os.path.expanduser("~/.mcp.json"))

JavaScript Example

JavaScript
const fs = require("fs");
const os = require("os");
const path = require("path");

async function validateKey(apiKey) {
  try {
    const res = await fetch("https://api.scavio.dev/api/v1/search", {
      method: "POST",
      headers: { "x-api-key": apiKey, "Content-Type": "application/json" },
      body: JSON.stringify({ query: "test", country_code: "us" })
    });
    return res.ok;
  } catch {
    return false;
  }
}

async function rotateAll(configPath) {
  const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
  let rotated = 0;
  for (const [name, server] of Object.entries(config.mcpServers || {})) {
    const env = server.env || {};
    for (const varName of Object.keys(env)) {
      if (!varName.includes("API_KEY") && !varName.includes("TOKEN")) continue;
      const newKey = process.env[`${varName}_NEW`];
      if (!newKey) continue;
      if (await validateKey(newKey)) {
        env[varName] = newKey;
        rotated++;
        console.log(`Rotated ${varName} for ${name}`);
      } else {
        console.log(`Validation failed for ${varName}, skipping`);
      }
    }
  }
  if (rotated > 0) {
    const tmp = path.join(os.tmpdir(), `mcp-${Date.now()}.json`);
    fs.writeFileSync(tmp, JSON.stringify(config, null, 2));
    fs.renameSync(tmp, configPath);
    console.log(`Config updated with ${rotated} rotated keys`);
  }
}

rotateAll(path.join(os.homedir(), ".mcp.json")).catch(console.error);

Expected Output

JSON
SCAVIO_API_KEY: rotation candidate found
New key validated successfully
Rotated SCAVIO_API_KEY for scavio-search
Config updated with 1 rotated keys

Related Tutorials

  • How to Implement MCP Auth Key Rotation
  • How to Secure MCP Endpoints with DLP Controls
  • How to Monitor MCP Server Health for Production Agents

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8 or higher installed. requests library installed. An existing MCP config file (.mcp.json or equivalent). A Scavio API key for validation testing. A Scavio API key gives you 50 free credits on signup.

Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Related Resources

Use Case

MCP Credential Management

Read more
Best Of

Best MCP Server Management and Optimization Tools in May 2026

Read more
Best Of

Best MCP Credential Management Tools in 2026

Read more
Solution

Rotate MCP Server Credentials Without Downtime

Read more
Use Case

MCP Custom Search Server

Read more
Solution

MCP Auth and Secret Management

Read more

Start Building

Build an automatic API key rotation system for MCP server configurations. Rotate keys on schedule, validate them, and update configs without downtime.

Get Free API KeyRead the Docs
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy