Create an MCP tool with secrets
Outcomes
Build an tool that can read a secret from and return a masked confirmation string. Jump to Example Code to see the complete code.
You will Learn
- How to read secrets from environment and
.env
files securely using a tool’s .
Prerequisites
Secrets are sensitive strings like passwords, api-keys, or other tokens that grant access to a protected resource or API. Although you could use secrets to transfer any static information to your , such as a parameter needed to call a remote API. In this guide, you’ll learn how to use secrets in your custom Arcade tools.
Store your secret
Secrets can be provided via environment variables.
You can set the environment variable in your terminal like so:
export SECRET_KEY="my-secret-value"
Or you can create a .env
file in the root of your and add your secret:
SECRET_KEY="my-secret-value"
Define your tool and access the secret
In your MCP Server, create a new that uses the secret:
- Use the
requires_secrets
parameter to declare which secrets your needs ("SECRET_KEY"
in this example). - The tool’s object has
get_secret
anduse_secret
methods that you can use to access the secret value.
@app.tool(
requires_secrets=["SECRET_KEY"], # declare we need SECRET_KEY
)
def use_secret(context: Context) -> str:
"""Read SECRET_KEY from context and return a masked confirmation string."""
try:
value = context.get_secret("SECRET_KEY")
masked = value[:2] + "***" if len(value) >= 2 else "***"
return f"Got SECRET_KEY of length {len(value)} -> {masked}"
except Exception as e:
return f"Error getting secret: {e}"
When your is executed, it will return: "Got SECRET_KEY of length..."
. In a real world application, you would use this secret to connect to a remote database, API, etc.
Security Best Practices
- Never log secret values Always mask or truncate when displaying
- Declare requirements Use
requires_secrets
to document dependencies - Handle missing secrets Use try/except when accessing secrets
- Use descriptive names Make it clear what each secret is for
Key Concepts
- Secure Access Secrets are accessed through , not imported directly
- Environment Integration Works with both environment variables and .env files
- Error Handling Always handle the case where a secret might be missing
- Masking Never expose full secret values in logs or return values
- Declaration Use
requires_secrets
to make dependencies explicit
Example Code
Environment Variables
SECRET_KEY="supersecret"
For the code to work, you must define your environment variables locally or in a .env
file.
#!/usr/bin/env python3
import sys
from arcade_mcp_server import Context, MCPApp
# Create the MCP application
app = MCPApp(
name="secrets_example",
version="1.0.0",
instructions="Example server demonstrating secrets usage",
)
@app.tool(
requires_secrets=["SECRET_KEY"], # declare we need SECRET_KEY
)
def use_secret(context: Context) -> str:
"""Read SECRET_KEY from context and return a masked confirmation string."""
try:
value = context.get_secret("SECRET_KEY")
masked = value[:2] + "***" if len(value) >= 2 else "***"
return f"Got SECRET_KEY of length {len(value)} -> {masked}"
except Exception as e:
return f"Error getting secret: {e}"
if __name__ == "__main__":
# Check if stdio transport was requested
transport = "stdio" if len(sys.argv) > 1 and sys.argv[1] == "stdio" else "http"
print(f"Starting {app.name} v{app.version}")
print(f"Transport: {transport}")
# Run the server
app.run(transport=transport, host="127.0.0.1", port=8000)
Run your MCP server
HTTP transport (default)
uv run secrets.py http
For HTTP transport, view your server’s API docs at http://127.0.0.1:8000/docs .