
enkryptai/secure-mcp-gateway
Developer toolsSecure MCP Gateway - Setup Admin level gateway functionality for MCP servers - with guardrails at each MCP server to overcome multiple security issues with using MCPs
Overview
Learn how the Secure MCP Gateway prevents top attacks and vulnerabilities in our latest blog: Discover real-world attack scenarios, security best practices, and how our gateway protects your AI applications. This Secure MCP Gateway is built with authentication, automatic tool discovery, caching, and guardrail enforcement. It sits between your MCP client and MCP servers. So, by it's nature it itself also acts as an MCP server as well as an MCP client :) When your MCP client connects to the Gateway, it acts as an MCP server. When the Gateway connects to the actual MCP server, it acts as an MCP client. - Also see: - CLI-Commands-Reference.md for the list of commands and their usage - API-Reference.md for the list of API endpoints and their usage - MCP Gateway Setup Notebook for a complete walkthrough of all the essential commands - 1. Features 🚀 - 2. High level steps of how the MCP Gateway works 🪜 - 3. Prerequisites 🧩 - 4. Gateway Setup 👨💻 - 5.
README
Enkrypt AI Secure MCP Gateway
📖 Featured Blog Post: Learn how the Secure MCP Gateway prevents top attacks and vulnerabilities in our latest blog:
How Enkrypt’s Secure MCP Gateway and MCP Scanner Prevent Top Attacks
Discover real-world attack scenarios, security best practices, and how our gateway protects your AI applications.
Overview
This Secure MCP Gateway is built with authentication, automatic tool discovery, caching, and guardrail enforcement.
It sits between your MCP client and MCP servers. So, by it’s nature it itself also acts as an MCP server as well as an MCP client :)
When your MCP client connects to the Gateway, it acts as an MCP server. When the Gateway connects to the actual MCP server, it acts as an MCP client.
-
Also see:
- CLI-Commands-Reference.md for the list of commands and their usage
- API-Reference.md for the list of API endpoints and their usage
- MCP Gateway Setup Notebook for a complete walkthrough of all the essential commands
Table of Contents
- 1. Features 🚀
- 2. High level steps of how the MCP Gateway works 🪜
- 3. Prerequisites 🧩
- 4. Gateway Setup 👨💻
- 5. (Optional) OpenTelemetry Setup 📊
- 6. Verify Installation and check the files generated ✅
- 7. Edit the Gateway config as needed ✏️
- 8. CLI Quick Start Guide 🖥️
- 9. (Optional) Add GitHub MCP Server to the Gateway 🤖
- 9.1 (Optional) Connect to MCP Servers with OAuth 🔐
- 10. (Optional) Protect GitHub MCP Server and Test Echo Server 🔒
- 11. Recommendations for using Guardrails 💡
- 12. Other tools available 🔧
- 13. (Optional) Sandbox Isolation 🛡️
- 14. Deployment Patterns 🪂
- 15. Uninstall the Gateway 🗑️
- 16. Troubleshooting 🕵
- 17. Known Issues being worked on 🏗️
- 18. Known Limitations ⚠️
- 19. Contribute 🤝
- 20. Testing 🧪
- 21. License
1. Features
Below are the list of features Enkrypt AI Secure MCP Gateway provides:
-
Authentication: We use Unique Key to authenticate with the Gateway. We also use Enkrypt API Key if you want to protect your MCPs with Enkrypt Guardrails. Additionally, a secure
admin_apikey(256-character random string) is automatically generated at the root of the config for administrative REST API operations. (Whenplugins.auth.providerisenkrypt,admin_apikeyis optional — the Enkrypt cloudapi_keydoubles as the admin credential for most REST endpoints. The cache-flush endpoint specifically uses a stricter org-id-gated policy under cloud auth — see Hot-Reload Auth Policy.) -
Ease of use: You can configure all your MCP servers either locally in
enkrypt_mcp_config.jsonor — better yet for teams and production — in Enkrypt cloud (runsecure-mcp-gateway generate-config --provider enkrypt). The cloud owns the server list, guardrail policies, andcommon_overrides, and the gateway pulls them at request time with a 5-minute TTL. -
Dynamic Tool Discovery: The Gateway discovers tools from the MCP servers dynamically and makes them available to the MCP client
-
Restrict Tool Invocation: If you don’t want all tools to be accessible of a an MCP server, you can restrict them by explicitly mentioning the tools in the Gateway config so that only the allowed tools are accessible to the MCP client
-
Caching: We cache the user gateway config and tools discovered from various MCP servers locally or in an external cache server like KeyDB if configured to improve performance
-
Guardrails: You can configure guardrails for each MCP server in Enkrypt both on input side (before sending the request to the MCP server) and output side (after receiving the response from the MCP server)
-
Logging: We log every request and response from the Gateway locally in your MCP logs and also forward them to Enkrypt (Coming soon) for monitoring. This enables you to see all the calls made in your account, servers used, tools invoked, requests blocked, etc.
-
Sandbox Isolation: MCP servers can be launched inside isolated sandbox environments (Docker, Podman, or microVMs) so that a compromised or malicious server cannot access the host filesystem, network, or other resources. Each sandbox is ephemeral — created per session and destroyed when done.
1.1 Guardrails
Input Protection: Topic detection, NSFW filtering, toxicity detection, injection attack prevention, keyword detection, policy violation detection, bias detection, and PII redaction (More coming soon like system prompt protection, copyright protection, etc.)
Output Protection: All input protections plus adherence checking and relevancy validation (More coming soon like hallucination detection, etc.) We also auto unredact the response if it was redacted on input.
1.2 Concepts
-
MCP Config is an array of MCP servers like
mcp_server_1,mcp_server_2,mcp_server_3etc.- Each config has a unique ID
-
User is a user of the gateway with unique email and ID
-
A project is a collection of users that share an MCP Config
- Project has a name and unique ID
- The MCP Config can be updated or can be pointed to a different config by the Admin
- Users can be added to multiple projects
-
An API Key is created for a user and project combination
- A user can have different API Keys for different projects
- This API Key is used to authenticate the user and identify the right project and MCP Config
-
See 6.5 Example config file generated and 7. Edit the Gateway config as needed for schema reference
2. High level steps of how the MCP Gateway works
3. Prerequisites
-
Install Claude Desktop as the MCP Client from their website if you haven’t already and login to it
- If you are using Linux and cannot run any unofficial version of Claude Desktop, you can use any supported MCP Client to test the Gateway. If it does not support mcp cli
mcp installcommand, then go through the scripts code and run the commands supported manually.
- If you are using Linux and cannot run any unofficial version of Claude Desktop, you can use any supported MCP Client to test the Gateway. If it does not support mcp cli
-
Any other dependencies required for the MCP servers we want to proxy requests to
-
Follow the instructions of the respective MCP server to install its dependencies
-
Like
Node.js,npx,docker, etc.
-
-
(Optional) A cache server like KeyDB installed and running (If you want to cache externally and not locally)
4. Gateway Setup
4.1 Local Installation with pip
4.1.3 Example of the generated config file
Note: The examples below show the full schema emitted by
secure-mcp-gateway generate-config(default--provider local_apikey). Every field is included so you can compare your generated file 1:1. Theoauth_configblock ships disabled ("enabled": false) — its keys are placeholders you only need to fill in if a server uses OAuth. Thetimeout_settingsblock holds the per-operation timeouts the gateway uses internally; defaults are sane and rarely need editing.
4.1.4 Install the Gateway for Claude Desktop
-
Run the following command to install the gateway for Claude:
secure-mcp-gateway install --client claude-desktop -
This will register Enkrypt Secure MCP Gateway with Claude Desktop.
-
NOTE: Please restart Claude Desktop after installation
4.1.5 Example of the Claude Desktop Config after installation
The env-var shape depends on your gateway’s
plugins.auth.provider. Same dichotomy as the Cursor section below:
local_apikeyprovider (default) → three env vars:ENKRYPT_GATEWAY_KEY+ENKRYPT_PROJECT_ID+ENKRYPT_USER_IDenkryptcloud provider → single env var:ENKRYPT_APIKEY
4.1.6 Install the Gateway for Cursor
-
Run the CLI Install Command for Cursor
secure-mcp-gateway install --client cursor -
This automatically updates your ~/.cursor/mcp.json (on Windows it is at: %USERPROFILE%.cursor\mcp.json) with the correct entry.
-
Although it is not usually required to restart, if you see it in loading state for a long time, please restart Cursor
The env-var shape depends on your gateway’s
plugins.auth.provider. The install command writes whichever shape matches:
Provider Env vars written Used for local_apikey(default)ENKRYPT_GATEWAY_KEY+ENKRYPT_PROJECT_ID+ENKRYPT_USER_IDLooking up the local apikey + project + user in your local config enkrypt(cloud)ENKRYPT_APIKEYSingle cloud apikey; project/user come from Enkrypt cloud Both
mcp.jsonshapes below are valid — pick the one matching how you generated your config. See Section 4.1.2 for the--provider enkryptflag.
4.1.7 Install the Gateway for Claude Code
Claude Code is Anthropic’s CLI-based coding agent. It uses claude mcp add commands to configure MCP servers. Unlike Claude Desktop and Cursor which use JSON config files, Claude Code manages MCP servers through its own CLI.
Prerequisite: The
claudeCLI must be installed on your system. See Claude Code docs for installation.
Step 1: Install the gateway
secure-mcp-gateway install --client claude-code
This automatically:
- Reads the gateway credentials from your generated config (provider-aware):
local_apikeyprovider (default) → emits three--envflags:ENKRYPT_GATEWAY_KEY,ENKRYPT_PROJECT_ID,ENKRYPT_USER_IDenkryptcloud provider → emits a single--envflag:ENKRYPT_APIKEY(sourced fromenkrypt_config.api_key, or--apikeyif you pass it on the CLI)
- Runs
claude mcp addwith--transport stdioand the correct credentials and gateway path - Registers the server as
Enkrypt-Secure-MCP-Gatewaywith--scope user(available across all Claude Code projects)
Step 2: Verify the server was added
claude mcp list
You should see Enkrypt-Secure-MCP-Gateway in the list.
Step 3: Use the gateway in Claude Code
Launch Claude Code and try:
list all servers, get all tools available
4.2 Local Installation with git clone
4.2.2 Run the setup script
-
This script creates the config file at
~/.enkrypt/enkrypt_mcp_config.jsonon macOS and%USERPROFILE%\.enkrypt\enkrypt_mcp_config.jsonon Windows based onsrc/secure_mcp_gateway/example_enkrypt_mcp_config.jsonfile -
It replaces
UNIQUE_GATEWAY_KEYand otherUUIDswith auto generated values and also replacesDUMMY_MCP_FILE_PATHwith the actual path to the test MCP filebad_mcps/echo_mcp.py -
It also installs the MCP client in Claude Desktop
-
NOTE: Please restart Claude Desktop after running the setup script to see the Gateway running in Claude Desktop
# On 🍎 Linux/macOS run the below
cd scripts
chmod +x *.sh
./setup.sh
# On 🪟 Windows run the below
cd scripts
setup.bat
# Now restart Claude Desktop to see the Gateway running
4.2.3 Setup Other MCP Clients
4.3 Docker Installation
4.3.2 Generate the config file
- This creates a config file in the
~/.enkrypt/docker/enkrypt_mcp_config.jsonfile on macOS/Linux and%USERPROFILE%\.enkrypt\docker\enkrypt_mcp_config.jsonfile on Windows.
Quick shorthand — If you have the CLI installed locally via pip, you can use the
--dockerflag on any command and skip the verbose Docker syntax:secure-mcp-gateway --docker generate-config
Choosing an auth provider at generation time
Identical to the local install — see §4.1.2 → “Choosing an auth provider at generation time” for the full explanation. In short:
- Default (omit
--provider) → fulllocal_apikeyschema with a sample echo server, project, user, gateway API key, and root-leveladmin_apikey. Boots offline, no cloud dependency. --provider enkrypt→ minimal cloud-backed schema. After generating, edit the file and setenkrypt_config.api_key(your Enkrypt cloud apikey) andplugins.auth.config.gateway_name(the saved name of the gateway you created in the Enkrypt console). The cloud owns servers/projects/users/apikeys, so those blocks are absent.
Copy-paste commands (all OSes, using the --docker shorthand — works in bash, zsh, CMD, and PowerShell since the wrapper handles per-OS quoting internally):
# 1. Default — local_apikey (offline, no cloud dependency)
secure-mcp-gateway --docker generate-config
# 2. Cloud-backed — enkrypt provider (requires container CLI >= v2.2.0; see warning below)
secure-mcp-gateway --docker generate-config --provider enkrypt
# 3. Re-generate over an existing file (adds timestamped .bkp.YYYYMMDD_HHMMSS next to the original)
secure-mcp-gateway --docker generate-config --overwrite
secure-mcp-gateway --docker generate-config --provider enkrypt --overwrite
# 4. If the default image tag isn't on Docker Hub yet, point at a locally-built image:
# docker build -t secure-mcp-gateway . # one-time, from this repo root
secure-mcp-gateway --docker --docker-image secure-mcp-gateway generate-config --provider enkrypt --overwrite
After the command succeeds, the file lands at:
- macOS/Linux:
~/.enkrypt/docker/enkrypt_mcp_config.json - Windows:
%USERPROFILE%\.enkrypt\docker\enkrypt_mcp_config.json
If you don’t have the CLI installed locally via pip, the equivalent raw docker run ... invocations for each OS shell are in the “Verbose Docker run commands” details block below.
⚠️ Re-running on an existing config?
generate-configrefuses to clobber an existing file by default — it exits withINFO: Config file already exists at . ... use --overwrite flag.Add--overwriteat the end of the command to regenerate (a timestamped.bkp.backup is written next to the original first). The flag works the same for--provider enkryptand the--dockershorthand.
⚠️ “unrecognized arguments: --provider enkrypt” when using
--docker? This means the in-container CLI is older than your host CLI (--providerwas added in v2.2.0). The--dockerwrapper now defaults toenkryptai/secure-mcp-gateway:, but if that tag isn’t on Docker Hub yet you’ll seeUnable to find image ... not found. Build the image from source:docker build -t secure-mcp-gateway . && secure-mcp-gateway --docker --docker-image secure-mcp-gateway generate-config --provider enkrypt --overwrite. See Docker command pattern → Image tag is pinned to your host CLI version for the full workaround table.
4.3.3 Install the Gateway in Claude Desktop
- You can find the Claude config location at the below locations in your system. For reference see Claude docs.
- macOS:
~/Library/Application Support/Claude - Windows:
%APPDATA%\Claude
- macOS:
Note: The generated config includes
MCP_TRANSPORT=stdiofor stdio mode communication with Claude Desktop. The command is provider-aware — it readsplugins.auth.providerfrom your gateway config and emits the correctenv/-eshape (ENKRYPT_GATEWAY_KEY/ENKRYPT_PROJECT_ID/ENKRYPT_USER_IDforlocal_apikey, singleENKRYPT_APIKEYforenkrypt).
Copy-paste command (all OSes — the --docker wrapper auto-mounts your Claude config directory):
secure-mcp-gateway --docker install --client claude-desktop
Hit
Unable to find image 'enkryptai/secure-mcp-gateway:' ... not found? You skipped the one-timedocker tagstep at the end of §4.3.1. Run it once and re-try.
After it runs, restart Claude Desktop to pick up the new config.
4.3.4 Example Claude Desktop config file
The
envblock depends on your gateway’splugins.auth.provider(see §4.1.2). Both shapes are shown below.
4.3.5 Install the Gateway in Cursor
- You can find the Cursor config location at the below locations. For reference see Cursor docs.
- macOS:
~/.cursor - Windows:
%USERPROFILE%\.cursor
- macOS:
Note: The generated config includes
MCP_TRANSPORT=stdiofor stdio mode communication with Cursor. The command is provider-aware — it readsplugins.auth.providerfrom your gateway config and emits the correctenv/-eshape (ENKRYPT_GATEWAY_KEY/ENKRYPT_PROJECT_ID/ENKRYPT_USER_IDforlocal_apikey, singleENKRYPT_APIKEYforenkrypt).
Copy-paste command (all OSes — the --docker wrapper auto-mounts ~/.cursor so the in-container install can write back to it):
secure-mcp-gateway --docker install --client cursor
Hit
Unable to find image 'enkryptai/secure-mcp-gateway:' ... not found? You skipped the one-timedocker tagstep at the end of §4.3.1. Run it once and re-try.
After it runs, restart Cursor to pick up the new server. The entry lands at ~/.cursor/mcp.json on macOS/Linux or %USERPROFILE%\.cursor\mcp.json on Windows.
4.3.6 Install the Gateway in Claude Code
Claude Code uses its own CLI (claude mcp add) to manage MCP servers. When running the gateway in Docker, Claude Code connects via npx mcp-remote to the gateway’s Streamable HTTP endpoint.
Prerequisites: Node.js and npm must be installed on your machine (
node -vandnpm -vto verify).
Step 1: Run the gateway container
Start the gateway as a background Docker container with the Streamable HTTP endpoint exposed:
# On 🍎 Linux/macOS
docker run -d --name enkrypt-gateway -p 8000:8000 -v ~/.enkrypt/docker:/app/.enkrypt/docker secure-mcp-gateway
# On 🪟 Windows (PowerShell)
docker run -d --name enkrypt-gateway -p 8000:8000 -v "$env:USERPROFILE\.enkrypt\docker:/app/.enkrypt/docker" secure-mcp-gateway
Step 2: Add the gateway to Claude Code
The HTTP headers differ by auth provider:
# For local_apikey provider (default)
claude mcp add --transport http --header "apikey:YOUR_GATEWAY_KEY" --header "project_id:YOUR_PROJECT_ID" --header "user_id:YOUR_USER_ID" --scope user Enkrypt-Secure-MCP-Gateway http://localhost:8000/mcp/
# For enkrypt cloud provider (generated with --provider enkrypt)
claude mcp add --transport http --header "apikey:YOUR_ENKRYPT_CLOUD_APIKEY" --scope user Enkrypt-Secure-MCP-Gateway http://localhost:8000/mcp/
Replace the placeholders with the values from your enkrypt_mcp_config.json (apikeys. and the matching project/user IDs for local_apikey, or enkrypt_config.api_key for enkrypt cloud).
Step 3: Verify
claude mcp list
Step 4: Use in Claude Code
Launch Claude Code and try prompts like list all servers, get all tools available.
4.3.7 Running Gateway with Docker Run (Advanced)
For advanced Docker deployments, you can run the gateway container directly with custom configurations. The auth env vars depend on your gateway’s plugins.auth.provider (see §4.1.2):
# Basic Docker run command — local_apikey provider (default)
docker run -d --name enkrypt-gateway -p 8000:8000 -v ~/.enkrypt/docker:/app/.enkrypt/docker -e ENKRYPT_GATEWAY_KEY="your-gateway-key" -e ENKRYPT_PROJECT_ID="your-project-id" -e ENKRYPT_USER_ID="your-user-id" secure-mcp-gateway:latest
# Basic Docker run command — enkrypt cloud provider (generated with --provider enkrypt)
docker run -d --name enkrypt-gateway -p 8000:8000 -v ~/.enkrypt/docker:/app/.enkrypt/docker -e ENKRYPT_APIKEY="your-enkrypt-cloud-apikey" secure-mcp-gateway:latest
Windows PowerShell:
# local_apikey provider (default)
docker run -d `
--name enkrypt-gateway `
-p 8000:8000 `
-v "$env:USERPROFILE\.enkrypt\docker:/app/.enkrypt/docker" `
-e ENKRYPT_GATEWAY_KEY="your-gateway-key" `
-e ENKRYPT_PROJECT_ID="your-project-id" `
-e ENKRYPT_USER_ID="your-user-id" `
secure-mcp-gateway:latest
# enkrypt cloud provider
docker run -d `
--name enkrypt-gateway `
-p 8000:8000 `
-v "$env:USERPROFILE\.enkrypt\docker:/app/.enkrypt/docker" `
-e ENKRYPT_APIKEY="your-enkrypt-cloud-apikey" `
secure-mcp-gateway:latest
Environment Variables
Auth env vars are provider-dependent — exactly one of the two shapes below is required:
| Variable | Description | Default | Required (provider) |
|---|---|---|---|
ENKRYPT_GATEWAY_KEY |
API key for authentication | - | Yes (local_apikey) |
ENKRYPT_PROJECT_ID |
Project ID from config | - | Yes (local_apikey) |
ENKRYPT_USER_ID |
User ID from config | - | Yes (local_apikey) |
ENKRYPT_APIKEY |
Enkrypt cloud API key (project/user resolved by Enkrypt) | - | Yes (enkrypt) |
MCP_TRANSPORT |
Transport mode: streamable-http or stdio |
streamable-http |
No |
SKIP_DEPENDENCY_INSTALL |
Skip runtime dependency installation | true (Docker), false (other) |
No |
HOST |
Gateway bind address | 0.0.0.0 |
No |
FASTAPI_HOST |
FastAPI server bind address | 0.0.0.0 |
No |
MCP_TRANSPORT
The MCP_TRANSPORT environment variable controls the transport mode for the gateway.
Transport modes:
streamable-http(default): HTTP server mode on port 8000. Use with-p 8000:8000for port mapping.stdio: Standard input/output mode for MCP clients that communicate via stdin/stdout. Use with-iflag.
Example for stdio mode (Claude Desktop, Cursor):
# local_apikey provider (default) — pass all 3 env vars
docker run --rm -i -e MCP_TRANSPORT=stdio -v ~/.enkrypt/docker:/app/.enkrypt/docker -e ENKRYPT_GATEWAY_KEY="your-gateway-key" -e ENKRYPT_PROJECT_ID="your-project-id" -e ENKRYPT_USER_ID="your-user-id" secure-mcp-gateway
# enkrypt cloud provider — pass a single env var
docker run --rm -i -e MCP_TRANSPORT=stdio -v ~/.enkrypt/docker:/app/.enkrypt/docker -e ENKRYPT_APIKEY="your-enkrypt-cloud-apikey" secure-mcp-gateway
SKIP_DEPENDENCY_INSTALL
The SKIP_DEPENDENCY_INSTALL environment variable controls whether the gateway reinstalls Python dependencies at runtime.
Default behavior:
- Docker environments: Defaults to
true(auto-detected). Dependencies are pre-installed in the Docker image, so runtime installation is skipped automatically. - Non-Docker environments: Defaults to
false. Dependencies are installed at startup to ensure compatibility.
When to explicitly set SKIP_DEPENDENCY_INSTALL=false in Docker:
- Development environments where you’re testing new dependencies
- When mounting source code volumes for live development
- If you’re unsure whether all dependencies are properly installed
When to explicitly set SKIP_DEPENDENCY_INSTALL=true outside Docker:
- Production deployments where dependencies are pre-installed
- To reduce startup time (faster cold starts)
- In environments where you’ve already run
pip install
Example with docker-compose integration:
# Connect to observability stack network — local_apikey provider (default)
# Note: SKIP_DEPENDENCY_INSTALL defaults to true in Docker, so it's optional
docker run -d --name enkrypt-gateway --network secure-mcp-gateway-observability_default -p 8000:8000 -p 8080:8080 -v ~/.enkrypt/docker:/app/.enkrypt/docker -e ENKRYPT_GATEWAY_KEY="your-gateway-key" -e ENKRYPT_PROJECT_ID="your-project-id" -e ENKRYPT_USER_ID="your-user-id" secure-mcp-gateway:latest
# Same, but for the enkrypt cloud provider
docker run -d --name enkrypt-gateway --network secure-mcp-gateway-observability_default -p 8000:8000 -p 8080:8080 -v ~/.enkrypt/docker:/app/.enkrypt/docker -e ENKRYPT_APIKEY="your-enkrypt-cloud-apikey" secure-mcp-gateway:latest
Windows PowerShell:
# Note: SKIP_DEPENDENCY_INSTALL defaults to true in Docker, so it's optional
# local_apikey provider (default)
docker run -d `
--name enkrypt-gateway `
--network secure-mcp-gateway-observability_default `
-p 8000:8000 `
-p 8080:8080 `
-v "$env:USERPROFILE\.enkrypt\docker:/app/.enkrypt/docker" `
-e ENKRYPT_GATEWAY_KEY="your-gateway-key" `
-e ENKRYPT_PROJECT_ID="your-project-id" `
-e ENKRYPT_USER_ID="your-user-id" `
secure-mcp-gateway:latest
# enkrypt cloud provider
docker run -d `
--name enkrypt-gateway `
--network secure-mcp-gateway-observability_default `
-p 8000:8000 `
-p 8080:8080 `
-v "$env:USERPROFILE\.enkrypt\docker:/app/.enkrypt/docker" `
-e ENKRYPT_APIKEY="your-enkrypt-cloud-apikey" `
secure-mcp-gateway:latest
Note: The --network flag connects the gateway to the observability stack (Grafana, Prometheus, Loki, Jaeger, plus the 9 Slack alert rules) if you’re running the monitoring services from section 5. The network name (secure-mcp-gateway-observability_default) is derived from the compose project name set at the top of observability/docker-compose.grafana.yml (the name: field is unchanged by the file rename, so the network name is stable).
Port Mapping
8000: Gateway MCP server (required) — bound by the defaultENTRYPOINT ["python3", "src/secure_mcp_gateway/gateway.py"].8080: OAuth callback server (optional, only needed for Authorization Code flow). Also bound by the gateway entrypoint when OAuth is configured.8001: REST admin API server. Not started by the default entrypoint. Mapping-p 8001:8001alone does nothing — there’s no listener on 8001 inside the container unless you also startpython -m secure_mcp_gateway.api_server(e.g. via a sidecardocker exec, a custom--entrypoint, or your own image that runs both processes). Built-in cache-flush + last-reload routes are also exposed directly on the gateway (port 8000) atPOST /api/v1/cache/flush-gateway-configandGET /api/v1/cache/last-reload, so most operators don’t need to expose 8001 at all.
Volume Mounts
~/.enkrypt/docker:/app/.enkrypt/docker- Config file location (required)- Additional mounts may be needed if your MCP servers require access to local files
⚠️ Important: MCP clients (Claude Desktop, Cursor, Claude Code) spawn Docker directly without a shell, so
~(tilde) will not be expanded. Always use absolute paths in your MCP client config JSON files (e.g./Users/yourname/.enkrypt/docker:/app/.enkrypt/dockeron macOS/Linux orC:\\Users\\yourname\\.enkrypt\\docker:/app/.enkrypt/dockeron Windows).
⚠️ Important: Configuring MCP Servers When Gateway Runs in Docker
When running the Enkrypt Gateway in Docker, DO NOT configure your MCP servers to also run in Docker mode. This causes Docker-in-Docker issues, networking problems, and volume mount complications.
❌ Avoid (Docker-based MCP servers):
{
"server_name": "github_server",
"config": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "your-token"
}
}
}
✅ Use instead (npx/npm/Python-based servers):
{
"server_name": "github_server",
"config": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-github"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "your-token"
}
}
}
Why?
- Docker-in-Docker requires privileged mode and special socket mounting
- Network isolation prevents containers from communicating properly
- Volume mounts don’t work as expected across container boundaries
- Performance overhead and security concerns
- Increased complexity and debugging difficulty
Recommended MCP Server Formats When Gateway is in Docker:
- ✅ npx-based servers:
npx -y @modelcontextprotocol/server-* - ✅ npm-based servers:
npm exec -y server-name - ✅ Python-based servers:
python /path/to/server.pyoruv run server.py - ✅ Node.js-based servers:
node /path/to/server.js - ✅ Remote MCP servers:
npx mcp-remote https://api.example.com/mcp/
Exception:
If you absolutely must use Docker-based MCP servers, consider:
- Running the gateway outside of Docker (local installation), OR
- Setting up proper Docker networking with
--network hostor custom bridge networks, OR - Using Docker-in-Docker with proper configuration (requires
--privilegedflag and/var/run/docker.sockmount - not recommended for production)
4.4 Remote Installation
5. (Optional) Observability Stack — Logs, Metrics, Traces & Slack Alerts
6. Verify Installation and check the files generated
6.3 Restart Claude Desktop to run the Gateway
-
After restarting, navigate to Claude Desktop
Settings -
Click on
Developer->Enkrypt Secure MCP Gateway
6.4 Example prompts
list all servers, get all tools available and echo test- This uses a test MCP server
echo_serverwhich is inbad_mcps/echo_mcp.py
- This uses a test MCP server
6.5 Example config file generated
-
Example
enkrypt_mcp_config.jsongenerated by thesetupscript in~/.enkrypt/enkrypt_mcp_config.jsonon macOS and%USERPROFILE%\.enkrypt\enkrypt_mcp_config.jsonon Windows -
If you ran docker command to install the Gateway, the config file will be in
~/.enkrypt/docker/enkrypt_mcp_config.jsonon macOS and%USERPROFILE%\.enkrypt\docker\enkrypt_mcp_config.jsonon Windows{ "admin_apikey": "AUTO_GENERATED_256_CHAR_ADMIN_API_KEY_FOR_ADMINISTRATIVE_OPERATIONS", "enkrypt_config": { "api_key": "YOUR_ENKRYPT_API_KEY", "base_url": "https://api.enkryptai.com" }, "common_mcp_gateway_config": { "enkrypt_log_level": "INFO", "enkrypt_mcp_use_external_cache": false, "enkrypt_cache_host": "localhost", "enkrypt_cache_port": 6379, "enkrypt_cache_db": 0, "enkrypt_cache_password": null, "enkrypt_tool_cache_expiration": 4, "enkrypt_gateway_cache_expiration": 24, "enkrypt_gateway_cache_expiration_minutes": 5, "enkrypt_config_watcher_poll_seconds": 2.0, "enkrypt_async_input_guardrails_enabled": false, "enkrypt_async_output_guardrails_enabled": false }, "plugins": { "auth": { "provider": "local_apikey", "config": {} }, "guardrails": { "provider": "enkrypt", "config": {} }, "telemetry": { "provider": "opentelemetry", "config": { "enabled": true, "url": "http://localhost:4317", "insecure": true } } }, "mcp_configs": { "fcbd4508-1432-4f13-abb9-c495c946f638": { "mcp_config_name": "default_config", "common_overrides": { "server_tools_guardrails_config": { "enabled": false } }, "mcp_config": [ { "server_name": "echo_server", "description": "Simple Echo Server", "config": { "command": "python", "args": [ "C:\\Users\\\\Documents\\GitHub\\EnkryptAI\\secure-mcp-gateway\\src\\secure_mcp_gateway\\bad_mcps\\echo_mcp.py" ] }, "tools": {}, "input_guardrails_config": { "enabled": false, "guardrail_name": "Sample Airline Guardrail", "additional_config": { "pii_redaction": false }, "block": [ "policy_violation" ] }, "output_guardrails_config": { "enabled": false, "guardrail_name": "Sample Airline Guardrail", "additional_config": { "relevancy": false, "hallucination": false, "adherence": false }, "block": [ "policy_violation" ] } } ] } }, "projects": { "3c09f06c-1f0d-4153-9ac5-366397937641": { "project_name": "default_project", "mcp_config_id": "fcbd4508-1432-4f13-abb9-c495c946f638", "users": [ "6469a670-1d64-4da5-b2b3-790de21ac726" ], "created_at": "2025-07-16T17:02:00.406877" } }, "users": { "6469a670-1d64-4da5-b2b3-790de21ac726": { "email": "[email protected]", "created_at": "2025-07-16T17:02:00.406902" } }, "apikeys": { "2W8UupCkazk4SsOcSu_1hAbiOgPdv0g-nN9NtfZyg-rvYGat": { "project_id": "3c09f06c-1f0d-4153-9ac5-366397937641", "user_id": "6469a670-1d64-4da5-b2b3-790de21ac726", "created_at": "2025-07-16T17:02:00.406905" } } }
6.6 Verify Cursor
-
You can see the MCP server in the list of MCP servers in Cursor by navigating to
~/.cursor/mcp.jsonand also by clicking on the settings icon on the top right and then clicking onTools & Integrationsor on theMCPtab -
Generally restarting is not needed but if it is in loading state for a long time, please restart Cursor
-
Now you can chat with the MCP server.
-
Example prompts:
-
(Click
Run Toolwhen Cursor asks you to) -
list all servers, get all tools available and echo test- This uses a test MCP server
echo_serverwhich is inbad_mcps/echo_mcp.py
- This uses a test MCP server
-
-
6.7 Verify Claude Code
-
Run
claude mcp listto see the gateway in the list of configured MCP servers -
Launch Claude Code and run
/mcpto check server status -
Try
list all servers, get all tools available and echo testas a prompt to verify the gateway is working
7. Edit the Gateway config as needed
7.0 Hot-Reload (Zero-Restart Config Updates)
Edits to enkrypt_mcp_config.json take effect on the next request without restarting the gateway process or reconnecting the MCP client.
How it works (automatic):
- A background watcher polls the config file mtime every
enkrypt_config_watcher_poll_seconds(default2.0). - When a change is detected, the gateway:
- Clears the file-level config cache so the next read sees the new contents
- Rebuilds the auth / guardrails / telemetry providers with the new credentials
- Resets the timeout manager and session pool
- Flushes the per-gateway config cache so the next request re-fetches via the (now reloaded) auth provider
- Sessions older than
enkrypt_gateway_cache_expiration_minutes(default5) are evicted on next access so previously-authenticated clients see the new config too.
How to force a flush immediately (manual):
The flush endpoint is mounted on both processes — the REST admin API (port 8001) and the MCP gateway (port 8000). They are separate Python processes with separate in-memory caches, so to refresh both you must call both:
# 1. Refresh the REST admin API process
curl -X POST http://localhost:8001/api/v1/cache/flush-gateway-config \
-H "apikey: " \
-H "Content-Type: application/json" \
-d '{"include_tool_cache": false}'
# 2. Refresh the MCP gateway process (same payload, same auth)
curl -X POST http://localhost:8000/api/v1/cache/flush-gateway-config \
-H "apikey: " \
-H "Content-Type: application/json" \
-d '{"include_tool_cache": false}'
# Returns on each:
# {
# "status": "ok",
# "summary": { "auth_reloaded": true, "guardrails_reloaded": true, ... },
# "authorized_via": "org_match" | "static_admin_key",
# "principal": "[email protected]" | null
# }
What this clears (per process):
- The file-level
get_common_config()cache - The auth provider — including
EnkryptAuthProvider._cache(the cloud-config TTL cache), so the next request triggers a fresh fetch from the Enkrypt cloud API - The guardrail provider (re-reads guardrail credentials)
- The telemetry provider, timeout manager, and session pool
- The per-gateway config cache (
flush_all_gateway_config_cache)
The flush endpoint also accepts "include_tool_cache": true to additionally drop per-server tool caches (forces re-discovery on next call). Use this when you’ve added new tools to a server.
Inspecting the last flush:
curl -H "apikey: " http://localhost:8000/api/v1/cache/last-reload
curl -H "apikey: " http://localhost:8001/api/v1/cache/last-reload
# Returns: {"last_reload_ts": , "last_reload_summary": {...}}
Cache-flush authorization policy
The apikey header is validated by auth_policy.authorize_apikey_for_cache_flush, which has two completely different paths depending on which auth provider is active. The policy is intentionally strict under plugins.auth.provider == "enkrypt": every flush rounds-trips Enkrypt cloud’s /consumer-info so the request’s principal (email) is recorded and the cloud’s org_id is verified against the gateway’s configured org_id.
| Provider | Accepted apikey | What gets recorded as principal |
|---|---|---|
plugins.auth.provider == "enkrypt" |
Any cloud apikey whose /consumer-info.org_id matches an entry in enkrypt_config.org_id in the gateway config (single string OR list of strings — see below). No static break-glass — root admin_apikey is NOT accepted under cloud auth. |
The cloud user’s email (or user_id if email is missing). |
plugins.auth.provider == "local_apikey" (and other non-enkrypt providers) |
Root admin_apikey, or the deprecated enkrypt_config.admin_apikey. No cloud roundtrip. |
null (static-admin path doesn’t carry identity). |
Response field authorized_via tells you which path matched: "org_match" (cloud) or "static_admin_key" (local).
Required config under provider=enkrypt:
{
"enkrypt_config": {
"api_key": "",
"base_url": "https://api.enkryptai.com",
// Single-org gateway: one string.
"org_id": ""
// Multi-org gateway: a list of allowed org_ids. Cache flushes
// are accepted from any apikey whose /consumer-info.org_id matches
// any entry. Useful when one gateway fronts multiple Enkrypt orgs
// (e.g. operator + customer org both flushing the same shared
// gateway). Blank / placeholder / non-string entries are silently
// dropped during normalization; an empty effective list is treated
// the same as the field being absent (500 no_org_gating_configured).
// "org_id": ["", ""]
},
"plugins": { "auth": { "provider": "enkrypt", "config": {} } }
}
enkrypt_config.org_id is mandatory for cache flush to work under cloud auth — without it every flush request returns 500 no_org_gating_configured. The placeholder "YOUR_ENKRYPT_ORG_ID" (which secure-mcp-gateway generate-config --provider enkrypt emits) is also treated as not-configured.
org_id accepts either a single string (the common one-org-per-gateway case) or a JSON list of strings (multi-org allow-list — one gateway can authorize flushes from several distinct orgs without having to flip the auth provider). A single-entry list like ["org-uuid-X"] behaves identically to the bare string form "org-uuid-X" (the error message even renders without brackets in that case, so single-org alerting stays unchanged).
Failure-mode reference:
| HTTP | reason |
When |
|---|---|---|
| 200 | ok_org_match / ok_static_admin_key |
flush succeeded; check authorized_via to know which path |
| 401 | missing_apikey |
no apikey header |
| 401 | invalid_apikey |
local-provider apikey didn’t match admin_apikey / cloud /consumer-info rejected the apikey |
| 403 | org_mismatch |
cloud apikey is valid but its org_id is not in enkrypt_config.org_id (single value or allow-list) |
| 409 | (no reason) |
another reload is already in progress |
| 500 | no_admin_configured |
local provider, no admin_apikey set |
| 500 | no_org_gating_configured |
enkrypt provider, enkrypt_config.org_id missing or still the placeholder |
| 502 | cloud_unavailable |
cloud /consumer-info timed out or returned 5xx |
Operator implications:
- Under
provider=enkrypt, the operator’s ownenkrypt_config.api_keystill works because it survives/consumer-infoand itsorg_idmatches by construction — but the request goes through the cloud (cached 5 min after first hit per apikey). - The Enkrypt cloud must be reachable to flush under
provider=enkrypt. If you need an emergency local flush during a cloud outage, temporarily switchplugins.auth.providertolocal_apikey(file-watcher applies the change in ~2 s; the next flush then acceptsadmin_apikey). - Every successful flush leaves a structured log line:
[gateway_cache_routes] cache flushed via= principal= include_tool_cache=— searchable in OpenSearch vialog.attributes.principal/log.attributes.via.
Relevant config keys:
| Key | Default | Meaning |
|---|---|---|
enkrypt_gateway_cache_expiration_minutes |
5 |
TTL for cached per-gateway configs and authenticated sessions. Shorter = config edits take effect faster, longer = fewer auth round-trips. |
enkrypt_gateway_cache_expiration |
24 |
Legacy hours-based TTL. Kept for backward compatibility; minutes field wins when both are set. |
enkrypt_config_watcher_poll_seconds |
2.0 |
How often the watcher re-checks the file mtime. Set to 0 to disable automatic hot-reload (manual flush API still works). |
Settings that still require restart:
| Setting | Reason |
|---|---|
Listen port 0.0.0.0:8000 |
Socket bind happens once at FastMCP startup |
enkrypt_mcp_use_external_cache toggle |
In-memory ↔ Redis swap would lose in-flight operations |
enkrypt_cache_host / enkrypt_cache_port |
Redis connection pool rebuild risks dropping in-flight pipelines |
plugins.telemetry.config.url / enabled |
OpenTelemetry’s global TracerProvider / MeterProvider can only be set once per process (SDK constraint) |
7.1 Enkrypt cloud auth provider and gateway headers
Setting plugins.auth.provider to "enkrypt" switches the gateway from local apikeys / projects / users / mcp_configs lookups to Enkrypt cloud: on every authenticated request the gateway calls GET {base_url}/mcp-gateway/get-gateway-config and maps the response into the internal config shape. Which cloud gateway config comes back is decided by the apikey plus the gateway headers described below.
8. CLI Quick Start Guide
Step 4: Set your Enkrypt API key (for guardrails)
If you want to use Enkrypt AI guardrails (input/output protection, PII redaction, toxicity filtering, etc.), you need to set your Enkrypt API key. You can get one from the Enkrypt AI dashboard.
# Set the Enkrypt API key
secure-mcp-gateway config set-enkrypt-api-key --api-key "YOUR_ENKRYPT_API_KEY"
# Verify it was set
secure-mcp-gateway config get-enkrypt-api-key
Without this key, guardrails features won’t work — but the gateway itself will still route tools normally.
Step 5: Turn telemetry on or off
The gateway ships with OpenTelemetry support for logging, tracing, and metrics. By default it’s enabled but will silently skip if the collector endpoint isn’t reachable. You can explicitly enable or disable it:
# Disable telemetry
secure-mcp-gateway config configure-telemetry --enabled false
# Enable telemetry with a custom collector URL
secure-mcp-gateway config configure-telemetry --enabled true --url "http://localhost:4317"
# Allow insecure (non-TLS) connections to the collector
secure-mcp-gateway config configure-telemetry --insecure true
Starting the telemetry stack: The gateway sends telemetry data to an OpenTelemetry collector — it doesn’t run one itself. The repo ships two ready-made backends in observability/: the OpenSearch stack (primary, OTel default ports 4317/4318 — see observability/README.opensearch.md) and the legacy Grafana stack (collector, Prometheus, Grafana, Jaeger, Loki + 9 Slack alert rules, on 4327/4328). Run one. For the Grafana stack:
cd observability
cp .env.grafana.example .env.grafana # (edit SLACK_WEBHOOK_URL if you want Slack alerts)
docker compose -f docker-compose.grafana.yml --env-file .env.grafana up -d
# then point plugins.telemetry.config.url at http://localhost:4327
| Service | URL |
|---|---|
| Grafana dashboards | http://localhost:3001 (anonymous admin; override via GRAFANA_HOST_PORT) |
| Jaeger trace viewer | http://localhost:16686 |
| Prometheus metrics | http://localhost:9090 |
| OTLP gRPC endpoint | http://localhost:4317 |
Once the stack is running, the gateway will automatically start sending traces, logs, and metrics to the collector. See §5 for full details and observability/README.md for the deep dive on alert customisation.
Step 6: System operations
# Check gateway health
secure-mcp-gateway system health-check
# Backup your entire config
secure-mcp-gateway system backup
# Restore from a backup
secure-mcp-gateway system restore --file
# Reset to defaults (⚠️ destructive)
secure-mcp-gateway system reset
Docker command pattern
Add --docker to any CLI command to run it inside the Docker container automatically.
The flag auto-detects your OS, sets HOST_OS and HOST_ENKRYPT_HOME, and mounts the
~/.enkrypt/docker volume — no long docker run incantation needed.
# Quick (recommended) — works on macOS, Linux, and Windows (all shells)
secure-mcp-gateway --docker
# Use a custom Docker image
secure-mcp-gateway --docker --docker-image my-registry/secure-mcp-gateway:v2.1.2
Image tag is pinned to your host CLI version
Starting in v2.2.0, the wrapper defaults to enkryptai/secure-mcp-gateway: (e.g. enkryptai/secure-mcp-gateway:2.2.0) instead of :latest. This prevents flag-skew bugs where a newer host CLI passes flags the older in-container CLI doesn’t recognise — e.g.
secure-mcp-gateway: error: unrecognized arguments: --provider enkrypt
(generate-config --provider enkrypt was added in v2.2.0; if your host CLI is v2.2.0 but the container is v2.1.6, that flag silently disappears in transit.)
If --docker-image is overridden and the override doesn’t contain the host CLI version string, the wrapper logs a WARN: line so the cause of any “unrecognized arguments” error is obvious.
If your default tag isn’t on Docker Hub yet (typical right after a host pip upgrade, before the matching image has been published), Docker exits with not found:
Unable to find image 'enkryptai/secure-mcp-gateway:2.2.0' locally
docker: Error response from daemon: failed to resolve reference "docker.io/enkryptai/secure-mcp-gateway:2.2.0": ... not found.
You have three workarounds:
| Workaround | Command | Trade-off |
|---|---|---|
| Build the image locally from this repo (recommended) | docker build -t secure-mcp-gateway . && secure-mcp-gateway --docker --docker-image secure-mcp-gateway |
Always matches your host CLI; one-time docker build cost. |
| Pin to a known-good published tag | secure-mcp-gateway --docker --docker-image enkryptai/secure-mcp-gateway: |
Stable; you only see flags supported by ``. |
Use :latest and accept skew |
secure-mcp-gateway --docker --docker-image enkryptai/secure-mcp-gateway:latest |
Wrapper emits a WARN: line; new flags may fail with unrecognized arguments. |
Examples:
# List configs
secure-mcp-gateway --docker config list
# Add a server
secure-mcp-gateway --docker config add-server --config-name "default_config" --server-name "my_server" --server-command "npx" --args="-y,@example/mcp-server" --description "My Server"
# Generate config (local_apikey, default)
secure-mcp-gateway --docker generate-config
# Generate config (enkrypt cloud) — requires container CLI >= v2.2.0
secure-mcp-gateway --docker generate-config --provider enkrypt --overwrite
# Health check
secure-mcp-gateway --docker system health-check
9. (Optional) Add GitHub MCP Server to the Gateway
9.1 (Optional) Connect to MCP Servers with OAuth
10. (Optional) Protect GitHub MCP Server and Test Echo Server
-
Go to Enkrypt App and login with either OTP or Google or Microsoft account
-
Click on
Policies -
Click on
Add new policy -
Name it
GitHub Safe Policyand paste the policy rules and clickSave -
This is how a saved policy looks like with the rules applied for
Policy violationGuardrails -
Now navigate back to home or hover over left sidebar and click
Guardrails -
Click on
Add New Guardrailbutton on the top right -
Name it
GitHub Guardrail, toggleInjection AttackOFF -
Scroll down on
Configure Guardrailsside panel and togglePolicy ViolationON, select the newly created policy and tickNeed Explanationif needed -
Now, click on
Savebutton on the bottom right to save the guardrail -
We can see the newly added guardrail in the list of guardrails
-
Now we have everything we need from the App. Let’s add the API Key to the
enkrypt_mcp_config.jsonfile -
Open the
enkrypt_mcp_config.jsonfile from~/.enkrypt/enkrypt_mcp_config.jsonon macOS or%USERPROFILE%\.enkrypt\enkrypt_mcp_config.jsonon Windows- If you ran docker command to install the Gateway, the config file will be in
~/.enkrypt/docker/enkrypt_mcp_config.jsonon macOS and%USERPROFILE%\.enkrypt\docker\enkrypt_mcp_config.jsonon Windows
- If you ran docker command to install the Gateway, the config file will be in
-
Add the API Key to the
common_mcp_gateway_configsection by replacingYOUR_ENKRYPT_API_KEYwith the API Key you copied from the App -
Inside the
GitHubserver block we added in the previous section,-
Add the newly created Guardrail
GitHub Guardrailto theinput_guardrails_configandoutput_guardrails_configsections -
By replacing
"guardrail_name": "Sample Airline Guardrail"with"guardrail_name": "GitHub Guardrail" -
Now change
enabledtotrueforinput_guardrails_configfrom previousfalse- We will leave
output_guardrails_configasfalsefor now
- We will leave
-
We already should have
policy_violationin theblockarray for both policies -
So the final config should look something like this:
{ "common_mcp_gateway_config": { ... "enkrypt_api_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx", ... }, "mcp_configs": { "fcbd4508-1432-4f13-abb9-c495c946f638": { "mcp_config_name": "default_config", "mcp_config": [ { "server_name": "echo_server", ... }, { "server_name": "github_server", "description": "GitHub Server", "config": { "command": "docker", "args": [ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server" ], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "github_pat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -
Install
docker run --rm -i -e MCP_TRANSPORT=stdio -v C:\\Users\\<user>\\.enkrypt\\docker:/app/.enkrypt/docker -e ENKRYPT_GATEWAY_KEY -e ENKRYPT_PROJECT_ID -e ENKRYPT_USER_ID secure-mcp-gatewayConfiguration
{
"mcpServers": {
"Enkrypt Secure MCP Gateway": {
"command": "mcp",
"args": [
"run",
"/Users/user/enkryptai/secure-mcp-gateway/venv/lib/python3.13/site-packages/secure_mcp_gateway/gateway.py"
],
"env": {
"ENKRYPT_GATEWAY_KEY": "2W8UupCkazk4SsOcSu_1hAbiOgPdv0g-nN9NtfZyg-rvYGat",
"ENKRYPT_PROJECT_ID": "3c09f06c-1f0d-4153-9ac5-366397937641",
"ENKRYPT_USER_ID": "6469a670-1d64-4da5-b2b3-790de21ac726"
}
}
}
}