Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions app/en/get-started/quickstarts/mcp-server-quickstart/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import { Steps, Tabs, Callout } from "nextra/components";
import { SignupLink } from "@/app/_components/analytics";
import { GuideOverview } from "@/app/_components/guide-overview";

# Build MCP Server QuickStart
# Build MCP server quickstart

Build and run an MCP server with tools that you create.

<GuideOverview>
<GuideOverview.Outcomes>

Build and run an MCP Server with tools that you create.
Build and run an MCP server with tools that you create.

</GuideOverview.Outcomes>

Expand Down Expand Up @@ -67,9 +69,9 @@ pip install arcade-mcp
</Tabs.Tab>
</Tabs>

## Create Your Server
## Create your server

In your terminal, run the following command to scaffold a new MCP Server called `my_server`:
In your terminal, run the following command to scaffold a new MCP server called `my_server`:

```bash
arcade new my_server
Expand Down Expand Up @@ -100,7 +102,7 @@ my_server/

> If you're having issues with the `arcade` command, please see the [Troubleshooting](#troubleshooting) section.

## Setup the secrets in your environment
## Set up the secrets in your environment

Secrets are sensitive strings like passwords, API keys, or other tokens that grant access to a protected resource or API. Arcade includes the "whisper_secret" tool that requires you to set a secret key in your environment. If you don't set the secret, the tool will return an error.

Expand Down Expand Up @@ -166,9 +168,9 @@ arcade login

Follow the instructions in your browser to connect your terminal to your Arcade account.

## Run your MCP Server
## Run your MCP server

Run your MCP Server using one of the following commands in your terminal:
Run your MCP server using one of the following commands in your terminal:

<Tabs
items={["stdio transport (default)", "http transport"]}
Expand Down Expand Up @@ -223,9 +225,9 @@ You should see output like this in your terminal:
INFO | 13:46:11 | arcade_mcp_server.mcp_app:299 | Starting my_server v1.0.0 with 3 tools
```

## Configure your MCP Clients
## Configure your MCP clients

Now you can connect MCP Clients to your MCP server:
Now you can connect MCP clients to your MCP server:

<Tabs
items={["Cursor IDE", "VS Code", "Claude Desktop"]}
Expand Down Expand Up @@ -292,10 +294,10 @@ Ensure you run `arcade login` and follow the instructions in your browser to con

Ensure you have set the environment variable in your terminal or `.env` file, and that it matches the secret key defined in the `@app.tool` decorator. If you are using the stdio transport, then ensure you add the environment variable to the MCP client's configuration file.

## Next Steps
## Next steps

- **Learn how to write a tool with auth**: [Create a tool with auth](/guides/create-tools/tool-basics/create-tool-auth)
- **Learn how to write a tool with secrets**: [Create a tool with secrets](/guides/create-tools/tool-basics/create-tool-secrets)
- **Learn more about the Context object**: [Tools and Context](/guides/create-tools/tool-basics/runtime-data-access)
- **Learn how to write tool evaluations**: [Create an evaluation suite](/guides/create-tools/evaluate-tools/create-evaluation-suite) to optimize them for LLM usage
- **Learn how to deploy your MCP server**: [Deploy your MCP server](/guides/deployment-hosting/arcade-deploy)
- **Learn how to deploy your MCP server**: [Deploy your MCP server](/guides/deployment-hosting/arcade-deploy)
44 changes: 23 additions & 21 deletions app/en/guides/create-tools/tool-basics/build-mcp-server/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { Steps, Tabs, Callout } from "nextra/components";

# Creating an MCP Server with Arcade

Learn how to build and run a secure MCP server with tools that you define.

