Skip to Content
HomeBuild toolsCreate a tool with secrets

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 .
  • How to configure secrets in the Arcade Dashboard.

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.

Why use secrets in your tools?

Secrets enable you to securely deploy a function that requires sensitive information at runtime. And while these can be consumed directly from the runtime environment inside your function, this becomes very inconvenient, expensive, hard to maintain, and insecure when deploying at scale.

For example, if your tool requires an to use an external service, but only after doing some computationally expensive work, you need to ensure that the API key is present before the computationally expensive work is done. The function below would fail if the API key is not present.

Python
import os def my_tool(task: str) -> str: result = expensive_computation(task) API_KEY = os.getenv("API_KEY") # The line below will fail if the API key is not present success = upload_result_to_service(result, API_KEY) if success: return "Result uploaded successfully" else: return "Failed to upload result"

We can work around this by carefully checking for the before doing the computationally expensive work, of course, but this is error prone and difficult to maintain, and you may only become aware of the issue after deploying multiple instances of your server.

Arcade provides a way to securely store and access secrets inside your tools in a way that is easy to manage across multiple instances of your servers, and that will prevent the from running if the secret is not provided. In this guide, you’ll learn how to use secrets in your custom Arcade tools.

Store your secret

Depending on where you’re running your server, you can store your secret in a few different ways.

You can create a .env file in the root of your and add your secret:

ENV
.env
MY_SECRET_KEY="my-secret-value"

The includes a .env.example file with the secret key name and example value. You can rename it to .env to start using it.

Terminal
mv .env.example .env

Using environment variables is ok for local development, but you should use the Arcade Dashboard for production deployments.

Define your tool and access the secret

This is only an illustrative example of how Arcade will ensure that the secret is present before the tool is executed. In a real world application, you would use this secret to store sensitive information like , database credentials, etc, and not to simply print a confirmation string.

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 and use_secret methods that you can use to access the secret value.
Python
secrets.py
@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

ENV
.env
SECRET_KEY="supersecret"

For the code to work, you must define your environment variables locally or in a .env file.

Python
secrets.py
#!/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

Terminal
uv run secrets.py http

For HTTP transport, view your server’s API docs at http://127.0.0.1:8000/docs .

Last updated on