kubiya-control-plane-api 0.9.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (479) hide show
  1. control_plane_api/LICENSE +676 -0
  2. control_plane_api/README.md +350 -0
  3. control_plane_api/__init__.py +4 -0
  4. control_plane_api/__version__.py +8 -0
  5. control_plane_api/alembic/README +1 -0
  6. control_plane_api/alembic/env.py +121 -0
  7. control_plane_api/alembic/script.py.mako +28 -0
  8. control_plane_api/alembic/versions/2613c65c3dbe_initial_database_setup.py +32 -0
  9. control_plane_api/alembic/versions/2df520d4927d_merge_heads.py +28 -0
  10. control_plane_api/alembic/versions/43abf98d6a01_add_paused_status_to_executions.py +73 -0
  11. control_plane_api/alembic/versions/6289854264cb_merge_multiple_heads.py +28 -0
  12. control_plane_api/alembic/versions/6a4d4dc3d8dc_generate_execution_transitions.py +50 -0
  13. control_plane_api/alembic/versions/87d11cf0a783_add_disconnected_status_to_worker_.py +44 -0
  14. control_plane_api/alembic/versions/add_ephemeral_queue_support.py +85 -0
  15. control_plane_api/alembic/versions/add_model_type_to_llm_models.py +31 -0
  16. control_plane_api/alembic/versions/add_plan_executions_table.py +114 -0
  17. control_plane_api/alembic/versions/add_trace_span_tables.py +154 -0
  18. control_plane_api/alembic/versions/add_user_info_to_traces.py +36 -0
  19. control_plane_api/alembic/versions/adjusting_foreign_keys.py +32 -0
  20. control_plane_api/alembic/versions/b4983d976db2_initial_tables.py +1128 -0
  21. control_plane_api/alembic/versions/d181a3b40e71_rename_custom_metadata_to_metadata_in_.py +50 -0
  22. control_plane_api/alembic/versions/df9117888e82_add_missing_columns.py +82 -0
  23. control_plane_api/alembic/versions/f25de6ad895a_missing_migrations.py +34 -0
  24. control_plane_api/alembic/versions/f71305fb69b9_fix_ephemeral_queue_deletion_foreign_key.py +54 -0
  25. control_plane_api/alembic/versions/mark_local_exec_queues_as_ephemeral.py +68 -0
  26. control_plane_api/alembic.ini +148 -0
  27. control_plane_api/api/index.py +12 -0
  28. control_plane_api/app/__init__.py +11 -0
  29. control_plane_api/app/activities/__init__.py +20 -0
  30. control_plane_api/app/activities/agent_activities.py +384 -0
  31. control_plane_api/app/activities/plan_generation_activities.py +499 -0
  32. control_plane_api/app/activities/team_activities.py +424 -0
  33. control_plane_api/app/activities/temporal_cloud_activities.py +588 -0
  34. control_plane_api/app/config/__init__.py +35 -0
  35. control_plane_api/app/config/api_config.py +469 -0
  36. control_plane_api/app/config/config_loader.py +224 -0
  37. control_plane_api/app/config/model_pricing.py +323 -0
  38. control_plane_api/app/config/storage_config.py +159 -0
  39. control_plane_api/app/config.py +115 -0
  40. control_plane_api/app/controllers/__init__.py +0 -0
  41. control_plane_api/app/controllers/execution_environment_controller.py +1315 -0
  42. control_plane_api/app/database.py +135 -0
  43. control_plane_api/app/exceptions.py +408 -0
  44. control_plane_api/app/lib/__init__.py +11 -0
  45. control_plane_api/app/lib/environment.py +65 -0
  46. control_plane_api/app/lib/event_bus/__init__.py +17 -0
  47. control_plane_api/app/lib/event_bus/base.py +136 -0
  48. control_plane_api/app/lib/event_bus/manager.py +335 -0
  49. control_plane_api/app/lib/event_bus/providers/__init__.py +6 -0
  50. control_plane_api/app/lib/event_bus/providers/http_provider.py +166 -0
  51. control_plane_api/app/lib/event_bus/providers/nats_provider.py +324 -0
  52. control_plane_api/app/lib/event_bus/providers/redis_provider.py +233 -0
  53. control_plane_api/app/lib/event_bus/providers/websocket_provider.py +497 -0
  54. control_plane_api/app/lib/job_executor.py +330 -0
  55. control_plane_api/app/lib/kubiya_client.py +293 -0
  56. control_plane_api/app/lib/litellm_pricing.py +166 -0
  57. control_plane_api/app/lib/mcp_validation.py +163 -0
  58. control_plane_api/app/lib/nats/__init__.py +13 -0
  59. control_plane_api/app/lib/nats/credentials_manager.py +288 -0
  60. control_plane_api/app/lib/nats/listener.py +374 -0
  61. control_plane_api/app/lib/planning_prompt_builder.py +153 -0
  62. control_plane_api/app/lib/planning_tools/__init__.py +41 -0
  63. control_plane_api/app/lib/planning_tools/agents.py +409 -0
  64. control_plane_api/app/lib/planning_tools/agno_toolkit.py +836 -0
  65. control_plane_api/app/lib/planning_tools/base.py +119 -0
  66. control_plane_api/app/lib/planning_tools/cognitive_memory_tools.py +403 -0
  67. control_plane_api/app/lib/planning_tools/context_graph_tools.py +545 -0
  68. control_plane_api/app/lib/planning_tools/environments.py +218 -0
  69. control_plane_api/app/lib/planning_tools/knowledge.py +204 -0
  70. control_plane_api/app/lib/planning_tools/models.py +93 -0
  71. control_plane_api/app/lib/planning_tools/planning_service.py +646 -0
  72. control_plane_api/app/lib/planning_tools/resources.py +242 -0
  73. control_plane_api/app/lib/planning_tools/teams.py +334 -0
  74. control_plane_api/app/lib/policy_enforcer_client.py +1016 -0
  75. control_plane_api/app/lib/redis_client.py +803 -0
  76. control_plane_api/app/lib/sqlalchemy_utils.py +486 -0
  77. control_plane_api/app/lib/state_transition_tools/__init__.py +7 -0
  78. control_plane_api/app/lib/state_transition_tools/execution_context.py +388 -0
  79. control_plane_api/app/lib/storage/__init__.py +20 -0
  80. control_plane_api/app/lib/storage/base_provider.py +274 -0
  81. control_plane_api/app/lib/storage/provider_factory.py +157 -0
  82. control_plane_api/app/lib/storage/vercel_blob_provider.py +468 -0
  83. control_plane_api/app/lib/supabase.py +71 -0
  84. control_plane_api/app/lib/supabase_utils.py +138 -0
  85. control_plane_api/app/lib/task_planning/__init__.py +138 -0
  86. control_plane_api/app/lib/task_planning/agent_factory.py +308 -0
  87. control_plane_api/app/lib/task_planning/agents.py +389 -0
  88. control_plane_api/app/lib/task_planning/cache.py +218 -0
  89. control_plane_api/app/lib/task_planning/entity_resolver.py +273 -0
  90. control_plane_api/app/lib/task_planning/helpers.py +293 -0
  91. control_plane_api/app/lib/task_planning/hooks.py +474 -0
  92. control_plane_api/app/lib/task_planning/models.py +503 -0
  93. control_plane_api/app/lib/task_planning/plan_validator.py +166 -0
  94. control_plane_api/app/lib/task_planning/planning_workflow.py +2911 -0
  95. control_plane_api/app/lib/task_planning/runner.py +656 -0
  96. control_plane_api/app/lib/task_planning/streaming_hook.py +213 -0
  97. control_plane_api/app/lib/task_planning/workflow.py +424 -0
  98. control_plane_api/app/lib/templating/__init__.py +88 -0
  99. control_plane_api/app/lib/templating/compiler.py +278 -0
  100. control_plane_api/app/lib/templating/engine.py +178 -0
  101. control_plane_api/app/lib/templating/parsers/__init__.py +29 -0
  102. control_plane_api/app/lib/templating/parsers/base.py +96 -0
  103. control_plane_api/app/lib/templating/parsers/env.py +85 -0
  104. control_plane_api/app/lib/templating/parsers/graph.py +112 -0
  105. control_plane_api/app/lib/templating/parsers/secret.py +87 -0
  106. control_plane_api/app/lib/templating/parsers/simple.py +81 -0
  107. control_plane_api/app/lib/templating/resolver.py +366 -0
  108. control_plane_api/app/lib/templating/types.py +214 -0
  109. control_plane_api/app/lib/templating/validator.py +201 -0
  110. control_plane_api/app/lib/temporal_client.py +232 -0
  111. control_plane_api/app/lib/temporal_credentials_cache.py +178 -0
  112. control_plane_api/app/lib/temporal_credentials_service.py +203 -0
  113. control_plane_api/app/lib/validation/__init__.py +24 -0
  114. control_plane_api/app/lib/validation/runtime_validation.py +388 -0
  115. control_plane_api/app/main.py +531 -0
  116. control_plane_api/app/middleware/__init__.py +10 -0
  117. control_plane_api/app/middleware/auth.py +645 -0
  118. control_plane_api/app/middleware/exception_handler.py +267 -0
  119. control_plane_api/app/middleware/prometheus_middleware.py +173 -0
  120. control_plane_api/app/middleware/rate_limiting.py +384 -0
  121. control_plane_api/app/middleware/request_id.py +202 -0
  122. control_plane_api/app/models/__init__.py +40 -0
  123. control_plane_api/app/models/agent.py +90 -0
  124. control_plane_api/app/models/analytics.py +206 -0
  125. control_plane_api/app/models/associations.py +107 -0
  126. control_plane_api/app/models/auth_user.py +73 -0
  127. control_plane_api/app/models/context.py +161 -0
  128. control_plane_api/app/models/custom_integration.py +99 -0
  129. control_plane_api/app/models/environment.py +64 -0
  130. control_plane_api/app/models/execution.py +125 -0
  131. control_plane_api/app/models/execution_transition.py +50 -0
  132. control_plane_api/app/models/job.py +159 -0
  133. control_plane_api/app/models/llm_model.py +78 -0
  134. control_plane_api/app/models/orchestration.py +66 -0
  135. control_plane_api/app/models/plan_execution.py +102 -0
  136. control_plane_api/app/models/presence.py +49 -0
  137. control_plane_api/app/models/project.py +61 -0
  138. control_plane_api/app/models/project_management.py +85 -0
  139. control_plane_api/app/models/session.py +29 -0
  140. control_plane_api/app/models/skill.py +155 -0
  141. control_plane_api/app/models/system_tables.py +43 -0
  142. control_plane_api/app/models/task_planning.py +372 -0
  143. control_plane_api/app/models/team.py +86 -0
  144. control_plane_api/app/models/trace.py +257 -0
  145. control_plane_api/app/models/user_profile.py +54 -0
  146. control_plane_api/app/models/worker.py +221 -0
  147. control_plane_api/app/models/workflow.py +161 -0
  148. control_plane_api/app/models/workspace.py +50 -0
  149. control_plane_api/app/observability/__init__.py +177 -0
  150. control_plane_api/app/observability/context_logging.py +475 -0
  151. control_plane_api/app/observability/decorators.py +337 -0
  152. control_plane_api/app/observability/local_span_processor.py +702 -0
  153. control_plane_api/app/observability/metrics.py +303 -0
  154. control_plane_api/app/observability/middleware.py +246 -0
  155. control_plane_api/app/observability/optional.py +115 -0
  156. control_plane_api/app/observability/tracing.py +382 -0
  157. control_plane_api/app/policies/README.md +149 -0
  158. control_plane_api/app/policies/approved_users.rego +62 -0
  159. control_plane_api/app/policies/business_hours.rego +51 -0
  160. control_plane_api/app/policies/rate_limiting.rego +100 -0
  161. control_plane_api/app/policies/tool_enforcement/README.md +336 -0
  162. control_plane_api/app/policies/tool_enforcement/bash_command_validation.rego +71 -0
  163. control_plane_api/app/policies/tool_enforcement/business_hours_enforcement.rego +82 -0
  164. control_plane_api/app/policies/tool_enforcement/mcp_tool_allowlist.rego +58 -0
  165. control_plane_api/app/policies/tool_enforcement/production_safeguards.rego +80 -0
  166. control_plane_api/app/policies/tool_enforcement/role_based_tool_access.rego +44 -0
  167. control_plane_api/app/policies/tool_restrictions.rego +86 -0
  168. control_plane_api/app/routers/__init__.py +4 -0
  169. control_plane_api/app/routers/agents.py +382 -0
  170. control_plane_api/app/routers/agents_v2.py +1598 -0
  171. control_plane_api/app/routers/analytics.py +1310 -0
  172. control_plane_api/app/routers/auth.py +59 -0
  173. control_plane_api/app/routers/client_config.py +57 -0
  174. control_plane_api/app/routers/context_graph.py +561 -0
  175. control_plane_api/app/routers/context_manager.py +577 -0
  176. control_plane_api/app/routers/custom_integrations.py +490 -0
  177. control_plane_api/app/routers/enforcer.py +132 -0
  178. control_plane_api/app/routers/environment_context.py +252 -0
  179. control_plane_api/app/routers/environments.py +761 -0
  180. control_plane_api/app/routers/execution_environment.py +847 -0
  181. control_plane_api/app/routers/executions/__init__.py +28 -0
  182. control_plane_api/app/routers/executions/router.py +286 -0
  183. control_plane_api/app/routers/executions/services/__init__.py +22 -0
  184. control_plane_api/app/routers/executions/services/demo_worker_health.py +156 -0
  185. control_plane_api/app/routers/executions/services/status_service.py +420 -0
  186. control_plane_api/app/routers/executions/services/test_worker_health.py +480 -0
  187. control_plane_api/app/routers/executions/services/worker_health.py +514 -0
  188. control_plane_api/app/routers/executions/streaming/__init__.py +22 -0
  189. control_plane_api/app/routers/executions/streaming/deduplication.py +352 -0
  190. control_plane_api/app/routers/executions/streaming/event_buffer.py +353 -0
  191. control_plane_api/app/routers/executions/streaming/event_formatter.py +964 -0
  192. control_plane_api/app/routers/executions/streaming/history_loader.py +588 -0
  193. control_plane_api/app/routers/executions/streaming/live_source.py +693 -0
  194. control_plane_api/app/routers/executions/streaming/streamer.py +849 -0
  195. control_plane_api/app/routers/executions.py +4888 -0
  196. control_plane_api/app/routers/health.py +165 -0
  197. control_plane_api/app/routers/health_v2.py +394 -0
  198. control_plane_api/app/routers/integration_templates.py +496 -0
  199. control_plane_api/app/routers/integrations.py +287 -0
  200. control_plane_api/app/routers/jobs.py +1809 -0
  201. control_plane_api/app/routers/metrics.py +517 -0
  202. control_plane_api/app/routers/models.py +82 -0
  203. control_plane_api/app/routers/models_v2.py +628 -0
  204. control_plane_api/app/routers/plan_executions.py +1481 -0
  205. control_plane_api/app/routers/plan_generation_async.py +304 -0
  206. control_plane_api/app/routers/policies.py +669 -0
  207. control_plane_api/app/routers/presence.py +234 -0
  208. control_plane_api/app/routers/projects.py +987 -0
  209. control_plane_api/app/routers/runners.py +379 -0
  210. control_plane_api/app/routers/runtimes.py +172 -0
  211. control_plane_api/app/routers/secrets.py +171 -0
  212. control_plane_api/app/routers/skills.py +1010 -0
  213. control_plane_api/app/routers/skills_definitions.py +140 -0
  214. control_plane_api/app/routers/storage.py +456 -0
  215. control_plane_api/app/routers/task_planning.py +611 -0
  216. control_plane_api/app/routers/task_queues.py +650 -0
  217. control_plane_api/app/routers/team_context.py +274 -0
  218. control_plane_api/app/routers/teams.py +1747 -0
  219. control_plane_api/app/routers/templates.py +248 -0
  220. control_plane_api/app/routers/traces.py +571 -0
  221. control_plane_api/app/routers/websocket_client.py +479 -0
  222. control_plane_api/app/routers/websocket_executions_status.py +437 -0
  223. control_plane_api/app/routers/websocket_gateway.py +323 -0
  224. control_plane_api/app/routers/websocket_traces.py +576 -0
  225. control_plane_api/app/routers/worker_queues.py +2555 -0
  226. control_plane_api/app/routers/worker_websocket.py +419 -0
  227. control_plane_api/app/routers/workers.py +1004 -0
  228. control_plane_api/app/routers/workflows.py +204 -0
  229. control_plane_api/app/runtimes/__init__.py +6 -0
  230. control_plane_api/app/runtimes/validation.py +344 -0
  231. control_plane_api/app/schemas/__init__.py +1 -0
  232. control_plane_api/app/schemas/job_schemas.py +302 -0
  233. control_plane_api/app/schemas/mcp_schemas.py +311 -0
  234. control_plane_api/app/schemas/template_schemas.py +133 -0
  235. control_plane_api/app/schemas/trace_schemas.py +168 -0
  236. control_plane_api/app/schemas/worker_queue_observability_schemas.py +165 -0
  237. control_plane_api/app/services/__init__.py +1 -0
  238. control_plane_api/app/services/agno_planning_strategy.py +233 -0
  239. control_plane_api/app/services/agno_service.py +838 -0
  240. control_plane_api/app/services/claude_code_planning_service.py +203 -0
  241. control_plane_api/app/services/context_graph_client.py +224 -0
  242. control_plane_api/app/services/custom_integration_service.py +415 -0
  243. control_plane_api/app/services/integration_resolution_service.py +345 -0
  244. control_plane_api/app/services/litellm_service.py +394 -0
  245. control_plane_api/app/services/plan_generator.py +79 -0
  246. control_plane_api/app/services/planning_strategy.py +66 -0
  247. control_plane_api/app/services/planning_strategy_factory.py +118 -0
  248. control_plane_api/app/services/policy_service.py +615 -0
  249. control_plane_api/app/services/state_transition_service.py +755 -0
  250. control_plane_api/app/services/storage_service.py +593 -0
  251. control_plane_api/app/services/temporal_cloud_provisioning.py +150 -0
  252. control_plane_api/app/services/toolsets/context_graph_skill.py +432 -0
  253. control_plane_api/app/services/trace_retention.py +354 -0
  254. control_plane_api/app/services/worker_queue_metrics_service.py +190 -0
  255. control_plane_api/app/services/workflow_cancellation_manager.py +135 -0
  256. control_plane_api/app/services/workflow_operations_service.py +611 -0
  257. control_plane_api/app/skills/__init__.py +100 -0
  258. control_plane_api/app/skills/base.py +239 -0
  259. control_plane_api/app/skills/builtin/__init__.py +37 -0
  260. control_plane_api/app/skills/builtin/agent_communication/__init__.py +8 -0
  261. control_plane_api/app/skills/builtin/agent_communication/skill.py +246 -0
  262. control_plane_api/app/skills/builtin/code_ingestion/__init__.py +4 -0
  263. control_plane_api/app/skills/builtin/code_ingestion/skill.py +267 -0
  264. control_plane_api/app/skills/builtin/cognitive_memory/__init__.py +4 -0
  265. control_plane_api/app/skills/builtin/cognitive_memory/skill.py +174 -0
  266. control_plane_api/app/skills/builtin/contextual_awareness/__init__.py +4 -0
  267. control_plane_api/app/skills/builtin/contextual_awareness/skill.py +387 -0
  268. control_plane_api/app/skills/builtin/data_visualization/__init__.py +4 -0
  269. control_plane_api/app/skills/builtin/data_visualization/skill.py +154 -0
  270. control_plane_api/app/skills/builtin/docker/__init__.py +4 -0
  271. control_plane_api/app/skills/builtin/docker/skill.py +104 -0
  272. control_plane_api/app/skills/builtin/file_generation/__init__.py +4 -0
  273. control_plane_api/app/skills/builtin/file_generation/skill.py +94 -0
  274. control_plane_api/app/skills/builtin/file_system/__init__.py +4 -0
  275. control_plane_api/app/skills/builtin/file_system/skill.py +110 -0
  276. control_plane_api/app/skills/builtin/knowledge_api/__init__.py +5 -0
  277. control_plane_api/app/skills/builtin/knowledge_api/skill.py +124 -0
  278. control_plane_api/app/skills/builtin/python/__init__.py +4 -0
  279. control_plane_api/app/skills/builtin/python/skill.py +92 -0
  280. control_plane_api/app/skills/builtin/remote_filesystem/__init__.py +5 -0
  281. control_plane_api/app/skills/builtin/remote_filesystem/skill.py +170 -0
  282. control_plane_api/app/skills/builtin/shell/__init__.py +4 -0
  283. control_plane_api/app/skills/builtin/shell/skill.py +161 -0
  284. control_plane_api/app/skills/builtin/slack/__init__.py +3 -0
  285. control_plane_api/app/skills/builtin/slack/skill.py +302 -0
  286. control_plane_api/app/skills/builtin/workflow_executor/__init__.py +4 -0
  287. control_plane_api/app/skills/builtin/workflow_executor/skill.py +469 -0
  288. control_plane_api/app/skills/business_intelligence.py +189 -0
  289. control_plane_api/app/skills/config.py +63 -0
  290. control_plane_api/app/skills/loaders/__init__.py +14 -0
  291. control_plane_api/app/skills/loaders/base.py +73 -0
  292. control_plane_api/app/skills/loaders/filesystem_loader.py +199 -0
  293. control_plane_api/app/skills/registry.py +125 -0
  294. control_plane_api/app/utils/helpers.py +12 -0
  295. control_plane_api/app/utils/workflow_executor.py +354 -0
  296. control_plane_api/app/workflows/__init__.py +11 -0
  297. control_plane_api/app/workflows/agent_execution.py +520 -0
  298. control_plane_api/app/workflows/agent_execution_with_skills.py +223 -0
  299. control_plane_api/app/workflows/namespace_provisioning.py +326 -0
  300. control_plane_api/app/workflows/plan_generation.py +254 -0
  301. control_plane_api/app/workflows/team_execution.py +442 -0
  302. control_plane_api/scripts/seed_models.py +240 -0
  303. control_plane_api/scripts/validate_existing_tool_names.py +492 -0
  304. control_plane_api/shared/__init__.py +8 -0
  305. control_plane_api/shared/version.py +17 -0
  306. control_plane_api/test_deduplication.py +274 -0
  307. control_plane_api/test_executor_deduplication_e2e.py +309 -0
  308. control_plane_api/test_job_execution_e2e.py +283 -0
  309. control_plane_api/test_real_integration.py +193 -0
  310. control_plane_api/version.py +38 -0
  311. control_plane_api/worker/__init__.py +0 -0
  312. control_plane_api/worker/activities/__init__.py +0 -0
  313. control_plane_api/worker/activities/agent_activities.py +1585 -0
  314. control_plane_api/worker/activities/approval_activities.py +234 -0
  315. control_plane_api/worker/activities/job_activities.py +199 -0
  316. control_plane_api/worker/activities/runtime_activities.py +1167 -0
  317. control_plane_api/worker/activities/skill_activities.py +282 -0
  318. control_plane_api/worker/activities/team_activities.py +479 -0
  319. control_plane_api/worker/agent_runtime_server.py +370 -0
  320. control_plane_api/worker/binary_manager.py +333 -0
  321. control_plane_api/worker/config/__init__.py +31 -0
  322. control_plane_api/worker/config/worker_config.py +273 -0
  323. control_plane_api/worker/control_plane_client.py +1491 -0
  324. control_plane_api/worker/examples/analytics_integration_example.py +362 -0
  325. control_plane_api/worker/health_monitor.py +159 -0
  326. control_plane_api/worker/metrics.py +237 -0
  327. control_plane_api/worker/models/__init__.py +1 -0
  328. control_plane_api/worker/models/error_events.py +105 -0
  329. control_plane_api/worker/models/inputs.py +89 -0
  330. control_plane_api/worker/runtimes/__init__.py +35 -0
  331. control_plane_api/worker/runtimes/agent_runtime/runtime.py +485 -0
  332. control_plane_api/worker/runtimes/agno/__init__.py +34 -0
  333. control_plane_api/worker/runtimes/agno/config.py +248 -0
  334. control_plane_api/worker/runtimes/agno/hooks.py +385 -0
  335. control_plane_api/worker/runtimes/agno/mcp_builder.py +195 -0
  336. control_plane_api/worker/runtimes/agno/runtime.py +1063 -0
  337. control_plane_api/worker/runtimes/agno/utils.py +163 -0
  338. control_plane_api/worker/runtimes/base.py +979 -0
  339. control_plane_api/worker/runtimes/claude_code/__init__.py +38 -0
  340. control_plane_api/worker/runtimes/claude_code/cleanup.py +184 -0
  341. control_plane_api/worker/runtimes/claude_code/client_pool.py +529 -0
  342. control_plane_api/worker/runtimes/claude_code/config.py +829 -0
  343. control_plane_api/worker/runtimes/claude_code/hooks.py +482 -0
  344. control_plane_api/worker/runtimes/claude_code/litellm_proxy.py +1702 -0
  345. control_plane_api/worker/runtimes/claude_code/mcp_builder.py +467 -0
  346. control_plane_api/worker/runtimes/claude_code/mcp_discovery.py +558 -0
  347. control_plane_api/worker/runtimes/claude_code/runtime.py +1546 -0
  348. control_plane_api/worker/runtimes/claude_code/tool_mapper.py +403 -0
  349. control_plane_api/worker/runtimes/claude_code/utils.py +149 -0
  350. control_plane_api/worker/runtimes/factory.py +173 -0
  351. control_plane_api/worker/runtimes/model_utils.py +107 -0
  352. control_plane_api/worker/runtimes/validation.py +93 -0
  353. control_plane_api/worker/services/__init__.py +1 -0
  354. control_plane_api/worker/services/agent_communication_tools.py +908 -0
  355. control_plane_api/worker/services/agent_executor.py +485 -0
  356. control_plane_api/worker/services/agent_executor_v2.py +793 -0
  357. control_plane_api/worker/services/analytics_collector.py +457 -0
  358. control_plane_api/worker/services/analytics_service.py +464 -0
  359. control_plane_api/worker/services/approval_tools.py +310 -0
  360. control_plane_api/worker/services/approval_tools_agno.py +207 -0
  361. control_plane_api/worker/services/cancellation_manager.py +177 -0
  362. control_plane_api/worker/services/code_ingestion_tools.py +465 -0
  363. control_plane_api/worker/services/contextual_awareness_tools.py +405 -0
  364. control_plane_api/worker/services/data_visualization.py +834 -0
  365. control_plane_api/worker/services/event_publisher.py +531 -0
  366. control_plane_api/worker/services/jira_tools.py +257 -0
  367. control_plane_api/worker/services/remote_filesystem_tools.py +498 -0
  368. control_plane_api/worker/services/runtime_analytics.py +328 -0
  369. control_plane_api/worker/services/session_service.py +365 -0
  370. control_plane_api/worker/services/skill_context_enhancement.py +181 -0
  371. control_plane_api/worker/services/skill_factory.py +471 -0
  372. control_plane_api/worker/services/system_prompt_enhancement.py +410 -0
  373. control_plane_api/worker/services/team_executor.py +715 -0
  374. control_plane_api/worker/services/team_executor_v2.py +1866 -0
  375. control_plane_api/worker/services/tool_enforcement.py +254 -0
  376. control_plane_api/worker/services/workflow_executor/__init__.py +52 -0
  377. control_plane_api/worker/services/workflow_executor/event_processor.py +287 -0
  378. control_plane_api/worker/services/workflow_executor/event_publisher.py +210 -0
  379. control_plane_api/worker/services/workflow_executor/executors/__init__.py +15 -0
  380. control_plane_api/worker/services/workflow_executor/executors/base.py +270 -0
  381. control_plane_api/worker/services/workflow_executor/executors/json_executor.py +50 -0
  382. control_plane_api/worker/services/workflow_executor/executors/python_executor.py +50 -0
  383. control_plane_api/worker/services/workflow_executor/models.py +142 -0
  384. control_plane_api/worker/services/workflow_executor_tools.py +1748 -0
  385. control_plane_api/worker/skills/__init__.py +12 -0
  386. control_plane_api/worker/skills/builtin/context_graph_search/README.md +213 -0
  387. control_plane_api/worker/skills/builtin/context_graph_search/__init__.py +5 -0
  388. control_plane_api/worker/skills/builtin/context_graph_search/agno_impl.py +808 -0
  389. control_plane_api/worker/skills/builtin/context_graph_search/skill.yaml +67 -0
  390. control_plane_api/worker/skills/builtin/contextual_awareness/__init__.py +4 -0
  391. control_plane_api/worker/skills/builtin/contextual_awareness/agno_impl.py +62 -0
  392. control_plane_api/worker/skills/builtin/data_visualization/agno_impl.py +18 -0
  393. control_plane_api/worker/skills/builtin/data_visualization/skill.yaml +84 -0
  394. control_plane_api/worker/skills/builtin/docker/agno_impl.py +65 -0
  395. control_plane_api/worker/skills/builtin/docker/skill.yaml +60 -0
  396. control_plane_api/worker/skills/builtin/file_generation/agno_impl.py +47 -0
  397. control_plane_api/worker/skills/builtin/file_generation/skill.yaml +64 -0
  398. control_plane_api/worker/skills/builtin/file_system/agno_impl.py +32 -0
  399. control_plane_api/worker/skills/builtin/file_system/skill.yaml +54 -0
  400. control_plane_api/worker/skills/builtin/knowledge_api/__init__.py +4 -0
  401. control_plane_api/worker/skills/builtin/knowledge_api/agno_impl.py +50 -0
  402. control_plane_api/worker/skills/builtin/knowledge_api/skill.yaml +66 -0
  403. control_plane_api/worker/skills/builtin/python/agno_impl.py +25 -0
  404. control_plane_api/worker/skills/builtin/python/skill.yaml +60 -0
  405. control_plane_api/worker/skills/builtin/schema_fix_mixin.py +260 -0
  406. control_plane_api/worker/skills/builtin/shell/agno_impl.py +31 -0
  407. control_plane_api/worker/skills/builtin/shell/skill.yaml +60 -0
  408. control_plane_api/worker/skills/builtin/slack/__init__.py +3 -0
  409. control_plane_api/worker/skills/builtin/slack/agno_impl.py +1282 -0
  410. control_plane_api/worker/skills/builtin/slack/skill.yaml +276 -0
  411. control_plane_api/worker/skills/builtin/workflow_executor/agno_impl.py +62 -0
  412. control_plane_api/worker/skills/builtin/workflow_executor/skill.yaml +79 -0
  413. control_plane_api/worker/skills/loaders/__init__.py +5 -0
  414. control_plane_api/worker/skills/loaders/base.py +23 -0
  415. control_plane_api/worker/skills/loaders/filesystem_loader.py +357 -0
  416. control_plane_api/worker/skills/registry.py +208 -0
  417. control_plane_api/worker/tests/__init__.py +1 -0
  418. control_plane_api/worker/tests/conftest.py +12 -0
  419. control_plane_api/worker/tests/e2e/__init__.py +0 -0
  420. control_plane_api/worker/tests/e2e/test_context_graph_real_api.py +338 -0
  421. control_plane_api/worker/tests/e2e/test_context_graph_templates_e2e.py +523 -0
  422. control_plane_api/worker/tests/e2e/test_enforcement_e2e.py +344 -0
  423. control_plane_api/worker/tests/e2e/test_execution_flow.py +571 -0
  424. control_plane_api/worker/tests/e2e/test_single_execution_mode.py +656 -0
  425. control_plane_api/worker/tests/integration/__init__.py +0 -0
  426. control_plane_api/worker/tests/integration/test_builtin_skills_fixes.py +245 -0
  427. control_plane_api/worker/tests/integration/test_context_graph_search_integration.py +365 -0
  428. control_plane_api/worker/tests/integration/test_control_plane_integration.py +308 -0
  429. control_plane_api/worker/tests/integration/test_hook_enforcement_integration.py +579 -0
  430. control_plane_api/worker/tests/integration/test_scheduled_job_workflow.py +237 -0
  431. control_plane_api/worker/tests/integration/test_system_prompt_enhancement_integration.py +343 -0
  432. control_plane_api/worker/tests/unit/__init__.py +0 -0
  433. control_plane_api/worker/tests/unit/test_builtin_skill_autoload.py +396 -0
  434. control_plane_api/worker/tests/unit/test_context_graph_search.py +450 -0
  435. control_plane_api/worker/tests/unit/test_context_graph_templates.py +403 -0
  436. control_plane_api/worker/tests/unit/test_control_plane_client.py +401 -0
  437. control_plane_api/worker/tests/unit/test_control_plane_client_jobs.py +345 -0
  438. control_plane_api/worker/tests/unit/test_job_activities.py +353 -0
  439. control_plane_api/worker/tests/unit/test_skill_context_enhancement.py +321 -0
  440. control_plane_api/worker/tests/unit/test_system_prompt_enhancement.py +415 -0
  441. control_plane_api/worker/tests/unit/test_tool_enforcement.py +324 -0
  442. control_plane_api/worker/utils/__init__.py +1 -0
  443. control_plane_api/worker/utils/chunk_batcher.py +330 -0
  444. control_plane_api/worker/utils/environment.py +65 -0
  445. control_plane_api/worker/utils/error_publisher.py +260 -0
  446. control_plane_api/worker/utils/event_batcher.py +256 -0
  447. control_plane_api/worker/utils/logging_config.py +335 -0
  448. control_plane_api/worker/utils/logging_helper.py +326 -0
  449. control_plane_api/worker/utils/parameter_validator.py +120 -0
  450. control_plane_api/worker/utils/retry_utils.py +60 -0
  451. control_plane_api/worker/utils/streaming_utils.py +665 -0
  452. control_plane_api/worker/utils/tool_validation.py +332 -0
  453. control_plane_api/worker/utils/workspace_manager.py +163 -0
  454. control_plane_api/worker/websocket_client.py +393 -0
  455. control_plane_api/worker/worker.py +1297 -0
  456. control_plane_api/worker/workflows/__init__.py +0 -0
  457. control_plane_api/worker/workflows/agent_execution.py +909 -0
  458. control_plane_api/worker/workflows/scheduled_job_wrapper.py +332 -0
  459. control_plane_api/worker/workflows/team_execution.py +611 -0
  460. kubiya_control_plane_api-0.9.15.dist-info/METADATA +354 -0
  461. kubiya_control_plane_api-0.9.15.dist-info/RECORD +479 -0
  462. kubiya_control_plane_api-0.9.15.dist-info/WHEEL +5 -0
  463. kubiya_control_plane_api-0.9.15.dist-info/entry_points.txt +5 -0
  464. kubiya_control_plane_api-0.9.15.dist-info/licenses/LICENSE +676 -0
  465. kubiya_control_plane_api-0.9.15.dist-info/top_level.txt +3 -0
  466. scripts/__init__.py +1 -0
  467. scripts/migrations.py +39 -0
  468. scripts/seed_worker_queues.py +128 -0
  469. scripts/setup_agent_runtime.py +142 -0
  470. worker_internal/__init__.py +1 -0
  471. worker_internal/planner/__init__.py +1 -0
  472. worker_internal/planner/activities.py +1499 -0
  473. worker_internal/planner/agent_tools.py +197 -0
  474. worker_internal/planner/event_models.py +148 -0
  475. worker_internal/planner/event_publisher.py +67 -0
  476. worker_internal/planner/models.py +199 -0
  477. worker_internal/planner/retry_logic.py +134 -0
  478. worker_internal/planner/worker.py +300 -0
  479. worker_internal/planner/workflows.py +970 -0
