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
@@ -0,0 +1,434 @@
1
+ # Project Structure Guide
2
+
3
+ Understanding how Tsikol projects are organized helps you build maintainable MCP servers.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Directory Layout](#directory-layout)
8
+ 2. [File Organization](#file-organization)
9
+ 3. [Naming Conventions](#naming-conventions)
10
+ 4. [Component Structure](#component-structure)
11
+ 5. [Configuration](#configuration)
12
+ 6. [Best Practices](#best-practices)
13
+
14
+ ## Directory Layout
15
+
16
+ A typical Tsikol project follows this structure:
17
+
18
+ ```
19
+ my-mcp-server/
20
+ ├── server.rb # Main server file and entry point
21
+ ├── Gemfile # Ruby dependencies
22
+ ├── README.md # Project documentation
23
+ ├── .gitignore # Git ignore rules
24
+ ├── app/ # Application components
25
+ │ ├── tools/ # Tool implementations
26
+ │ ├── resources/ # Resource implementations
27
+ │ └── prompts/ # Prompt implementations
28
+ ├── config/ # Configuration files (optional)
29
+ ├── lib/ # Additional libraries (optional)
30
+ ├── test/ # Test files
31
+ └── tmp/ # Temporary files (logs, etc.)
32
+ ```
33
+
34
+ ## File Organization
35
+
36
+ ### Tools Directory (`app/tools/`)
37
+
38
+ Tools are organized by functionality:
39
+
40
+ ```
41
+ app/tools/
42
+ ├── file_manager.rb # Single tool
43
+ ├── database_query.rb # Single tool
44
+ └── analytics/ # Grouped tools
45
+ ├── report_generator.rb
46
+ ├── data_processor.rb
47
+ └── metrics_calculator.rb
48
+ ```
49
+
50
+ ### Resources Directory (`app/resources/`)
51
+
52
+ Resources follow URI-based organization:
53
+
54
+ ```
55
+ app/resources/
56
+ ├── system_status.rb # URI: system/status
57
+ ├── health_check.rb # URI: health/check
58
+ └── api/ # Grouped resources
59
+ ├── endpoints.rb # URI: api/endpoints
60
+ └── documentation.rb # URI: api/documentation
61
+ ```
62
+
63
+ ### Prompts Directory (`app/prompts/`)
64
+
65
+ Prompts are organized by purpose:
66
+
67
+ ```
68
+ app/prompts/
69
+ ├── code_assistant.rb # Single prompt
70
+ ├── writer.rb # Single prompt
71
+ └── development/ # Grouped prompts
72
+ ├── debugger.rb
73
+ ├── refactorer.rb
74
+ └── reviewer.rb
75
+ ```
76
+
77
+ ## Naming Conventions
78
+
79
+ ### File Names
80
+
81
+ - Use snake_case: `file_manager.rb`, `system_status.rb`
82
+ - Match the class name: `FileManager` → `file_manager.rb`
83
+ - For namespaced classes: `Analytics::ReportGenerator` → `analytics/report_generator.rb`
84
+
85
+ ### Class Names
86
+
87
+ - Use PascalCase: `FileManager`, `SystemStatus`
88
+ - Inherit from appropriate base: `< Tsikol::Tool`, `< Tsikol::Resource`, `< Tsikol::Prompt`
89
+ - Use modules for namespacing: `module Analytics; class ReportGenerator < Tsikol::Tool`
90
+
91
+ ### URIs and Names
92
+
93
+ - Resources: URI matches file structure
94
+ - File: `app/resources/weather/alerts.rb`
95
+ - URI: `weather/alerts`
96
+ - Tools: Name is class name in snake_case
97
+ - Class: `FileManager`
98
+ - Name: `file_manager`
99
+ - Prompts: Explicit name in class
100
+ - Class: `CodeAssistant`
101
+ - Name: `code_assistant` (set with `name "code_assistant"`)
102
+
103
+ ## Component Structure
104
+
105
+ ### Tool Structure
106
+
107
+ ```ruby
108
+ # app/tools/example_tool.rb
109
+ class ExampleTool < Tsikol::Tool
110
+ description "Brief description of what this tool does"
111
+
112
+ parameter :required_param do
113
+ type :string
114
+ required
115
+ description "What this parameter is for"
116
+ end
117
+
118
+ parameter :optional_param do
119
+ type :integer
120
+ optional
121
+ default 10
122
+ description "Optional parameter with default"
123
+ end
124
+
125
+ def execute(required_param:, optional_param: 10)
126
+ # Implementation
127
+ end
128
+
129
+ private
130
+
131
+ def helper_method
132
+ # Private helpers
133
+ end
134
+
135
+ def set_server(server)
136
+ @server = server
137
+ # Setup logging
138
+ end
139
+ end
140
+ ```
141
+
142
+ ### Resource Structure
143
+
144
+ ```ruby
145
+ # app/resources/example_resource.rb
146
+ class ExampleResource < Tsikol::Resource
147
+ uri "example/resource"
148
+ description "What this resource provides"
149
+
150
+ def read
151
+ # Return data as string (JSON, text, etc.)
152
+ {
153
+ data: fetch_data,
154
+ timestamp: Time.now.iso8601
155
+ }.to_json
156
+ end
157
+
158
+ private
159
+
160
+ def fetch_data
161
+ # Implementation
162
+ end
163
+
164
+ def set_server(server)
165
+ @server = server
166
+ end
167
+ end
168
+ ```
169
+
170
+ ### Prompt Structure
171
+
172
+ ```ruby
173
+ # app/prompts/example_prompt.rb
174
+ class ExamplePrompt < Tsikol::Prompt
175
+ name "example_prompt"
176
+ description "What this prompt helps with"
177
+
178
+ argument :topic do
179
+ type :string
180
+ required
181
+ description "The topic to discuss"
182
+ end
183
+
184
+ def get_messages(topic:)
185
+ [
186
+ {
187
+ role: "system",
188
+ content: {
189
+ type: "text",
190
+ text: "You are a helpful assistant."
191
+ }
192
+ },
193
+ {
194
+ role: "user",
195
+ content: {
196
+ type: "text",
197
+ text: "Help me with: #{topic}"
198
+ }
199
+ }
200
+ ]
201
+ end
202
+
203
+ def set_server(server)
204
+ @server = server
205
+ end
206
+ end
207
+ ```
208
+
209
+ ## Configuration
210
+
211
+ ### Server Configuration
212
+
213
+ The main `server.rb` file configures your MCP server:
214
+
215
+ ```ruby
216
+ #!/usr/bin/env ruby
217
+ # frozen_string_literal: true
218
+
219
+ require 'bundler/setup'
220
+ require 'tsikol'
221
+
222
+ # Require all components
223
+ Dir.glob('app/**/*.rb').each { |file| require_relative file }
224
+
225
+ Tsikol.start(name: "my-mcp-server") do
226
+ # Register components
227
+ tool FileManager
228
+ tool DatabaseQuery
229
+ resource SystemStatus
230
+ prompt CodeAssistant
231
+
232
+ # Enable capabilities
233
+ logging true
234
+ completion true
235
+ sampling true
236
+
237
+ # Add middleware
238
+ use Tsikol::LoggingMiddleware
239
+ use Tsikol::RateLimitMiddleware, max_requests: 100
240
+
241
+ # Lifecycle hooks
242
+ before_start do
243
+ # Initialize
244
+ end
245
+
246
+ after_start do
247
+ # Ready
248
+ end
249
+ end
250
+ ```
251
+
252
+ ### Environment Configuration
253
+
254
+ Use environment variables for configuration:
255
+
256
+ ```ruby
257
+ # config/environment.rb
258
+ module Config
259
+ DATABASE_URL = ENV.fetch('DATABASE_URL', 'sqlite://db/development.db')
260
+ API_KEY = ENV.fetch('API_KEY', nil)
261
+ LOG_LEVEL = ENV.fetch('LOG_LEVEL', 'info')
262
+ MAX_REQUEST_SIZE = ENV.fetch('MAX_REQUEST_SIZE', '1048576').to_i
263
+ end
264
+
265
+ # In server.rb
266
+ require_relative 'config/environment'
267
+ ```
268
+
269
+ ## Best Practices
270
+
271
+ ### 1. Single Responsibility
272
+
273
+ Each component should have one clear purpose:
274
+
275
+ ```ruby
276
+ # Good: Focused tool
277
+ class FileReader < Tsikol::Tool
278
+ description "Read file contents"
279
+ # Just reads files
280
+ end
281
+
282
+ # Bad: Doing too much
283
+ class FileManager < Tsikol::Tool
284
+ description "Read, write, delete, compress, upload files"
285
+ # Too many responsibilities
286
+ end
287
+ ```
288
+
289
+ ### 2. Consistent Naming
290
+
291
+ Follow conventions throughout:
292
+
293
+ ```ruby
294
+ # File: app/tools/code_analyzer.rb
295
+ class CodeAnalyzer < Tsikol::Tool
296
+ # Matches file name
297
+ end
298
+
299
+ # File: app/resources/system/metrics.rb
300
+ module System
301
+ class Metrics < Tsikol::Resource
302
+ uri "system/metrics" # Matches file path
303
+ end
304
+ end
305
+ ```
306
+
307
+ ### 3. Modular Organization
308
+
309
+ Group related components:
310
+
311
+ ```
312
+ app/tools/git/
313
+ ├── commit.rb
314
+ ├── branch.rb
315
+ ├── merge.rb
316
+ └── push.rb
317
+ ```
318
+
319
+ ### 4. Shared Code
320
+
321
+ Put shared code in lib:
322
+
323
+ ```ruby
324
+ # lib/database.rb
325
+ module Database
326
+ def self.connection
327
+ @connection ||= establish_connection
328
+ end
329
+ end
330
+
331
+ # In tools
332
+ require_relative '../../lib/database'
333
+
334
+ class QueryTool < Tsikol::Tool
335
+ def execute(query:)
336
+ Database.connection.execute(query)
337
+ end
338
+ end
339
+ ```
340
+
341
+ ### 5. Testing Structure
342
+
343
+ Mirror your app structure:
344
+
345
+ ```
346
+ test/
347
+ ├── tools/
348
+ │ ├── file_manager_test.rb
349
+ │ └── analytics/
350
+ │ └── report_generator_test.rb
351
+ ├── resources/
352
+ │ └── system_status_test.rb
353
+ └── test_helper.rb
354
+ ```
355
+
356
+ ## Advanced Patterns
357
+
358
+ ### Namespaced Components
359
+
360
+ For larger projects:
361
+
362
+ ```ruby
363
+ # app/tools/analytics/sales_report.rb
364
+ module Analytics
365
+ class SalesReport < Tsikol::Tool
366
+ description "Generate sales reports"
367
+
368
+ def execute(period:)
369
+ # Implementation
370
+ end
371
+ end
372
+ end
373
+
374
+ # In server.rb
375
+ tool Analytics::SalesReport
376
+ ```
377
+
378
+ ### Shared Base Classes
379
+
380
+ Create base classes for common functionality:
381
+
382
+ ```ruby
383
+ # app/tools/base_tool.rb
384
+ class BaseTool < Tsikol::Tool
385
+ def set_server(server)
386
+ @server = server
387
+ setup_logging
388
+ setup_metrics
389
+ end
390
+
391
+ private
392
+
393
+ def setup_logging
394
+ define_singleton_method(:log) do |level, message, data: nil|
395
+ @server.log(level, message, data: data)
396
+ end
397
+ end
398
+
399
+ def setup_metrics
400
+ @metrics = @server.metrics
401
+ end
402
+ end
403
+
404
+ # app/tools/specific_tool.rb
405
+ class SpecificTool < BaseTool
406
+ # Inherits common setup
407
+ end
408
+ ```
409
+
410
+ ### Plugin System
411
+
412
+ For extensible servers:
413
+
414
+ ```ruby
415
+ # lib/plugin_loader.rb
416
+ module PluginLoader
417
+ def self.load_plugins(server)
418
+ Dir.glob('plugins/*/init.rb').each do |plugin|
419
+ require_relative plugin
420
+ end
421
+ end
422
+ end
423
+
424
+ # plugins/custom_tools/init.rb
425
+ require_relative 'tools/custom_tool'
426
+ Tsikol.current_server.tool CustomTool
427
+ ```
428
+
429
+ ## Next Steps
430
+
431
+ - Learn about [Tools](tools.md) in detail
432
+ - Understand [Resources](resources.md)
433
+ - Explore [Prompts](prompts.md)
434
+ - Set up [Testing](testing.md)