tsikol 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 (75) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +22 -0
  3. data/CONTRIBUTING.md +84 -0
  4. data/LICENSE +21 -0
  5. data/README.md +579 -0
  6. data/Rakefile +12 -0
  7. data/docs/README.md +69 -0
  8. data/docs/api/middleware.md +721 -0
  9. data/docs/api/prompt.md +858 -0
  10. data/docs/api/resource.md +651 -0
  11. data/docs/api/server.md +509 -0
  12. data/docs/api/test-helpers.md +591 -0
  13. data/docs/api/tool.md +527 -0
  14. data/docs/cookbook/authentication.md +651 -0
  15. data/docs/cookbook/caching.md +877 -0
  16. data/docs/cookbook/dynamic-tools.md +970 -0
  17. data/docs/cookbook/error-handling.md +887 -0
  18. data/docs/cookbook/logging.md +1044 -0
  19. data/docs/cookbook/rate-limiting.md +717 -0
  20. data/docs/examples/code-assistant.md +922 -0
  21. data/docs/examples/complete-server.md +726 -0
  22. data/docs/examples/database-manager.md +1198 -0
  23. data/docs/examples/devops-tools.md +1382 -0
  24. data/docs/examples/echo-server.md +501 -0
  25. data/docs/examples/weather-service.md +822 -0
  26. data/docs/guides/completion.md +472 -0
  27. data/docs/guides/getting-started.md +462 -0
  28. data/docs/guides/middleware.md +823 -0
  29. data/docs/guides/project-structure.md +434 -0
  30. data/docs/guides/prompts.md +920 -0
  31. data/docs/guides/resources.md +720 -0
  32. data/docs/guides/sampling.md +804 -0
  33. data/docs/guides/testing.md +863 -0
  34. data/docs/guides/tools.md +627 -0
  35. data/examples/README.md +92 -0
  36. data/examples/advanced_features.rb +129 -0
  37. data/examples/basic-migrated/app/prompts/weather_chat.rb +44 -0
  38. data/examples/basic-migrated/app/resources/weather_alerts.rb +18 -0
  39. data/examples/basic-migrated/app/tools/get_current_weather.rb +34 -0
  40. data/examples/basic-migrated/app/tools/get_forecast.rb +30 -0
  41. data/examples/basic-migrated/app/tools/get_weather_by_coords.rb +48 -0
  42. data/examples/basic-migrated/server.rb +25 -0
  43. data/examples/basic.rb +73 -0
  44. data/examples/full_featured.rb +175 -0
  45. data/examples/middleware_example.rb +112 -0
  46. data/examples/sampling_example.rb +104 -0
  47. data/examples/weather-service/app/prompts/weather/chat.rb +90 -0
  48. data/examples/weather-service/app/resources/weather/alerts.rb +59 -0
  49. data/examples/weather-service/app/tools/weather/get_current.rb +82 -0
  50. data/examples/weather-service/app/tools/weather/get_forecast.rb +90 -0
  51. data/examples/weather-service/server.rb +28 -0
  52. data/exe/tsikol +6 -0
  53. data/lib/tsikol/cli/templates/Gemfile.erb +10 -0
  54. data/lib/tsikol/cli/templates/README.md.erb +38 -0
  55. data/lib/tsikol/cli/templates/gitignore.erb +49 -0
  56. data/lib/tsikol/cli/templates/prompt.rb.erb +53 -0
  57. data/lib/tsikol/cli/templates/resource.rb.erb +29 -0
  58. data/lib/tsikol/cli/templates/server.rb.erb +24 -0
  59. data/lib/tsikol/cli/templates/tool.rb.erb +60 -0
  60. data/lib/tsikol/cli.rb +203 -0
  61. data/lib/tsikol/error_handler.rb +141 -0
  62. data/lib/tsikol/health.rb +198 -0
  63. data/lib/tsikol/http_transport.rb +72 -0
  64. data/lib/tsikol/lifecycle.rb +149 -0
  65. data/lib/tsikol/middleware.rb +168 -0
  66. data/lib/tsikol/prompt.rb +101 -0
  67. data/lib/tsikol/resource.rb +53 -0
  68. data/lib/tsikol/router.rb +190 -0
  69. data/lib/tsikol/server.rb +660 -0
  70. data/lib/tsikol/stdio_transport.rb +108 -0
  71. data/lib/tsikol/test_helpers.rb +261 -0
  72. data/lib/tsikol/tool.rb +111 -0
  73. data/lib/tsikol/version.rb +5 -0
  74. data/lib/tsikol.rb +72 -0
  75. metadata +219 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 486f6d3cabbbf5b62f65a7135c592c1f1e23bf8d8f0ca5f7cdd72a3519230ec2
