ruby_llm_swarm-mcp 0.8.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 (92) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +277 -0
  4. data/lib/generators/ruby_llm/mcp/install/install_generator.rb +42 -0
  5. data/lib/generators/ruby_llm/mcp/install/templates/initializer.rb +56 -0
  6. data/lib/generators/ruby_llm/mcp/install/templates/mcps.yml +29 -0
  7. data/lib/generators/ruby_llm/mcp/oauth/install_generator.rb +354 -0
  8. data/lib/generators/ruby_llm/mcp/oauth/templates/concerns/mcp_token_storage.rb.tt +114 -0
  9. data/lib/generators/ruby_llm/mcp/oauth/templates/concerns/user_mcp_oauth_concern.rb.tt +90 -0
  10. data/lib/generators/ruby_llm/mcp/oauth/templates/controllers/mcp_connections_controller.rb.tt +239 -0
  11. data/lib/generators/ruby_llm/mcp/oauth/templates/jobs/cleanup_expired_oauth_states_job.rb.tt +27 -0
  12. data/lib/generators/ruby_llm/mcp/oauth/templates/jobs/example_job.rb.tt +78 -0
  13. data/lib/generators/ruby_llm/mcp/oauth/templates/lib/mcp_client.rb.tt +68 -0
  14. data/lib/generators/ruby_llm/mcp/oauth/templates/migrations/create_mcp_oauth_credentials.rb.tt +19 -0
  15. data/lib/generators/ruby_llm/mcp/oauth/templates/migrations/create_mcp_oauth_states.rb.tt +21 -0
  16. data/lib/generators/ruby_llm/mcp/oauth/templates/models/mcp_oauth_credential.rb.tt +54 -0
  17. data/lib/generators/ruby_llm/mcp/oauth/templates/models/mcp_oauth_state.rb.tt +30 -0
  18. data/lib/generators/ruby_llm/mcp/oauth/templates/views/index.html.erb +646 -0
  19. data/lib/generators/ruby_llm/mcp/oauth/templates/views/show.html.erb +560 -0
  20. data/lib/ruby_llm/chat.rb +34 -0
  21. data/lib/ruby_llm/mcp/adapters/base_adapter.rb +179 -0
  22. data/lib/ruby_llm/mcp/adapters/mcp_sdk_adapter.rb +292 -0
  23. data/lib/ruby_llm/mcp/adapters/mcp_transports/coordinator_stub.rb +33 -0
  24. data/lib/ruby_llm/mcp/adapters/mcp_transports/sse.rb +52 -0
  25. data/lib/ruby_llm/mcp/adapters/mcp_transports/stdio.rb +52 -0
  26. data/lib/ruby_llm/mcp/adapters/mcp_transports/streamable_http.rb +86 -0
  27. data/lib/ruby_llm/mcp/adapters/ruby_llm_adapter.rb +92 -0
  28. data/lib/ruby_llm/mcp/attachment.rb +18 -0
  29. data/lib/ruby_llm/mcp/auth/browser/callback_handler.rb +71 -0
  30. data/lib/ruby_llm/mcp/auth/browser/callback_server.rb +30 -0
  31. data/lib/ruby_llm/mcp/auth/browser/http_server.rb +112 -0
  32. data/lib/ruby_llm/mcp/auth/browser/opener.rb +39 -0
  33. data/lib/ruby_llm/mcp/auth/browser/pages.rb +607 -0
  34. data/lib/ruby_llm/mcp/auth/browser_oauth_provider.rb +280 -0
  35. data/lib/ruby_llm/mcp/auth/client_registrar.rb +170 -0
  36. data/lib/ruby_llm/mcp/auth/discoverer.rb +124 -0
  37. data/lib/ruby_llm/mcp/auth/flows/authorization_code_flow.rb +105 -0
  38. data/lib/ruby_llm/mcp/auth/flows/client_credentials_flow.rb +66 -0
  39. data/lib/ruby_llm/mcp/auth/grant_strategies/authorization_code.rb +31 -0
  40. data/lib/ruby_llm/mcp/auth/grant_strategies/base.rb +31 -0
  41. data/lib/ruby_llm/mcp/auth/grant_strategies/client_credentials.rb +31 -0
  42. data/lib/ruby_llm/mcp/auth/http_response_handler.rb +63 -0
  43. data/lib/ruby_llm/mcp/auth/memory_storage.rb +90 -0
  44. data/lib/ruby_llm/mcp/auth/oauth_provider.rb +305 -0
  45. data/lib/ruby_llm/mcp/auth/security.rb +44 -0
  46. data/lib/ruby_llm/mcp/auth/session_manager.rb +54 -0
  47. data/lib/ruby_llm/mcp/auth/token_manager.rb +236 -0
  48. data/lib/ruby_llm/mcp/auth/transport_oauth_helper.rb +107 -0
  49. data/lib/ruby_llm/mcp/auth/url_builder.rb +76 -0
  50. data/lib/ruby_llm/mcp/auth.rb +359 -0
  51. data/lib/ruby_llm/mcp/client.rb +401 -0
  52. data/lib/ruby_llm/mcp/completion.rb +16 -0
  53. data/lib/ruby_llm/mcp/configuration.rb +310 -0
  54. data/lib/ruby_llm/mcp/content.rb +28 -0
  55. data/lib/ruby_llm/mcp/elicitation.rb +48 -0
  56. data/lib/ruby_llm/mcp/error.rb +34 -0
  57. data/lib/ruby_llm/mcp/errors.rb +91 -0
  58. data/lib/ruby_llm/mcp/logging.rb +16 -0
  59. data/lib/ruby_llm/mcp/native/cancellable_operation.rb +57 -0
  60. data/lib/ruby_llm/mcp/native/client.rb +387 -0
  61. data/lib/ruby_llm/mcp/native/json_rpc.rb +170 -0
  62. data/lib/ruby_llm/mcp/native/messages/helpers.rb +39 -0
  63. data/lib/ruby_llm/mcp/native/messages/notifications.rb +42 -0
  64. data/lib/ruby_llm/mcp/native/messages/requests.rb +206 -0
  65. data/lib/ruby_llm/mcp/native/messages/responses.rb +106 -0
  66. data/lib/ruby_llm/mcp/native/messages.rb +36 -0
  67. data/lib/ruby_llm/mcp/native/notification.rb +16 -0
  68. data/lib/ruby_llm/mcp/native/protocol.rb +36 -0
  69. data/lib/ruby_llm/mcp/native/response_handler.rb +110 -0
  70. data/lib/ruby_llm/mcp/native/transport.rb +88 -0
  71. data/lib/ruby_llm/mcp/native/transports/sse.rb +607 -0
  72. data/lib/ruby_llm/mcp/native/transports/stdio.rb +356 -0
  73. data/lib/ruby_llm/mcp/native/transports/streamable_http.rb +926 -0
  74. data/lib/ruby_llm/mcp/native/transports/support/http_client.rb +28 -0
  75. data/lib/ruby_llm/mcp/native/transports/support/rate_limit.rb +49 -0
  76. data/lib/ruby_llm/mcp/native/transports/support/timeout.rb +36 -0
  77. data/lib/ruby_llm/mcp/native.rb +12 -0
  78. data/lib/ruby_llm/mcp/notification_handler.rb +100 -0
  79. data/lib/ruby_llm/mcp/progress.rb +35 -0
  80. data/lib/ruby_llm/mcp/prompt.rb +132 -0
  81. data/lib/ruby_llm/mcp/railtie.rb +14 -0
  82. data/lib/ruby_llm/mcp/resource.rb +112 -0
  83. data/lib/ruby_llm/mcp/resource_template.rb +85 -0
  84. data/lib/ruby_llm/mcp/result.rb +108 -0
  85. data/lib/ruby_llm/mcp/roots.rb +45 -0
  86. data/lib/ruby_llm/mcp/sample.rb +152 -0
  87. data/lib/ruby_llm/mcp/server_capabilities.rb +49 -0
  88. data/lib/ruby_llm/mcp/tool.rb +228 -0
  89. data/lib/ruby_llm/mcp/version.rb +7 -0
  90. data/lib/ruby_llm/mcp.rb +125 -0
  91. data/lib/tasks/release.rake +23 -0
  92. metadata +184 -0
