## Summary
- Add shared span attributes for tool error diagnostics, including
developer-facing messages when present.
- Wire those attributes through MCP server, worker RunTool, and HTTP
CallTool spans while keeping default MCP response content public-only.
- Cover no-leak response behavior, non-recording spans, outputless
worker responses, and the shared attribute contract.
## Verification
- `uv run ruff format ...`
- `uv run ruff check ...`
- `uv run pytest -W ignore
libs/tests/arcade_mcp_server/test_debug_exposure_integration.py
libs/tests/core/test_log_extras.py
libs/tests/worker/test_worker_base.py`
Made with [Cursor](https://cursor.com)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Adds new telemetry attributes that propagate tool error messages
(including optional developer_message) into active spans across MCP
server and worker execution paths; risk is mainly around potential
leakage of sensitive developer messages into tracing backends and
changes to observability contracts.
>
> **Overview**
> Adds a shared
`arcade_core.log_extras.build_tool_error_span_attributes()` helper and
wires it into tool error paths so the current OpenTelemetry span is
annotated with stable `tool_error_*` attributes (including
`developer_message` when present).
>
> MCP tool calls now record these span attributes on failure while
keeping default MCP response content sanitized, and `arcade-serve`
records the same attributes on both `RunTool` and HTTP `CallTool` spans
(handling `output=None`). Versions and dependency constraints are bumped
to consume the new core helper, with tests added/updated to lock the
span-attribute contract and verify behavior for non-recording spans and
no-leak responses.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
33a53991d72140a662152f508dc53e9b769b9f07. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Resolves
https://linear.app/arcadedev/issue/TOO-788/mypy-failures-are-silently-dropped-during-arcade-mcp-ci
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: primarily CI/Makefile behavior and type-annotation tweaks;
functional logic is unchanged aside from stricter failure propagation in
`make check`.
>
> **Overview**
> **Stops CI from silently ignoring mypy failures.** The `make check`
target now runs `mypy` across `libs/arcade*/` and exits non-zero if any
package fails, reporting the failed libs.
>
> Separately tightens typing to satisfy `mypy` (removing `type: ignore`
on OAuth helpers, adding `cast()`/`Any` annotations for JSON response
shapes and subprocess kwargs, and handling non-`str` `server_address`
hosts), and bumps patch versions for `arcade-mcp` and
`arcade-mcp-server`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e79575b13a2d03adf3548104a0064c643f1e21b1. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Summary
- New arcade connect command that logs in, creates/reuses an Arcade
Cloud gateway, and configures your MCP client in one step
- Supports 5 clients: Claude Desktop, Cursor, VS Code, Windsurf, Amazon
Q
- Selection modes: --toolkit, --tool, --preset, --gateway, --all, or
interactive picker
- Reuses existing gateways when one already covers the requested tools
- Resolves gateway names to slugs (--gateway opencode finds slug
pascal_opencode)
- OAuth auth by default, --api-key fallback with auto-created project
key
- --slug option to set a custom gateway slug on creation
- Tool catalog cached to ~/.arcade/cache/tools.json (5min TTL, scoped to
org/project)
- Fills in the three previously placeholder configure_*_arcade()
functions
```bash
❯ uv run arcade connect cursor --toolkit x
Fetching tool catalog...
Setting up gateway for toolkits: x
Checking existing gateways...
Found existing gateway: quickstart-x (slug:
gw_3CHqdAlQXSSQ28soevSheOJvXzs)
Configuring cursor to connect to gateway: gw_3CHqdAlQXSSQ28soevSheOJvXzs
Configured Cursor with Arcade gateway 'x'
Gateway URL: https://api.arcade.dev/mcp/gw_3CHqdAlQXSSQ28soevSheOJvXzs
Config file: /Users/pascal/.cursor/mcp.json
Restart Cursor for changes to take effect.
Setup complete!
Gateway URL: https://api.arcade.dev/mcp/gw_3CHqdAlQXSSQ28soevSheOJvXzs
Auth: OAuth (handled by your MCP client)
Try asking your AI assistant:
- Post a tweet saying 'Hello from Arcade!'
- Search recent tweets about AI tools
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Adds a new end-to-end flow that performs OAuth login, calls Arcade
Engine/Coordinator APIs (gateway + API key creation), and writes MCP
client config files, so failures could affect remote resource creation
and local client configuration.
>
> **Overview**
> Adds a new `arcade connect` CLI command that logs in (if needed),
fetches/caches the user’s tool catalog, creates or reuses an Arcade
Cloud gateway (optionally with a custom `--slug`), and writes the
appropriate MCP client config to point at the gateway.
>
> Implements real Arcade Cloud gateway configuration for `claude`,
`cursor`, and `vscode` (replacing prior placeholders) and extends
support to **Windsurf** and **Amazon Q**, including optional `--api-key`
mode that auto-creates a project API key and writes it as a `Bearer`
header.
>
> Refocuses `arcade configure` on *local filesystem* servers (and nudges
remote usage to `connect`), adds toolkit config helpers, expands test
coverage for gateway/toolkit configuration and the new connect flow, and
bumps the package version to `1.14.0`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d9357c144a8bddd05dfb39f9f922f577bdbb8bf0. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
templates the changes in https://github.com/ArcadeAI/monorepo/pull/765
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: adds `uv` configuration to generated templates and bumps the
package version, with no runtime logic changes.
>
> **Overview**
> Updates the `arcade new` **full** template `pyproject.toml` to include
a new `[tool.uv]` section that pins resolver behavior via `exclude-newer
= "1 week"` while exempting key `arcade-*` packages.
>
> Bumps the root project version from `1.12.2` to `1.12.3`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fd47343d52ee51700affad5c3f1701b3e143002f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
We should be checking if the entrypoint file is in the current directory
before we validate that it's a valid python file. Otherwise, the error
message will be "invalid name for python file" when someone provides a
path to a valid python file.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: only adjusts input validation/error messaging for `arcade
configure` stdio entrypoints and bumps the package patch version.
>
> **Overview**
> Improves `arcade configure` stdio entrypoint validation by **rejecting
path-like values** (e.g., containing `/` or `\\`) before checking
filename format, producing a clearer error when users pass a path
instead of a file in the current directory.
>
> Bumps the project version from `1.13.0` to `1.13.1`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4d02ee947740f839fd46d9faf62cfa766d5dae47. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- On every CLI command invocation (except `update`/`upgrade`/`mcp`), a
detached subprocess checks PyPI for newer versions (throttled to once
per 4 hours) and caches the result at `~/.arcade/update_cache.json`
- On the next invocation, if a newer version is known, a yellow
one-liner notification is printed suggesting `arcade update`
- Respects `ARCADE_DISABLE_AUTOUPDATE=1` environment variable to opt out
entirely
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Adds a background PyPI version check that spawns detached subprocesses
and may print update notifications on most CLI invocations; mistakes
could impact CLI reliability or corrupt MCP stdio output (mitigated by
explicit command exclusions).
>
> **Overview**
> Adds `arcade update` (and hidden `arcade upgrade` alias) to
self-upgrade the `arcade-mcp` CLI by detecting the original install
method (`uv tool`, `pipx`, `uv pip`, or `pip`) and running the
appropriate upgrade command.
>
> Introduces a **throttled background update check** on most CLI
invocations: a detached subprocess queries PyPI, writes
`~/.arcade/update_cache.json`, and on subsequent runs prints a one-line
notification when a newer version is cached; this is disabled via
`ARCADE_DISABLE_AUTOUPDATE=1` and explicitly skipped for
`update`/`upgrade`/`mcp` to avoid MCP stdio output corruption.
>
> Bumps the package version to `1.13.0`, adds a `packaging` dependency,
and includes comprehensive tests covering PyPI/yanked/prerelease
handling, install-method detection, caching, and callback integration.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2d9646ecc2211e8cfecd6e4901d14b1f5b7bb306. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Monorepo has new linting and formatting preferences. Updated the
`--full` to reflect that.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk: changes only affect the generated `--full` project template
and CLI help surface (flag is now hidden), plus a patch version bump.
>
> **Overview**
> Updates `arcade new --full` to be *internal-only* by hiding the flag
and revises the full template to match monorepo conventions
(Ruff/pre-commit versions and hook IDs, `.ruff.toml` now extends the
repo config, `pyproject.toml` formatting/booleans, adds `pytest`
`asyncio_mode`, and removes `pre-commit install` from the template
`Makefile`).
>
> Adds a regression test ensuring generated full-template files match
these conventions, and bumps the root package version to `1.12.2`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2c1a285752d67dc4dd1aa8e0b6f25ca2f0a33fa2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Updated authlib==1.6.6 to authlib==1.6.9 in the CLI's pyproject.toml.
The breaking changes in 1.6.7–1.6.9 are all in the JWT/JOSE/OIDC
modules, which the CLI doesn't use. The only authlib import is
OAuth2Client from authlib.integrations.httpx_client (in
libs/arcade-cli/arcade_cli/authn.py), used for OAuth 2.0 + PKCE. That
module is unaffected.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk dependency/version bump; only affects the CLI’s OAuth2
`OAuth2Client` usage and does not change runtime code paths beyond
pulling in the newer library.
>
> **Overview**
> Bumps the package version from `1.12.0` to `1.12.1` and upgrades the
pinned `authlib` dependency from `1.6.6` to `1.6.9` in `pyproject.toml`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f55973deb75f6388b286eca0ca7c16948518e64f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Medium Risk**
> Moderate risk because it changes the default `arcade new --full`
scaffolding (dependencies, entry points, Makefile workflow, licensing)
and removes interactive prompts, which could break existing expectations
for generated projects.
>
> **Overview**
> `arcade new --full` scaffolding is simplified to be non-interactive
and always generate an `arcade_<name>` package, with derived name
variants (title/hyphenated) and updated next-step instructions (`make
install/dev/test/lint`).
>
> The full template is updated to produce a runnable `arcade-mcp-server`
`MCPApp` (`__main__.py` + `project.scripts`), switch sample
code/tests/evals to a new async Reddit example tool (auth + metadata)
using `httpx`, and refresh dev tooling (new `Makefile`, ruff config
tweaks, added pytest `conftest.py`).
>
> Template licensing/metadata is standardized to Arcade proprietary
(removes community/official conditionals and the templated README), and
the repo version is bumped to `1.12.0`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fd39c9ed9beba068fe85cf96979f04a31a40daa4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Low Risk**
> Mostly CI/test and CLI output tweaks, plus a small refactor to reuse
existing subprocess termination logic; low risk with minor potential for
CI environment/version compatibility issues.
>
> **Overview**
> Expands CI coverage by adding Python `3.13` and `3.14` to the GitHub
Actions matrices (main tests, install test, and no-auth CLI
integration), and removes a redundant editable install step in the
no-auth workflow.
>
> Cleans up Windows subprocess handling by dropping
`arcade_cli.deploy._graceful_terminate` and calling the shared
`arcade_core.subprocess_utils.graceful_terminate_process` directly, with
corresponding test updates.
>
> Improves `arcade new` scaffolding guidance by printing numbered “Next
steps” with explicit stdio/HTTP run options, and adds/updates CLI tests
to assert this output. Also bumps package version to `1.11.2` and
tightens pre-commit `ruff` excludes (no longer excluding `_scratch`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
55c2ae106f13e5657acdbebf63e00d74c171181f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Resolves TOO-201
Documentation PR for this is here:
https://github.com/ArcadeAI/docs/pull/626
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes how environment variables/secrets are discovered and loaded,
which can subtly alter runtime behavior depending on directory structure
and existing env vars; bounded traversal and added tests reduce but
don’t eliminate this risk.
>
> **Overview**
> **Improves `.env` discovery across the MCP server and CLI.** Adds
`find_env_file()` (bounded by the nearest `pyproject.toml` by default)
and switches settings loading, `arcade deploy`, `arcade configure` stdio
env injection, and provider API-key resolution to use it.
>
> Updates dev reload to also watch the discovered `.env` even when it
lives outside the current working directory, adjusts `deploy --secrets
all` to only run when a `.env` was found, and moves the minimal
scaffold’s `.env.example` to the project root with updated
tests/integration checks. Version bumps align examples and top-level
deps with `arcade-mcp-server` `1.17.4` and `arcade-mcp` `1.11.2`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
40cff1738c14674ce01f09fd325ece9c874cd072. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **Medium Risk**
> Touches authentication/login flow, credentials-file permissions, and
subprocess lifecycle behavior across platforms; while mostly defensive,
regressions could impact login or process management on Windows/macOS
runners.
>
> **Overview**
> Improves Windows/cross-platform reliability across the CLI and MCP
server: OAuth login now binds the callback server to `127.0.0.1`, avoids
slow loopback reverse-DNS, adds a configurable callback timeout
(`--timeout` + env default), and opens URLs via a Windows-friendly
`_open_browser` to avoid flashing console windows.
>
> Centralizes CLI output via a shared `console` that forces UTF-8 on
Windows, standardizes UTF-8 file reads/writes throughout, tightens
credentials-file permissions on Windows using `icacls`, and adds shared
Windows subprocess helpers for **no-window** process creation and
graceful termination (used by `deploy`, MCP reload, and usage-tracking
worker).
>
> Updates client configuration UX/robustness (Windows AppData resolution
via `platformdirs`, Cursor config path fallbacks + compatibility writes,
overwrite warnings, absolute `uv` path for GUI clients, safer path
display) and improves `deploy` child-process handling to avoid
pipe-buffer deadlocks while giving better debug-aware error messages.
>
> Expands CI to run tests on Linux/Windows/macOS, adds a no-auth CLI
integration workflow, disables usage tracking in toolkits CI, and adds
extensive regression tests for Windows signals, subprocess cleanup,
UTF-8, and config-path edge cases; bumps `arcade-core` to `4.4.2` and
`arcade-mcp-server` to `1.17.2` (with updated dependency pin).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0fabd8ca1cd647039ba6ddbdf3f7809c330bab9e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Summary
- Removes the `Hint` column from `arcade secret list` table output —
secret hints were removed from the API in
[monorepo#322](https://github.com/ArcadeAI/monorepo/pull/322), causing a
`KeyError: 'hint'` crash
- Adds a test for `print_secret_table` with populated secrets (verifying
no hint column)
- Bumps version from 1.10.0 → 1.11.0
Closes TOO-444
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@EricGustin you can use this cli command:
```
uv run arcade evals mcp_building_evals_results/eval_toolkit_iteration_dict.py \
-p openai:gpt-4o,gpt-4o-mini \
-p anthropic:claude-sonnet-4-20250514 \
-k openai:$OPENAI_API_KEY \
-k anthropic:$ANTHROPIC_API_KEY \
-d \
--num-runs 3 \
--seed random \
--multi-run-pass-rule majority \
--max-concurrent 6 \
-o mcp_building_evals_results/results
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches core eval execution and all result formatters while adding new
CLI inputs and output schema (`run_stats`/`critic_stats` and capture
`runs`), so regressions could affect evaluation results and report
compatibility despite being additive and validated.
>
> **Overview**
> Adds **multi-run evaluation support** to `arcade evals` via new flags
`--num-runs`, `--seed`, and `--multi-run-pass-rule`, with upfront
validation and plumbing through the CLI runner into eval/capture suite
execution.
>
> Fixes provider selection UX/bug by making `--use-provider/-p`
**repeatable** (instead of a space-delimited string), updates
docs/examples accordingly, and extends capture mode to optionally record
**per-run tool calls** (`CapturedRun`) when `num_runs > 1`.
>
> Enhances all output formatters (HTML/Markdown/Text/JSON) to
**propagate and display** per-case `run_stats` and `critic_stats`,
including new HTML UI for run tabs/cards and comparative tables showing
mean ± stddev when multi-run data is present.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2ee1654b7d1fbb9538373507355636164b16a066. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
`[tool.uv]`'s `dev-dependencies` is deprecated. I got tired of seeing
the warning.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk build/CI tooling change, but it may affect environment setup
if `uv sync` extra resolution differs from the old `--dev` behavior.
>
> **Overview**
> Removes the deprecated `dev-dependencies` config and instead defines
development requirements as a `dev` optional-dependency extra in
`pyproject.toml`.
>
> Updates local/CI install paths (Makefile, composite action, and
install-test workflow) to install dev requirements via `uv sync --extra
all --extra dev` rather than `uv sync --dev`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
472ab6e5e498b69d88ac8f08ba8414e901272f26. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- BUGBOT_STATUS --><sup><a
href="https://cursor.com/dashboard?tab=bugbot">Cursor Bugbot</a> found 1
potential issue for commit <u>472ab6e</u></sup><!-- /BUGBOT_STATUS -->
1. Resolves
[TOO-363](https://linear.app/arcadedev/issue/TOO-363/arcade-deploy-fails-when-additional-deps-are-added-to-the-server).
2. Resolves
[TOO-364](https://linear.app/arcadedev/issue/TOO-364/arcade-cores-tool-skip-logic-is-missing-case-for-direct-execution).
3. Resolves
[TOO-358](https://linear.app/arcadedev/issue/TOO-358/missing-evals-error-message-shows-wrong-command).
4. Resolves
[TOO-365](https://linear.app/arcadedev/issue/TOO-365/arcade-evals-unit-tests-are-hanging).
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Medium risk because it changes how `arcade deploy` spawns the server
process and adjusts toolkit discovery skip logic, which can affect
deployments and tool discovery; however, the changes are small and
covered by new unit/integration tests.
>
> **Overview**
> `arcade deploy` now starts the validation server using the project’s
`.venv` interpreter (via `find_python_interpreter`) instead of the CLI’s
own `sys.executable`, preventing missing dependency failures when the
CLI is installed in an isolated env.
>
> `arcade-core`’s `Toolkit.tools_from_directory` skip logic is hardened
to also skip the currently executing entrypoint by module name
(`__main__.__spec__.name`) when file paths don’t match (e.g., bundled
execution). CLI error printing now escapes plain messages to avoid rich
markup issues, and `arcade-evals` lock acquisition accepts an optional
timeout default.
>
> Adds unit tests for the new toolkit skip behavior and an integration
test that boots the MCP server via direct Python invocation to mirror
deployment behavior, and bumps `arcade-core`, `arcade-mcp-server`, and
root dependency versions accordingly.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e7785634c231c059f2e0bd1bc73a56bd7470a494. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Bumps [authlib](https://github.com/authlib/authlib) from 1.6.5 to 1.6.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/authlib/authlib/releases">authlib's
releases</a>.</em></p>
<blockquote>
<h2>v1.6.6</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(ClientAuth): fix incorrect signature when Content-Type is
x-www-form-urlencoded by <a
href="https://github.com/shc261392"><code>@shc261392</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/778">authlib/authlib#778</a></li>
<li>Fix: Use <code>expires_in</code> when <code>expires_at</code> is
unparsable by <a
href="https://github.com/bendavis78"><code>@bendavis78</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/842">authlib/authlib#842</a></li>
<li><code>get_jwt_config</code> takes a <code>client</code> parameter.
by <a href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/844">authlib/authlib#844</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/shc261392"><code>@shc261392</code></a>
made their first contribution in <a
href="https://redirect.github.com/authlib/authlib/pull/778">authlib/authlib#778</a></li>
<li><a
href="https://github.com/bendavis78"><code>@bendavis78</code></a> made
their first contribution in <a
href="https://redirect.github.com/authlib/authlib/pull/842">authlib/authlib#842</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/authlib/authlib/compare/v1.6.5...v1.6.6">https://github.com/authlib/authlib/compare/v1.6.5...v1.6.6</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/authlib/authlib/blob/main/docs/changelog.rst">authlib's
changelog</a>.</em></p>
<blockquote>
<h2>Version 1.6.6</h2>
<p><strong>Released on Dec 12, 2025</strong></p>
<ul>
<li><code>get_jwt_config</code> takes a <code>client</code> parameter,
:pr:<code>844</code>.</li>
<li>Fix incorrect signature when <code>Content-Type</code> is
x-www-form-urlencoded for OAuth 1.0 Client, :pr:<code>778</code>.</li>
<li>Use <code>expires_in</code> in <code>OAuth2Token</code> when
<code>expires_at</code> is unparsable, :pr:<code>842</code>.</li>
<li>Always track <code>state</code> in session for OAuth client
integrations.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bb7a315bef"><code>bb7a315</code></a>
chore: release 1.6.6</li>
<li><a
href="0a423d4638"><code>0a423d4</code></a>
Merge pull request <a
href="https://redirect.github.com/authlib/authlib/issues/844">#844</a>
from azmeuk/806-get-jwt-config-client</li>
<li><a
href="2808378611"><code>2808378</code></a>
Merge commit from fork</li>
<li><a
href="714502a473"><code>714502a</code></a>
feat: get_jwt_config takes a client parameter</li>
<li><a
href="260d04edee"><code>260d04e</code></a>
Fix: Use <code>expires_in</code> when <code>expires_at</code> is
unparsable</li>
<li><a
href="eb37124bbb"><code>eb37124</code></a>
Merge pull request <a
href="https://redirect.github.com/authlib/authlib/issues/778">#778</a>
from shc261392/fix-httpx-oauth1-form-data-incorrect-s...</li>
<li><a
href="0ba9ec4fee"><code>0ba9ec4</code></a>
docs: fix guide on requests self signed certificate</li>
<li><a
href="a2e9943815"><code>a2e9943</code></a>
docs: indicate that <a
href="https://redirect.github.com/authlib/authlib/issues/743">#743</a>
needs a migration</li>
<li><a
href="06015d2065"><code>06015d2</code></a>
test: factorize the token fixture</li>
<li>See full diff in <a
href="https://github.com/authlib/authlib/compare/v1.6.5...v1.6.6">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/ArcadeAI/arcade-mcp/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This is the quick fix for placing the dateutil as a required dep instead
of as an 'extra' dep.
This is the second time in one week that a missing dependency has bitten
us. I've created a ticket (TOO-317) to catch this class of bugs in our
CI pipeline.
The 'MCP server started' events would fail to send to posthog if the CLI
was not installed. This PR fixes this by moving PostHog from being a
dependency of the CLI to a dependency of arcade-core.
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Aligns versions and dependency ranges across the CLI and server
packages; removes an unnecessary dependency.
>
> - Bump `arcade-mcp-server` to `1.14.2` and `arcade-mcp` to `1.8.1`
> - Update `arcade-core` constraint to `>=4.2.1,<5.0.0`; CLI now
requires `arcade-mcp-server>=1.14.2`
> - Remove `posthog` from CLI dependencies
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
69f8bb397737d4c01f57630863762109819dbc4f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
https://github.com/ArcadeAI/docs/pull/622 moved a lot of files to new
URLs
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Updates references to Arcade docs after site restructure and bumps
package versions.
>
> - Update docs URLs in `README.md`, `SECURITY.md`, contrib READMEs
(CrewAI, LangChain), and CLI template README to new `/en/...` paths
> - Update `documentation_url` in `arcade_mcp_server/server.py` error
message to the new "compare server types" doc
> - Bump versions: `arcade-mcp-server` to `1.14.1` and root `arcade-mcp`
to `1.7.2`
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
673b1ee7c2e5be6885ffd64914e7600b4685aaac. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Bumps [authlib](https://github.com/authlib/authlib) from 1.3.0 to 1.6.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/authlib/authlib/releases">authlib's
releases</a>.</em></p>
<blockquote>
<h2>v1.6.5</h2>
<h2>What's Changed</h2>
<ul>
<li>Add a <code>request</code> param to RFC7591
<code>generate_client_info</code> and
<code>generate_client_secret</code> methods by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/825">authlib/authlib#825</a></li>
<li>feat: support list params in prepare_grant_uri by <a
href="https://github.com/lisongmin"><code>@lisongmin</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/827">authlib/authlib#827</a></li>
<li>chore(deps): bump SonarSource/sonarqube-scan-action from 5 to 6 in
/.github/workflows by <a
href="https://github.com/dependabot"><code>@dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/authlib/authlib/pull/828">authlib/authlib#828</a></li>
<li>fix(jose): add max size for JWE zip=DEF decompression by <a
href="https://github.com/lepture"><code>@lepture</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/830">authlib/authlib#830</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/lisongmin"><code>@lisongmin</code></a>
made their first contribution in <a
href="https://redirect.github.com/authlib/authlib/pull/827">authlib/authlib#827</a></li>
<li><a
href="https://github.com/dependabot"><code>@dependabot</code></a>[bot]
made their first contribution in <a
href="https://redirect.github.com/authlib/authlib/pull/828">authlib/authlib#828</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/authlib/authlib/compare/v1.6.4...v1.6.5">https://github.com/authlib/authlib/compare/v1.6.4...v1.6.5</a></p>
<h2>v1.6.4</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(jose): prevent public/unprotected header overwriting protected
header by <a
href="https://github.com/lepture"><code>@lepture</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/809">authlib/authlib#809</a></li>
<li>Fix <code>InsecureTransportError</code> raising by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/810">authlib/authlib#810</a></li>
<li>Add conventional-commits pre-commit hook by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/811">authlib/authlib#811</a></li>
<li>Fix response_mode=form_post with Starlette client by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/812">authlib/authlib#812</a></li>
<li>Specify README.md as project long description by <a
href="https://github.com/EpicWink"><code>@EpicWink</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/817">authlib/authlib#817</a></li>
<li>Migrate tests to pytest paradigm by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/813">authlib/authlib#813</a></li>
<li>jose/jws: Reject unprotected ‘crit’ and enforce type; add tests by
<a href="https://github.com/AL-Cybision"><code>@AL-Cybision</code></a>
in <a
href="https://redirect.github.com/authlib/authlib/pull/823">authlib/authlib#823</a></li>
<li>Use explicit *.test urls in unit tests by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/824">authlib/authlib#824</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/EpicWink"><code>@EpicWink</code></a>
made their first contribution in <a
href="https://redirect.github.com/authlib/authlib/pull/817">authlib/authlib#817</a></li>
<li><a
href="https://github.com/AL-Cybision"><code>@AL-Cybision</code></a>
made their first contribution in <a
href="https://redirect.github.com/authlib/authlib/pull/823">authlib/authlib#823</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/authlib/authlib/compare/v1.6.3...v1.6.4">https://github.com/authlib/authlib/compare/v1.6.3...v1.6.4</a></p>
<h2>Version 1.6.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Add diff-cover check in GHA by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/803">authlib/authlib#803</a></li>
<li>Run GHA unit tests with uv by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/805">authlib/authlib#805</a></li>
<li>Move from pre-commit to prek by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/804">authlib/authlib#804</a></li>
<li>Sign OIDC id_token according to
<code>id_token_signed_response_alg</code> client metadata by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/802">authlib/authlib#802</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/authlib/authlib/compare/v1.6.2...v1.6.3">https://github.com/authlib/authlib/compare/v1.6.2...v1.6.3</a></p>
<h2>Version 1.6.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Allow insecure transport for 127.0.0.1 for debugging by <a
href="https://github.com/geigerzaehler"><code>@geigerzaehler</code></a>
in <a
href="https://redirect.github.com/authlib/authlib/pull/788">authlib/authlib#788</a></li>
<li>Raise a MissingCodeError when code parameter is missing by <a
href="https://github.com/lepture"><code>@lepture</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/786">authlib/authlib#786</a></li>
<li>Temporarily restore OAuth2Request body parameter by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/791">authlib/authlib#791</a></li>
<li>Raise MissingCodeException when code parameter is missing by <a
href="https://github.com/lepture"><code>@lepture</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/794">authlib/authlib#794</a></li>
<li>Fix id_token generation with EdDSA alg by <a
href="https://github.com/azmeuk"><code>@azmeuk</code></a> in <a
href="https://redirect.github.com/authlib/authlib/pull/800">authlib/authlib#800</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/authlib/authlib/compare/v1.6.1...v1.6.2">https://github.com/authlib/authlib/compare/v1.6.1...v1.6.2</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/authlib/authlib/blob/main/docs/changelog.rst">authlib's
changelog</a>.</em></p>
<blockquote>
<h2>Version 1.6.5</h2>
<p><strong>Released on Oct 2, 2025</strong></p>
<ul>
<li>RFC7591 <code>generate_client_info</code> and
<code>generate_client_secret</code> take a <code>request</code>
parameter.</li>
<li>Add size limitation when decode JWS/JWE to prevent DoS.</li>
<li>Add size limitation for <code>DEF</code> JWE zip algorithm.</li>
</ul>
<h2>Version 1.6.4</h2>
<p><strong>Released on Sep 17, 2025</strong></p>
<ul>
<li>Fix <code>InsecureTransportError</code> error raising.
:issue:<code>795</code></li>
<li>Fix <code>response_mode=form_post</code> with Starlette client.
:issue:<code>793</code></li>
<li>Validate <code>crit</code> header value, reject unprotected header
in <code>crit</code> header.</li>
</ul>
<h2>Version 1.6.3</h2>
<p><strong>Released on Aug 26, 2025</strong></p>
<ul>
<li>OIDC <code>id_token</code> are signed according to
<code>id_token_signed_response_alg</code>
client metadata. :issue:<code>755</code></li>
</ul>
<h2>Version 1.6.2</h2>
<p><strong>Released on Aug 23, 2025</strong></p>
<ul>
<li>Temporarily restore <code>OAuth2Request</code> <code>body</code>
parameter. :issue:<code>781</code> :pr:<code>791</code></li>
<li>Allow <code>127.0.0.1</code> in insecure transport mode.
:pr:<code>788</code></li>
<li>Raise <code>MissingCodeException</code> when the <code>code</code>
parameter is missing. :issue:<code>793</code> :pr:<code>794</code></li>
<li>Fix <code>id_token</code> generation with <code>EdDSA</code> algs.
:issue:<code>799</code> :pr:<code>800</code></li>
</ul>
<h2>Version 1.6.1</h2>
<p><strong>Released on Jul 20, 2025</strong></p>
<ul>
<li>Filter key set with additional "alg" and "use"
parameters.</li>
<li>Restore and deprecate <code>OAuth2Request</code> <code>body</code>
parameter. :issue:<code>781</code></li>
</ul>
<h2>Version 1.6.0</h2>
<p><strong>Released on May 22, 2025</strong></p>
<ul>
<li>Fix issue when :rfc:<code>RFC9207 <9207></code> is enabled and
the authorization endpoint response is not a redirection.
:pr:<code>733</code></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9ec42561cd"><code>9ec4256</code></a>
chore: release 1.6.5</li>
<li><a
href="b62b5b2757"><code>b62b5b2</code></a>
Merge branch 'fix-GHSA-pq5p-34cr-23v9'</li>
<li><a
href="e0863d5129"><code>e0863d5</code></a>
Merge pull request <a
href="https://redirect.github.com/authlib/authlib/issues/830">#830</a>
from authlib/fix-GHSA-g7f3-828f-7h7m</li>
<li><a
href="867e3f87b0"><code>867e3f8</code></a>
fix(jose): add size limitation to prevent DoS</li>
<li><a
href="75ad6d4d62"><code>75ad6d4</code></a>
Merge pull request <a
href="https://redirect.github.com/authlib/authlib/issues/828">#828</a>
from authlib/dependabot/github_actions/dot-github/wor...</li>
<li><a
href="68b982352d"><code>68b9823</code></a>
chore(deps): bump SonarSource/sonarqube-scan-action</li>
<li><a
href="5bdfc4bfff"><code>5bdfc4b</code></a>
Merge pull request <a
href="https://redirect.github.com/authlib/authlib/issues/827">#827</a>
from lisongmin/support-list-params-in-prepare-grant-uri</li>
<li><a
href="30ea3c5f85"><code>30ea3c5</code></a>
feat: support list params in prepare_grant_uri</li>
<li><a
href="4b5b570339"><code>4b5b570</code></a>
fix(jose): add max size for JWE zip=DEF decompression</li>
<li><a
href="6e35a02ecf"><code>6e35a02</code></a>
Merge pull request <a
href="https://redirect.github.com/authlib/authlib/issues/825">#825</a>
from azmeuk/request-params</li>
<li>Additional commits viewable in <a
href="https://github.com/authlib/authlib/compare/v1.3.0...v1.6.5">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/ArcadeAI/arcade-mcp/network/alerts).
</details>
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Skip GHA secret-backed toolkit tests for dependabot, add Dockerized
Postgres test setup and default to postgres user, and bump authlib to
1.6.5.
>
> - **CI**:
> - Update `Test stand-alone toolkits (with secrets)` condition to also
exclude `github.actor == 'dependabot[bot]'`.
> - Execute optional `tests/test_setup.sh` before pytest when present.
> - **Postgres toolkit tests**:
> - Default `POSTGRES_DATABASE_CONNECTION_STRING` user changed to
`postgres` in `toolkits/postgres/tests/test_postgres.py`.
> - Add `toolkits/postgres/tests/test_setup.sh` to spin up a Docker
`postgres` and wait until ready.
> - **Dependencies**:
> - Upgrade `authlib` to `1.6.5` in `pyproject.toml`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f3600e7536a409ecd8e645f473d747b9ba363765. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: evan <evan@arcade.dev>
`arcade-mcp-server` version was not bumped in
https://github.com/ArcadeAI/arcade-mcp/pull/717, so this PR bumps
`arcade-mcp-server`, and then update's `arcade-mcp`'s dependency on
`arcade-mcp-server` by increasing the minimum version
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Bumps arcade-mcp-server to 1.13.0, updates arcade-mcp to 1.6.2, and
raises related dependency minimums (including example auth server).
>
> - **Versions**:
> - Bump `libs/arcade-mcp-server` project version from `1.12.0` to
`1.13.0`.
> - Bump `arcade-mcp` package version from `1.6.1` to `1.6.2`.
> - **Dependencies**:
> - Raise `arcade-mcp` dependency on `arcade-mcp-server` to `>=1.13.0`
in `pyproject.toml` (including `all` extra).
> - Increase example server
`examples/mcp_servers/authorization/pyproject.toml` minimum
`arcade-mcp-server` to `>=1.12.0`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8a4f606bd8d0b48dd50e3e8e836d31bb679c6eba. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Fixes broken publishing action:
https://github.com/ArcadeAI/arcade-mcp/actions/runs/20147239181
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Removes template force-include to avoid duplicate files and adds CI
wheel-duplicate validation; bumps version to 1.6.1.
>
> - **Packaging**:
> - Bump `arcade-mcp` version from `1.6.0` to `1.6.1` in
`pyproject.toml`.
> - Remove `[tool.hatch.build.targets.wheel.force-include]` for
`arcade_cli/templates` to prevent double-including template files.
> - **CI/CD**:
> - In `.github/workflows/release-on-version-change.yml`, add a
post-build Python step to validate built wheels for duplicate filenames
before publishing.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3a15e08772b2b4851b185b04c763f3f5898bdbd5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Fixes [PLT-720: Refactor CLI to support multiple orgs +
projects](https://linear.app/arcadedev/issue/PLT-720/refactor-cli-to-support-multiple-orgs-projects)
This PR removes the legacy login flow (login to get an API key) from
Arcade CLI. Believe it or not, this flow predates the ability to get an
API key from the Dashboard, or even the Dashboard itself!
Notable changes:
**Legacy handling** - When a user with an existing `credentials.yaml`
updates the CLI, they will get instructions on fixing their old
credentials:
<img width="978" height="146" alt="Screenshot 2025-12-08 at 10 10 37"
src="https://github.com/user-attachments/assets/5aeaef2c-bef7-4642-a2f7-f917b257c94b"
/>
Any commands that require login (non-public commands) will be blocked
with the above message until `arcade logout / arcade login` is performed
again.
**New login flow**
```sh
arcade login
Opening a browser to log you in...
✅ Logged in as nate@arcade.dev.
Active project: Nate Barbettini's organization / Default project
Run 'arcade org list' or 'arcade project list' to see available options.
```
**List and set the active organization**
```sh
arcade org list
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┓
┃ Name ┃ ID ┃ Default ┃ Active ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━┩
│ Nate Barbettini's organization │ 1c64968e-fdc5-4c55-8612-2ce46cd7881b │ ✓ │ ✓ │
│ Sergio 743 │ 1f1f6184-58dc-4bac-bdde-b9184e43fdf3 │ │ │
└────────────────────────────────┴──────────────────────────────────────┴─────────┴────────┘
Use 'arcade org set <org_id>' to switch organizations.
```
```sh
arcade org set 1c64968e-fdc5-4c55-8612-2ce46cd7881b
✓ Switched to organization: Nate Barbettini's organization
Active project: Default project
```
**List and set the active project**
```sh
arcade project list
Active organization: Nate Barbettini's organization
Use 'arcade org list' and 'arcade org set <org_id>' to switch organizations.
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┓
┃ Name ┃ ID ┃ Default ┃ Active ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━┩
│ Default project │ 35166bf3-6e68-481e-bf16-f747fadc6c22 │ ✓ │ ✓ │
│ Second project │ 62963205-31ea-4fda-9fc4-af10db89c06f │ │ │
└─────────────────┴──────────────────────────────────────┴─────────┴────────┘
Use 'arcade project set <project_id>' to switch projects.
```
```sh
arcade project set 35166bf3-6e68-481e-bf16-f747fadc6c22
✓ Switched to project: Default project
```
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Migrates CLI to OAuth2 (PKCE) with saved org/project context, adds
org/project commands, rewrites Engine calls to org-scoped endpoints, and
bumps core packages.
>
> - **Auth & Config**
> - Implement OAuth2 Authorization Code + PKCE (`arcade_cli/authn.py`)
with local callback server and Jinja templates.
> - Persist tokens and active `context` (org/project) in
`credentials.yaml` via updated config models
(`arcade_core/config_model.py`).
> - Add token refresh and CLI config fetch utilities
(`arcade_core/auth_tokens.py`).
> - Detect legacy API-key credentials and block protected commands until
re-login; add `whoami` command.
> - **Org/Project Management**
> - New subcommands: `arcade org list|set`, `arcade project list|set`
(fetch via Coordinator).
> - **Engine API usage (org-scoped)**
> - Introduce org/project URL rewriting transports
(`arcade_core/network/org_transport.py`) and helpers
(`get_org_scoped_url`, `get_arcade_client`, `get_auth_headers`).
> - Update `deploy`, `server`, and `secret` commands to use Bearer
tokens and org-scoped paths; adjust log streaming/status, secrets CRUD,
and deployment workflows.
> - **CLI UX**
> - Replace legacy login URLs/constants; add success/failure HTML
templates for browser callback.
> - Tweak `dashboard` to health-check without credentials.
> - Usage tracking now includes `org_id`/`project_id` properties.
> - **Tests**
> - Update tests for dashboard, secrets, utils, and usage identity
(OAuth `/whoami`).
> - **Dependencies & Versions**
> - Bump packages: `arcade-core@4.0.0`, `arcade-mcp-server@1.12.0`,
`arcade-serve@3.2.0`, `arcade-tdk@3.3.0`; add `authlib`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
49702c2f74b9db15bb286d3ec71179b4e74a9134. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
New and improved error message
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Enhances dependency checks to display uv/pip install commands and
updates evals command accordingly; bumps package version to 1.5.9.
>
> - **CLI utils**:
> - Update `require_dependency` to accept `uv_install_command` and
`pip_install_command` and format error message with both install
options.
> - **Evals command (`arcade_cli/main.py`)**:
> - Update `require_dependency` calls for `arcade_evals` and
`arcade_tdk` to provide uv/pip install commands.
> - **Version**:
> - Bump `project.version` in `pyproject.toml` from `1.5.8` to `1.5.9`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
217a6a87686e27747ef59d66bc0db05a270b294a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Update `arcade-core` and `arcade-tdk` dependency versions to resolve
`ImportError` caused by incompatible `Figma` auth provider imports.
The `Figma` OAuth2 provider was introduced in `arcade-core` 3.3.5.
`arcade-tdk` 3.2.0 and `arcade-mcp-server` 1.10.2 started importing
`Figma`, but their `pyproject.toml` dependency constraints were not
updated to require `arcade-core>=3.3.5`. This led to `ImportError` when
`arcade-tdk` or `arcade-mcp-server` were installed with an older
`arcade-core` version. This PR updates the minimum required versions in
`pyproject.toml` files across `arcade-tdk`, `arcade-mcp-server`, and the
root project to ensure compatibility.
---
Linear Issue:
[TOO-231](https://linear.app/arcadedev/issue/TOO-231/worker-fails-to-start-due-to-arcade-core-auth-import)
<a
href="https://cursor.com/background-agent?bcId=bc-4383bd24-eb8c-4d2e-bafe-c116a9d83e8b"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/open-in-cursor-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/open-in-cursor-light.svg"><img alt="Open in
Cursor"
src="https://cursor.com/open-in-cursor.svg"></picture></a> <a
href="https://cursor.com/agents?id=bc-4383bd24-eb8c-4d2e-bafe-c116a9d83e8b"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/open-in-web-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/open-in-web-light.svg"><img alt="Open in Web"
src="https://cursor.com/open-in-web.svg"></picture></a>
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Align dependency minimums to `arcade-core>=3.3.5` and
`arcade-tdk>=3.2.0` and bump package versions across projects.
>
> - **Dependencies**:
> - Raise `arcade-core` minimum to `>=3.3.5,<4.0.0` in
`libs/arcade-mcp-server/pyproject.toml`,
`libs/arcade-tdk/pyproject.toml`, and root `pyproject.toml`.
> - Raise `arcade-tdk` minimum to `>=3.2.0,<4.0.0` in
`libs/arcade-mcp-server/pyproject.toml` and root `pyproject.toml`.
> - **Version bumps**:
> - `libs/arcade-mcp-server` version `1.10.2` → `1.10.3`.
> - `libs/arcade-tdk` version `3.2.0` → `3.2.1`.
> - Root package `arcade-mcp` version `1.5.6` → `1.5.7`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
abec5dff0d18c9e9c1c5a0ceafa73c67b6af661a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This PR does three things:
1. Executes synchronous tool calls in thread pool allowing for up to 4 +
# of CPUs executions in parallel.
2. Makes force quitting via double SIGINT/SIGTERM possible and via
single SIGINT/SIGTERM + graceful shutdown timeout expiry possible, even
if there are active connections.
3. Sets `timeout_graceful_shutdown` to
`ARCADE_UVICORN_TIMEOUT_GRACEFUL_SHUTDOWN` env var if set, else defaults
to 15.
4. Disable the worker health check span to reduce noise
Tradeoffs:
Since this PR introduces executing synchronous tools via `await
asyncio.to_thread(func, **func_args)`, this means that there is no way
for the thread to be killed until it finishes. The ramifications of this
is that the force quitting logic that is also implemented in this PR has
to be very harsh `os._exit(1)` just in case there is a sync tool
actively executing. This means that `MCPApp` teardown logic will not
execute when force quitting is required. Although this was already the
case because we weren't previously able to force quit! This tradeoff is
justified for now since "parallel" tool executions will relieve us of
many worker timeouts that we are seeing in prod.
Future work:
Minimize/eliminate the need for `os._exit(1)` such that `MCPApp`
teardown logic will always execute, even when force quitting. The
solution will likely be moving away from `await asyncio.to_thread(func,
**func_args)` (while maintaining "parallelism" and then utilize the
`TaskTrackerMiddleware` introduced in this PR to cancel all of the
active HTTP requests.
Resolves PLT-713
Another small one.
When you `arcade deploy`, you need to
1. Run the command from the root of your project, and
2. Specify the relative path to your entrypoint file if it is not
located at the root of your repository or if it is named something other
than `server.py`.
#672 was a quick fix. This PR makes it a long term fix.
Whether a tool is added via `MCPApp.add_tools_from_module`,
`MCPApp.add_tool`, or `@app.tool`, the server's version and description
will be the same.
# PR Description
Consider this PR the result of a full pass through of this repository.
## Add helper for adding tools to an `MCPApp`
You can now add all of the tools in a module to an `MCPApp` via
`app.add_tools_from_module(...)`
## Edit what `arcade new` generates
First, I updated the backend to use hatchling.
Second, the structure generated before this PR was simple, but did not
create a proper Python module.
This hindered developers in the following ways:
1. Difficult to add the tools in your server to an evaluation suite
2. Difficult to add more than one tool to an MCPApp at a time
3. All other niceties that come with being able to import modules
```
# Before
server/
├── .env.example
├── server.py
└── pyproject.toml
```
This PR updates the structure generated such that a valid Python module
is generated:
```
# After
server/
├── pyproject.toml
└── src/
└── server/
├── __init__.py
├── .env.example
└── server.py
```
## Fix Tool Chaining
`self._ctx.server.executor.run(...)` was being called, but `MCPServer`
does not have an instance of `ToolExecutor` (and it's not intended to be
an instance anyways). I updated `Tool.call_raw` to pass the programmatic
tool call through the `MCPServer._handle_call_tool`. This means that the
programmatic tool calls now go through the same steps that a typical
tool call (initiated by the MCP client) would.
This means that **toolA**, which specifies **requirementsA**, is
permitted to call **toolB**, which specifies **requirementsB**, without
needing to explicitly declare or satisfy **requirementsB**. I believe
this is acceptable because the secrets and/or auth token associated with
**toolB's** `Context` are not exposed to **toolA**, and the secrets
and/or auth token associated with **toolA's** `Context` are not exposed
to **toolB**.
## Fix User Elicitation
1. The read & write streams were created with a maximum queue size of 0.
I increased this to 100.
2. I updated `ServerSession`'s run loop to both read messages from the
stream & process them concurrently. This enables server initiated
requests (like user elicitation and progress reporting) to be handled
while tools are being executed. Otherwise, the server initiated requests
would wait for the tool to finish executing and the tool execution would
wait for the server initiated request to finish.
3.
## Fix Progress Reporting
Progress tokens sent by the client were not being stored. Therefore
there was no way to notify a client with progress updates. I am now
storing the `progressToken`, along with other `_meta` sent from the
client, in the `ServerSession`'s `_request_meta`. I am setting
`_request_meta` whenever the `MCPServer` is handling an incoming message
from a client.
## Fix handling of server names with spaces
Before:
Server name: "The simple server name"
Tool name: whisper_secret
Name seen by client: "The_simple_server_name_WhisperSecret"
After
Server name: "The simple server name"
Tool name: whisper_secret
Name seen by client: "TheSimpleServerName_WhisperSecret"
## Add Integration Tests
The stdio integration test is much more comprehensive than the http
integration test. These tests will let me sleep a bit more at night
## Add Example MCP Servers
Example servers for sampling, user-elicitation, progress reporting,
logging, tool chaining, combining prebuilt tools with custom tools, tool
secrets, tool auth, evaluations, and more!
## Add Docker template
Added a Docker template for running an MCP server in Docker (and removed
the old docker stuff)
Seeing that arcade-ai==2.2.3 doesn't allow for core, serve, or tdk
versions 3.x.x and that it doesn't know about arcade-mcp-server or
arcade-mcp, I feel confident that we can get this past the release
candidate stage. The current state of our documentation
(docs.arcade.dev) still references the 'old way' of doing things, so we
can gradually introduce these new packages to users without the hassle
of specifying pre release flags when installing
### New packages:
arcade-mcp==1.0.0
arcade-mcp-server==1.0.0
### Breaking change with major bump:
arcade-core==3.0.0 from 2.4.0
arcade-serve==3.0.0 from 2.1.0
arcade-tdk==3.0.0 from 2.5.0
### Deprecated:
arcade-ai==2.2.3
TLDR;
The philosophy of CLI usage is "fire and forget" and "best effort". You
can opt out by setting `ARCADE_USAGE_TRACKING=0`.
We are capturing two events: `CLI execution succeeded` and `CLI
execution failed`. Reporting to PostHog is a short lived (maximum 10
seconds) subprocess that does not block the main CLI execution process.
`~/.arcade/usage.json` persists two values `anon_id` and
`linked_principal_id`. The logged in status of the CLI user determines
which ID is used. Upon `arcade login`, the `anon_id` is aliased with
`linked_principal_id`. Upon `arcade logout` the `linked_principal_id` is
removed and the `anon_id` is rotated.
## CLI Usage Tracking - How It Works
The usage tracking system implements an identity management and event
tracking pipeline. Here's how the pieces work together:
### **Identity State Management (`usage.json`)**
The system maintains a persistent identity file at
`~/.arcade/usage.json` with this structure:
```json
{
"anon_id": "uuid",
"linked_principal_id": "uuid" | null
}
```
**Key mechanics:**
- **`anon_id`**: Generated once on first CLI use and persists across
sessions. This UUID tracks all anonymous activity.
- **`linked_principal_id`**: Initially `null`. Once the user logs in and
we successfully alias their identity, this field stores their
`principal_id` to indicate this `anon_id` has been linked.
- **Atomic writes**: All updates use a temp file + atomic rename pattern
to prevent corruption from concurrent CLI processes
- **File locking**: Uses `fcntl` (Unix) to coordinate reads/writes
across multiple simultaneous CLI invocations
- **In-memory cache**: The `UsageIdentity` class caches the loaded data
to avoid repeated file I/O within a single CLI invocation
### **Identity Resolution Flow**
When tracking an event, the system determines the `distinct_id` (who to
attribute the event to) via this waterfall:
1. **Check `linked_principal_id`** in `usage.json`
- If present → use it (user was previously aliased)
- This is the fastest path and avoids API calls
2. **Fetch `principal_id` from Arcade Cloud API**
- Makes HTTP request to `/api/v1/auth/validate` with the user's API key
from `~/.arcade/credentials.yaml`
- If authenticated → returns `principal_id`
- Has 2s timeout for responsiveness
3. **Fall back to `anon_id`**
- If not authenticated or API call fails → use anonymous ID
- Marks event with `is_anon=True` flag
### **The Aliasing Lifecycle**
PostHog aliasing links anonymous activity to authenticated users. Here's
the state machine:
#### **Stage 1: Anonymous User**
```
usage.json: { "anon_id": "abc-123", "linked_principal_id": null }
All events → sent with distinct_id="abc-123" and is_anon=True
```
#### **Stage 2: Login Event**
1. User runs `arcade login`
2. Command completes successfully (auth token saved)
3. `CommandTracker` detects successful login
4. Fetches `principal_id` from API
5. Checks `should_alias()` → returns `True` because
`linked_principal_id` is `null`
6. **Calls `alias()` synchronously** (blocking):
```python
posthog.alias(previous_id="abc-123", distinct_id="zyx-321")
```
7. Updates `usage.json`:
```json
{ "anon_id": "abc-123", "linked_principal_id": "zyx-321" }
```
8. PostHog backend merges all events with `distinct_id="abc-123"` into
the user profile for `"zyx-321"`
#### **Stage 3: Authenticated User**
```
usage.json: { "anon_id": "abc-123", "linked_principal_id": "zyx-321" }
All events → sent with distinct_id="zyx-321" and is_anon=False
```
- Events are directly attributed to the authenticated user
- No more API calls needed (uses cached `linked_principal_id`)
#### **Stage 4: Logout Event**
1. User runs `arcade logout`
2. Logout event is sent with the authenticated `distinct_id`
3. `CommandTracker` detects successful logout
4. **Rotates identity** by calling `reset_to_anonymous()`:
```json
{ "anon_id": "xyz-789", "linked_principal_id": null }
```
5. New `anon_id` prevents cross-contamination if another user logs in
### **Critical Constraint: Alias Timing**
PostHog requires that `alias()` is called **BEFORE** any events are sent
with the new `distinct_id`. This is why:
- **`alias()` is synchronous (blocking)**: Guarantees it completes
before the login success event is sent
- **Subsequent events use `linked_principal_id`**: Once aliased, all
future events use the authenticated ID
- **Lazy aliasing**: If a user authenticates via another mechanism (not
through `arcade login`), the system detects this on the next command and
performs aliasing before sending that command's event
### **Event Capture Pipeline**
When `CommandTracker.track_command_execution()` is called:
1. **Resolve identity** → determines `distinct_id` and `is_anon` flag
2. **Build event properties**:
```python
{
"command_name": "toolkit.run",
"cli_version": "1.2.3",
"python_version": "3.11.0",
"os_type": "Darwin",
"os_release": "23.4.0",
"duration": 1250.42, # milliseconds
"error_message": "..." # if failed
}
```
3. **Call `UsageService.capture()`**:
- Serializes event data to JSON
- Spawns detached subprocess: `python -m arcade_cli.usage`
- Passes data via `ARCADE_USAGE_EVENT_DATA` env var
- **Returns immediately** (non-blocking)
4. **Detached subprocess (`__main__.py`)**:
- Runs independently, survives parent CLI exit
- Deserializes event data
- If `is_anon=True`, sets `$process_person_profile=False` (tells PostHog
not to create a full profile)
- Sends event to PostHog with 5s timeout
- Exits (hard exit after 10s max via timeout thread)
### **Concurrency Handling**
Multiple CLI processes can run simultaneously. The system handles this
via:
- **File locking** on `usage.json` (shared lock for reads, exclusive for
writes)
- **Atomic writes** via temp files ensure incomplete writes never
corrupt the file
- **Idempotent aliasing**: `should_alias()` prevents redundant alias
calls
### **Edge Cases Handled**
1. **Side-channel authentication**: User authenticates outside of
`arcade login` (e.g., manually editing credentials)
- Detected via "lazy aliasing" check on every command
- Performs alias if `linked_principal_id` doesn't match current
`principal_id`
2. **API failures during identity fetch**: Falls back to anonymous
tracking
- 2s timeout prevents hanging
- Silent failure doesn't disrupt CLI
3. **PostHog merge restrictions**: Can't alias returning users who
already have a profile
- System stores `linked_principal_id` to avoid retrying impossible
aliases
- New users (never logged in before) get full history stitched
4. **Multiple accounts on same machine**: Logout rotates `anon_id`
- User A's anonymous activity won't leak into User B's profile
### **Privacy & Performance**
- **Opt-out**: `ARCADE_USAGE_TRACKING=0` disables all tracking
- **Non-blocking**: Events never slow down CLI (detached subprocess)
- **Anonymous profiles**: `$process_person_profile=False` for `anon_id`
events minimizes data collection
- **Silent failures**: Network issues or PostHog errors never surface to
users
1. Updates docs to prefer `uv run server.py` instead of `arcade mcp` or
`python -m arcade_mcp_server`
2. Found a bug with running stdio servers while updating the docs, so i
snuck that in this PR
- Updates the `arcade docs` templates, dir/file paths, and URL paths to
reflect the new docs repo structure
- References "MCP Server" instead of "toolkit"
- Auto-detects when it's a Starter MCP server and adds the corresponding
warning in the main doc page
- Fixes a bug that generated the wrong file path to the Python & JS
examples when the package name had an underscore character)
- Introduces some minor improvements, such as pulling the MCP Server
description for `ToolInfo` from the package `pyproject.toml`, instead of
a standard description varying only the MCP Server name
---------
Co-authored-by: Eric Gustin <34000337+EricGustin@users.noreply.github.com>