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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +22 -0
- data/CONTRIBUTING.md +84 -0
- data/LICENSE +21 -0
- data/README.md +579 -0
- data/Rakefile +12 -0
- data/docs/README.md +69 -0
- data/docs/api/middleware.md +721 -0
- data/docs/api/prompt.md +858 -0
- data/docs/api/resource.md +651 -0
- data/docs/api/server.md +509 -0
- data/docs/api/test-helpers.md +591 -0
- data/docs/api/tool.md +527 -0
- data/docs/cookbook/authentication.md +651 -0
- data/docs/cookbook/caching.md +877 -0
- data/docs/cookbook/dynamic-tools.md +970 -0
- data/docs/cookbook/error-handling.md +887 -0
- data/docs/cookbook/logging.md +1044 -0
- data/docs/cookbook/rate-limiting.md +717 -0
- data/docs/examples/code-assistant.md +922 -0
- data/docs/examples/complete-server.md +726 -0
- data/docs/examples/database-manager.md +1198 -0
- data/docs/examples/devops-tools.md +1382 -0
- data/docs/examples/echo-server.md +501 -0
- data/docs/examples/weather-service.md +822 -0
- data/docs/guides/completion.md +472 -0
- data/docs/guides/getting-started.md +462 -0
- data/docs/guides/middleware.md +823 -0
- data/docs/guides/project-structure.md +434 -0
- data/docs/guides/prompts.md +920 -0
- data/docs/guides/resources.md +720 -0
- data/docs/guides/sampling.md +804 -0
- data/docs/guides/testing.md +863 -0
- data/docs/guides/tools.md +627 -0
- data/examples/README.md +92 -0
- data/examples/advanced_features.rb +129 -0
- data/examples/basic-migrated/app/prompts/weather_chat.rb +44 -0
- data/examples/basic-migrated/app/resources/weather_alerts.rb +18 -0
- data/examples/basic-migrated/app/tools/get_current_weather.rb +34 -0
- data/examples/basic-migrated/app/tools/get_forecast.rb +30 -0
- data/examples/basic-migrated/app/tools/get_weather_by_coords.rb +48 -0
- data/examples/basic-migrated/server.rb +25 -0
- data/examples/basic.rb +73 -0
- data/examples/full_featured.rb +175 -0
- data/examples/middleware_example.rb +112 -0
- data/examples/sampling_example.rb +104 -0
- data/examples/weather-service/app/prompts/weather/chat.rb +90 -0
- data/examples/weather-service/app/resources/weather/alerts.rb +59 -0
- data/examples/weather-service/app/tools/weather/get_current.rb +82 -0
- data/examples/weather-service/app/tools/weather/get_forecast.rb +90 -0
- data/examples/weather-service/server.rb +28 -0
- data/exe/tsikol +6 -0
- data/lib/tsikol/cli/templates/Gemfile.erb +10 -0
- data/lib/tsikol/cli/templates/README.md.erb +38 -0
- data/lib/tsikol/cli/templates/gitignore.erb +49 -0
- data/lib/tsikol/cli/templates/prompt.rb.erb +53 -0
- data/lib/tsikol/cli/templates/resource.rb.erb +29 -0
- data/lib/tsikol/cli/templates/server.rb.erb +24 -0
- data/lib/tsikol/cli/templates/tool.rb.erb +60 -0
- data/lib/tsikol/cli.rb +203 -0
- data/lib/tsikol/error_handler.rb +141 -0
- data/lib/tsikol/health.rb +198 -0
- data/lib/tsikol/http_transport.rb +72 -0
- data/lib/tsikol/lifecycle.rb +149 -0
- data/lib/tsikol/middleware.rb +168 -0
- data/lib/tsikol/prompt.rb +101 -0
- data/lib/tsikol/resource.rb +53 -0
- data/lib/tsikol/router.rb +190 -0
- data/lib/tsikol/server.rb +660 -0
- data/lib/tsikol/stdio_transport.rb +108 -0
- data/lib/tsikol/test_helpers.rb +261 -0
- data/lib/tsikol/tool.rb +111 -0
- data/lib/tsikol/version.rb +5 -0
- data/lib/tsikol.rb +72 -0
- metadata +219 -0
data/docs/api/server.md
ADDED
@@ -0,0 +1,509 @@
|
|
1
|
+
# Server API Reference
|
2
|
+
|
3
|
+
The `Tsikol::Server` class is the core of your MCP server, handling protocol communication, component registration, and request routing.
|
4
|
+
|
5
|
+
## Class: Tsikol::Server
|
6
|
+
|
7
|
+
### Constructor
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
server = Tsikol::Server.new(name: "my-server", version: "1.0.0")
|
11
|
+
```
|
12
|
+
|
13
|
+
#### Parameters
|
14
|
+
|
15
|
+
- `name` (String, required): The server name
|
16
|
+
- `version` (String, optional): Server version (default: "1.0.0")
|
17
|
+
- `options` (Hash, optional): Additional configuration options
|
18
|
+
|
19
|
+
### Configuration Methods
|
20
|
+
|
21
|
+
#### `#use(middleware, options = {})`
|
22
|
+
|
23
|
+
Add middleware to the processing chain.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
server.use Tsikol::LoggingMiddleware, level: :debug
|
27
|
+
server.use AuthenticationMiddleware, secret_key: ENV['SECRET']
|
28
|
+
```
|
29
|
+
|
30
|
+
#### `#logging(enabled)`
|
31
|
+
|
32
|
+
Enable or disable logging capability.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
server.logging true
|
36
|
+
```
|
37
|
+
|
38
|
+
#### `#completion(enabled)`
|
39
|
+
|
40
|
+
Enable or disable completion support.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
server.completion true
|
44
|
+
```
|
45
|
+
|
46
|
+
#### `#sampling(enabled)`
|
47
|
+
|
48
|
+
Enable or disable sampling capability.
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
server.sampling true
|
52
|
+
```
|
53
|
+
|
54
|
+
### Component Registration
|
55
|
+
|
56
|
+
#### `#register_tool(name, &block)`
|
57
|
+
|
58
|
+
Register an inline tool.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
server.register_tool("echo") do |message:|
|
62
|
+
message
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
#### `#register_tool_class(klass)`
|
67
|
+
|
68
|
+
Register a tool class.
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
server.register_tool_class(FileManager)
|
72
|
+
# or
|
73
|
+
server.tool FileManager
|
74
|
+
```
|
75
|
+
|
76
|
+
#### `#register_tool_instance(instance)`
|
77
|
+
|
78
|
+
Register a tool instance.
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
tool = FileManager.new(config: config)
|
82
|
+
server.register_tool_instance(tool)
|
83
|
+
```
|
84
|
+
|
85
|
+
#### `#register_resource(uri, &block)`
|
86
|
+
|
87
|
+
Register an inline resource.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
server.register_resource("version") do
|
91
|
+
"1.0.0"
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
#### `#register_resource_class(klass)`
|
96
|
+
|
97
|
+
Register a resource class.
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
server.register_resource_class(SystemStatus)
|
101
|
+
# or
|
102
|
+
server.resource SystemStatus
|
103
|
+
```
|
104
|
+
|
105
|
+
#### `#register_prompt_class(klass)`
|
106
|
+
|
107
|
+
Register a prompt class.
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
server.register_prompt_class(CodeAssistant)
|
111
|
+
# or
|
112
|
+
server.prompt CodeAssistant
|
113
|
+
```
|
114
|
+
|
115
|
+
### Lifecycle Hooks
|
116
|
+
|
117
|
+
#### `#before_start(&block)`
|
118
|
+
|
119
|
+
Execute code before the server starts.
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
server.before_start do
|
123
|
+
puts "Initializing server..."
|
124
|
+
load_configuration
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
#### `#after_start(&block)`
|
129
|
+
|
130
|
+
Execute code after the server starts.
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
server.after_start do
|
134
|
+
puts "Server ready!"
|
135
|
+
notify_monitoring_service
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
#### `#before_stop(&block)`
|
140
|
+
|
141
|
+
Execute code before the server stops.
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
server.before_stop do
|
145
|
+
save_state
|
146
|
+
close_connections
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
#### `#after_stop(&block)`
|
151
|
+
|
152
|
+
Execute code after the server stops.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
server.after_stop do
|
156
|
+
puts "Server stopped"
|
157
|
+
cleanup_resources
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
### Request Handling
|
162
|
+
|
163
|
+
#### `#handle_request(request)`
|
164
|
+
|
165
|
+
Process a JSON-RPC request.
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
request = {
|
169
|
+
"jsonrpc" => "2.0",
|
170
|
+
"id" => 1,
|
171
|
+
"method" => "tools/call",
|
172
|
+
"params" => { "name" => "echo", "arguments" => { "message" => "Hello" } }
|
173
|
+
}
|
174
|
+
|
175
|
+
response = server.handle_request(request)
|
176
|
+
```
|
177
|
+
|
178
|
+
#### `#start`
|
179
|
+
|
180
|
+
Start the server and listen for requests on stdin/stdout.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
server.start # Blocks until interrupted
|
184
|
+
```
|
185
|
+
|
186
|
+
### Capability Methods
|
187
|
+
|
188
|
+
#### `#capabilities`
|
189
|
+
|
190
|
+
Get server capabilities.
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
caps = server.capabilities
|
194
|
+
# => {
|
195
|
+
# tools: { supported: true },
|
196
|
+
# resources: { supported: true },
|
197
|
+
# prompts: { supported: true },
|
198
|
+
# completion: { supported: true },
|
199
|
+
# sampling: { supported: true }
|
200
|
+
# }
|
201
|
+
```
|
202
|
+
|
203
|
+
#### `#logging_enabled?`
|
204
|
+
|
205
|
+
Check if logging is enabled.
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
if server.logging_enabled?
|
209
|
+
# Logging is available
|
210
|
+
end
|
211
|
+
```
|
212
|
+
|
213
|
+
#### `#completion_enabled?`
|
214
|
+
|
215
|
+
Check if completion is enabled.
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
if server.completion_enabled?
|
219
|
+
# Completion is available
|
220
|
+
end
|
221
|
+
```
|
222
|
+
|
223
|
+
#### `#sampling_enabled?`
|
224
|
+
|
225
|
+
Check if sampling is enabled.
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
if server.sampling_enabled?
|
229
|
+
# Sampling is available
|
230
|
+
end
|
231
|
+
```
|
232
|
+
|
233
|
+
### Logging Methods
|
234
|
+
|
235
|
+
#### `#log(level, message, data: nil)`
|
236
|
+
|
237
|
+
Log a message (only if logging is enabled).
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
server.log(:info, "Processing request", data: { method: "tools/call" })
|
241
|
+
server.log(:error, "Request failed", data: { error: e.message })
|
242
|
+
```
|
243
|
+
|
244
|
+
Log levels:
|
245
|
+
- `:debug`
|
246
|
+
- `:info`
|
247
|
+
- `:warning`
|
248
|
+
- `:error`
|
249
|
+
|
250
|
+
### Sampling Methods
|
251
|
+
|
252
|
+
#### `#sample_text(messages:, temperature: 0.7, max_tokens: nil, stop_sequences: nil, model_hint: nil)`
|
253
|
+
|
254
|
+
Request text generation from the client (only if sampling is enabled).
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
response = server.sample_text(
|
258
|
+
messages: [
|
259
|
+
{ role: "system", content: { type: "text", text: "You are helpful." } },
|
260
|
+
{ role: "user", content: { type: "text", text: "Hello!" } }
|
261
|
+
],
|
262
|
+
temperature: 0.5,
|
263
|
+
max_tokens: 100
|
264
|
+
)
|
265
|
+
|
266
|
+
if response[:error]
|
267
|
+
# Handle error
|
268
|
+
else
|
269
|
+
generated_text = response[:text]
|
270
|
+
end
|
271
|
+
```
|
272
|
+
|
273
|
+
### Utility Methods
|
274
|
+
|
275
|
+
#### `#name`
|
276
|
+
|
277
|
+
Get the server name.
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
server.name # => "my-server"
|
281
|
+
```
|
282
|
+
|
283
|
+
#### `#version`
|
284
|
+
|
285
|
+
Get the server version.
|
286
|
+
|
287
|
+
```ruby
|
288
|
+
server.version # => "1.0.0"
|
289
|
+
```
|
290
|
+
|
291
|
+
#### `#tools`
|
292
|
+
|
293
|
+
Get registered tools.
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
server.tools # => { "echo" => #<Proc>, "file_manager" => FileManager }
|
297
|
+
```
|
298
|
+
|
299
|
+
#### `#resources`
|
300
|
+
|
301
|
+
Get registered resources.
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
server.resources # => { "version" => #<Proc>, "system/status" => SystemStatus }
|
305
|
+
```
|
306
|
+
|
307
|
+
#### `#prompts`
|
308
|
+
|
309
|
+
Get registered prompts.
|
310
|
+
|
311
|
+
```ruby
|
312
|
+
server.prompts # => { "code_assistant" => CodeAssistant }
|
313
|
+
```
|
314
|
+
|
315
|
+
## DSL Methods
|
316
|
+
|
317
|
+
The server provides a DSL for configuration:
|
318
|
+
|
319
|
+
```ruby
|
320
|
+
Tsikol.server "my-server" do
|
321
|
+
# Enable capabilities
|
322
|
+
logging true
|
323
|
+
completion true
|
324
|
+
sampling true
|
325
|
+
|
326
|
+
# Add middleware
|
327
|
+
use Tsikol::LoggingMiddleware
|
328
|
+
use Tsikol::RateLimitMiddleware, max_requests: 100
|
329
|
+
|
330
|
+
# Register components
|
331
|
+
tool FileManager
|
332
|
+
resource SystemStatus
|
333
|
+
prompt CodeAssistant
|
334
|
+
|
335
|
+
# Inline tool
|
336
|
+
tool "echo" do |message:|
|
337
|
+
message
|
338
|
+
end
|
339
|
+
|
340
|
+
# Inline resource
|
341
|
+
resource "version" do
|
342
|
+
"1.0.0"
|
343
|
+
end
|
344
|
+
|
345
|
+
# Lifecycle hooks
|
346
|
+
before_start do
|
347
|
+
puts "Starting..."
|
348
|
+
end
|
349
|
+
|
350
|
+
after_start do
|
351
|
+
puts "Ready!"
|
352
|
+
end
|
353
|
+
end
|
354
|
+
```
|
355
|
+
|
356
|
+
## Starting the Server
|
357
|
+
|
358
|
+
### Method 1: Direct Start
|
359
|
+
|
360
|
+
```ruby
|
361
|
+
server = Tsikol::Server.new(name: "my-server")
|
362
|
+
# Configure server...
|
363
|
+
server.start
|
364
|
+
```
|
365
|
+
|
366
|
+
### Method 2: Using Tsikol.start
|
367
|
+
|
368
|
+
```ruby
|
369
|
+
Tsikol.start(name: "my-server") do
|
370
|
+
# Configuration block
|
371
|
+
tool MyTool
|
372
|
+
resource MyResource
|
373
|
+
end
|
374
|
+
```
|
375
|
+
|
376
|
+
### Method 3: Using Tsikol.server
|
377
|
+
|
378
|
+
```ruby
|
379
|
+
server = Tsikol.server "my-server" do
|
380
|
+
# Configuration block
|
381
|
+
end
|
382
|
+
|
383
|
+
# Later...
|
384
|
+
server.start
|
385
|
+
```
|
386
|
+
|
387
|
+
## Error Handling
|
388
|
+
|
389
|
+
The server handles various error conditions:
|
390
|
+
|
391
|
+
```ruby
|
392
|
+
# Invalid request format
|
393
|
+
{
|
394
|
+
jsonrpc: "2.0",
|
395
|
+
id: 1,
|
396
|
+
error: {
|
397
|
+
code: -32600,
|
398
|
+
message: "Invalid Request"
|
399
|
+
}
|
400
|
+
}
|
401
|
+
|
402
|
+
# Method not found
|
403
|
+
{
|
404
|
+
jsonrpc: "2.0",
|
405
|
+
id: 1,
|
406
|
+
error: {
|
407
|
+
code: -32601,
|
408
|
+
message: "Method not found"
|
409
|
+
}
|
410
|
+
}
|
411
|
+
|
412
|
+
# Invalid parameters
|
413
|
+
{
|
414
|
+
jsonrpc: "2.0",
|
415
|
+
id: 1,
|
416
|
+
error: {
|
417
|
+
code: -32602,
|
418
|
+
message: "Invalid params"
|
419
|
+
}
|
420
|
+
}
|
421
|
+
|
422
|
+
# Internal error
|
423
|
+
{
|
424
|
+
jsonrpc: "2.0",
|
425
|
+
id: 1,
|
426
|
+
error: {
|
427
|
+
code: -32603,
|
428
|
+
message: "Internal error",
|
429
|
+
data: { details: "..." }
|
430
|
+
}
|
431
|
+
}
|
432
|
+
```
|
433
|
+
|
434
|
+
## Thread Safety
|
435
|
+
|
436
|
+
The server is designed to be thread-safe:
|
437
|
+
|
438
|
+
- Component registration should happen before starting
|
439
|
+
- Request handling is thread-safe
|
440
|
+
- Logging methods are thread-safe
|
441
|
+
- Sampling requests are thread-safe
|
442
|
+
|
443
|
+
## Examples
|
444
|
+
|
445
|
+
### Basic Server
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
require 'tsikol'
|
449
|
+
|
450
|
+
server = Tsikol::Server.new(name: "basic-server")
|
451
|
+
|
452
|
+
server.register_tool("greet") do |name:|
|
453
|
+
"Hello, #{name}!"
|
454
|
+
end
|
455
|
+
|
456
|
+
server.register_resource("time") do
|
457
|
+
Time.now.iso8601
|
458
|
+
end
|
459
|
+
|
460
|
+
server.start
|
461
|
+
```
|
462
|
+
|
463
|
+
### Advanced Server
|
464
|
+
|
465
|
+
```ruby
|
466
|
+
require 'tsikol'
|
467
|
+
|
468
|
+
class MyServer < Tsikol::Server
|
469
|
+
def initialize
|
470
|
+
super(name: "advanced-server", version: "2.0.0")
|
471
|
+
|
472
|
+
configure_middleware
|
473
|
+
register_components
|
474
|
+
setup_hooks
|
475
|
+
end
|
476
|
+
|
477
|
+
private
|
478
|
+
|
479
|
+
def configure_middleware
|
480
|
+
use Tsikol::LoggingMiddleware, level: :info
|
481
|
+
use Tsikol::ErrorHandlingMiddleware
|
482
|
+
use Tsikol::RateLimitMiddleware, max_requests: 1000
|
483
|
+
end
|
484
|
+
|
485
|
+
def register_components
|
486
|
+
tool FileManager
|
487
|
+
tool DatabaseQuery
|
488
|
+
resource SystemMetrics
|
489
|
+
prompt AiAssistant
|
490
|
+
end
|
491
|
+
|
492
|
+
def setup_hooks
|
493
|
+
before_start { initialize_database }
|
494
|
+
after_start { notify_monitoring }
|
495
|
+
before_stop { save_state }
|
496
|
+
after_stop { cleanup }
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
server = MyServer.new
|
501
|
+
server.start
|
502
|
+
```
|
503
|
+
|
504
|
+
## See Also
|
505
|
+
|
506
|
+
- [Getting Started Guide](../guides/getting-started.md)
|
507
|
+
- [Tool API](tool.md)
|
508
|
+
- [Resource API](resource.md)
|
509
|
+
- [Middleware API](middleware.md)
|