@@ -0,0 +1,560 @@
1
+ <div class="mcp-connections-container">
2
+
3
+ <%= link_to "← Back to Connections", mcp_connections_path, class: "mcp-btn mcp-btn-secondary" %>
4
+ <div class="mcp-header">
5
+ <h1><%= @credential.name %></h1>
6
+ <div class="mcp-header-meta">
7
+ <code class="mcp-code"><%= @credential.server_url %></code>
8
+ <% if @credential.expired? %>
9
+ <span class="mcp-badge mcp-badge-danger">Expired</span>
10
+ <% elsif @credential.expires_soon? %>
11
+ <span class="mcp-badge mcp-badge-warning">Expiring Soon</span>
12
+ <% else %>
13
+ <span class="mcp-badge mcp-badge-success">Active</span>
14
+ <% end %>
15
+ </div>
16
+ </div>
17
+
18
+ <% if flash[:notice] %>
19
+ <div class="mcp-alert mcp-alert-success">
20
+ <%= flash[:notice] %>
21
+ </div>
22
+ <% end %>
23
+
24
+ <% if flash[:alert] %>
25
+ <div class="mcp-alert mcp-alert-warning">
26
+ <%= flash[:alert] %>
27
+ </div>
28
+ <% end %>
29
+
30
+ <div class="mcp-tools-section">
31
+ <h2>Available Tools (<%= @tools.count %>)</h2>
32
+ <% if @tools.any? %>
33
+ <div class="mcp-tools-list">
34
+ <% @tools.each do |tool| %>
35
+ <div class="mcp-tool-card">
36
+ <div class="mcp-tool-header">
37
+ <h3 class="mcp-tool-name"><%= tool.name %></h3>
38
+ <div class="mcp-tool-badges">
39
+ <% if tool.annotations&.read_only_hint %>
40
+ <span class="mcp-badge mcp-badge-info">Read Only</span>
41
+ <% end %>
42
+ <% if tool.annotations&.destructive_hint %>
43
+ <span class="mcp-badge mcp-badge-warning">Destructive</span>
44
+ <% end %>
45
+ <% if tool.annotations&.idempotent_hint %>
46
+ <span class="mcp-badge mcp-badge-success">Idempotent</span>
47
+ <% end %>
48
+ </div>
49
+ </div>
50
+
51
+ <% if tool.description.present? %>
52
+ <p class="mcp-tool-description"><%= tool.description %></p>
53
+ <% else %>
54
+ <p class="mcp-tool-description mcp-text-muted">No description available</p>
55
+ <% end %>
56
+
57
+ <% if tool.params_schema.present? && tool.params_schema["properties"]&.any? %>
58
+ <div class="mcp-tool-schema">
59
+ <h4>Input Parameters</h4>
60
+ <div class="mcp-parameters">
61
+ <% tool.params_schema["properties"].each do |param_name, param_info| %>
62
+ <div class="mcp-parameter">
63
+ <div class="mcp-parameter-header">
64
+ <code class="mcp-param-name"><%= param_name %></code>
65
+ <span class="mcp-param-type"><%= param_info["type"] %></span>
66
+ <% if tool.params_schema["required"]&.include?(param_name) %>
67
+ <span class="mcp-badge mcp-badge-required">Required</span>
68
+ <% end %>
69
+ </div>
70
+ <% if param_info["description"].present? %>
71
+ <p class="mcp-parameter-description"><%= param_info["description"] %></p>
72
+ <% end %>
73
+ <% if param_info["items"].present? %>
74
+ <div class="mcp-parameter-items">
75
+ <small class="mcp-text-muted">Items: <%= param_info["items"]["type"] %></small>
76
+ </div>
77
+ <% end %>
78
+ </div>
79
+ <% end %>
80
+ </div>
81
+
82
+ <details class="mcp-schema-details">
83
+ <summary>View Full Schema</summary>
84
+ <pre class="mcp-schema-code"><%= JSON.pretty_generate(tool.params_schema) %></pre>
85
+ </details>
86
+ </div>
87
+ <% elsif tool.params_schema.present? %>
88
+ <div class="mcp-tool-schema">
89
+ <p class="mcp-text-muted"><em>No input parameters required</em></p>
90
+ </div>
91
+ <% end %>
92
+ </div>
93
+ <% end %>
94
+ </div>
95
+ <% else %>
96
+ <div class="mcp-alert mcp-alert-info">
97
+ <p>No tools available from this MCP server.</p>
98
+ </div>
99
+ <% end %>
100
+ </div>
101
+ </div>
102
+
103
+ <style>
104
+ /* MCP Tools Show Page - Self-contained styles */
105
+ .mcp-connections-container {
106
+ max-width: 1200px;
107
+ margin: 2rem auto;
108
+ padding: 0 1rem;
109
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
110
+ line-height: 1.6;
111
+ }
112
+
113
+ .mcp-header {
114
+ margin: 2rem 0;
115
+ }
116
+
117
+ .mcp-header h1 {
118
+ font-size: 2rem;
119
+ font-weight: 600;
120
+ margin-bottom: 0.5rem;
121
+ color: #1a1a1a;
122
+ }
123
+
124
+ .mcp-header-meta {
125
+ display: flex;
126
+ align-items: center;
127
+ gap: 1rem;
128
+ flex-wrap: wrap;
129
+ margin-top: 0.5rem;
130
+ }
131
+
132
+ .mcp-tools-section {
133
+ margin-top: 2rem;
134
+ }
135
+
136
+ .mcp-tools-section h2 {
137
+ font-size: 1.5rem;
138
+ font-weight: 600;
139
+ margin-bottom: 1.5rem;
140
+ color: #2a2a2a;
141
+ }
142
+
143
+ .mcp-tools-list {
144
+ display: flex;
145
+ flex-direction: column;
146
+ gap: 1.5rem;
147
+ margin-top: 1.5rem;
148
+ }
149
+
150
+ .mcp-tool-card {
151
+ background: white;
152
+ border: 1px solid #dee2e6;
153
+ border-radius: 8px;
154
+ padding: 1.5rem;
155
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
156
+ transition: box-shadow 0.2s ease;
157
+ }
158
+
159
+ .mcp-tool-card:hover {
160
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
161
+ }
162
+
163
+ .mcp-tool-header {
164
+ margin-bottom: 1rem;
165
+ }
166
+
167
+ .mcp-tool-name {
168
+ font-size: 1.25rem;
169
+ font-weight: 600;
170
+ color: #007bff;
171
+ margin: 0 0 0.5rem 0;
172
+ word-break: break-word;
173
+ }
174
+
175
+ .mcp-tool-badges {
176
+ display: flex;
177
+ gap: 0.5rem;
178
+ flex-wrap: wrap;
179
+ margin-top: 0.5rem;
180
+ }
181
+
182
+ .mcp-tool-description {
183
+ font-size: 0.95rem;
184
+ color: #495057;
185
+ margin-bottom: 1rem;
186
+ line-height: 1.5;
187
+ }
188
+
189
+ .mcp-tool-schema {
190
+ margin-top: 1rem;
191
+ padding-top: 1rem;
192
+ border-top: 1px solid #dee2e6;
193
+ }
194
+
195
+ .mcp-tool-schema h4 {
196
+ font-size: 0.875rem;
197
+ font-weight: 600;
198
+ color: #6c757d;
199
+ text-transform: uppercase;
200
+ letter-spacing: 0.05em;
201
+ margin-bottom: 0.5rem;
202
+ }
203
+
204
+ .mcp-schema-details {
205
+ margin-top: 0.5rem;
206
+ }
207
+
208
+ .mcp-schema-details summary {
209
+ cursor: pointer;
210
+ font-size: 0.875rem;
211
+ color: #007bff;
212
+ padding: 0.5rem;
213
+ background-color: #f8f9fa;
214
+ border-radius: 4px;
215
+ user-select: none;
216
+ }
217
+
218
+ .mcp-schema-details summary:hover {
219
+ background-color: #e9ecef;
220
+ }
221
+
222
+ .mcp-schema-code {
223
+ margin-top: 0.5rem;
224
+ padding: 1rem;
225
+ background-color: #f5f5f5;
226
+ border: 1px solid #dee2e6;
227
+ border-radius: 4px;
228
+ overflow-x: auto;
229
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
230
+ font-size: 0.875rem;
231
+ line-height: 1.5;
232
+ color: #212529;
233
+ }
234
+
235
+ .mcp-parameters {
236
+ display: flex;
237
+ flex-direction: column;
238
+ gap: 1rem;
239
+ margin-bottom: 1rem;
240
+ }
241
+
242
+ .mcp-parameter {
243
+ padding: 0.75rem;
244
+ background-color: #f8f9fa;
245
+ border-radius: 4px;
246
+ border-left: 3px solid #007bff;
247
+ }
248
+
249
+ .mcp-parameter-header {
250
+ display: flex;
251
+ align-items: center;
252
+ gap: 0.5rem;
253
+ margin-bottom: 0.5rem;
254
+ flex-wrap: wrap;
255
+ }
256
+
257
+ .mcp-param-name {
258
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
259
+ font-size: 0.9rem;
260
+ font-weight: 600;
261
+ color: #007bff;
262
+ background-color: #e7f3ff;
263
+ padding: 0.25rem 0.5rem;
264
+ border-radius: 3px;
265
+ }
266
+
267
+ .mcp-param-type {
268
+ font-size: 0.75rem;
269
+ color: #6c757d;
270
+ background-color: #e9ecef;
271
+ padding: 0.25rem 0.5rem;
272
+ border-radius: 3px;
273
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
274
+ }
275
+
276
+ .mcp-parameter-description {
277
+ font-size: 0.875rem;
278
+ color: #495057;
279
+ margin: 0;
280
+ line-height: 1.5;
281
+ }
282
+
283
+ .mcp-parameter-items {
284
+ margin-top: 0.25rem;
285
+ }
286
+
287
+ /* Badge styles */
288
+ .mcp-badge {
289
+ display: inline-block;
290
+ padding: 0.25rem 0.5rem;
291
+ font-size: 0.75rem;
292
+ font-weight: 600;
293
+ line-height: 1;
294
+ text-align: center;
295
+ white-space: nowrap;
296
+ border-radius: 4px;
297
+ }
298
+
299
+ .mcp-badge-success {
300
+ background-color: #d4edda;
301
+ color: #155724;
302
+ }
303
+
304
+ .mcp-badge-warning {
305
+ background-color: #fff3cd;
306
+ color: #856404;
307
+ }
308
+
309
+ .mcp-badge-danger {
310
+ background-color: #f8d7da;
311
+ color: #721c24;
312
+ }
313
+
314
+ .mcp-badge-info {
315
+ background-color: #d1ecf1;
316
+ color: #0c5460;
317
+ }
318
+
319
+ .mcp-badge-required {
320
+ background-color: #f8d7da;
321
+ color: #721c24;
322
+ font-size: 0.7rem;
323
+ }
324
+
325
+ /* Button styles */
326
+ .mcp-btn {
327
+ display: inline-block;
328
+ padding: 0.5rem 1rem;
329
+ font-size: 0.875rem;
330
+ font-weight: 500;
331
+ line-height: 1.5;
332
+ text-align: center;
333
+ text-decoration: none;
334
+ border: 1px solid transparent;
335
+ border-radius: 4px;
336
+ cursor: pointer;
337
+ transition: all 0.15s ease-in-out;
338
+ }
339
+
340
+ .mcp-btn:hover {
341
+ opacity: 0.9;
342
+ }
343
+
344
+ .mcp-btn-secondary {
345
+ color: white;
346
+ background-color: #6c757d;
347
+ border-color: #6c757d;
348
+ }
349
+
350
+ .mcp-btn-secondary:hover {
351
+ background-color: #5a6268;
352
+ border-color: #5a6268;
353
+ }
354
+
355
+ /* Code styles */
356
+ .mcp-code {
357
+ background-color: #f5f5f5;
358
+ padding: 0.25rem 0.5rem;
359
+ border-radius: 3px;
360
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
361
+ font-size: 0.875em;
362
+ color: #212529;
363
+ }
364
+
365
+ /* Text utilities */
366
+ .mcp-text-muted {
367
+ color: #6c757d;
368
+ }
369
+
370
+ /* Alert styles */
371
+ .mcp-alert {
372
+ padding: 1rem;
373
+ margin-bottom: 1rem;
374
+ border: 1px solid transparent;
375
+ border-radius: 4px;
376
+ }
377
+
378
+ .mcp-alert-info {
379
+ background-color: #d1ecf1;
380
+ border-color: #bee5eb;
381
+ color: #0c5460;
382
+ }
383
+
384
+ .mcp-alert-warning {
385
+ background-color: #fff3cd;
386
+ border-color: #ffeaa7;
387
+ color: #856404;
388
+ }
389
+
390
+ .mcp-alert-success {
391
+ background-color: #d4edda;
392
+ border-color: #c3e6cb;
393
+ color: #155724;
394
+ }
395
+
396
+ /* Responsive */
397
+ @media (max-width: 768px) {
398
+ .mcp-connections-container {
399
+ padding: 0 0.5rem;
400
+ }
401
+
402
+ .mcp-header h1 {
403
+ font-size: 1.5rem;
404
+ }
405
+
406
+ .mcp-tool-card {
407
+ padding: 1rem;
408
+ }
409
+ }
410
+
411
+ /* Dark Mode Support */
412
+ @media (prefers-color-scheme: dark) {
413
+ body {
414
+ background-color: #1a1a1a;
415
+ }
416
+
417
+ .mcp-connections-container {
418
+ color: #e0e0e0;
419
+ background-color: #1a1a1a;
420
+ }
421
+
422
+ .mcp-header h1 {
423
+ color: #f0f0f0;
424
+ }
425
+
426
+ .mcp-tools-section h2 {
427
+ color: #f0f0f0;
428
+ }
429
+
430
+ /* Tool card dark mode */
431
+ .mcp-tool-card {
432
+ background: #2a2a2a;
433
+ border-color: #3a3a3a;
434
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
435
+ }
436
+
437
+ .mcp-tool-card:hover {
438
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.4);
439
+ }
440
+
441
+ .mcp-tool-name {
442
+ color: #4dabf7;
443
+ }
444
+
445
+ .mcp-tool-description {
446
+ color: #b0b0b0;
447
+ }
448
+
449
+ /* Tool schema dark mode */
450
+ .mcp-tool-schema {
451
+ border-top-color: #3a3a3a;
452
+ }
453
+
454
+ .mcp-tool-schema h4 {
455
+ color: #8a8a8a;
456
+ }
457
+
458
+ .mcp-schema-details summary {
459
+ background-color: #1a1a1a;
460
+ color: #4dabf7;
461
+ }
462
+
463
+ .mcp-schema-details summary:hover {
464
+ background-color: #333333;
465
+ }
466
+
467
+ .mcp-schema-code {
468
+ background-color: #1a1a1a;
469
+ border-color: #3a3a3a;
470
+ color: #e0e0e0;
471
+ }
472
+
473
+ /* Parameter dark mode */
474
+ .mcp-parameter {
475
+ background-color: #1a1a1a;
476
+ border-left-color: #4dabf7;
477
+ }
478
+
479
+ .mcp-param-name {
480
+ color: #4dabf7;
481
+ background-color: #0d3a5c;
482
+ }
483
+
484
+ .mcp-param-type {
485
+ color: #8a8a8a;
486
+ background-color: #2a2a2a;
487
+ }
488
+
489
+ .mcp-parameter-description {
490
+ color: #b0b0b0;
491
+ }
492
+
493
+ /* Badge dark mode */
494
+ .mcp-badge-success {
495
+ background-color: #1e4620;
496
+ color: #8fd98f;
497
+ }
498
+
499
+ .mcp-badge-warning {
500
+ background-color: #4a3a00;
501
+ color: #ffd966;
502
+ }
503
+
504
+ .mcp-badge-danger {
505
+ background-color: #4a1a1f;
506
+ color: #ff8a95;
507
+ }
508
+
509
+ .mcp-badge-info {
510
+ background-color: #0c3d47;
511
+ color: #9fe5f0;
512
+ }
513
+
514
+ .mcp-badge-required {
515
+ background-color: #4a1a1f;
516
+ color: #ff8a95;
517
+ }
518
+
519
+ /* Button dark mode */
520
+ .mcp-btn-secondary {
521
+ background-color: #5a6268;
522
+ border-color: #5a6268;
523
+ }
524
+
525
+ .mcp-btn-secondary:hover {
526
+ background-color: #4e555b;
527
+ border-color: #4e555b;
528
+ }
529
+
530
+ /* Code dark mode */
531
+ .mcp-code {
532
+ background-color: #1a1a1a;
533
+ color: #e0e0e0;
534
+ }
535
+
536
+ /* Text utilities dark mode */
537
+ .mcp-text-muted {
538
+ color: #8a8a8a;
539
+ }
540
+
541
+ /* Alert dark mode */
542
+ .mcp-alert-info {
543
+ background-color: #0c3d47;
544
+ border-color: #0f5460;
545
+ color: #9fe5f0;
546
+ }
547
+
548
+ .mcp-alert-warning {
549
+ background-color: #4a3a00;
550
+ border-color: #665000;
551
+ color: #ffd966;
552
+ }
553
+
554
+ .mcp-alert-success {
555
+ background-color: #1e4620;
556
+ border-color: #2a5e2c;
557
+ color: #8fd98f;
558
+ }
559
+ }
560
+ </style>
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is an override of the RubyLLM::Chat class to add convenient methods to more
4
+ # easily work with the MCP clients.
5
+ module RubyLLM
6
+ class Chat
7
+ def with_resources(*resources, **args)
8
+ resources.each do |resource|
9
+ resource.include(self, **args)
10
+ end
11
+ self
12
+ end
13
+
14
+ def with_resource(resource)
15
+ resource.include(self)
16
+ self
17
+ end
18
+
19
+ def with_resource_template(resource_template, arguments: {})
20
+ resource = resource_template.fetch_resource(arguments: arguments)
21
+ resource.include(self)
22
+ self
23
+ end
24
+
25
+ def with_prompt(prompt, arguments: {})
26
+ prompt.include(self, arguments: arguments)
27
+ self
28
+ end
29
+
30
+ def ask_prompt(prompt, ...)
31
+ prompt.ask(self, ...)
32
+ end
33
+ end
34
+ end