@@ -0,0 +1,467 @@
1
+ """
2
+ MCP (Model Context Protocol) server builder for Claude Code runtime.
3
+
4
+ This module handles the creation and configuration of MCP servers from
5
+ both external sources and custom skills.
6
+
7
+ The Claude Code SDK automatically:
8
+ - Connects to MCP servers
9
+ - Discovers available tools
10
+ - Names them as mcp__<server_name>__<tool_name>
11
+ - Makes them available to Claude
12
+
13
+ We only need to:
14
+ 1. Validate and format MCP server configs
15
+ 2. Convert custom skills to SDK MCP servers (for custom tools)
16
+ """
17
+
18
+ from typing import Dict, Any, List, Tuple, Optional
19
+ import structlog
20
+ import asyncio
21
+
22
+ logger = structlog.get_logger(__name__)
23
+
24
+
25
+ def _validate_and_normalize_mcp_config(server_name: str, config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
26
+ """
27
+ Validate and normalize MCP server configuration dict.
28
+
29
+ The Claude SDK expects TypedDict configs (McpStdioServerConfig or McpSSEServerConfig).
30
+ These are just dictionaries with specific required/optional fields.
31
+
32
+ Stdio format:
33
+ {
34
+ "command": str, # Required
35
+ "args": list[str], # Optional
36
+ "env": dict[str, str] # Optional
37
+ }
38
+
39
+ SSE format:
40
+ {
41
+ "type": "sse", # Required, must be "sse"
42
+ "url": str, # Required
43
+ "headers": dict[str, str] # Optional
44
+ }
45
+
46
+ Args:
47
+ server_name: Name of the MCP server
48
+ config: Configuration dict from execution environment
49
+
50
+ Returns:
51
+ Validated config dict, or None if invalid
52
+ """
53
+ try:
54
+ # Check if it's stdio transport (has 'command' field)
55
+ if "command" in config:
56
+ command = config.get("command")
57
+ if not command:
58
+ logger.error(
59
+ "stdio_mcp_server_missing_command",
60
+ server_name=server_name,
61
+ config=config
62
+ )
63
+ return None
64
+
65
+ # Build normalized stdio config
66
+ normalized = {
67
+ "command": command,
68
+ }
69
+ if "args" in config:
70
+ normalized["args"] = config["args"]
71
+ if "env" in config:
72
+ normalized["env"] = config["env"]
73
+
74
+ logger.info(
75
+ "validated_stdio_mcp_server",
76
+ server_name=server_name,
77
+ command=command,
78
+ has_args="args" in normalized,
79
+ has_env="env" in normalized
80
+ )
81
+
82
+ # Print detailed config for debugging
83
+ print(f"\n{'='*80}")
84
+ print(f"🔍 STDIO MCP SERVER FULL CONFIG (after template resolution)")
85
+ print(f"{'='*80}")
86
+ print(f"Server Name: {server_name}")
87
+ print(f"Command: {command}")
88
+ if "args" in normalized:
89
+ print(f"Args: {normalized['args']}")
90
+ if "env" in normalized:
91
+ print(f"\nEnvironment Variables:")
92
+ for env_name, env_value in normalized["env"].items():
93
+ # Mask sensitive values
94
+ if any(sensitive in env_name.lower() for sensitive in ["key", "token", "auth", "secret", "password"]):
95
+ masked_value = env_value[:20] + "..." if len(env_value) > 20 else "***"
96
+ print(f" {env_name}: {masked_value} (length: {len(env_value)})")
97
+ else:
98
+ print(f" {env_name}: {env_value}")
99
+ print(f"{'='*80}\n")
100
+
101
+ return normalized
102
+
103
+ # Check if it's HTTP/SSE transport (has 'type'/'transport_type' and 'url' fields)
104
+ # Support both 'type' and 'transport_type' for backward compatibility
105
+ elif ("type" in config or "transport_type" in config) and "url" in config:
106
+ transport_type = config.get("type") or config.get("transport_type")
107
+ url = config.get("url")
108
+
109
+ if not url:
110
+ logger.error(
111
+ "http_sse_mcp_server_missing_url",
112
+ server_name=server_name,
113
+ transport_type=transport_type,
114
+ config=config
115
+ )
116
+ return None
117
+
118
+ # Validate transport type
119
+ if transport_type not in ("sse", "http"):
120
+ logger.error(
121
+ "unsupported_mcp_transport_type",
122
+ server_name=server_name,
123
+ transport_type=transport_type,
124
+ supported=["sse", "http"]
125
+ )
126
+ return None
127
+
128
+ # Build normalized config - preserve transport type!
129
+ # HTTP = recommended (native Claude SDK support, bidirectional)
130
+ # SSE = deprecated (requires workaround, unidirectional)
131
+ normalized = {
132
+ "type": transport_type, # Keep original: "http" or "sse"
133
+ "url": url,
134
+ }
135
+ if "headers" in config:
136
+ normalized["headers"] = config["headers"]
137
+
138
+ # Log full configuration including headers for debugging
139
+ logger.info(
140
+ "validated_http_mcp_server",
141
+ server_name=server_name,
142
+ transport=transport_type,
143
+ url=url,
144
+ has_headers="headers" in normalized,
145
+ )
146
+
147
+ # Print detailed config for debugging
148
+ transport_label = "HTTP" if transport_type == "http" else "SSE (DEPRECATED)"
149
+ print(f"\n{'='*80}")
150
+ print(f"🔍 {transport_label} MCP SERVER FULL CONFIG (after template resolution)")
151
+ print(f"{'='*80}")
152
+ print(f"Server Name: {server_name}")
153
+ print(f"Transport: {transport_type}")
154
+ print(f"URL: {url}")
155
+ if "headers" in normalized:
156
+ print(f"\nHeaders:")
157
+ for header_name, header_value in normalized["headers"].items():
158
+ # Mask sensitive values but show structure
159
+ if any(sensitive in header_name.lower() for sensitive in ["key", "token", "auth", "secret"]):
160
+ masked_value = header_value[:20] + "..." if len(header_value) > 20 else "***"
161
+ print(f" {header_name}: {masked_value} (length: {len(header_value)})")
162
+ else:
163
+ print(f" {header_name}: {header_value}")
164
+ else:
165
+ print(f"\nHeaders: (none)")
166
+ print(f"{'='*80}\n")
167
+
168
+ return normalized
169
+
170
+ else:
171
+ logger.error(
172
+ "invalid_mcp_server_config_format",
173
+ server_name=server_name,
174
+ config=config,
175
+ error="Must have either 'command' (stdio) or 'type'+'url' (SSE/HTTP)"
176
+ )
177
+ return None
178
+
179
+ except Exception as e:
180
+ logger.error(
181
+ "mcp_config_validation_error",
182
+ server_name=server_name,
183
+ error=str(e),
184
+ exc_info=True
185
+ )
186
+ return None
187
+
188
+
189
+ def extract_mcp_tool_names(
190
+ server_name: str,
191
+ server_obj: Any,
192
+ explicit_tools: Optional[List[str]] = None
193
+ ) -> List[str]:
194
+ """
195
+ Extract MCP tool names from server object.
196
+
197
+ ⚠️ Note: This function is kept for backward compatibility but isn't used
198
+ in the main flow. Tool discovery is handled by discover_all_mcp_resources()
199
+ in mcp_discovery.py as a workaround for Claude SDK bug #3426.
200
+
201
+ Args:
202
+ server_name: Name of the MCP server
203
+ server_obj: MCP server object
204
+ explicit_tools: Optional list of tool names
205
+
206
+ Returns:
207
+ Empty list (discovery handled in mcp_discovery.py)
208
+ """
209
+ logger.debug(
210
+ "extract_mcp_tool_names_skipped",
211
+ server_name=server_name,
212
+ message="Tool extraction handled by mcp_discovery.py pre-discovery"
213
+ )
214
+
215
+ # Return empty list - discovery handled elsewhere
216
+ return []
217
+
218
+
219
+ def build_mcp_servers(
220
+ skills: List[Any],
221
+ context_mcp_servers: Dict[str, Any] = None,
222
+ mcp_tools_config: Optional[Dict[str, List[str]]] = None
223
+ ) -> Tuple[Dict[str, Any], List[str]]:
224
+ """
225
+ Build MCP server configurations from context and custom skills.
226
+
227
+ This function:
228
+ 1. Validates and formats external MCP server configs (stdio/SSE)
229
+ 2. Converts custom skills to SDK MCP servers (for custom tools)
230
+
231
+ ⚠️ Note about tool discovery:
232
+ The Claude SDK has a bug (#3426) where it doesn't properly expose SSE MCP tools.
233
+ Tool discovery is handled separately in config.py via discover_all_mcp_resources()
234
+ which pre-discovers tools and adds them to allowedTools as a workaround.
235
+
236
+ Args:
237
+ skills: List of skill objects to convert to MCP servers
238
+ context_mcp_servers: Optional MCP servers from execution context (as config dicts)
239
+ mcp_tools_config: Optional dict mapping server_name -> list of tool names (not used)
240
+
241
+ Returns:
242
+ Tuple of (MCP server configurations dict, empty list)
243
+ Note: Second return value is always empty - tool discovery handled in config.py
244
+ """
245
+ if mcp_tools_config is None:
246
+ mcp_tools_config = {}
247
+ from claude_agent_sdk import create_sdk_mcp_server, tool as mcp_tool
248
+
249
+ # DEBUG: Log what we received
250
+ print(f"\n🔍 DEBUG: build_mcp_servers() INPUTS:")
251
+ print(f" context_mcp_servers type: {type(context_mcp_servers)}")
252
+ print(f" context_mcp_servers value: {context_mcp_servers}")
253
+ print(f" context_mcp_servers count: {len(context_mcp_servers) if context_mcp_servers else 0}")
254
+ if context_mcp_servers:
255
+ print(f" Server names from context: {list(context_mcp_servers.keys())}")
256
+ print()
257
+
258
+ mcp_servers = {}
259
+
260
+ # Include MCP servers from context (if any)
261
+ if context_mcp_servers:
262
+ logger.info(
263
+ "processing_mcp_servers_from_context",
264
+ server_count=len(context_mcp_servers),
265
+ server_names=list(context_mcp_servers.keys()),
266
+ note="SDK will discover tools automatically from these servers"
267
+ )
268
+
269
+ for server_name, server_config in context_mcp_servers.items():
270
+ logger.debug(
271
+ "processing_mcp_server_from_context",
272
+ server_name=server_name,
273
+ config_keys=list(server_config.keys()) if isinstance(server_config, dict) else "not_dict",
274
+ has_command="command" in server_config if isinstance(server_config, dict) else False,
275
+ has_type="type" in server_config if isinstance(server_config, dict) else False,
276
+ has_url="url" in server_config if isinstance(server_config, dict) else False,
277
+ )
278
+ # Validate and normalize config dict (already in Claude SDK TypedDict format)
279
+ normalized_config = _validate_and_normalize_mcp_config(server_name, server_config)
280
+ if normalized_config:
281
+ mcp_servers[server_name] = normalized_config
282
+ transport = normalized_config.get("type", "stdio") if "type" in normalized_config else "stdio"
283
+ logger.info(
284
+ "mcp_server_configured",
285
+ server_name=server_name,
286
+ transport=transport,
287
+ note="SDK will connect and discover tools automatically" if transport == "http"
288
+ else "SDK will connect (pre-discovery may be needed for SSE)" if transport == "sse"
289
+ else "SDK will connect and discover tools automatically"
290
+ )
291
+ else:
292
+ logger.warning(
293
+ "skipping_mcp_server_invalid_config",
294
+ server_name=server_name,
295
+ config=server_config
296
+ )
297
+ continue
298
+
299
+ # Convert custom skills to MCP servers
300
+ for skill in skills:
301
+ tools_list = []
302
+ registered_tool_names = [] # Track tool names for logging
303
+ skill_name = getattr(skill, "name", "custom_skill")
304
+
305
+ # Check for Toolkit pattern (has .functions attribute)
306
+ if hasattr(skill, "functions") and hasattr(skill.functions, "items"):
307
+ logger.info(
308
+ "found_skill_with_registered_functions",
309
+ skill_name=skill_name,
310
+ function_count=len(skill.functions),
311
+ function_names=list(skill.functions.keys()),
312
+ )
313
+
314
+ # Extract tools from functions registry
315
+ for func_name, func_obj in skill.functions.items():
316
+ # Skip helper tools for workflow_executor skills to avoid confusion
317
+ if func_name in ["list_all_workflows", "get_workflow_info"]:
318
+ logger.debug(
319
+ "skipping_helper_tool_for_workflow_executor",
320
+ skill_name=skill_name,
321
+ tool_name=func_name,
322
+ )
323
+ continue
324
+
325
+ # Get entrypoint (the actual callable)
326
+ entrypoint = getattr(func_obj, "entrypoint", None)
327
+ if not entrypoint:
328
+ logger.warning(
329
+ "function_missing_entrypoint",
330
+ skill_name=skill_name,
331
+ function_name=func_name,
332
+ )
333
+ continue
334
+
335
+ # Get function metadata - use function name as-is
336
+ tool_name = func_name
337
+ tool_description = (
338
+ getattr(func_obj, "description", None)
339
+ or entrypoint.__doc__
340
+ or f"{tool_name} tool"
341
+ )
342
+ tool_parameters = getattr(func_obj, "parameters", {})
343
+
344
+ # Create a closure that captures the entrypoint with proper variable scope
345
+ def make_tool_wrapper(
346
+ tool_entrypoint,
347
+ tool_func_name,
348
+ tool_func_description,
349
+ tool_func_parameters,
350
+ ):
351
+ """Factory to create tool wrappers with proper closure"""
352
+
353
+ @mcp_tool(tool_func_name, tool_func_description, tool_func_parameters)
354
+ async def wrapped_tool(args: dict) -> dict:
355
+ try:
356
+ logger.debug(
357
+ "executing_builtin_skill_tool",
358
+ tool_name=tool_func_name,
359
+ args=args,
360
+ )
361
+ # Call the entrypoint with unpacked args
362
+ if asyncio.iscoroutinefunction(tool_entrypoint):
363
+ result = (
364
+ await tool_entrypoint(**args)
365
+ if args
366
+ else await tool_entrypoint()
367
+ )
368
+ else:
369
+ # Run synchronous tools in thread pool to avoid blocking
370
+ result = await asyncio.to_thread(
371
+ lambda: tool_entrypoint(**args)
372
+ if args
373
+ else tool_entrypoint()
374
+ )
375
+
376
+ logger.info(
377
+ "builtin_skill_tool_completed",
378
+ tool_name=tool_func_name,
379
+ result_length=len(str(result)),
380
+ )
381
+
382
+ return {
383
+ "content": [{"type": "text", "text": str(result)}]
384
+ }
385
+ except Exception as e:
386
+ logger.error(
387
+ "builtin_skill_tool_execution_failed",
388
+ tool_name=tool_func_name,
389
+ error=str(e),
390
+ exc_info=True,
391
+ )
392
+ return {
393
+ "content": [
394
+ {
395
+ "type": "text",
396
+ "text": f"Error executing {tool_func_name}: {str(e)}",
397
+ }
398
+ ],
399
+ "isError": True,
400
+ }
401
+
402
+ return wrapped_tool
403
+
404
+ wrapped_tool = make_tool_wrapper(
405
+ entrypoint, tool_name, tool_description, tool_parameters
406
+ )
407
+ tools_list.append(wrapped_tool)
408
+ registered_tool_names.append(tool_name)
409
+
410
+ logger.info(
411
+ "registered_mcp_tool_from_skill_function",
412
+ skill_name=skill_name,
413
+ tool_name=tool_name,
414
+ full_mcp_tool_name=f"mcp__{skill_name}__{tool_name}",
415
+ note="SDK will make this available automatically"
416
+ )
417
+
418
+ # Legacy: Check if skill has get_tools() method
419
+ elif hasattr(skill, "get_tools"):
420
+ for tool_func in skill.get_tools():
421
+ # Wrap each tool function with MCP tool decorator
422
+ tool_name = getattr(tool_func, "__name__", "custom_tool")
423
+ tool_description = getattr(tool_func, "__doc__", f"{tool_name} tool")
424
+
425
+ # Create MCP tool wrapper
426
+ @mcp_tool(tool_name, tool_description, {})
427
+ async def wrapped_tool(args: dict) -> dict:
428
+ # Run synchronous tools in thread pool to avoid blocking
429
+ if asyncio.iscoroutinefunction(tool_func):
430
+ result = (
431
+ await tool_func(**args) if args else await tool_func()
432
+ )
433
+ else:
434
+ result = await asyncio.to_thread(
435
+ lambda: tool_func(**args) if args else tool_func()
436
+ )
437
+ return {"content": [{"type": "text", "text": str(result)}]}
438
+
439
+ tools_list.append(wrapped_tool)
440
+ registered_tool_names.append(tool_name)
441
+
442
+ # Create MCP server for this skill if it has tools
443
+ if tools_list:
444
+ server_name = skill_name
445
+
446
+ mcp_servers[server_name] = create_sdk_mcp_server(
447
+ name=server_name, version="1.0.0", tools=tools_list
448
+ )
449
+
450
+ logger.info(
451
+ "created_mcp_server_for_skill",
452
+ skill_name=skill_name,
453
+ server_name=server_name,
454
+ tool_count=len(tools_list),
455
+ tool_names=registered_tool_names,
456
+ note="SDK will make these tools available as mcp__<server>__<tool>"
457
+ )
458
+
459
+ logger.info(
460
+ "built_mcp_servers",
461
+ server_count=len(mcp_servers),
462
+ servers=list(mcp_servers.keys()),
463
+ note="SDK will discover and provide all tools automatically - no manual intervention needed"
464
+ )
465
+
466
+ # Return empty list for tool names - SDK discovers them automatically
467
+ return mcp_servers, []