@@ -307,6 +307,10 @@ async def _start(self) -> None:
307307 await self ._tool_manager .load_from_catalog (self ._initial_catalog )
308308 except Exception :
309309 logger .exception ("Failed to load tools from initial catalog" )
310+
311+ # Check for missing secrets and log warnings (only when worker routes are disabled)
312+ await self ._check_and_warn_missing_secrets ()
313+
310314 await self ._resource_manager .start ()
311315 await self ._prompt_manager .start ()
312316 await self .lifespan_manager .startup ()
@@ -654,6 +658,40 @@ async def _create_tool_context(
654658
655659 return tool_context
656660
661+ async def _check_and_warn_missing_secrets (self ) -> None :
662+ """
663+ Check for missing tool secrets and log warnings.
664+
665+ This method is called during server startup to provide early feedback
666+ about missing configuration. It only runs when worker routes are disabled
667+ (when ARCADE_WORKER_SECRET is not set), as worker routes receive secrets
668+ with tool execution information.
669+ """
670+ # Skip validation if worker routes are enabled
671+ if self .settings .arcade .server_secret :
672+ logger .debug ("Skipping secret validation check - worker routes are enabled" )
673+ return
674+
675+ # Get all available secrets from settings and environment
676+ available_secrets = set (self .settings .tool_secrets ().keys ()) | set (os .environ .keys ())
677+
678+ # Check each tool for missing secrets
679+ managed_tools = await self ._tool_manager .registry .list ()
680+ for managed_tool in managed_tools :
681+ tool = managed_tool ["materialized" ]
682+ if tool .definition .requirements and tool .definition .requirements .secrets :
683+ missing_secrets = []
684+ for secret_requirement in tool .definition .requirements .secrets :
685+ if secret_requirement .key not in available_secrets :
686+ missing_secrets .append (secret_requirement .key )
687+
688+ if missing_secrets :
689+ secret_list = "', '" .join (missing_secrets )
690+ tool_name = tool .definition .name
691+ logger .warning (
692+ f"Tool '{ tool_name } ' declares secret(s) '{ secret_list } ' which is/are not set. It will return an error if called."
693+ )
694+
657695 async def _handle_call_tool (
658696 self ,
659697 message : CallToolRequest ,
0 commit comments