General OSS health (#643)
This commit is contained in:
parent
49e53d2b33
commit
5f55258268
75 changed files with 90 additions and 329 deletions
121
README.md
121
README.md
|
|
@ -32,16 +32,16 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p align="center" style="display: flex; justify-content: center; gap: 5px; font-size: 15px;">
|
<p align="center" style="display: flex; justify-content: center; gap: 5px; font-size: 15px;">
|
||||||
<a href="https://docs.arcade.dev/home" target="_blank">Documentation</a> •
|
<a href="https://docs.arcade.dev/tools" target="_blank">Prebuilt Tools</a> •
|
||||||
<a href="https://docs.arcade.dev/tools" target="_blank">Tools</a> •
|
|
||||||
<a href="https://docs.arcade.dev/home/quickstart" target="_blank">Quickstart</a> •
|
|
||||||
<a href="https://docs.arcade.dev/home/contact-us" target="_blank">Contact Us</a>
|
<a href="https://docs.arcade.dev/home/contact-us" target="_blank">Contact Us</a>
|
||||||
|
|
||||||
# Arcade MCP Server Framework
|
# Arcade MCP Server Framework
|
||||||
|
|
||||||
**To learn more about Arcade.dev, check out our [documentation](https://docs.arcade.dev/home).**
|
* **To see example servers built with Arcade MCP Server Framework (this repo), check out our [examples](examples/)**
|
||||||
|
|
||||||
**To learn more about the Arcade MCP Server Framework, check out our [Arcade MCP documentation](https://python.mcp.arcade.dev/)**
|
* **To learn more about the Arcade MCP Server Framework (this repo), check out our [Arcade MCP documentation](https://docs.arcade.dev/en/home/build-tools/create-a-mcp-server)**
|
||||||
|
|
||||||
|
* **To learn more about other offerings from Arcade.dev, check out our [documentation](https://docs.arcade.dev/home).**
|
||||||
|
|
||||||
_Pst. hey, you, give us a star if you like it!_
|
_Pst. hey, you, give us a star if you like it!_
|
||||||
|
|
||||||
|
|
@ -49,13 +49,13 @@ _Pst. hey, you, give us a star if you like it!_
|
||||||
<img src="https://img.shields.io/github/stars/ArcadeAI/arcade-mcp.svg" alt="GitHub stars">
|
<img src="https://img.shields.io/github/stars/ArcadeAI/arcade-mcp.svg" alt="GitHub stars">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
### Quick Start: Create a New Server
|
## Quick Start: Create a New Server
|
||||||
|
|
||||||
The fastest way to get started is with the `arcade new` command, which creates a complete MCP server project:
|
The fastest way to get started is with the `arcade new` CLI command, which creates a complete MCP server project:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install the CLI
|
# Install the CLI
|
||||||
uv pip install arcade-mcp
|
uv tool install arcade-mcp
|
||||||
|
|
||||||
# Create a new server project
|
# Create a new server project
|
||||||
arcade new my_server
|
arcade new my_server
|
||||||
|
|
@ -64,7 +64,7 @@ arcade new my_server
|
||||||
cd my_server
|
cd my_server
|
||||||
```
|
```
|
||||||
|
|
||||||
This generates a complete project with:
|
This generates a project with:
|
||||||
|
|
||||||
- **server.py** - Main server file with MCPApp and example tools
|
- **server.py** - Main server file with MCPApp and example tools
|
||||||
|
|
||||||
|
|
@ -72,24 +72,84 @@ This generates a complete project with:
|
||||||
|
|
||||||
- **.env.example** - Example `.env` file containing a secret required by one of the generated tools in `server.py`
|
- **.env.example** - Example `.env` file containing a secret required by one of the generated tools in `server.py`
|
||||||
|
|
||||||
The generated `server.py` includes proper command-line argument handling:
|
The generated `server.py` includes proper command-line argument handling and three example tools:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
"""simple_server MCP server"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
from arcade_mcp_server import MCPApp
|
|
||||||
|
|
||||||
app = MCPApp(name="my_server", version="1.0.0")
|
import httpx
|
||||||
|
from arcade_mcp_server import Context, MCPApp
|
||||||
|
from arcade_mcp_server.auth import Reddit
|
||||||
|
|
||||||
|
app = MCPApp(name="simple_server", version="1.0.0", log_level="DEBUG")
|
||||||
|
|
||||||
|
|
||||||
@app.tool
|
@app.tool
|
||||||
def greet(name: Annotated[str, "Name to greet"]) -> str:
|
def greet(name: Annotated[str, "The name of the person to greet"]) -> str:
|
||||||
"""Greet someone by name."""
|
"""Greet a person by name."""
|
||||||
return f"Hello, {name}!"
|
return f"Hello, {name}!"
|
||||||
|
|
||||||
|
|
||||||
|
# To use this tool locally, you need to either set the secret in the .env file or as an environment variable
|
||||||
|
@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.
|
||||||
|
# LLMs and MCP clients cannot see or access your secrets
|
||||||
|
# You can define secrets in a .env file.
|
||||||
|
try:
|
||||||
|
secret = context.get_secret("MY_SECRET_KEY")
|
||||||
|
except Exception as e:
|
||||||
|
return str(e)
|
||||||
|
|
||||||
|
return "The last 4 characters of the secret are: " + secret[-4:]
|
||||||
|
|
||||||
|
# To use this tool locally, you need to install the Arcade CLI (uv tool install arcade-mcp)
|
||||||
|
# and then run 'arcade login' to authenticate.
|
||||||
|
@app.tool(requires_auth=Reddit(scopes=["read"]))
|
||||||
|
async def get_posts_in_subreddit(
|
||||||
|
context: Context, subreddit: Annotated[str, "The name of the subreddit"]
|
||||||
|
) -> dict:
|
||||||
|
"""Get posts from a specific subreddit"""
|
||||||
|
# Normalize the subreddit name
|
||||||
|
subreddit = subreddit.lower().replace("r/", "").replace(" ", "")
|
||||||
|
|
||||||
|
# Prepare the httpx request
|
||||||
|
# OAuth token is injected 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": "{{ toolkit_name }}-mcp-server",
|
||||||
|
}
|
||||||
|
params = {"limit": 5}
|
||||||
|
url = f"https://oauth.reddit.com/r/{subreddit}/hot"
|
||||||
|
|
||||||
|
# Make the request
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.get(url, headers=headers, params=params)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
# Return the response
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
# Run with specific transport
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
transport = sys.argv[1] if len(sys.argv) > 1 else "http"
|
# Get transport from command line argument, default to "stdio"
|
||||||
|
# - "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
|
||||||
|
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)
|
app.run(transport=transport, host="127.0.0.1", port=8000)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This approach gives you:
|
This approach gives you:
|
||||||
|
|
@ -106,11 +166,11 @@ This approach gives you:
|
||||||
Run your server directly with Python:
|
Run your server directly with Python:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run with HTTP transport (default)
|
# Run with stdio transport (default)
|
||||||
uv run server.py
|
uv run server.py
|
||||||
|
|
||||||
# Run with stdio transport (for Claude Desktop)
|
# Run with http transport via command line argument
|
||||||
uv run server.py stdio
|
uv run server.py http
|
||||||
|
|
||||||
# Or use python directly
|
# Or use python directly
|
||||||
python server.py http
|
python server.py http
|
||||||
|
|
@ -124,26 +184,15 @@ Your server will start and listen for connections. With HTTP transport, you can
|
||||||
Once your server is running, connect it to your favorite AI assistant:
|
Once your server is running, connect it to your favorite AI assistant:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Configure Claude Desktop (configures for stdio)
|
arcade configure claude # Configure Claude Desktop to connect to your stdio server in your current directory
|
||||||
arcade configure claude --from-local
|
arcade configure cursor --transport http --port 8080 # Configure Cursor to connect to your local HTTP server on port 8080
|
||||||
|
arcade configure vscode --entrypoint my_server.py # Configure VSCode to connect to your stdio server that will run when my_server.py is executed directly
|
||||||
# Configure Cursor (configures for http streamable)
|
|
||||||
arcade configure cursor --from-local
|
|
||||||
|
|
||||||
# Configure VS Code (configures for http streamable)
|
|
||||||
arcade configure vscode --from-local
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Client Libraries
|
## Installing this Repo from Source
|
||||||
|
```bash
|
||||||
- **[ArcadeAI/arcade-py](https://github.com/ArcadeAI/arcade-py):**
|
git clone https://github.com/ArcadeAI/arcade-mcp.git && cd arcade-mcp && make install
|
||||||
The Python client for interacting with Arcade.
|
```
|
||||||
|
|
||||||
- **[ArcadeAI/arcade-js](https://github.com/ArcadeAI/arcade-js):**
|
|
||||||
The JavaScript client for interacting with Arcade.
|
|
||||||
|
|
||||||
- **[ArcadeAI/arcade-go](https://github.com/ArcadeAI/arcade-go):**
|
|
||||||
The Go client for interacting with Arcade.
|
|
||||||
|
|
||||||
## Support and Community
|
## Support and Community
|
||||||
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 651 KiB After Width: | Height: | Size: 651 KiB |
2
examples/.gitignore
vendored
2
examples/.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
||||||
# Un-ignore poetry.lock because the projects in this directory represent runnable sample apps
|
|
||||||
!poetry.lock
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
"""
|
|
||||||
This example demonstrates how to directly call a tool that does not require authorization.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from arcadepy import Arcade # pip install arcade-py
|
|
||||||
|
|
||||||
|
|
||||||
def call_non_auth_tool(client: Arcade, user_id: str) -> None:
|
|
||||||
"""Directly call a prebuilt tool that does not require authorization.
|
|
||||||
|
|
||||||
In this example, we are
|
|
||||||
1. Preparing the inputs to the Math.Add tool
|
|
||||||
2. Executing the tool
|
|
||||||
3. Printing the output of the tool's execution, i.e., the result of adding 9001 and 42
|
|
||||||
|
|
||||||
This is a simple example of calling a non-auth tool. Next, try writing your own non-auth tool for your own use case.
|
|
||||||
"""
|
|
||||||
# Prepare the inputs to the tool as a dictionary where keys are the names of the parameters expected by the tool and the values are the actual values to pass to the tool
|
|
||||||
tool_input = {"a": 9001, "b": 42}
|
|
||||||
|
|
||||||
# Execute the tool
|
|
||||||
response = client.tools.execute(
|
|
||||||
tool_name="Math.Add",
|
|
||||||
input=tool_input,
|
|
||||||
user_id=user_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Print the output of the tool execution
|
|
||||||
print(response.output.value)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
cloud_host = "https://api.arcade.dev"
|
|
||||||
|
|
||||||
client = Arcade(
|
|
||||||
base_url=cloud_host, # Alternatively, use http://localhost:9099 if you are running Arcade Engine locally, or any base_url if you're hosting elsewhere
|
|
||||||
)
|
|
||||||
|
|
||||||
user_id = "you@example.com"
|
|
||||||
call_non_auth_tool(client, user_id)
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
"""
|
|
||||||
This example demonstrates how to directly call a tool that requires authorization.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from arcadepy import Arcade # pip install arcade-py
|
|
||||||
|
|
||||||
|
|
||||||
def call_auth_tool(client: Arcade, user_id: str) -> None:
|
|
||||||
"""Directly call a prebuilt tool that requires authorization.
|
|
||||||
|
|
||||||
In this example, we are
|
|
||||||
1. Authorizing Arcade to read emails from the user's Gmail account with the user's permission to do so
|
|
||||||
2. Reading 5 emails from the user's Gmail account
|
|
||||||
3. Printing the emails
|
|
||||||
|
|
||||||
Try altering this example to call a tool that requires a different authorization.
|
|
||||||
"""
|
|
||||||
# Start the authorization process
|
|
||||||
auth_response = client.tools.authorize(
|
|
||||||
tool_name="Gmail.ListEmails",
|
|
||||||
user_id=user_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
# If not already authorized, then wait for the user to authorize the permissions required by the tool
|
|
||||||
if auth_response.status != "completed":
|
|
||||||
print(f"Click this link to authorize: {auth_response.url}")
|
|
||||||
|
|
||||||
# Wait for the user to complete the auth flow, if necessary
|
|
||||||
client.auth.wait_for_completion(auth_response)
|
|
||||||
|
|
||||||
# Prepare the inputs to the tool as a dictionary where keys are the names of the parameters expected by the tool and the values are the actual values to pass to the tool
|
|
||||||
tool_input = {"n_emails": 5}
|
|
||||||
|
|
||||||
# Execute the tool
|
|
||||||
response = client.tools.execute(
|
|
||||||
tool_name="Gmail.ListEmails",
|
|
||||||
input=tool_input,
|
|
||||||
user_id=user_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Print the output of the tool execution.
|
|
||||||
print(response)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
client = Arcade(
|
|
||||||
base_url="https://api.arcade.dev", # Alternatively, use http://localhost:9099 if you are running Arcade Engine locally, or any base_url if you're hosting elsewhere
|
|
||||||
)
|
|
||||||
|
|
||||||
user_id = "you@example.com"
|
|
||||||
call_auth_tool(client, user_id)
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
"""
|
|
||||||
This example shows how to call a tool that requires authorization with an LLM using the OpenAI Python client.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from openai import OpenAI
|
|
||||||
|
|
||||||
|
|
||||||
def call_tool_with_openai(client: OpenAI) -> dict:
|
|
||||||
response = client.chat.completions.create(
|
|
||||||
messages=[
|
|
||||||
{"role": "user", "content": "Star the ArcadeAI/arcade-mcp repository."},
|
|
||||||
],
|
|
||||||
model="gpt-4o-mini", # TODO: Try "claude-3-5-sonnet-20240620" or other models from our supported model providers. Checkout out our docs for a full list https://docs.arcade.dev
|
|
||||||
user="you@example.com",
|
|
||||||
tools=["Github.SetStarred"],
|
|
||||||
tool_choice="generate", # TODO: Try "execute" and note any differences
|
|
||||||
)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
arcade_api_key = os.environ.get(
|
|
||||||
"ARCADE_API_KEY"
|
|
||||||
) # If you forget your Arcade API key, it is stored at ~/.arcade/credentials.yaml on `arcade login`
|
|
||||||
cloud_host = "https://api.arcade.dev" + "/v1"
|
|
||||||
|
|
||||||
openai_client = OpenAI(
|
|
||||||
api_key=arcade_api_key,
|
|
||||||
base_url=cloud_host, # Alternatively, use http://localhost:9099/v1 if you are running Arcade Engine locally
|
|
||||||
)
|
|
||||||
|
|
||||||
chat_result = call_tool_with_openai(openai_client)
|
|
||||||
# If the tool call requires authorization, then wait for the user to authorize and then call the tool again
|
|
||||||
if (
|
|
||||||
chat_result.choices[0].tool_authorizations
|
|
||||||
and chat_result.choices[0].tool_authorizations[0].get("status") == "pending"
|
|
||||||
):
|
|
||||||
print(chat_result.choices[0].message.content)
|
|
||||||
input("After you have authorized, press Enter to continue...")
|
|
||||||
chat_result = call_tool_with_openai(openai_client)
|
|
||||||
|
|
||||||
print(chat_result.choices[0].message.content)
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
"""
|
|
||||||
This example demonstrates how to get an authorization token for a user and then use it to make a request to the Google API on behalf of the user.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from arcadepy import Arcade
|
|
||||||
from google.oauth2.credentials import Credentials # pip install google-auth
|
|
||||||
from googleapiclient.discovery import build # pip install google-api-python-client
|
|
||||||
|
|
||||||
|
|
||||||
def get_auth_token(client: Arcade, user_id: str) -> str:
|
|
||||||
"""Get an authorization token for a user.
|
|
||||||
|
|
||||||
In this example, we are
|
|
||||||
1. Starting the authorization process for the Gmail Readonly scope
|
|
||||||
2. Waiting for the user to authorize the scope
|
|
||||||
3. Getting the authorization token
|
|
||||||
4. Using the authorization token to make a request to the Google API on behalf of the user
|
|
||||||
"""
|
|
||||||
# Start the authorization process
|
|
||||||
auth_response = client.auth.start(
|
|
||||||
user_id, "google", scopes=["https://www.googleapis.com/auth/gmail.readonly"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if auth_response.status != "completed":
|
|
||||||
print(f"Click this link to authorize: {auth_response.url}")
|
|
||||||
auth_response = client.auth.wait_for_completion(auth_response)
|
|
||||||
|
|
||||||
return auth_response.context.token
|
|
||||||
|
|
||||||
|
|
||||||
def use_auth_token(token: str) -> None:
|
|
||||||
"""Use an authorization token to make a request to the Google API on behalf of a user.
|
|
||||||
|
|
||||||
In this example, we are
|
|
||||||
1. Using the authorization token that we got from the authorization process to make a request to the Google API
|
|
||||||
client.auth.wait_for_completion(auth_response)
|
|
||||||
"""
|
|
||||||
# Use the token from the authorization response
|
|
||||||
creds = Credentials(token)
|
|
||||||
service = build("gmail", "v1", credentials=creds)
|
|
||||||
|
|
||||||
# Now you can use the Google API
|
|
||||||
results = service.users().labels().list(userId="me").execute()
|
|
||||||
labels = results.get("labels", [])
|
|
||||||
print("Labels:", labels)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
cloud_host = "https://api.arcade.dev"
|
|
||||||
|
|
||||||
client = Arcade(
|
|
||||||
base_url=cloud_host, # Alternatively, use http://localhost:9099 if you are running Arcade locally, or any base_url if you're hosting elsewhere
|
|
||||||
)
|
|
||||||
|
|
||||||
user_id = "you@example.com"
|
|
||||||
|
|
||||||
token = get_auth_token(client, user_id)
|
|
||||||
use_auth_token(token)
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
ARG VERSION=latest
|
|
||||||
|
|
||||||
# Base worker image
|
|
||||||
FROM ghcr.io/arcadeai/worker-base:${VERSION}
|
|
||||||
|
|
||||||
# Copy requirements and constraints
|
|
||||||
COPY toolkits.txt ./
|
|
||||||
|
|
||||||
# Install toolkits from file
|
|
||||||
RUN pip install -r toolkits.txt
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
## Custom Worker Image
|
|
||||||
|
|
||||||
This example shows how to build a custom worker image with toolkits.
|
|
||||||
|
|
||||||
### Requirements
|
|
||||||
|
|
||||||
- Docker
|
|
||||||
|
|
||||||
### Build
|
|
||||||
|
|
||||||
```
|
|
||||||
docker build -t custom-worker:0.1.0 .
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -p 8002:8002 custom-worker:0.1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
### Change the Toolkits
|
|
||||||
|
|
||||||
To change the toolkits, edit the `toolkits.txt` file.
|
|
||||||
|
|
||||||
```
|
|
||||||
arcade-gmail==0.1.0
|
|
||||||
arcade-firecrawl==0.1.0
|
|
||||||
arcade-zoom==0.1.2
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
arcade-gmail
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
## Deploy a Custom Arcade Worker on Modal
|
|
||||||
|
|
||||||
### Requirements
|
|
||||||
|
|
||||||
- Python 3.10+
|
|
||||||
- Modal CLI
|
|
||||||
|
|
||||||
### Deploy
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd examples/serving-tools
|
|
||||||
modal deploy run-arcade-worker.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Changing the Toolkits
|
|
||||||
|
|
||||||
To change the toolkits, edit the `toolkits` list in the `run-arcade-worker.py` file.
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
from modal import App, Image, asgi_app
|
|
||||||
|
|
||||||
# Define the FastAPI app
|
|
||||||
app = App("arcade-worker")
|
|
||||||
|
|
||||||
toolkits = ["arcade_gmail", "arcade_slack"]
|
|
||||||
|
|
||||||
image = (
|
|
||||||
Image.debian_slim().pip_install("arcade_tdk").pip_install("arcade_serve").pip_install(toolkits)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.function(image=image)
|
|
||||||
@asgi_app()
|
|
||||||
def fastapi_app():
|
|
||||||
from arcade_serve.fastapi.worker import FastAPIWorker
|
|
||||||
from arcade_tdk import Toolkit
|
|
||||||
from fastapi import FastAPI
|
|
||||||
|
|
||||||
web_app = FastAPI()
|
|
||||||
|
|
||||||
# Initialize app and Arcade FastAPIWorker
|
|
||||||
worker_secret = os.environ.get("ARCADE_WORKER_SECRET", "dev")
|
|
||||||
worker = FastAPIWorker(web_app, secret=worker_secret)
|
|
||||||
|
|
||||||
# Register toolkits we've installed
|
|
||||||
installed_toolkits = Toolkit.find_all_arcade_toolkits()
|
|
||||||
for toolkit in installed_toolkits:
|
|
||||||
if toolkit.package_name in toolkits:
|
|
||||||
worker.register_toolkit(toolkit)
|
|
||||||
|
|
||||||
return web_app
|
|
||||||
|
|
@ -14,7 +14,7 @@ Arcade CLI provides a comprehensive command-line interface for the Arcade platfo
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
```bash
|
```bash
|
||||||
pip install arcade-mcp
|
uv tool install arcade-mcp
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
||||||
|
|
@ -531,7 +531,7 @@ def configure(
|
||||||
Examples:
|
Examples:
|
||||||
arcade configure claude
|
arcade configure claude
|
||||||
arcade configure cursor --transport http --port 8080
|
arcade configure cursor --transport http --port 8080
|
||||||
arcade configure vscode --host arcade --entrypoint ../../../mcp/server.py --config .vscode/mcp.json
|
arcade configure vscode --host arcade --entrypoint my_server.py --config .vscode/mcp.json
|
||||||
arcade configure claude --host local --name my_server_name
|
arcade configure claude --host local --name my_server_name
|
||||||
"""
|
"""
|
||||||
from arcade_cli.configure import configure_client
|
from arcade_cli.configure import configure_client
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ def greet(name: Annotated[str, "The name of the person to greet"]) -> str:
|
||||||
return f"Hello, {name}!"
|
return f"Hello, {name}!"
|
||||||
|
|
||||||
|
|
||||||
# To use this tool, you need to either set the secret in the .env file or as an environment variable
|
# To use this tool locally, you need to either set the secret in the .env file or as an environment variable
|
||||||
@app.tool(requires_secrets=["MY_SECRET_KEY"])
|
@app.tool(requires_secrets=["MY_SECRET_KEY"])
|
||||||
def whisper_secret(context: Context) -> Annotated[str, "The last 4 characters of the secret"]:
|
def whisper_secret(context: Context) -> Annotated[str, "The last 4 characters of the secret"]:
|
||||||
"""Reveal the last 4 characters of a secret"""
|
"""Reveal the last 4 characters of a secret"""
|
||||||
|
|
@ -31,8 +31,8 @@ def whisper_secret(context: Context) -> Annotated[str, "The last 4 characters of
|
||||||
|
|
||||||
return "The last 4 characters of the secret are: " + secret[-4:]
|
return "The last 4 characters of the secret are: " + secret[-4:]
|
||||||
|
|
||||||
# To use this tool, you need to either set your ARCADE_API_KEY as an environment variable or
|
# To use this tool locally, you need to install the Arcade CLI (uv tool install arcade-mcp)
|
||||||
# use the Arcade CLI (uv pip install arcade-mcp) and run 'arcade login' to authenticate.
|
# and then run 'arcade login' to authenticate.
|
||||||
@app.tool(requires_auth=Reddit(scopes=["read"]))
|
@app.tool(requires_auth=Reddit(scopes=["read"]))
|
||||||
async def get_posts_in_subreddit(
|
async def get_posts_in_subreddit(
|
||||||
context: Context, subreddit: Annotated[str, "The name of the subreddit"]
|
context: Context, subreddit: Annotated[str, "The name of the subreddit"]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue