legate 0.1.0

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 (317) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +345 -0
  4. data/bin/legate +13 -0
  5. data/examples/00_quickstart.rb +51 -0
  6. data/examples/01_simple_agent.rb +105 -0
  7. data/examples/02_multi_tool_agent.rb +140 -0
  8. data/examples/03_custom_tool.rb +93 -0
  9. data/examples/04_agent_instructions.rb +84 -0
  10. data/examples/05_state_and_sessions.rb +91 -0
  11. data/examples/06_callbacks.rb +186 -0
  12. data/examples/07_async_jobs.rb +112 -0
  13. data/examples/08_loop_agent.rb +197 -0
  14. data/examples/09_sequential_workflow.rb +40 -0
  15. data/examples/10_parallel_workflow.rb +34 -0
  16. data/examples/11_agent_delegation.rb +24 -0
  17. data/examples/12_http_client_tool.rb +156 -0
  18. data/examples/13_authentication.rb +220 -0
  19. data/examples/14_mcp_client.rb +154 -0
  20. data/examples/15_mcp_server.rb +79 -0
  21. data/examples/16_webhooks.rb +91 -0
  22. data/examples/README_sequential_agents.md +164 -0
  23. data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
  24. data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
  25. data/examples/advanced/auth/excon_middleware.rb +317 -0
  26. data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
  27. data/examples/advanced/auth/fiber_auth_example.rb +281 -0
  28. data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
  29. data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
  30. data/examples/advanced/auth/oauth2_auth.rb +419 -0
  31. data/examples/advanced/auth/oidc_auth.rb +514 -0
  32. data/examples/advanced/auth/openweather_api.rb +251 -0
  33. data/examples/advanced/auth/openweather_tool.rb +153 -0
  34. data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
  35. data/examples/advanced/auth/service_account.rb +135 -0
  36. data/examples/advanced/auth/test_with_httpbin.rb +202 -0
  37. data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
  38. data/examples/advanced/callback_monitoring.rb +679 -0
  39. data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
  40. data/examples/advanced/mas/loop_workflow.rb +28 -0
  41. data/examples/advanced/mas/mock_planner.rb +77 -0
  42. data/examples/advanced/mas/proper_delegation_example.rb +276 -0
  43. data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
  44. data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
  45. data/examples/advanced/mcp/mcp_server_async.rb +76 -0
  46. data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
  47. data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
  48. data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
  49. data/examples/advanced/random_calculator.rb +104 -0
  50. data/examples/advanced/sleep_agent.rb +153 -0
  51. data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
  52. data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
  53. data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
  54. data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
  55. data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
  56. data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
  57. data/examples/tools/oauth2_example.rb +136 -0
  58. data/examples/tools/sleepy_tool.rb +42 -0
  59. data/lib/legate/activity_log.rb +71 -0
  60. data/lib/legate/agent.rb +959 -0
  61. data/lib/legate/agent_code_generator.rb +185 -0
  62. data/lib/legate/agent_definition.rb +812 -0
  63. data/lib/legate/agentic/decision.rb +49 -0
  64. data/lib/legate/agentic/loop.rb +134 -0
  65. data/lib/legate/agentic.rb +5 -0
  66. data/lib/legate/agents/loop_agent.rb +248 -0
  67. data/lib/legate/agents/parallel_agent.rb +163 -0
  68. data/lib/legate/agents/sequential_agent.rb +190 -0
  69. data/lib/legate/agents.rb +14 -0
  70. data/lib/legate/auth/config.rb +148 -0
  71. data/lib/legate/auth/coordinator.rb +218 -0
  72. data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
  73. data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
  74. data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
  75. data/lib/legate/auth/credential.rb +157 -0
  76. data/lib/legate/auth/encryption.rb +108 -0
  77. data/lib/legate/auth/error.rb +94 -0
  78. data/lib/legate/auth/exchanged_credential.rb +180 -0
  79. data/lib/legate/auth/excon_middleware.rb +285 -0
  80. data/lib/legate/auth/http_client_utils.rb +364 -0
  81. data/lib/legate/auth/manager.rb +531 -0
  82. data/lib/legate/auth/manager_store.rb +394 -0
  83. data/lib/legate/auth/middleware_factory.rb +290 -0
  84. data/lib/legate/auth/runner.rb +279 -0
  85. data/lib/legate/auth/scheme.rb +125 -0
  86. data/lib/legate/auth/schemes/api_key.rb +212 -0
  87. data/lib/legate/auth/schemes/google_service_account.rb +108 -0
  88. data/lib/legate/auth/schemes/http_bearer.rb +98 -0
  89. data/lib/legate/auth/schemes/oauth2.rb +396 -0
  90. data/lib/legate/auth/schemes/openid_connect.rb +346 -0
  91. data/lib/legate/auth/schemes/service_account.rb +388 -0
  92. data/lib/legate/auth/schemes.rb +40 -0
  93. data/lib/legate/auth/token_manager.rb +362 -0
  94. data/lib/legate/auth/token_store.rb +86 -0
  95. data/lib/legate/auth/tool_context_extension.rb +97 -0
  96. data/lib/legate/auth/tool_integration.rb +188 -0
  97. data/lib/legate/auth/url_guard.rb +81 -0
  98. data/lib/legate/auth.rb +453 -0
  99. data/lib/legate/callbacks/callback_context.rb +71 -0
  100. data/lib/legate/cli/agent_commands.rb +950 -0
  101. data/lib/legate/cli/auth_commands.rb +520 -0
  102. data/lib/legate/cli/base_command.rb +24 -0
  103. data/lib/legate/cli/deployment_commands.rb +934 -0
  104. data/lib/legate/cli/output_helper.rb +108 -0
  105. data/lib/legate/cli/session_commands.rb +138 -0
  106. data/lib/legate/cli/skaffold_commands.rb +223 -0
  107. data/lib/legate/cli/tool_commands.rb +261 -0
  108. data/lib/legate/cli/web_commands.rb +182 -0
  109. data/lib/legate/cli.rb +40 -0
  110. data/lib/legate/configuration/webhooks.rb +113 -0
  111. data/lib/legate/configuration.rb +39 -0
  112. data/lib/legate/definition_store.rb +23 -0
  113. data/lib/legate/errors.rb +118 -0
  114. data/lib/legate/event.rb +161 -0
  115. data/lib/legate/gemini_ai_beta_patch.rb +39 -0
  116. data/lib/legate/generators/agent_generator.rb +412 -0
  117. data/lib/legate/generators/code_validator.rb +48 -0
  118. data/lib/legate/generators/legate/install_generator.rb +35 -0
  119. data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
  120. data/lib/legate/generators/legate/templates/initializer.rb +18 -0
  121. data/lib/legate/generators/runtime_tool_loader.rb +76 -0
  122. data/lib/legate/generators/tool_generator.rb +408 -0
  123. data/lib/legate/generators.rb +11 -0
  124. data/lib/legate/global_definition_registry.rb +506 -0
  125. data/lib/legate/global_tool_manager.rb +135 -0
  126. data/lib/legate/llm/adapter.rb +69 -0
  127. data/lib/legate/llm/gemini.rb +172 -0
  128. data/lib/legate/llm/ollama.rb +80 -0
  129. data/lib/legate/llm.rb +34 -0
  130. data/lib/legate/mcp/client.rb +320 -0
  131. data/lib/legate/mcp/connection/sse.rb +292 -0
  132. data/lib/legate/mcp/connection/stdio.rb +273 -0
  133. data/lib/legate/mcp/connection_manager.rb +103 -0
  134. data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
  135. data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
  136. data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
  137. data/lib/legate/mcp/tool_wrapper.rb +138 -0
  138. data/lib/legate/mcp/util/schema_converter.rb +134 -0
  139. data/lib/legate/mcp.rb +23 -0
  140. data/lib/legate/plan_executor.rb +375 -0
  141. data/lib/legate/planner.rb +839 -0
  142. data/lib/legate/rails/railtie.rb +43 -0
  143. data/lib/legate/rails.rb +9 -0
  144. data/lib/legate/redaction.rb +32 -0
  145. data/lib/legate/session.rb +299 -0
  146. data/lib/legate/session_service/active_record.rb +300 -0
  147. data/lib/legate/session_service/base.rb +68 -0
  148. data/lib/legate/session_service/event_broadcast.rb +74 -0
  149. data/lib/legate/session_service/in_memory.rb +188 -0
  150. data/lib/legate/tool/metadata_dsl.rb +122 -0
  151. data/lib/legate/tool.rb +276 -0
  152. data/lib/legate/tool_code_generator.rb +103 -0
  153. data/lib/legate/tool_context.rb +350 -0
  154. data/lib/legate/tool_loader.rb +39 -0
  155. data/lib/legate/tool_registry.rb +73 -0
  156. data/lib/legate/tool_result.rb +61 -0
  157. data/lib/legate/tools/agent_tool.rb +187 -0
  158. data/lib/legate/tools/base/http_client.rb +319 -0
  159. data/lib/legate/tools/base/safe_url.rb +56 -0
  160. data/lib/legate/tools/base_async_job_tool.rb +91 -0
  161. data/lib/legate/tools/calculator.rb +89 -0
  162. data/lib/legate/tools/cat_facts.rb +81 -0
  163. data/lib/legate/tools/check_job_status_tool.rb +48 -0
  164. data/lib/legate/tools/current_time_tool.rb +64 -0
  165. data/lib/legate/tools/echo.rb +43 -0
  166. data/lib/legate/tools/http_request_tool.rb +105 -0
  167. data/lib/legate/tools/random_number_tool.rb +64 -0
  168. data/lib/legate/tools/read_webpage_tool.rb +92 -0
  169. data/lib/legate/tools/sleepy_tool.rb +74 -0
  170. data/lib/legate/tools/webhook_tool.rb +146 -0
  171. data/lib/legate/version.rb +5 -0
  172. data/lib/legate/web/app.rb +984 -0
  173. data/lib/legate/web/public/css/main.css +4980 -0
  174. data/lib/legate/web/public/images/favicon-256.png +0 -0
  175. data/lib/legate/web/public/images/favicon-32.png +0 -0
  176. data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
  177. data/lib/legate/web/public/images/legate-logo-light.png +0 -0
  178. data/lib/legate/web/public/js/legate.js +616 -0
  179. data/lib/legate/web/public/styles/main.scss +4402 -0
  180. data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
  181. data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
  182. data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
  183. data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
  184. data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
  185. data/lib/legate/web/routes/api_routes.rb +56 -0
  186. data/lib/legate/web/routes/authentication_routes.rb +1541 -0
  187. data/lib/legate/web/routes/core_routes.rb +111 -0
  188. data/lib/legate/web/routes/documentation_routes.rb +220 -0
  189. data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
  190. data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
  191. data/lib/legate/web/sass_compiler.rb +73 -0
  192. data/lib/legate/web/views/_active_session_info.slim +25 -0
  193. data/lib/legate/web/views/_activity_list.slim +55 -0
  194. data/lib/legate/web/views/_agent_card.slim +56 -0
  195. data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
  196. data/lib/legate/web/views/_agent_status_controls.slim +71 -0
  197. data/lib/legate/web/views/_agent_tool_table.slim +74 -0
  198. data/lib/legate/web/views/_chat_message.slim +95 -0
  199. data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
  200. data/lib/legate/web/views/_display_agent_description.slim +11 -0
  201. data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
  202. data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
  203. data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
  204. data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
  205. data/lib/legate/web/views/_display_agent_model.slim +17 -0
  206. data/lib/legate/web/views/_display_agent_name.slim +42 -0
  207. data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
  208. data/lib/legate/web/views/_display_agent_type.slim +65 -0
  209. data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
  210. data/lib/legate/web/views/_edit_agent_description.slim +16 -0
  211. data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
  212. data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
  213. data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
  214. data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
  215. data/lib/legate/web/views/_edit_agent_model.slim +23 -0
  216. data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
  217. data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
  218. data/lib/legate/web/views/_edit_agent_type.slim +67 -0
  219. data/lib/legate/web/views/_session_error.slim +4 -0
  220. data/lib/legate/web/views/_skeleton.slim +69 -0
  221. data/lib/legate/web/views/_tool_card.slim +9 -0
  222. data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
  223. data/lib/legate/web/views/agent.slim +436 -0
  224. data/lib/legate/web/views/agent_auth.slim +562 -0
  225. data/lib/legate/web/views/agents.slim +369 -0
  226. data/lib/legate/web/views/auth.slim +112 -0
  227. data/lib/legate/web/views/auth_credential_detail.slim +327 -0
  228. data/lib/legate/web/views/auth_credentials.slim +261 -0
  229. data/lib/legate/web/views/auth_debug.slim +94 -0
  230. data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
  231. data/lib/legate/web/views/auth_mapping_new.slim +123 -0
  232. data/lib/legate/web/views/auth_mappings.slim +120 -0
  233. data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
  234. data/lib/legate/web/views/auth_schemes.slim +259 -0
  235. data/lib/legate/web/views/auth_test.slim +418 -0
  236. data/lib/legate/web/views/chat.slim +192 -0
  237. data/lib/legate/web/views/docs_index.slim +105 -0
  238. data/lib/legate/web/views/docs_show.slim +105 -0
  239. data/lib/legate/web/views/error_404.slim +5 -0
  240. data/lib/legate/web/views/index.slim +148 -0
  241. data/lib/legate/web/views/layout.slim +144 -0
  242. data/lib/legate/web/views/tool_detail.slim +87 -0
  243. data/lib/legate/web/views/tools.slim +50 -0
  244. data/lib/legate/web/webhook_listener.rb +367 -0
  245. data/lib/legate/web.rb +9 -0
  246. data/lib/legate.rb +220 -0
  247. data/public/docs/advanced/callbacks.md +828 -0
  248. data/public/docs/advanced/mcp_schema_conversion.md +59 -0
  249. data/public/docs/authentication/api_reference/config.md +210 -0
  250. data/public/docs/authentication/api_reference/credential.md +246 -0
  251. data/public/docs/authentication/api_reference/encryption.md +218 -0
  252. data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
  253. data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
  254. data/public/docs/authentication/api_reference/index.md +30 -0
  255. data/public/docs/authentication/api_reference/scheme.md +250 -0
  256. data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
  257. data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
  258. data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
  259. data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
  260. data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
  261. data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
  262. data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
  263. data/public/docs/authentication/api_reference/token_manager.md +221 -0
  264. data/public/docs/authentication/api_reference/token_store.md +146 -0
  265. data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
  266. data/public/docs/authentication/guides/api_key.md +190 -0
  267. data/public/docs/authentication/guides/bearer.md +172 -0
  268. data/public/docs/authentication/guides/configuration.md +255 -0
  269. data/public/docs/authentication/guides/custom_flow.md +523 -0
  270. data/public/docs/authentication/guides/index.md +24 -0
  271. data/public/docs/authentication/guides/migration.md +435 -0
  272. data/public/docs/authentication/guides/oauth2.md +252 -0
  273. data/public/docs/authentication/guides/oidc.md +241 -0
  274. data/public/docs/authentication/guides/overview.md +155 -0
  275. data/public/docs/authentication/guides/secure_storage.md +301 -0
  276. data/public/docs/authentication/guides/service_account.md +228 -0
  277. data/public/docs/authentication/guides/token_lifecycle.md +295 -0
  278. data/public/docs/authentication/guides/web_ui_integration.md +504 -0
  279. data/public/docs/authentication/index.md +58 -0
  280. data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
  281. data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
  282. data/public/docs/authentication/troubleshooting/index.md +11 -0
  283. data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
  284. data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
  285. data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
  286. data/public/docs/cli/legate_cli_usage.md +363 -0
  287. data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
  288. data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
  289. data/public/docs/core_concepts/legate_configuration.md +116 -0
  290. data/public/docs/core_concepts/legate_definition_store.md +102 -0
  291. data/public/docs/core_concepts/legate_planner.md +94 -0
  292. data/public/docs/core_concepts/legate_session_service.md +104 -0
  293. data/public/docs/error_handling/legate_error_handling.md +122 -0
  294. data/public/docs/examples.md +199 -0
  295. data/public/docs/getting_started.md +111 -0
  296. data/public/docs/guides/agentic_agents.md +137 -0
  297. data/public/docs/guides/ai_code_generators.md +437 -0
  298. data/public/docs/guides/auto_loading.md +326 -0
  299. data/public/docs/guides/configuring_agent_webhooks.md +219 -0
  300. data/public/docs/guides/http_client_usage.md +264 -0
  301. data/public/docs/guides/llm_providers.md +137 -0
  302. data/public/docs/guides/mcp_client_integration.md +232 -0
  303. data/public/docs/guides/mcp_server_exposure.md +206 -0
  304. data/public/docs/guides/rails_integration.md +128 -0
  305. data/public/docs/guides/sending_outbound_webhooks.md +227 -0
  306. data/public/docs/guides/streaming.md +112 -0
  307. data/public/docs/guides/webhooks.md +288 -0
  308. data/public/docs/introduction.md +51 -0
  309. data/public/docs/multi_agent_systems/advanced_features.md +57 -0
  310. data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
  311. data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
  312. data/public/docs/multi_agent_systems/state_management.md +47 -0
  313. data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
  314. data/public/docs/tools/legate_built_in_tools.md +332 -0
  315. data/public/docs/tools/legate_tools_and_registry.md +263 -0
  316. data/public/docs/web_ui/legate_web_ui.md +137 -0
  317. metadata +823 -0
@@ -0,0 +1,59 @@
1
+ # MCP Schema Conversion Details
2
+
3
+ This document details the automatic conversion processes between the different schema formats used by Legate, the Model Context Protocol (MCP), and the `fast-mcp` gem. Understanding this is helpful when defining tools or troubleshooting integration issues.
4
+
5
+ ## Formats
6
+
7
+ * **Legate Parameters:** Defined within a `Legate::Tool` subclass using the `parameter` DSL (with `tool_description` for the description). Internally these are stored as a Ruby hash like:
8
+ ```ruby
9
+ {
10
+ param_name: {
11
+ type: :symbol, # :string, :integer, :numeric, :boolean, :array, :hash
12
+ required: boolean,
13
+ description: string
14
+ },
15
+ # ...
16
+ }
17
+ ```
18
+ * **MCP JSON Schema:** Standard JSON Schema objects used in MCP `tools/list` (`inputSchema`) and `resources/list` (`schema`).
19
+ ```json
20
+ {
21
+ "type": "object",
22
+ "properties": {
23
+ "param_name": { "type": "string", "description": "..." }
24
+ },
25
+ "required": ["param_name"]
26
+ }
27
+ ```
28
+ * **Dry::Schema:** Used by `fast-mcp` within the `arguments` block to define and validate tool parameters.
29
+ ```ruby
30
+ arguments do
31
+ required(:param_name).filled(:string).description("...")
32
+ end
33
+ ```
34
+
35
+ ## Conversion Flows
36
+
37
+ ### 1. MCP JSON Schema -> Legate Params
38
+
39
+ * **Where:** Done by `Legate::Mcp::ToolWrapper.from_mcp_schema` using `Legate::Mcp::Util::SchemaConverter.json_to_legate`.
40
+ * **Use Case:** When an Legate Agent connects to an external MCP server and discovers its tools (Client Mode).
41
+ * **Mapping (V1):** Basic types (`string`, `integer`, `number`, `boolean`) are mapped to corresponding Legate types (`:string`, `:integer`, `:numeric`, `:boolean`). `required` status and `description` are preserved.
42
+ * **Limitations (V1):** Complex types (`object`, `array`), constraints (`minLength`, `enum`, `format` etc.) are **ignored** during conversion. Only the basic type, requirement, and description are used.
43
+
44
+ ### 2. Legate Params -> Dry::Schema
45
+
46
+ * **Where:** Done by `Legate::Mcp::Server::LegateToolAdapter.wrap` using `Legate::Mcp::Util::SchemaConverter.legate_to_dry_schema`.
47
+ * **Use Case:** When exposing an `Legate::Tool` via `fast-mcp` (Server Mode).
48
+ * **Mapping (V1):** Basic Legate types (`:string`, `:integer`, `:numeric`, `:boolean`) are mapped to appropriate `Dry::Schema` calls (`filled(:string)`, `filled(:integer)`, `filled(Dry::Types['coercible.float'])`, `filled(:bool)`). `:required` status maps to `required()` or `optional()`.
49
+ * **Limitations (V1):** Legate types `:array`, `:hash`, `:object` receive basic mappings (`value(:array)`, `value(:hash)`) **without** nested schema validation. Parameter descriptions from Legate metadata are **not** added to the Dry::Schema block itself (they are set separately on the `fast-mcp` tool using `description` DSL by the adapter).
50
+
51
+ ### 3. Legate Params -> JSON for MCP Call (Client)
52
+
53
+ * **Where:** Inside `Legate::Mcp::ToolWrapper#perform_execution`.
54
+ * **Use Case:** When an Legate Agent executes an external MCP tool.
55
+ * **Mapping (V1):** Simple conversion of the Legate params hash (symbol keys) to a JSON hash (string keys). Assumes a flat structure.
56
+
57
+ ## Key Takeaway
58
+
59
+ For V1, schema conversion primarily supports basic data types and required fields. Complex nested structures or validation rules defined in one system may not be fully enforced or represented when crossing the Legate <-> MCP boundary.
@@ -0,0 +1,210 @@
1
+ # Legate::Auth::Config
2
+
3
+ The `Config` class represents the configuration for interactive authentication flows. It includes all the necessary information to initiate, track, and complete an authentication process that requires user interaction.
4
+
5
+ ## Overview
6
+
7
+ In interactive authentication flows like OAuth2 or OpenID Connect, the user needs to be redirected to an authentication provider to authenticate and grant permissions. The `Config` class encapsulates all the details needed for this interaction, including the scheme, credential, redirect URI, and callback handling.
8
+
9
+ ## Class Methods
10
+
11
+ ### `new`
12
+
13
+ Creates a new authentication configuration instance.
14
+
15
+ **Parameters:**
16
+ - `scheme` (Legate::Auth::Scheme): The authentication scheme to use
17
+ - `credential` (Legate::Auth::Credential): The credential for the authentication flow
18
+ - `auth_request_id` (String, optional): A unique identifier for this authentication request (default: nil)
19
+ - `options` (Hash, optional): Additional configuration options (default: {})
20
+
21
+ **Examples:**
22
+
23
+ ```ruby
24
+ # Create a basic authentication configuration
25
+ config = Legate::Auth::Config.new(
26
+ scheme: oauth2_scheme,
27
+ credential: oauth2_credential
28
+ )
29
+
30
+ # With an explicit request ID and options
31
+ config = Legate::Auth::Config.new(
32
+ scheme: oauth2_scheme,
33
+ credential: oauth2_credential,
34
+ auth_request_id: 'req_123456',
35
+ options: { prompt: 'consent' }
36
+ )
37
+ ```
38
+
39
+ ### `from_h`
40
+
41
+ Creates a Config instance from a hash representation.
42
+
43
+ **Parameters:**
44
+ - `hash` (Hash): The hash to create the config from
45
+ - `scheme` (Legate::Auth::Scheme, optional): The scheme to associate (default: nil)
46
+ - `credential` (Legate::Auth::Credential, optional): The credential to associate (default: nil)
47
+
48
+ **Returns:**
49
+ - Legate::Auth::Config: A new Config instance
50
+
51
+ **Examples:**
52
+
53
+ ```ruby
54
+ config = Legate::Auth::Config.from_h(
55
+ saved_hash,
56
+ scheme: oauth2_scheme,
57
+ credential: oauth2_credential
58
+ )
59
+ ```
60
+
61
+ ## Instance Attributes
62
+
63
+ ### Readers (read-only)
64
+
65
+ - `scheme` - The authentication scheme
66
+ - `credential` - The authentication credential
67
+ - `auth_request_id` - The unique request identifier
68
+
69
+ ### Accessors (read/write)
70
+
71
+ - `auth_uri` - The URI to redirect the user to for authentication
72
+ - `redirect_uri` - The redirect URI for the callback
73
+ - `state` - The state parameter for CSRF protection
74
+ - `pkce` - PKCE parameters for the flow
75
+ - `response_uri` - The response URI from the provider callback
76
+ - `options` - Additional configuration options
77
+
78
+ ## Instance Methods
79
+
80
+ ### `build_authorization_uri`
81
+
82
+ Builds the authorization URI for the authentication flow using the associated scheme.
83
+
84
+ **Parameters:**
85
+ - `redirect_uri` (String, optional): The redirect URI for the callback
86
+ - `state` (String, optional): The state parameter for CSRF protection
87
+
88
+ **Returns:**
89
+ - String: The authorization URI
90
+
91
+ **Examples:**
92
+
93
+ ```ruby
94
+ config = Legate::Auth::Config.new(
95
+ scheme: oauth2_scheme,
96
+ credential: oauth2_credential
97
+ )
98
+
99
+ auth_uri = config.build_authorization_uri(
100
+ 'https://app.example.com/callback',
101
+ SecureRandom.hex(16)
102
+ )
103
+ ```
104
+
105
+ ### `to_h`
106
+
107
+ Converts the configuration to a hash.
108
+
109
+ **Parameters:**
110
+ - `include_credentials` (Boolean, optional): Whether to include credential data (default: false)
111
+
112
+ **Returns:**
113
+ - Hash: A hash representation of the configuration
114
+
115
+ **Examples:**
116
+
117
+ ```ruby
118
+ config = Legate::Auth::Config.new(
119
+ scheme: oauth2_scheme,
120
+ credential: oauth2_credential,
121
+ auth_request_id: 'req_123456'
122
+ )
123
+
124
+ # Without credentials (safe for logging)
125
+ puts config.to_h
126
+
127
+ # With credentials included
128
+ puts config.to_h(include_credentials: true)
129
+ ```
130
+
131
+ ### `validate_response!`
132
+
133
+ Validates an authentication response against this request configuration (matching request ID, presence of a response URI, and state).
134
+
135
+ **Parameters:**
136
+ - `response_config` (Legate::Auth::Config): The response configuration to validate against this request
137
+
138
+ **Returns:**
139
+ - Boolean: `true` if the response is valid
140
+
141
+ **Raises:**
142
+ - `Legate::Auth::ConfigurationError`: If the response is invalid (ID mismatch, missing response URI, or state mismatch)
143
+
144
+ **Examples:**
145
+
146
+ ```ruby
147
+ # Validate a response Config against the original request Config
148
+ config.validate_response!(response_config)
149
+ ```
150
+
151
+ ## Usage in Authentication Flows
152
+
153
+ The `Config` class is a key component in interactive authentication flows:
154
+
155
+ 1. **Creation**: A `Config` is created with the scheme and credential
156
+ 2. **URI Generation**: The config builds the authorization URI via `build_authorization_uri`
157
+ 3. **User Redirection**: The application redirects the user to the `auth_uri`
158
+ 4. **Callback Handling**: When the user completes authentication, the provider redirects back with an authorization code or token
159
+ 5. **Request Matching**: The application matches the callback to the original request using the `auth_request_id`
160
+
161
+ Here's an example of how it's used in a typical OAuth2 flow:
162
+
163
+ ```ruby
164
+ # 1. Configure the OAuth2 scheme and credential
165
+ scheme = Legate::Auth::Schemes::OAuth2.new(
166
+ authorization_url: 'https://auth.example.com/authorize',
167
+ token_url: 'https://auth.example.com/token',
168
+ scopes: ['profile', 'email']
169
+ )
170
+
171
+ credential = Legate::Auth::Credential.new(
172
+ auth_type: :oauth2,
173
+ client_id: ENV['CLIENT_ID'],
174
+ client_secret: ENV['CLIENT_SECRET']
175
+ )
176
+
177
+ # 2. Create a Config and build the authorization URI
178
+ config = Legate::Auth::Config.new(
179
+ scheme: scheme,
180
+ credential: credential
181
+ )
182
+
183
+ auth_uri = config.build_authorization_uri(
184
+ 'https://app.example.com/callback',
185
+ SecureRandom.hex(16)
186
+ )
187
+
188
+ # 3. In a web application, redirect the user to the auth URI
189
+ # redirect_to auth_uri
190
+
191
+ # 4. When the user is redirected back, set the response URI on the config
192
+ config.response_uri = 'https://app.example.com/callback?code=12345&state=abc123'
193
+
194
+ # 5. Exchange the authorization code for a token
195
+ # (exchange_token reads code/state from config.response_uri and verifies state)
196
+ token = scheme.exchange_token(config, credential)
197
+ ```
198
+
199
+ ## Security Considerations
200
+
201
+ - The `auth_request_id` should be cryptographically secure to prevent request forgery
202
+ - State parameters should be validated on callback to prevent CSRF attacks
203
+ - The `auth_uri` should always use HTTPS to protect the authentication process
204
+
205
+ ## See Also
206
+
207
+ - [Legate::Auth::Scheme](./scheme)
208
+ - [Legate::Auth::Schemes::OAuth2](./schemes/oauth2)
209
+ - [Legate::Auth::Schemes::OpenIDConnect](./schemes/openid_connect)
210
+ - [Legate::Auth::ExchangedCredential](./exchanged_credential)
@@ -0,0 +1,246 @@
1
+ # Legate::Auth::Credential
2
+
3
+ The `Credential` class represents authentication credentials required by different authentication schemes. It handles different types of credentials such as API keys, OAuth2 client credentials, service account keys, and HTTP Bearer tokens.
4
+
5
+ ## Overview
6
+
7
+ A credential contains the initial authentication information needed to begin an authentication flow or to directly authenticate requests. It can handle different credential types and supports environment variable resolution for sensitive values.
8
+
9
+ ## Class Constants
10
+
11
+ - `VALID_TYPES`: Valid credential types - `:api_key`, `:oauth2`, `:oidc`, `:service_account`, `:google_service_account`, `:http_bearer`, `:basic`
12
+ - `ENV_PREFIX`: Prefix for environment variable references (`'ENV:'`)
13
+
14
+ ## Class Methods
15
+
16
+ ### `new`
17
+
18
+ Creates a new credential instance.
19
+
20
+ **Parameters:**
21
+ - `auth_type` (Symbol): The type of authentication (:api_key, :oauth2, :oidc, :service_account, :http_bearer)
22
+ - `kwargs` (Hash): Additional attributes for the specific auth type
23
+
24
+ **Raises:**
25
+ - `Legate::Auth::CredentialError`: If the credential is invalid
26
+
27
+ **Examples:**
28
+
29
+ ```ruby
30
+ # API Key credential
31
+ credential = Legate::Auth::Credential.new(
32
+ auth_type: :api_key,
33
+ api_key: 'my-api-key'
34
+ )
35
+
36
+ # OAuth2 credential
37
+ credential = Legate::Auth::Credential.new(
38
+ auth_type: :oauth2,
39
+ client_id: 'my-client-id',
40
+ client_secret: 'my-client-secret'
41
+ )
42
+
43
+ # OAuth2 credential with environment variable
44
+ credential = Legate::Auth::Credential.new(
45
+ auth_type: :oauth2,
46
+ client_id: 'my-client-id',
47
+ client_secret: 'ENV:MY_CLIENT_SECRET'
48
+ )
49
+
50
+ # Service Account credential (service_account_key is a raw JSON string)
51
+ credential = Legate::Auth::Credential.new(
52
+ auth_type: :service_account,
53
+ service_account_key: File.read('service-account.json')
54
+ )
55
+
56
+ # Service Account credential from a file path
57
+ credential = Legate::Auth::Credential.new(
58
+ auth_type: :service_account,
59
+ service_account_key_file: '/path/to/service-account.json'
60
+ )
61
+
62
+ # HTTP Bearer token
63
+ credential = Legate::Auth::Credential.new(
64
+ auth_type: :http_bearer,
65
+ bearer_token: 'my-bearer-token'
66
+ )
67
+ ```
68
+
69
+ ## Instance Methods
70
+
71
+ ### `[]`
72
+
73
+ Gets an attribute value, optionally resolving environment variables.
74
+
75
+ **Parameters:**
76
+ - `name` (Symbol, String): The attribute name
77
+ - `resolve_env` (Boolean, optional): Whether to resolve environment variables (default: true)
78
+
79
+ **Returns:**
80
+ - The attribute value, or nil if not present
81
+
82
+ **Raises:**
83
+ - `Legate::Auth::EnvironmentVariableNotFoundError`: If an environment variable is not found
84
+
85
+ **Examples:**
86
+
87
+ ```ruby
88
+ # Get a regular attribute
89
+ client_id = credential[:client_id]
90
+
91
+ # Get an attribute without resolving environment variables
92
+ raw_value = credential[:client_secret, resolve_env: false]
93
+
94
+ # Get an attribute with environment variable resolution (default)
95
+ resolved_value = credential[:client_secret]
96
+ ```
97
+
98
+ ### `[]=`
99
+
100
+ Sets an attribute value.
101
+
102
+ **Parameters:**
103
+ - `name` (Symbol, String): The attribute name
104
+ - `value` (Object): The attribute value
105
+
106
+ **Examples:**
107
+
108
+ ```ruby
109
+ # Set an attribute
110
+ credential[:client_id] = 'new-client-id'
111
+
112
+ # Set an environment variable reference
113
+ credential[:client_secret] = 'ENV:NEW_CLIENT_SECRET'
114
+ ```
115
+
116
+ ### `to_h`
117
+
118
+ Converts the credential to a hash.
119
+
120
+ **Parameters:**
121
+ - `resolve_env` (Boolean, optional): Whether to resolve environment variables (default: false)
122
+
123
+ **Returns:**
124
+ - Hash: A hash representation of the credential
125
+
126
+ **Examples:**
127
+
128
+ ```ruby
129
+ # Get hash representation without resolving environment variables
130
+ hash = credential.to_h
131
+
132
+ # Get hash representation with environment variables resolved
133
+ resolved_hash = credential.to_h(resolve_env: true)
134
+ ```
135
+
136
+ ### `has_attribute?`
137
+
138
+ Checks if the credential has an attribute.
139
+
140
+ **Parameters:**
141
+ - `name` (Symbol, String): The attribute name
142
+
143
+ **Returns:**
144
+ - Boolean: True if the attribute exists
145
+
146
+ **Examples:**
147
+
148
+ ```ruby
149
+ # Check if an attribute exists
150
+ if credential.has_attribute?(:client_id)
151
+ # Use the client_id
152
+ end
153
+ ```
154
+
155
+ ## Required Attributes by Type
156
+
157
+ Each credential type requires specific attributes:
158
+
159
+ | Type | Required Attributes | Description |
160
+ |------|---------------------|-------------|
161
+ | `:api_key` | `:api_key` | The API key for authentication |
162
+ | `:oauth2` | `:client_id` | The OAuth2 client ID |
163
+ | `:oidc` | `:client_id` | The OpenID Connect client ID |
164
+ | `:service_account` | `:service_account_key` or `:service_account_key_file` | The service account key or key file |
165
+ | `:google_service_account` | `:service_account_key` or `:service_account_key_file` | The Google service account key or key file |
166
+ | `:http_bearer` | `:bearer_token` | The Bearer token |
167
+
168
+ ## Environment Variable Resolution
169
+
170
+ The Credential class supports referencing environment variables for sensitive values by prefixing the value with `ENV:`:
171
+
172
+ ```ruby
173
+ # Reference an environment variable
174
+ credential = Legate::Auth::Credential.new(
175
+ auth_type: :oauth2,
176
+ client_id: 'my-client-id',
177
+ client_secret: 'ENV:MY_CLIENT_SECRET'
178
+ )
179
+
180
+ # When accessing the attribute, the environment variable is resolved
181
+ secret = credential[:client_secret] # Resolves to the value of ENV['MY_CLIENT_SECRET']
182
+ ```
183
+
184
+ ## Examples
185
+
186
+ ### API Key Authentication
187
+
188
+ ```ruby
189
+ # Standard API key
190
+ credential = Legate::Auth::Credential.new(
191
+ auth_type: :api_key,
192
+ api_key: 'my-api-key'
193
+ )
194
+
195
+ # API key from environment variable
196
+ credential = Legate::Auth::Credential.new(
197
+ auth_type: :api_key,
198
+ api_key: 'ENV:API_KEY'
199
+ )
200
+
201
+ # API key with additional options
202
+ credential = Legate::Auth::Credential.new(
203
+ auth_type: :api_key,
204
+ api_key: 'my-api-key',
205
+ location: 'header', # Where to place the API key
206
+ name: 'X-Custom-API-Key' # Name of the header or parameter
207
+ )
208
+ ```
209
+
210
+ ### OAuth2 Authentication
211
+
212
+ ```ruby
213
+ credential = Legate::Auth::Credential.new(
214
+ auth_type: :oauth2,
215
+ client_id: 'ENV:OAUTH_CLIENT_ID',
216
+ client_secret: 'ENV:OAUTH_CLIENT_SECRET'
217
+ )
218
+ ```
219
+
220
+ ### Service Account Authentication
221
+
222
+ ```ruby
223
+ # service_account_key takes the raw JSON string (not a parsed Hash)
224
+ credential = Legate::Auth::Credential.new(
225
+ auth_type: :service_account,
226
+ service_account_key: File.read('service-account.json')
227
+ )
228
+
229
+ # Or point at the file directly with service_account_key_file
230
+ credential = Legate::Auth::Credential.new(
231
+ auth_type: :service_account,
232
+ service_account_key_file: '/path/to/service-account.json'
233
+ )
234
+ ```
235
+
236
+ ## Security Considerations
237
+
238
+ - Always use environment variables (`ENV:` prefix) for sensitive values like client secrets and API keys
239
+ - Never hardcode sensitive credentials in your code
240
+ - The `resolve_env: false` option can be useful for logging to avoid exposing sensitive values
241
+
242
+ ## See Also
243
+
244
+ - [Legate::Auth::Scheme](./scheme)
245
+ - [Legate::Auth::ExchangedCredential](./exchanged_credential)
246
+ - [Legate::Auth::TokenManager](./token_manager)