PagerDuty typed OAuth object (#718)
<!-- CURSOR_SUMMARY --> > [!NOTE] > Adds a typed `PagerDuty` OAuth2 provider and wires it through TDK/MCP exports, with tests and coordinated version/dependency bumps. > > - **Auth (core)**: > - Add typed OAuth2 provider `PagerDuty` (`provider_id="pagerduty"`) in `arcade_core/auth.py`. > - **TDK & MCP Server**: > - Re-export `PagerDuty` in `arcade_tdk/auth/__init__.py` and `arcade_mcp_server/auth/__init__.py`. > - **Tests**: > - Extend `test_tool_decorator.py` and `test_create_tool_definition.py` to cover `PagerDuty` success/failure and tool requirement generation. > - **Versioning/Deps**: > - Bump versions: `arcade-core`→`4.1.0`, `arcade-tdk`→`3.4.0`, `arcade-mcp-server`→`1.14.0`, root `arcade-mcp`→`1.7.1`. > - Update dependency ranges to require the bumped versions. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2b60261b1962586ea58831ccb6ea66e57053ac86. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Francisco Liberal <francisco@arcade.dev>
This commit is contained in:
parent
0fb3b75b8b
commit
7a06bdfa7e
9 changed files with 86 additions and 45 deletions
|
|
@ -150,6 +150,15 @@ class Notion(OAuth2):
|
|||
super().__init__(id=id, scopes=scopes)
|
||||
|
||||
|
||||
class PagerDuty(OAuth2):
|
||||
"""Marks a tool as requiring PagerDuty authorization."""
|
||||
|
||||
provider_id: str = "pagerduty"
|
||||
|
||||
def __init__(self, *, id: Optional[str] = None, scopes: Optional[list[str]] = None): # noqa: A002
|
||||
super().__init__(id=id, scopes=scopes)
|
||||
|
||||
|
||||
class Reddit(OAuth2):
|
||||
"""Marks a tool as requiring Reddit authorization."""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
[project]
|
||||
name = "arcade-core"
|
||||
version = "4.0.0"
|
||||
version = "4.1.0"
|
||||
description = "Arcade Core - Core library for Arcade platform"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{name = "Arcade", email = "dev@arcade.dev"},
|
||||
]
|
||||
license = { text = "MIT" }
|
||||
authors = [{ name = "Arcade", email = "dev@arcade.dev" }]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from arcade_core.auth import (
|
|||
Microsoft,
|
||||
Notion,
|
||||
OAuth2,
|
||||
PagerDuty,
|
||||
Reddit,
|
||||
Slack,
|
||||
Spotify,
|
||||
|
|
@ -36,6 +37,7 @@ __all__ = [
|
|||
"LinkedIn",
|
||||
"Microsoft",
|
||||
"Notion",
|
||||
"PagerDuty",
|
||||
"OAuth2",
|
||||
"Reddit",
|
||||
"Slack",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||
|
||||
[project]
|
||||
name = "arcade-mcp-server"
|
||||
version = "1.13.0"
|
||||
version = "1.14.0"
|
||||
description = "Model Context Protocol (MCP) server framework for Arcade.dev"
|
||||
readme = "README.md"
|
||||
authors = [{ name = "Arcade.dev" }]
|
||||
|
|
@ -21,14 +21,14 @@ classifiers = [
|
|||
]
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"arcade-core>=4.0.0,<5.0.0",
|
||||
"arcade-core>=4.1.0,<5.0.0",
|
||||
"arcade-serve>=3.2.0,<4.0.0",
|
||||
"arcade-tdk>=3.3.0,<4.0.0",
|
||||
"arcade-tdk>=3.4.0,<4.0.0",
|
||||
"arcadepy>=1.5.0",
|
||||
"pydantic>=2.0.0",
|
||||
"fastapi>=0.100.0",
|
||||
"uvicorn>=0.30.0",
|
||||
"watchfiles>=0.18.0", # included with uvicorn, but listed to be explicit
|
||||
"watchfiles>=0.18.0", # included with uvicorn, but listed to be explicit
|
||||
"sse-starlette>=2.0.0",
|
||||
"starlette>=0.37.0",
|
||||
"anyio>=4.0.0",
|
||||
|
|
@ -39,12 +39,7 @@ dependencies = [
|
|||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest>=8.0.0",
|
||||
"pytest-asyncio>=0.23.0",
|
||||
"mypy>=1.0.0",
|
||||
"ruff>=0.1.0",
|
||||
]
|
||||
dev = ["pytest>=8.0.0", "pytest-asyncio>=0.23.0", "mypy>=1.0.0", "ruff>=0.1.0"]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["arcade_mcp_server"]
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from arcade_core.auth import (
|
|||
Microsoft,
|
||||
Notion,
|
||||
OAuth2,
|
||||
PagerDuty,
|
||||
Reddit,
|
||||
Slack,
|
||||
Spotify,
|
||||
|
|
@ -36,6 +37,7 @@ __all__ = [
|
|||
"LinkedIn",
|
||||
"Microsoft",
|
||||
"Notion",
|
||||
"PagerDuty",
|
||||
"OAuth2",
|
||||
"Reddit",
|
||||
"Slack",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
[project]
|
||||
name = "arcade-tdk"
|
||||
version = "3.3.0"
|
||||
version = "3.4.0"
|
||||
description = "Arcade TDK - Toolkit Development Kit for building Arcade tools"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{name = "Arcade", email = "dev@arcade.dev"},
|
||||
]
|
||||
license = { text = "MIT" }
|
||||
authors = [{ name = "Arcade", email = "dev@arcade.dev" }]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
|
|
@ -18,10 +16,7 @@ classifiers = [
|
|||
"Programming Language :: Python :: 3.13",
|
||||
]
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"arcade-core>=4.0.0,<5.0.0",
|
||||
"pydantic>=2.7.0",
|
||||
]
|
||||
dependencies = ["arcade-core>=4.1.0,<5.0.0", "pydantic>=2.7.0"]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import asyncio
|
|||
import pytest
|
||||
from arcade_core.auth import AuthProviderType, Google
|
||||
from arcade_tdk import tool
|
||||
from arcade_tdk.auth import OAuth2
|
||||
from arcade_tdk.auth import OAuth2, PagerDuty
|
||||
|
||||
|
||||
def test_sync_function():
|
||||
|
|
@ -50,6 +50,13 @@ async def test_async_function():
|
|||
"google",
|
||||
"my_google_provider123",
|
||||
),
|
||||
(PagerDuty, {"scopes": ["test_scope", "another.scope"]}, "pagerduty", None),
|
||||
(
|
||||
PagerDuty,
|
||||
{"id": "my_pagerduty_provider123", "scopes": ["test_scope", "another.scope"]},
|
||||
"pagerduty",
|
||||
"my_pagerduty_provider123",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_tool_decorator_with_auth_success(
|
||||
|
|
@ -102,6 +109,21 @@ def test_tool_decorator_with_auth_success(
|
|||
"scopes": ["test_scope", "another.scope"],
|
||||
},
|
||||
),
|
||||
(
|
||||
PagerDuty,
|
||||
{
|
||||
"provider_id": "my_example_provider_id_123",
|
||||
"scopes": ["test_scope", "another.scope"],
|
||||
},
|
||||
),
|
||||
(
|
||||
PagerDuty,
|
||||
{
|
||||
"provider_id": "my_example_provider_id_123",
|
||||
"id": "my_example_id_123",
|
||||
"scopes": ["test_scope", "another.scope"],
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_tool_decorator_with_auth_failure(auth_class, auth_kwargs):
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ from arcade_core.schema import (
|
|||
from arcade_core.utils import snake_to_pascal_case
|
||||
from arcade_tdk import tool
|
||||
from arcade_tdk.annotations import Inferrable
|
||||
from arcade_tdk.auth import Figma, GitHub, Google, OAuth2, Slack, X
|
||||
from arcade_tdk.auth import Figma, GitHub, Google, OAuth2, PagerDuty, Slack, X
|
||||
|
||||
|
||||
### Tests on @tool decorator
|
||||
|
|
@ -159,6 +159,17 @@ def func_with_x_requirement():
|
|||
pass
|
||||
|
||||
|
||||
@tool(
|
||||
desc="A function that requires PagerDuty authorization",
|
||||
requires_auth=PagerDuty(
|
||||
id="my_pagerduty_provider123",
|
||||
scopes=["read", "write"],
|
||||
),
|
||||
)
|
||||
def func_with_pagerduty_auth_requirement():
|
||||
pass
|
||||
|
||||
|
||||
### Tests on input params
|
||||
@tool(desc="A function with a non-inferrable input parameter")
|
||||
def func_with_non_inferrable_param(param1: Annotated[str, "First param", Inferrable(False)]):
|
||||
|
|
@ -507,6 +518,22 @@ def func_with_complex_return() -> dict[str, str]:
|
|||
)
|
||||
},
|
||||
),
|
||||
pytest.param(
|
||||
func_with_pagerduty_auth_requirement,
|
||||
{
|
||||
"requirements": ToolRequirements(
|
||||
authorization=ToolAuthRequirement(
|
||||
provider_id="pagerduty",
|
||||
provider_type="oauth2",
|
||||
id="my_pagerduty_provider123",
|
||||
oauth2=OAuth2Requirement(
|
||||
scopes=["read", "write"],
|
||||
),
|
||||
)
|
||||
)
|
||||
},
|
||||
id="func_with_pagerduty_auth_requirement",
|
||||
),
|
||||
# Tests on input params
|
||||
pytest.param(
|
||||
func_with_non_inferrable_param,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
[project]
|
||||
name = "arcade-mcp"
|
||||
version = "1.7.0"
|
||||
version = "1.7.1"
|
||||
description = "Arcade.dev - Tool Calling platform for Agents"
|
||||
readme = "README.md"
|
||||
license = {file = "LICENSE"}
|
||||
authors = [
|
||||
{name = "Arcade", email = "dev@arcade.dev"},
|
||||
]
|
||||
license = { file = "LICENSE" }
|
||||
authors = [{ name = "Arcade", email = "dev@arcade.dev" }]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
|
|
@ -21,8 +19,8 @@ requires-python = ">=3.10"
|
|||
|
||||
dependencies = [
|
||||
# CLI dependencies
|
||||
"arcade-mcp-server>=1.13.0,<2.0.0",
|
||||
"arcade-core>=4.0.0,<5.0.0",
|
||||
"arcade-mcp-server>=1.14.0,<2.0.0",
|
||||
"arcade-core>=4.1.0,<5.0.0",
|
||||
"typer==0.10.0",
|
||||
"rich>=14.0.0,<15.0.0",
|
||||
"Jinja2==3.1.6",
|
||||
|
|
@ -43,11 +41,11 @@ all = [
|
|||
"pytz>=2024.1",
|
||||
"python-dateutil>=2.8.2",
|
||||
# mcp
|
||||
"arcade-mcp-server>=1.13.0,<2.0.0",
|
||||
"arcade-mcp-server>=1.14.0,<2.0.0",
|
||||
# serve
|
||||
"arcade-serve>=3.2.0,<4.0.0",
|
||||
# tdk
|
||||
"arcade-tdk>=3.3.0,<4.0.0",
|
||||
"arcade-tdk>=3.4.0,<4.0.0",
|
||||
]
|
||||
# Evals also depends on arcade-core and openai, but they are already required deps
|
||||
evals = [
|
||||
|
|
@ -89,10 +87,7 @@ requires = ["hatchling"]
|
|||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = [
|
||||
"libs/arcade-cli/arcade_cli",
|
||||
"libs/arcade-evals/arcade_evals",
|
||||
]
|
||||
packages = ["libs/arcade-cli/arcade_cli", "libs/arcade-evals/arcade_evals"]
|
||||
|
||||
[tool.uv.workspace]
|
||||
members = [
|
||||
|
|
@ -113,7 +108,7 @@ warn_unused_ignores = true
|
|||
show_error_codes = true
|
||||
ignore_missing_imports = true
|
||||
exclude = [
|
||||
'.*{{.*}}.*' # Ignore files that have names that use Jinja template syntax
|
||||
'.*{{.*}}.*', # Ignore files that have names that use Jinja template syntax
|
||||
]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
|
|
@ -133,11 +128,7 @@ addopts = [
|
|||
|
||||
[tool.coverage.run]
|
||||
source = ["libs"]
|
||||
omit = [
|
||||
"*/tests/*",
|
||||
"*/test_*",
|
||||
"*/__pycache__/*",
|
||||
]
|
||||
omit = ["*/tests/*", "*/test_*", "*/__pycache__/*"]
|
||||
parallel = true
|
||||
patch = ["subprocess"]
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue