From 9dd76e4162dc20a098945f8755d4223e2b6f10a4 Mon Sep 17 00:00:00 2001 From: Will Date: Thu, 16 Jul 2026 14:35:15 +0100 Subject: [PATCH] feat(plugin): expose submit_feedback in both modes, add feedback flag The StackOne MCP server exposes submit_feedback on every account. The plugin now inherits it in both modes: - default mode: fetch_tools already returns it (kept available under provider/action filters by the SDK); - search_and_execute mode: _build_tools now appends it alongside tool_search/tool_execute. Adds a feedback flag (default True) threaded to both paths so callers can omit the feedback tool. Requires the stackone-ai SDK change that inherits submit_feedback from MCP and accepts the feedback kwarg. Co-Authored-By: Claude Opus 4.8 (1M context) --- stackone_adk/plugin.py | 7 ++++++- tests/test_plugin.py | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/stackone_adk/plugin.py b/stackone_adk/plugin.py index 5b00c71..064c298 100644 --- a/stackone_adk/plugin.py +++ b/stackone_adk/plugin.py @@ -98,6 +98,9 @@ class StackOnePlugin(BasePlugin): timeout: Per-request timeout in seconds for HTTP calls (account discovery and tool execution). Defaults to 180s — increase further for very slow connectors (e.g. some Workday endpoints). + feedback: Whether to expose the global ``submit_feedback`` tool, which the + StackOne MCP server provides on every account. Enabled by default in both + modes; set to ``False`` to omit it. """ def __init__( @@ -114,6 +117,7 @@ def __init__( search: SearchConfig | None = None, execute: ExecuteToolsConfig | None = None, timeout: float = DEFAULT_TIMEOUT, + feedback: bool = True, ) -> None: super().__init__(name=plugin_name) @@ -162,7 +166,7 @@ def __init__( "(the LLM's search query handles that)." ) # Use SDK's internal builder until a public API is exposed. - meta_tools = self._toolset._build_tools(account_ids=account_ids) + meta_tools = self._toolset._build_tools(account_ids=account_ids, feedback=feedback) for tool in meta_tools: self._tools.append(StackOneAdkTool(tool)) else: @@ -170,6 +174,7 @@ def __init__( account_ids=account_ids, providers=providers, actions=actions, + feedback=feedback, ) for tool in stackone_tools: try: diff --git a/tests/test_plugin.py b/tests/test_plugin.py index f3e7c8f..bf3921a 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -103,7 +103,7 @@ def test_default_init_auto_discovers(self, mock_toolset_cls, mock_discover): mock_discover.assert_called_once() mock_toolset.fetch_tools.assert_called_once_with( - account_ids=["acct-auto"], providers=None, actions=None + account_ids=["acct-auto"], providers=None, actions=None, feedback=True ) assert len(plugin.get_tools()) == 2 assert plugin.name == "stackone_plugin" @@ -156,6 +156,7 @@ def test_skips_discovery_when_account_ids_provided(self, mock_toolset_cls, mock_ account_ids=["acct-1", "acct-2"], providers=["calendly"], actions=["*_list_*"], + feedback=True, ) @patch(PLUGIN_PATCH_DISCOVER, return_value=["acct-auto"]) @@ -261,7 +262,7 @@ def test_search_mode_uses_build_tools(self, mock_toolset_cls, mock_discover): kwargs = mock_toolset_cls.call_args.kwargs assert kwargs["search"] == {"method": "auto"} - mock_toolset._build_tools.assert_called_once_with(account_ids=["acct-1"]) + mock_toolset._build_tools.assert_called_once_with(account_ids=["acct-1"], feedback=True) mock_toolset.fetch_tools.assert_not_called() tools = plugin.get_tools() assert len(tools) == 2 @@ -288,6 +289,32 @@ def test_search_mode_threads_through_config(self, mock_toolset_cls, mock_discove assert kwargs["execute"] == {"account_ids": ["acct-explicit"], "timeout": 120} assert kwargs["timeout"] == 200 + @patch(PLUGIN_PATCH_DISCOVER, return_value=["acct-1"]) + @patch(PLUGIN_PATCH_TOOLSET) + def test_search_mode_can_disable_feedback(self, mock_toolset_cls, mock_discover): + mock_toolset = MagicMock() + mock_toolset._build_tools.return_value = _make_mock_tools(2) + mock_toolset_cls.return_value = mock_toolset + + StackOnePlugin(api_key="sk-test", mode="search_and_execute", feedback=False) + + mock_toolset._build_tools.assert_called_once_with(account_ids=["acct-1"], feedback=False) + + +class TestStackOnePluginFeedback: + @patch(PLUGIN_PATCH_DISCOVER, return_value=["acct-auto"]) + @patch(PLUGIN_PATCH_TOOLSET) + def test_default_mode_can_disable_feedback(self, mock_toolset_cls, mock_discover): + mock_toolset = MagicMock() + mock_toolset.fetch_tools.return_value = _make_mock_tools(0) + mock_toolset_cls.return_value = mock_toolset + + StackOnePlugin(api_key="sk-test", feedback=False) + + mock_toolset.fetch_tools.assert_called_once_with( + account_ids=["acct-auto"], providers=None, actions=None, feedback=False + ) + @patch(PLUGIN_PATCH_DISCOVER) @patch(PLUGIN_PATCH_TOOLSET) def test_search_mode_with_explicit_account_ids(self, mock_toolset_cls, mock_discover): @@ -302,7 +329,9 @@ def test_search_mode_with_explicit_account_ids(self, mock_toolset_cls, mock_disc ) mock_discover.assert_not_called() - mock_toolset._build_tools.assert_called_once_with(account_ids=["acct-a", "acct-b"]) + mock_toolset._build_tools.assert_called_once_with( + account_ids=["acct-a", "acct-b"], feedback=True + ) @patch(PLUGIN_PATCH_DISCOVER, return_value=["acct-1"]) @patch(PLUGIN_PATCH_TOOLSET)