The `arcade_mcp_server` package is the secure framework to build and run MCP servers with your Arcade tools. It is easiest to use with the `arcade-mcp` package (Arcade's CLI) which can scaffold your MCP server with all the necessary files and dependencies, configure MCP Clients to connect to your server, deploy your server to the cloud, and more. This guide walks you through the complete process of creating a custom MCP server with Arcade.

<GuideOverview>
Expand All @@ -26,7 +28,7 @@ Build and run a secure MCP server with tools that you define.

- How to run MCP servers with Arcade tools using the [`arcade_mcp_server`](/references/mcp/python) package
- How to use `arcade new` from the `arcade-mcp` CLI to create your server project with all necessary files and dependencies.
- How to run your local MCP Server with the Arcade CLI and register it with the Arcade Engine so that your agent can find and use your tool.
- How to run your local MCP server with the Arcade CLI and register it with the Arcade Engine so that your agent can find and use your tool.

</GuideOverview.YouWillLearn>
</GuideOverview>
Expand Down Expand Up @@ -63,9 +65,9 @@ pip install arcade-mcp
</Tabs.Tab>
</Tabs>

## Create Your Server
## Create your server

In your terminal, run the following command to scaffold a new MCP Server called `my_server`:
In your terminal, run the following command to scaffold a new MCP server called `my_server`:

```bash
arcade new my_server
Expand All @@ -84,9 +86,9 @@ my_server/
└── pyproject.toml
```

1. **server.py** Main server file with MCPApp and example tools. It creates an `MCPApp`, defines tools with `@app.tool`, and will start the server with `app.run()` when the file is executed directly.
1. **server.py** Main server file with MCPApp and example tools. It creates an `MCPApp`, defines tools with `@app.tool`, and will start the server with `app.run()` when you execute the file directly.
1. **pyproject.toml** Dependencies and project configuration
1. **.env.example** Example `.env` file at the project root containing a secret required by one of the generated tools in `server.py`. Arcade automatically discovers `.env` files by traversing upward from the current directory, so placing it at the project root makes it accessible from any subdirectory. Environments are loaded on server start, so **if you update the `.env` file, you will need to restart your server.**
1. **.env.example** Example `.env` file at the project root containing a secret required by one of the generated tools in `server.py`. Arcade automatically discovers `.env` files by traversing upward from the current directory, so placing it at the project root makes it accessible from any subdirectory. The system loads environments on server start, so **if you update the `.env` file, you will need to restart your server.**

```python filename="server.py" showLineNumbers
#!/usr/bin/env python3
Expand All @@ -112,7 +114,7 @@ def greet(name: Annotated[str, "The name of the person to greet"]) -> str:
@app.tool(requires_secrets=["MY_SECRET_KEY"])
def whisper_secret(context: Context) -> Annotated[str, "The last 4 characters of the secret"]:
"""Reveal the last 4 characters of a secret"""
# Secrets are injected into the context at runtime.
# Arcade injects secrets into the context at runtime.
# LLMs and MCP clients cannot see or access your secrets
# You can define secrets in a .env file.
try:
Expand All @@ -133,12 +135,12 @@ async def get_posts_in_subreddit(
subreddit = subreddit.lower().replace("r/", "").replace(" ", "")

# Prepare the httpx request
# OAuth token is injected into the context at runtime.
# Arcade injects OAuth token into the context at runtime.
# LLMs and MCP clients cannot see or access your OAuth tokens.
oauth_token = context.get_auth_token_or_empty()
headers = {
"Authorization": f"Bearer {oauth_token}",
"User-Agent": "finally-mcp-server",
"User-Agent": "finally mcp server",
}
params = {"limit": 5}
url = f"https://oauth.reddit.com/r/{subreddit}/hot"
Expand All @@ -157,17 +159,17 @@ if __name__ == "__main__":
# - "stdio" (default): Standard I/O for Claude Desktop, CLI tools, etc.
# Supports tools that require_auth or require_secrets out-of-the-box
# - "http": HTTPS streaming for Cursor, VS Code, etc.
# Does not support tools that require_auth or require_secrets unless the server is deployed
# using 'arcade deploy' or added in the Arcade Developer Dashboard with 'Arcade' server type
# The system does not support tools that require_auth or require_secrets unless you deploy the server
# using 'arcade deploy' or add in the Arcade Developer Dashboard with 'Arcade' server type
transport = sys.argv[1] if len(sys.argv) > 1 else "stdio"

# Run the server
app.run(transport=transport, host="127.0.0.1", port=8000)
```

## Setup the secrets in your environment
## Set up the secrets in your environment

Secrets are sensitive strings like passwords, API keys, or other tokens that grant access to a protected resource or API. Arcade includes the "whisper_secret" tool that requires a secret key to be set in your environment. If the secret is not set, the tool will return an error.
Secrets are sensitive strings like passwords, API keys, or other tokens that grant access to a protected resource or API. Arcade includes the "whisper_secret" tool that requires a secret key in your environment. If you do not set the secret, the tool will return an error.

<Tabs items={[".env file", "Environment Variable"]}>
<Tabs.Tab>
Expand All @@ -177,7 +179,7 @@ You can create a `.env` file at your project root directory and add your secret:
MY_SECRET_KEY="my-secret-value"
```

Arcade automatically discovers `.env` files by traversing upward from the current directory through parent directories. This means you can place your `.env` file at the project root (`my_server/`), and it will be found even when running your server from a subdirectory like `src/my_server/`.
Arcade automatically discovers `.env` files by traversing upward from the current directory through parent directories. This means you can place your `.env` file at the project root (`my_server/`), and Arcade will locate it even when running your server from a subdirectory like `src/my_server/`.

The generated project includes a `.env.example` file at the project root with the secret key name and example value.
You can rename it to `.env` to start using it.
Expand Down Expand Up @@ -231,11 +233,11 @@ Since the Reddit tool accesses information only available to your Reddit account
arcade login
```

Follow the instructions in your browser, and once you've finished, your terminal will be connected to your Arcade account.
Follow the instructions in your browser, and once you've finished, your terminal will connect to your Arcade account.

## Run your MCP Server
## Run your MCP server

Run your MCP Server using one of the following commands in your terminal:
Run your MCP server using one of the following commands in your terminal:

<Tabs
items={["stdio transport (default)", "http transport"]}
Expand Down Expand Up @@ -289,9 +291,9 @@ You should see output like this in your terminal:
INFO | 13:46:11 | arcade_mcp_server.mcp_app:299 | Starting my_server v1.0.0 with 3 tools
```

## Configure your MCP Client(s)
## Configure your MCP clients

Now you can connect MCP Clients to your MCP server:
Now your MCP clients can connect to your MCP server:

<Tabs
items={["Cursor IDE", "VS Code", "Claude Desktop"]}
Expand Down Expand Up @@ -332,7 +334,7 @@ Now you can connect MCP Clients to your MCP server:
</Tabs.Tab>
</Tabs>

That's it! Your MCP server is running and connected to your AI assistant.
That's it Your MCP server is running and connected to your AI assistant.

</Steps>

Expand All @@ -345,10 +347,10 @@ That's it! Your MCP server is running and connected to your AI assistant.
- **Tool Docstrings** Use docstrings to provide a description of a tool to the language model
- **Command Line Arguments** Pass transport type as command line argument

### Next steps
## Next steps

- **Create custom tools that use auth**: [Learn how to create tools with authorization](/guides/create-tools/tool-basics/create-tool-auth)
- **Create custom tools that use secrets**: [Learn how to create tools with secrets](/guides/create-tools/tool-basics/create-tool-secrets)
- **Learn the capabilities of the `Context` object**: [Understanding the Context object](/guides/create-tools/tool-basics/runtime-data-access)
- **Evaluate your tools**: [Explore how to evaluate tool performance](/guides/create-tools/evaluate-tools/why-evaluate)
- **Deploy your MCP server**: [Learn how to deploy your MCP server](/guides/deployment-hosting/arcade-deploy)
- **Deploy your MCP server**: [Learn how to deploy your MCP server](/guides/deployment-hosting/arcade-deploy)
32 changes: 18 additions & 14 deletions app/en/guides/create-tools/tool-basics/create-tool-secrets/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { Steps, Tabs, Callout } from "nextra/components";

# Create an MCP tool with secrets

Build an MCP tool that can read a secret from Context and return a masked confirmation string.

<GuideOverview>
<GuideOverview.Outcomes>

Expand All @@ -31,13 +33,15 @@ Build an MCP tool that can read a secret from Context and return a masked confir
</GuideOverview.YouWillLearn>
</GuideOverview>

This page shows you how to create MCP tools that require secrets for runtime configuration and secure external service access. You'll learn to use Arcade's Context object to access secrets safely and configure them across different deployment environments.

Secrets are sensitive strings like passwords, API keys, or other tokens that grant access to a protected resource or API. You can also use secrets to provide other static configuration values your tool needs, such as parameters for calling 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 tool function, this becomes very inconvenient, expensive, hard to maintain, and insecure when deploying at scale.
Secrets enable you to securely deploy a function that requires sensitive information at runtime. And while tools can consume these secrets directly from the runtime environment inside your tool function, this becomes inconvenient, expensive, hard to maintain, and insecure when deploying at scale.

For example, if your tool requires an API key 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.
For example, if your tool requires an API key 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 system performs the computationally expensive work. The function below would fail if the API key is not present.

```python
import os
Expand All @@ -56,9 +60,9 @@ def my_tool(task: str) -> str:
return "Failed to upload result"
```

We can work around this by carefully checking for the API key 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.
You can work around this by carefully checking for the API key before doing the computationally expensive work, 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 tool from running if the secret is not provided. In this guide, you'll learn how to use secrets in your custom Arcade tools.
Arcade provides a way to securely store and access secrets inside your tools in a way that allows straightforward management across multiple instances of your servers, and that will prevent the tool from running if the secret is not provided. In this guide, you'll learn how to use secrets in your custom Arcade tools.

<Steps>

Expand Down Expand Up @@ -108,10 +112,10 @@ You can store your secret in the Arcade Dashboard by:
- Entering the secret ID and value
- Clicking the "Create" button

This will make the secret available to your MCP server, when deployed to Arcade.
This will make the secret available to your MCP server when you deploy to Arcade.

<Callout type="info">
The Arcade Dashboard will make the secret available to your MCP server when it is deployed. Secrets set in the Arcade Dashboard are not available to your MCP server when it is running locally.
The system deploys the Arcade Dashboard secret to your MCP server. Secrets set in the Arcade Dashboard are not available to your MCP server when it is running locally.
</Callout>

</Tabs.Tab>
Expand All @@ -123,7 +127,7 @@ arcade secret set MY_SECRET_KEY="my-secret-value"
```

<Callout type="info">
The Arcade CLI will make the secret available to your MCP server when it is deployed, because it upserts the secret into the Arcade Cloud. Secrets set in the Arcade CLI are not available to your MCP server when it is running locally.
The system deploys the Arcade CLI secret to your MCP server, because it upserts the secret into Arcade Cloud. Secrets set in the Arcade CLI are not available to your MCP server when it is running locally.
</Callout>

</Tabs.Tab>
Expand Down Expand Up @@ -166,7 +170,7 @@ To ensure your stdio MCP server has access to the secrets, you can either
```json
{
"mcpServers": {
"simple": {
"basic": {
"command": "uv",
"args": [
"run",
Expand All @@ -190,12 +194,12 @@ Note that the specific key name may vary depending on the MCP client you are usi

<Callout type="info">
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
is present before the tool executes. In a real world application, you would
use this secret to store sensitive information like API keys, database
credentials, etc, and not to simply print a confirmation string.
credentials, etc, and not to print a confirmation string.
</Callout>

In your [MCP Server](/guides/create-tools/tool-basics/build-mcp-server), create a new tool that uses the secret:
In your [MCP server](/guides/create-tools/tool-basics/build-mcp-server), create a new tool that uses the secret:

- Use the `requires_secrets` parameter to declare which secrets your tool needs (`"SECRET_KEY"` in this example).
- The tool's Context object has a `get_secret` method that you can use to access the secret value.
Expand All @@ -214,7 +218,7 @@ def use_secret(context: Context) -> str:
return f"Error getting secret: {e}"
```

When your tool 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.
When your tool executes, 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.

</Steps>

Expand All @@ -231,7 +235,7 @@ When your tool is executed, it will return: `"Got SECRET_KEY of length..."`. In

## Key Concepts

- **Secure Access:** Secrets are accessed through context, not imported directly
- **Secure Access:** Systems access secrets 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
Expand Down Expand Up @@ -318,4 +322,4 @@ For HTTP transport, view your server's API docs at [http://127.0.0.1:8000/docs](

</Tabs.Tab>

</Tabs>
</Tabs>