4
+ data.tar.gz: 4ad29f7c0cd2235bb954472cddae5adbe2e9664fc1094581ec1bfa18506d609f
5
+ SHA512:
6
+ metadata.gz: 226b841f33b0c3f7cbec1a42f0b706fa262a0b86fe512f60d0e063dcbd98eaa38801eac80dd204c86314d50bd4a08c4ab3eb2089e38e9a9f62d6e5119626c528
7
+ data.tar.gz: 77e614efd0dc4a7211da3b9602a52bed1f26b6e1b7fffa5c38b75eaa7a3091dc13aef95317a2a04ffea7104ae52d3dbaed897c692cebf0d857d915c220794568
data/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2024-01-29
9
+
10
+ ### Added
11
+ - Initial release of Tsikol MCP Framework
12
+ - Full MCP protocol support (Tools, Resources, Prompts)
13
+ - Logging, Completion, and Sampling capabilities
14
+ - Middleware system for cross-cutting concerns
15
+ - Error handling with circuit breakers
16
+ - Lifecycle hooks (server and tool-level)
17
+ - Built-in health monitoring and metrics
18
+ - Testing utilities and mock client
19
+ - CLI tool with generators
20
+ - Rails-like project structure
21
+ - Auto-discovery of components
22
+ - Comprehensive documentation and examples
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,84 @@
1
+ # Contributing to Tsikol
2
+
3
+ We love your input! We want to make contributing to Tsikol as easy and transparent as possible, whether it's:
4
+
5
+ - Reporting a bug
6
+ - Discussing the current state of the code
7
+ - Submitting a fix
8
+ - Proposing new features
9
+ - Becoming a maintainer
10
+
11
+ ## We Develop with Github
12
+
13
+ We use GitHub to host code, to track issues and feature requests, as well as accept pull requests.
14
+
15
+ ## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html)
16
+
17
+ Pull requests are the best way to propose changes to the codebase:
18
+
19
+ 1. Fork the repo and create your branch from `main`.
20
+ 2. If you've added code that should be tested, add tests.
21
+ 3. If you've changed APIs, update the documentation.
22
+ 4. Ensure the test suite passes.
23
+ 5. Make sure your code lints.
24
+ 6. Issue that pull request!
25
+
26
+ ## Any contributions you make will be under the MIT Software License
27
+
28
+ In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
29
+
30
+ ## Report bugs using Github's [issues](https://github.com/arturodz/tsikol/issues)
31
+
32
+ We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/arturodz/tsikol/issues/new); it's that easy!
33
+
34
+ ## Write bug reports with detail, background, and sample code
35
+
36
+ **Great Bug Reports** tend to have:
37
+
38
+ - A quick summary and/or background
39
+ - Steps to reproduce
40
+ - Be specific!
41
+ - Give sample code if you can
42
+ - What you expected would happen
43
+ - What actually happens
44
+ - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
45
+
46
+ ## Development Setup
47
+
48
+ 1. Fork and clone the repository
49
+ 2. Run `bundle install`
50
+ 3. Run tests with `bundle exec rake test`
51
+ 4. Make your changes
52
+ 5. Add tests for your changes
53
+ 6. Run tests again to ensure they pass
54
+ 7. Submit a pull request
55
+
56
+ ## Testing
57
+
58
+ ```bash
59
+ # Run all tests
60
+ bundle exec rake test
61
+
62
+ # Run specific test file
63
+ ruby -Ilib:test test/example_test.rb
64
+ ```
65
+
66
+ ## Code Style
67
+
68
+ - Follow Ruby community style guidelines
69
+ - Use RuboCop for linting: `bundle exec rubocop`
70
+ - Keep methods small and focused
71
+ - Write descriptive commit messages
72
+
73
+ ## Adding New Features
74
+
75
+ When adding new features:
76
+
77
+ 1. Update the appropriate documentation
78
+ 2. Add examples if applicable
79
+ 3. Update the CHANGELOG.md
80
+ 4. Add tests covering the new functionality
81
+
82
+ ## License
83
+
84
+ By contributing, you agree that your contributions will be licensed under its MIT License.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Tsikol Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,579 @@
1
+ # Tsikol - Ruby MCP Framework
2
+
3
+ A elegant and easy to use framework for building Model Context Protocol (MCP) servers in Ruby.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Rails-like Structure** - Familiar project organization with `app/tools`, `app/resources`, `app/prompts`
8
+ - 🔧 **Flexible DSL** - Define components inline or in separate files
9
+ - 🔄 **Full MCP Protocol Support** - Tools, Resources, Prompts, Logging, Completion, Sampling
10
+ - 🛡️ **Middleware System** - Add cross-cutting concerns like auth, rate limiting, logging
11
+ - 📊 **Built-in Monitoring** - Health checks, metrics, error tracking
12
+ - 🧪 **Testing Utilities** - Comprehensive test helpers and mock client
13
+ - ⚡ **Hot Reload** - Auto-discovery of components
14
+ - 🔍 **Advanced Error Handling** - Circuit breakers, error recovery, detailed logging
15
+
16
+ ## Installation
17
+
18
+ Add to your Gemfile:
19
+
20
+ ```ruby
21
+ gem 'tsikol'
22
+ ```
23
+
24
+ Or install directly:
25
+
26
+ ```bash
27
+ gem install tsikol
28
+ ```
29
+
30
+ ## CLI Usage
31
+
32
+ Tsikol includes a powerful CLI tool for scaffolding projects and generating components.
33
+
34
+ ### Create a New Project
35
+
36
+ ```bash
37
+ tsikol new my-mcp-server
38
+ cd my-mcp-server
39
+ bundle install
40
+ ```
41
+
42
+ This creates a complete project structure with:
43
+ - `server.rb` - Main server file
44
+ - `Gemfile` - Dependencies
45
+ - `app/` directory structure for components
46
+ - README and .gitignore
47
+
48
+ ### Generate Components
49
+
50
+ The CLI can generate tools, resources, and prompts with automatic server.rb updates:
51
+
52
+ #### Generate a Tool
53
+
54
+ ```bash
55
+ # Basic tool
56
+ tsikol generate tool calculate
57
+
58
+ # Tool with parameters (name:type format)
59
+ tsikol generate tool calculate a:number b:number operation:string
60
+
61
+ # Optional parameters use ? suffix
62
+ tsikol generate tool weather_forecast location:string days?:integer units?:string
63
+
64
+ # Short alias
65
+ tsikol g tool my_tool param1:string param2:boolean
66
+ ```
67
+
68
+ #### Generate a Resource
69
+
70
+ ```bash
71
+ # Basic resource
72
+ tsikol generate resource system_status
73
+
74
+ # Resource with custom URI (auto-converts underscores to slashes)
75
+ tsikol generate resource user_profile # Creates URI: user/profile
76
+
77
+ # Short alias
78
+ tsikol g resource my_data
79
+ ```
80
+
81
+ #### Generate a Prompt
82
+
83
+ ```bash
84
+ # Basic prompt
85
+ tsikol generate prompt code_review
86
+
87
+ # Prompt with arguments
88
+ tsikol generate prompt code_review language:string code:string style?:string
89
+
90
+ # Short alias
91
+ tsikol g prompt chat_assistant topic:string context?:string
92
+ ```
93
+
94
+ ### How the CLI Works
95
+
96
+ 1. **Generates the component file** in the appropriate directory:
97
+ - Tools → `app/tools/`
98
+ - Resources → `app/resources/`
99
+ - Prompts → `app/prompts/`
100
+
101
+ 2. **Updates server.rb automatically**:
102
+ - Adds the require statement
103
+ - Registers the component in the routes
104
+
105
+ 3. **Smart insertion** - Components are grouped by type in server.rb
106
+
107
+ ### Example Workflow
108
+
109
+ ```bash
110
+ # Create a new weather service
111
+ tsikol new weather-service
112
+ cd weather-service
113
+
114
+ # Generate tools
115
+ tsikol g tool get_current_weather location:string units?:string
116
+ tsikol g tool get_forecast location:string days:integer
117
+
118
+ # Generate resources
119
+ tsikol g resource weather_alerts
120
+ tsikol g resource service_status
121
+
122
+ # Generate prompts
123
+ tsikol g prompt weather_chat city:string topic:string
124
+
125
+ # Your server.rb is automatically updated with all components!
126
+ ./server.rb
127
+ ```
128
+
129
+ ## Quick Start
130
+
131
+ ### Simple Server
132
+
133
+ ```ruby
134
+ #!/usr/bin/env ruby
135
+ require 'tsikol'
136
+
137
+ Tsikol.server "my-server" do
138
+ tool "greet" do |name:|
139
+ "Hello, #{name}!"
140
+ end
141
+
142
+ resource "status" do
143
+ "Server is running"
144
+ end
145
+
146
+ prompt "chat" do |topic:|
147
+ "Let's discuss #{topic}"
148
+ end
149
+ end
150
+ ```
151
+
152
+ ### Rails-like Structure
153
+
154
+ ```ruby
155
+ # server.rb
156
+ require 'tsikol'
157
+
158
+ Tsikol.start(name: "weather-service") do
159
+ # Direct class references
160
+ tool GetCurrentWeather
161
+ tool GetForecast
162
+ resource WeatherAlerts
163
+ prompt WeatherChat
164
+ end
165
+ ```
166
+
167
+ ```ruby
168
+ # app/tools/get_current_weather.rb
169
+ class GetCurrentWeather < Tsikol::Tool
170
+ description "Get current weather for a location"
171
+
172
+ parameter :location do
173
+ type :string
174
+ required
175
+ description "City name"
176
+
177
+ complete do |partial|
178
+ ["New York", "London", "Tokyo"].select { |c| c.start_with?(partial) }
179
+ end
180
+ end
181
+
182
+ def execute(location:)
183
+ "Currently 72°F in #{location}"
184
+ end
185
+ end
186
+ ```
187
+
188
+ ## Core Concepts
189
+
190
+ ### Tools
191
+
192
+ Tools are functions that can be called by the MCP client:
193
+
194
+ ```ruby
195
+ # Inline definition
196
+ tool "calculate" do |a:, b:, operation: "add"|
197
+ case operation
198
+ when "add" then a + b
199
+ when "subtract" then a - b
200
+ when "multiply" then a * b
201
+ when "divide" then b.zero? ? "Error: Division by zero" : a.to_f / b
202
+ end
203
+ end
204
+
205
+ # Class-based definition
206
+ class Calculate < Tsikol::Tool
207
+ description "Perform calculations"
208
+
209
+ parameter :a do
210
+ type :number
211
+ required
212
+ description "First number"
213
+ end
214
+
215
+ parameter :b do
216
+ type :number
217
+ required
218
+ description "Second number"
219
+ end
220
+
221
+ parameter :operation do
222
+ type :string
223
+ optional
224
+ default "add"
225
+ enum ["add", "subtract", "multiply", "divide"]
226
+ end
227
+
228
+ def execute(a:, b:, operation: "add")
229
+ # Implementation
230
+ end
231
+ end
232
+ ```
233
+
234
+ ### Resources
235
+
236
+ Resources provide data that can be read by the client:
237
+
238
+ ```ruby
239
+ # Inline definition
240
+ resource "config/database" do
241
+ {
242
+ host: ENV['DB_HOST'],
243
+ port: ENV['DB_PORT'],
244
+ name: ENV['DB_NAME']
245
+ }.to_json
246
+ end
247
+
248
+ # Class-based definition
249
+ class DatabaseConfig < Tsikol::Resource
250
+ uri "config/database"
251
+ description "Database configuration"
252
+
253
+ def read
254
+ # Return content
255
+ end
256
+ end
257
+ ```
258
+
259
+ ### Prompts
260
+
261
+ Prompts generate messages for AI interactions:
262
+
263
+ ```ruby
264
+ # Inline definition
265
+ prompt "code_review" do |language:, code:|
266
+ "Review this #{language} code:\n```#{language}\n#{code}\n```"
267
+ end
268
+
269
+ # Class-based definition
270
+ class CodeReview < Tsikol::Prompt
271
+ name "code_review"
272
+ description "Generate code review prompt"
273
+
274
+ argument :language do
275
+ type :string
276
+ required
277
+ complete do |partial|
278
+ ["ruby", "python", "javascript"].select { |l| l.start_with?(partial) }
279
+ end
280
+ end
281
+
282
+ def get_messages(language:, code:)
283
+ [{
284
+ role: "user",
285
+ content: {
286
+ type: "text",
287
+ text: "Review this #{language} code:\n```#{language}\n#{code}\n```"
288
+ }
289
+ }]
290
+ end
291
+ end
292
+ ```
293
+
294
+ ### Completion (Autocomplete)
295
+
296
+ Provide intelligent autocomplete suggestions for tool parameters and prompt arguments:
297
+
298
+ ```ruby
299
+ # Tool with parameter completion
300
+ class SearchFiles < Tsikol::Tool
301
+ description "Search for files in the project"
302
+
303
+ parameter :file_type do
304
+ type :string
305
+ required
306
+ description "Type of file to search for"
307
+
308
+ complete do |partial|
309
+ # Return suggestions based on partial input
310
+ extensions = ["rb", "js", "py", "md", "yml", "json", "xml"]
311
+ extensions.select { |ext| ext.start_with?(partial) }
312
+ end
313
+ end
314
+
315
+ parameter :directory do
316
+ type :string
317
+ optional
318
+ description "Directory to search in"
319
+
320
+ complete do |partial|
321
+ # Dynamic completion based on filesystem
322
+ Dir.glob("#{partial}*").select { |f| File.directory?(f) }
323
+ end
324
+ end
325
+
326
+ def execute(file_type:, directory: ".")
327
+ Dir.glob("#{directory}/**/*.#{file_type}")
328
+ end
329
+ end
330
+
331
+ # Inline completion for tools
332
+ tool "database_query" do |table:, operation:|
333
+ "Executing #{operation} on #{table}"
334
+ end
335
+
336
+ # Define completions separately
337
+ completion_for "tool", "database_query", "table" do |partial|
338
+ # List available tables
339
+ ["users", "posts", "comments", "tags"].select { |t| t.start_with?(partial) }
340
+ end
341
+
342
+ completion_for "tool", "database_query", "operation" do |partial|
343
+ ["select", "insert", "update", "delete"].select { |op| op.start_with?(partial) }
344
+ end
345
+ ```
346
+
347
+ ## Advanced Features
348
+
349
+ ### Middleware
350
+
351
+ Add cross-cutting concerns with middleware:
352
+
353
+ ```ruby
354
+ Tsikol.server "my-server" do
355
+ # Built-in middleware
356
+ use Tsikol::LoggingMiddleware
357
+ use Tsikol::RateLimitMiddleware, max_requests: 100, window: 60
358
+ use Tsikol::ValidationMiddleware
359
+
360
+ # Custom middleware
361
+ use AuthMiddleware, api_keys: ["secret-key"]
362
+
363
+ # Tools, resources, prompts...
364
+ end
365
+ ```
366
+
367
+ ### Lifecycle Hooks
368
+
369
+ ```ruby
370
+ Tsikol.server "my-server" do
371
+ before_start do
372
+ log :info, "Initializing connections..."
373
+ # Setup code
374
+ end
375
+
376
+ after_start do
377
+ log :info, "Server ready!"
378
+ end
379
+
380
+ before_stop do
381
+ log :info, "Cleaning up..."
382
+ # Cleanup code
383
+ end
384
+
385
+ # Tool-specific hooks
386
+ before_tool "critical_operation" do |params|
387
+ log :warning, "About to run critical operation", data: params
388
+ end
389
+
390
+ after_tool "critical_operation" do |params, result|
391
+ log :info, "Critical operation completed", data: { result: result }
392
+ end
393
+ end
394
+ ```
395
+
396
+ ### Sampling (AI Assistance)
397
+
398
+ Enable AI-assisted content generation where the MCP server can request help from the AI client:
399
+
400
+ ```ruby
401
+ Tsikol.server "my-server" do
402
+ # Enable sampling and define handler
403
+ on_sampling do |request|
404
+ # The request contains:
405
+ # - messages: Array of conversation messages
406
+ # - model_preferences: Hints about which model to use
407
+ # - system_prompt: Optional system instructions
408
+ # - max_tokens: Maximum response length
409
+
410
+ # In production, the MCP client (e.g., Claude) handles this
411
+ # For testing, you can simulate responses:
412
+ {
413
+ role: "assistant",
414
+ content: {
415
+ type: "text",
416
+ text: "AI-generated response based on: #{request[:messages].last}"
417
+ }
418
+ }
419
+ end
420
+
421
+ # Tool that uses AI assistance
422
+ tool "write_documentation" do |code:, style: "technical"|
423
+ # In a real MCP client, this would trigger a sampling request
424
+ prompt = case style
425
+ when "technical"
426
+ "Write technical documentation for this code"
427
+ when "tutorial"
428
+ "Write a beginner-friendly tutorial for this code"
429
+ when "api"
430
+ "Write API reference documentation"
431
+ end
432
+
433
+ # The actual AI response would come from the client
434
+ "#{prompt}:\n\n```ruby\n#{code}\n```"
435
+ end
436
+
437
+ # Advanced example with context
438
+ tool "refactor_code" do |code:, goal:|
439
+ # Build conversation for AI
440
+ messages = [
441
+ {
442
+ role: "system",
443
+ content: "You are an expert Ruby developer focused on clean code."
444
+ },
445
+ {
446
+ role: "user",
447
+ content: "Refactor this code to #{goal}:\n\n```ruby\n#{code}\n```"
448
+ }
449
+ ]
450
+
451
+ # In production, this would send a sampling request
452
+ # with the messages to the MCP client
453
+ "Refactored code would appear here"
454
+ end
455
+ end
456
+
457
+ # Class-based tool with sampling
458
+ class CodeGenerator < Tsikol::Tool
459
+ description "Generate code using AI assistance"
460
+
461
+ parameter :description do
462
+ type :string
463
+ required
464
+ description "What code to generate"
465
+ end
466
+
467
+ parameter :language do
468
+ type :string
469
+ optional
470
+ default "ruby"
471
+ enum ["ruby", "python", "javascript", "go"]
472
+ end
473
+
474
+ def execute(description:, language: "ruby")
475
+ # Build sampling request
476
+ sampling_request = {
477
+ messages: [
478
+ {
479
+ role: "user",
480
+ content: {
481
+ type: "text",
482
+ text: "Generate #{language} code that: #{description}"
483
+ }
484
+ }
485
+ ],
486
+ model_preferences: {
487
+ hints: [{ name: "claude-3-sonnet" }],
488
+ temperature: 0.7
489
+ },
490
+ max_tokens: 2000
491
+ }
492
+
493
+ # This would be sent to the MCP client
494
+ # Response would contain AI-generated code
495
+ "Generated #{language} code for: #{description}"
496
+ end
497
+ end
498
+ ```
499
+
500
+ ### Health Monitoring
501
+
502
+ Built-in health endpoints are automatically added:
503
+
504
+ - `resource "health"` - Basic health status
505
+ - `resource "health/detailed"` - Detailed health with metrics
506
+ - `resource "metrics"` - Raw metrics data
507
+
508
+ ### Error Handling
509
+
510
+ Advanced error handling with circuit breakers:
511
+
512
+ ```ruby
513
+ tool "external_api" do
514
+ # Automatically wrapped with circuit breaker
515
+ # After 5 failures, circuit opens for 60 seconds
516
+ call_external_service
517
+ end
518
+ ```
519
+
520
+ ## Testing
521
+
522
+ Tsikol includes comprehensive testing utilities:
523
+
524
+ ```ruby
525
+ require 'tsikol/test_helpers'
526
+
527
+ class MyServerTest < Minitest::Test
528
+ include Tsikol::TestHelpers::Assertions
529
+
530
+ def setup
531
+ @server = create_my_server
532
+ @client = Tsikol::TestHelpers::TestClient.new(@server)
533
+ end
534
+
535
+ def test_echo_tool
536
+ @client.initialize_connection
537
+ assert_tool_result(@client, "echo", { "msg" => "Hi" }, "Echo: Hi")
538
+ end
539
+
540
+ def test_error_handling
541
+ response = @client.call_tool("failing_tool")
542
+ assert_error_response(response, -32603, /Internal error/)
543
+ end
544
+ end
545
+ ```
546
+
547
+ ## Project Structure
548
+
549
+ ```
550
+ my-mcp-server/
551
+ ├── server.rb # Main entry point
552
+ ├── Gemfile
553
+ ├── app/
554
+ │ ├── tools/ # Tool classes
555
+ │ ├── resources/ # Resource classes
556
+ │ └── prompts/ # Prompt classes
557
+ ├── config/
558
+ │ └── tsikol.yml # Configuration (optional)
559
+ └── test/
560
+ └── server_test.rb # Tests
561
+ ```
562
+
563
+ ## Examples
564
+
565
+ See the `examples/` directory for complete examples:
566
+
567
+ - `basic.rb` - Simple inline server
568
+ - `weather-service/` - Full Rails-like project
569
+ - `middleware_example.rb` - Middleware demonstration
570
+ - `sampling_example.rb` - AI assistance
571
+ - `advanced_features.rb` - All features combined
572
+
573
+ ## License
574
+
575
+ MIT License - see LICENSE file for details.
576
+
577
+ ## Acknowledgments
578
+
579
+ Built for the Model Context Protocol (MCP) by Anthropic.