04 - Tool Secrets
Read secrets from environment and .env
files securely via Context.
Running the Example
- Run:
uv run 04_secrets.py
- Run (stdio):
uv run 04_secrets.py stdio
- Create
.env
: AddAPI_KEY=supersecret
to a.env
file
Source Code
#!/usr/bin/env python3
"""04: Read secrets from .env via Context
Run:
uv run 04_secrets.py # HTTP transport (default)
uv run 04_secrets.py stdio # stdio transport for Claude Desktop
Environment:
# Create a .env in the working directory with:
# API_KEY=supersecret
"""
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=["API_KEY"], # declare we need API_KEY
)
def use_secret(context: Context) -> str:
"""Read API_KEY from context and return a masked confirmation string."""
try:
value = context.get_secret("API_KEY")
masked = value[:2] + "***" if len(value) >= 2 else "***"
return f"Got API_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)
Working with Secrets
1. Environment Variables
Secrets can be provided via environment variables:
2. Using .env Files
Create a .env
file in the directoryof your server:
3. Declaring Required Secrets
Use the requires_secrets
parameter to declare which secrets your tool needs:
@tool(requires_secrets=["API_KEY", "DATABASE_URL"])
def my_secure_tool(context: Context) -> str:
api_key = context.get_secret("API_KEY")
db_url = context.get_secret("DATABASE_URL")
4. 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 context, 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