stack-service-base 0.0.56 → 0.0.58
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 +4 -4
- data/lib/stack-service-base/examples/mcp_config.ru +73 -0
- data/lib/stack-service-base/mcp_processor.rb +94 -0
- data/lib/stack-service-base/mcp_tool_registry.rb +84 -0
- data/lib/stack-service-base/open_telemetry.rb +18 -1
- data/lib/stack-service-base/version.rb +1 -1
- metadata +161 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f07b63778720acb4d2629f0cd7fd0cb9042194f9e8cf4b8c36fd766555a3e7ef
|
|
4
|
+
data.tar.gz: b44692326f9a69a994ab2915dccbbf714bc1500d9d02b5f2acc4c717d642e8a9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dbe54cb277386c5ef81d3c5746ccb4c2f8931d7d83145f6184e4bd461cdaff7e320b2ede10dd79eed87aba917917a569b9419813aed167f9e39f8464772f301c
|
|
7
|
+
data.tar.gz: 0fb8592aeb9801157144a4e25fa27a78179722c28493ffe350694e3a705f1d8bd309a4326ca03a695f70fbe9bdff7a3bfa17603272cd5f94fcd6249192cfaa96
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'sinatra'
|
|
2
|
+
require 'stack-service-base'
|
|
3
|
+
|
|
4
|
+
StackServiceBase.rack_setup self
|
|
5
|
+
|
|
6
|
+
SERVICES = {
|
|
7
|
+
"database-backend" => {
|
|
8
|
+
status: "running",
|
|
9
|
+
uptime: 72 * 3600, # seconds
|
|
10
|
+
last_restart: Time.now - 72 * 3600
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
require 'stack-service-base/mcp_processor'
|
|
15
|
+
require 'stack-service-base/mcp_tool_registry'
|
|
16
|
+
|
|
17
|
+
MCP_PROCESSOR = McpProcessor.new
|
|
18
|
+
|
|
19
|
+
Tool :service_status do
|
|
20
|
+
description 'Check current status of a service'
|
|
21
|
+
input service_name: { type: "string", description: "Service name to inspect", required: true }
|
|
22
|
+
execute do |inputs|
|
|
23
|
+
service_name = inputs[:service_name]
|
|
24
|
+
service = SERVICES[service_name]
|
|
25
|
+
rpc_error!(404, "Unknown service #{service_name}") unless service
|
|
26
|
+
{
|
|
27
|
+
toolResult: {
|
|
28
|
+
service_name: service_name,
|
|
29
|
+
status: service[:status],
|
|
30
|
+
uptime_sec: service[:uptime],
|
|
31
|
+
last_restart: service[:last_restart].utc.iso8601,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
Tool :restart_service do
|
|
38
|
+
description 'Restart a service'
|
|
39
|
+
input service_name: { type: "string", description: "Service name to restart", required: true },
|
|
40
|
+
force: { type: "boolean", default: false, description: "Force restart if graceful fails" }
|
|
41
|
+
execute do |inputs|
|
|
42
|
+
service_name = inputs[:service_name]
|
|
43
|
+
service = SERVICES[service_name]
|
|
44
|
+
rpc_error!(404, "Unknown service #{service_name}") unless service
|
|
45
|
+
|
|
46
|
+
service[:status] = "running"
|
|
47
|
+
service[:last_restart] = Time.now
|
|
48
|
+
service[:uptime] = 0
|
|
49
|
+
|
|
50
|
+
{
|
|
51
|
+
toolResult: {
|
|
52
|
+
service_name: service_name,
|
|
53
|
+
status: service[:status],
|
|
54
|
+
restarted_at: service[:last_restart].utc.iso8601,
|
|
55
|
+
force: inputs.fetch(:force, false)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
before { content_type :json }
|
|
62
|
+
error McpProcessor::ParseError do |err|
|
|
63
|
+
status err.status
|
|
64
|
+
err.body
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
get '/', &MCP_PROCESSOR.method(:root_endpoint)
|
|
68
|
+
post '/' do
|
|
69
|
+
request.body.rewind
|
|
70
|
+
MCP_PROCESSOR.rpc_endpoint(request.body.read)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
run Sinatra::Application
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
class JsonRpcError < StandardError
|
|
2
|
+
attr_reader :code
|
|
3
|
+
|
|
4
|
+
def initialize(code:, message:)
|
|
5
|
+
super(message)
|
|
6
|
+
@code = code
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module RpcErrorHelpers
|
|
11
|
+
def rpc_error!(code, message)
|
|
12
|
+
raise ::JsonRpcError.new(code: code, message: message)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class McpProcessor
|
|
17
|
+
include RpcErrorHelpers
|
|
18
|
+
ParseError = Class.new(StandardError) do
|
|
19
|
+
attr_reader :body, :status
|
|
20
|
+
|
|
21
|
+
def initialize(body:, status:)
|
|
22
|
+
@body = body
|
|
23
|
+
@status = status
|
|
24
|
+
super("MCP parse error")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initialize(logger: LOGGER)
|
|
29
|
+
@logger = logger
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def root_endpoint
|
|
33
|
+
root_response
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def rpc_endpoint(raw_body)
|
|
37
|
+
req = JSON.parse(raw_body.to_s)
|
|
38
|
+
rpc_response(id: req["id"], method: req["method"], params: req["params"])
|
|
39
|
+
rescue JSON::ParserError
|
|
40
|
+
body = error_response(id: nil, code: -32700, message: "Parse error")
|
|
41
|
+
raise ParseError.new(body: body, status: 400)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def list_tools
|
|
45
|
+
{ tools: ToolRegistry.list, nextCursor: nil }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def root_response
|
|
49
|
+
json_rpc_response(id: nil) { list_tools }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def error_response(id:, code:, message:)
|
|
53
|
+
json_rpc_response(id: id) { rpc_error!(code, message) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def rpc_response(id:, method:, params:)
|
|
57
|
+
json_rpc_response(id: id) { handle(method: method, params: params) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def handle(method:, params:)
|
|
61
|
+
case method
|
|
62
|
+
when "tools/list" then list_tools
|
|
63
|
+
when "tools/call" then call_tool(params || {})
|
|
64
|
+
else
|
|
65
|
+
rpc_error!(-32601, "Unknown method #{method}")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def json_rpc_response(id:)
|
|
72
|
+
body = { jsonrpc: "2.0", id: id }
|
|
73
|
+
|
|
74
|
+
begin
|
|
75
|
+
result = yield(body)
|
|
76
|
+
body[:result] = result unless body[:error] || result.nil?
|
|
77
|
+
rescue JsonRpcError => e
|
|
78
|
+
body[:error] = { code: e.code, message: e.message }
|
|
79
|
+
rescue => e
|
|
80
|
+
@logger&.error("Unhandled RPC error: #{e.class}: #{e.message}\n#{e.backtrace&.first}")
|
|
81
|
+
body[:error] = { code: -32603, message: "Internal error" }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
body.delete(:result) if body[:error]
|
|
85
|
+
JSON.dump(body)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def call_tool(params)
|
|
89
|
+
name = params["name"]
|
|
90
|
+
arguments = params["arguments"] || {}
|
|
91
|
+
tool = ToolRegistry.fetch(name) || rpc_error!(-32601, "Unknown tool #{name}")
|
|
92
|
+
tool.call(arguments)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module ToolRegistry
|
|
2
|
+
class ExecutionContext
|
|
3
|
+
include RpcErrorHelpers
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class Definition
|
|
7
|
+
attr_reader :name
|
|
8
|
+
|
|
9
|
+
def initialize(name)
|
|
10
|
+
@name = name.to_s
|
|
11
|
+
@inputs = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def description(text = nil)
|
|
15
|
+
return @description if text.nil?
|
|
16
|
+
@description = text
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def input(fields = {})
|
|
20
|
+
@inputs.merge!(fields.transform_keys(&:to_s))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def input_schema
|
|
24
|
+
properties = {}
|
|
25
|
+
required = []
|
|
26
|
+
|
|
27
|
+
@inputs.each do |field, config|
|
|
28
|
+
cfg = config.transform_keys { |key| key.is_a?(Symbol) ? key : key.to_sym }
|
|
29
|
+
required << field if cfg.delete(:required)
|
|
30
|
+
properties[field] = cfg.transform_keys(&:to_s)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
{ type: "object", properties: properties, required: required }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def execute(&block) = @executor = block
|
|
37
|
+
|
|
38
|
+
def to_h
|
|
39
|
+
{
|
|
40
|
+
name: name,
|
|
41
|
+
description: description,
|
|
42
|
+
inputSchema: input_schema
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def call(arguments)
|
|
47
|
+
raise JsonRpcError.new(code: 500, message: "Tool #{name} missing executor") unless @executor
|
|
48
|
+
|
|
49
|
+
ExecutionContext.new.instance_exec(symbolize_keys(arguments || {}), &@executor)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def symbolize_keys(hash)
|
|
55
|
+
hash.each_with_object({}) do |(key, value), memo|
|
|
56
|
+
memo[key.to_sym] = value
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
module_function
|
|
62
|
+
|
|
63
|
+
def define(name, &block)
|
|
64
|
+
definition = Definition.new(name)
|
|
65
|
+
definition.instance_eval(&block)
|
|
66
|
+
registry[definition.name] = definition
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def registry
|
|
70
|
+
@registry ||= {}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def list
|
|
74
|
+
registry.values.map(&:to_h)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def fetch(name)
|
|
78
|
+
registry[name.to_s]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def Tool(name, &block)
|
|
83
|
+
ToolRegistry.define(name, &block)
|
|
84
|
+
end
|
|
@@ -2,6 +2,7 @@ require 'async'
|
|
|
2
2
|
|
|
3
3
|
ENV['OTEL_LOG_LEVEL'] ||= 'debug'
|
|
4
4
|
ENV['OTEL_TRACES_EXPORTER'] ||= 'console,otlp'
|
|
5
|
+
ENV['OTEL_LOGS_EXPORTER'] ||= 'otlp,console'
|
|
5
6
|
|
|
6
7
|
unless defined? OTEL_ENABLED
|
|
7
8
|
OTEL_ENABLED = !ENV['OTEL_EXPORTER_OTLP_ENDPOINT'].to_s.empty?
|
|
@@ -14,13 +15,17 @@ $stdout.puts "OTEL_ENABLED: #{OTEL_ENABLED}"
|
|
|
14
15
|
if OTEL_ENABLED
|
|
15
16
|
STACK_NAME = ENV['STACK_NAME'] || 'undefined_stack'
|
|
16
17
|
SERVICE_NAME = ENV['STACK_SERVICE_NAME'] || 'undefined_service'
|
|
17
|
-
ENV['
|
|
18
|
+
HOSTNAME=ENV['HOSTNAME'] || 'undefined'
|
|
19
|
+
ENV['OTEL_RESOURCE_ATTRIBUTES'] ||= "deployment.environment=#{STACK_NAME},service.name=#{SERVICE_NAME},hostname=#{HOSTNAME}"
|
|
18
20
|
ENV.select{ |k,v| k =~ /OTEL/}.each { |k,v| $stdout.puts "#{k}: #{v}"}
|
|
19
21
|
|
|
20
22
|
require 'opentelemetry/sdk'
|
|
21
23
|
require 'opentelemetry/exporter/otlp'
|
|
22
24
|
require 'opentelemetry/instrumentation/all'
|
|
23
25
|
require 'opentelemetry-api'
|
|
26
|
+
require 'opentelemetry-sdk'
|
|
27
|
+
require 'opentelemetry-logs-sdk'
|
|
28
|
+
require 'opentelemetry-exporter-otlp-logs'
|
|
24
29
|
end
|
|
25
30
|
|
|
26
31
|
if defined? Async and OTEL_ENABLED
|
|
@@ -75,9 +80,21 @@ def otel_initialize
|
|
|
75
80
|
# c.service_name = SERVICE_NAME
|
|
76
81
|
end
|
|
77
82
|
|
|
83
|
+
# Logs API
|
|
84
|
+
# ENV['OTEL_LOGS_EXPORTER'] = 'otlp,console' # Export logs to the console ,console
|
|
85
|
+
if ENV['OTEL_LOGS_EXPORTER'] =~ /console/
|
|
86
|
+
processor = OpenTelemetry::SDK::Logs::Export::SimpleLogRecordProcessor.new(OpenTelemetry::SDK::Logs::Export::ConsoleLogRecordExporter.new)
|
|
87
|
+
OpenTelemetry.logger_provider.add_log_record_processor(processor)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Access a Logger for your library from the LoggerProvider configured by the OpenTelemetry API
|
|
91
|
+
logger = OpenTelemetry.logger_provider.logger(name: SERVICE_NAME, version: '0.1.0')
|
|
92
|
+
logger.on_emit( timestamp: Time.now, severity_text: 'INFO', body: 'Log provider initialized ', attributes: { 'ready' => true } )
|
|
93
|
+
|
|
78
94
|
at_exit do
|
|
79
95
|
OpenTelemetry.tracer_provider.force_flush
|
|
80
96
|
OpenTelemetry.tracer_provider.shutdown
|
|
97
|
+
OpenTelemetry.logger_provider.shutdown
|
|
81
98
|
end
|
|
82
99
|
|
|
83
100
|
$tracer_ = OpenTelemetry.tracer_provider.tracer(SERVICE_NAME)
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stack-service-base
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.58
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Artyom B
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rack
|
|
@@ -94,6 +93,48 @@ dependencies:
|
|
|
94
93
|
- - ">="
|
|
95
94
|
- !ruby/object:Gem::Version
|
|
96
95
|
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: opentelemetry-logs-api
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: opentelemetry-logs-sdk
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '0'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: opentelemetry-exporter-otlp-logs
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0'
|
|
131
|
+
type: :runtime
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0'
|
|
97
138
|
- !ruby/object:Gem::Dependency
|
|
98
139
|
name: nats-pure
|
|
99
140
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -234,8 +275,118 @@ dependencies:
|
|
|
234
275
|
- - "~>"
|
|
235
276
|
- !ruby/object:Gem::Version
|
|
236
277
|
version: 0.5.1
|
|
237
|
-
|
|
238
|
-
|
|
278
|
+
- !ruby/object:Gem::Dependency
|
|
279
|
+
name: rspec-benchmark
|
|
280
|
+
requirement: !ruby/object:Gem::Requirement
|
|
281
|
+
requirements:
|
|
282
|
+
- - ">="
|
|
283
|
+
- !ruby/object:Gem::Version
|
|
284
|
+
version: '0'
|
|
285
|
+
type: :development
|
|
286
|
+
prerelease: false
|
|
287
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
288
|
+
requirements:
|
|
289
|
+
- - ">="
|
|
290
|
+
- !ruby/object:Gem::Version
|
|
291
|
+
version: '0'
|
|
292
|
+
- !ruby/object:Gem::Dependency
|
|
293
|
+
name: rack-test
|
|
294
|
+
requirement: !ruby/object:Gem::Requirement
|
|
295
|
+
requirements:
|
|
296
|
+
- - ">="
|
|
297
|
+
- !ruby/object:Gem::Version
|
|
298
|
+
version: '0'
|
|
299
|
+
type: :development
|
|
300
|
+
prerelease: false
|
|
301
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
302
|
+
requirements:
|
|
303
|
+
- - ">="
|
|
304
|
+
- !ruby/object:Gem::Version
|
|
305
|
+
version: '0'
|
|
306
|
+
- !ruby/object:Gem::Dependency
|
|
307
|
+
name: async-rspec
|
|
308
|
+
requirement: !ruby/object:Gem::Requirement
|
|
309
|
+
requirements:
|
|
310
|
+
- - ">="
|
|
311
|
+
- !ruby/object:Gem::Version
|
|
312
|
+
version: '0'
|
|
313
|
+
type: :development
|
|
314
|
+
prerelease: false
|
|
315
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
316
|
+
requirements:
|
|
317
|
+
- - ">="
|
|
318
|
+
- !ruby/object:Gem::Version
|
|
319
|
+
version: '0'
|
|
320
|
+
- !ruby/object:Gem::Dependency
|
|
321
|
+
name: rspec-snapshot
|
|
322
|
+
requirement: !ruby/object:Gem::Requirement
|
|
323
|
+
requirements:
|
|
324
|
+
- - ">="
|
|
325
|
+
- !ruby/object:Gem::Version
|
|
326
|
+
version: '0'
|
|
327
|
+
type: :development
|
|
328
|
+
prerelease: false
|
|
329
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
330
|
+
requirements:
|
|
331
|
+
- - ">="
|
|
332
|
+
- !ruby/object:Gem::Version
|
|
333
|
+
version: '0'
|
|
334
|
+
- !ruby/object:Gem::Dependency
|
|
335
|
+
name: testcontainers
|
|
336
|
+
requirement: !ruby/object:Gem::Requirement
|
|
337
|
+
requirements:
|
|
338
|
+
- - ">="
|
|
339
|
+
- !ruby/object:Gem::Version
|
|
340
|
+
version: '0'
|
|
341
|
+
type: :development
|
|
342
|
+
prerelease: false
|
|
343
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
344
|
+
requirements:
|
|
345
|
+
- - ">="
|
|
346
|
+
- !ruby/object:Gem::Version
|
|
347
|
+
version: '0'
|
|
348
|
+
- !ruby/object:Gem::Dependency
|
|
349
|
+
name: simplecov
|
|
350
|
+
requirement: !ruby/object:Gem::Requirement
|
|
351
|
+
requirements:
|
|
352
|
+
- - ">="
|
|
353
|
+
- !ruby/object:Gem::Version
|
|
354
|
+
version: '0'
|
|
355
|
+
type: :development
|
|
356
|
+
prerelease: false
|
|
357
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
358
|
+
requirements:
|
|
359
|
+
- - ">="
|
|
360
|
+
- !ruby/object:Gem::Version
|
|
361
|
+
version: '0'
|
|
362
|
+
- !ruby/object:Gem::Dependency
|
|
363
|
+
name: sinatra
|
|
364
|
+
requirement: !ruby/object:Gem::Requirement
|
|
365
|
+
requirements:
|
|
366
|
+
- - ">="
|
|
367
|
+
- !ruby/object:Gem::Version
|
|
368
|
+
version: '0'
|
|
369
|
+
type: :development
|
|
370
|
+
prerelease: false
|
|
371
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
372
|
+
requirements:
|
|
373
|
+
- - ">="
|
|
374
|
+
- !ruby/object:Gem::Version
|
|
375
|
+
version: '0'
|
|
376
|
+
- !ruby/object:Gem::Dependency
|
|
377
|
+
name: slim
|
|
378
|
+
requirement: !ruby/object:Gem::Requirement
|
|
379
|
+
requirements:
|
|
380
|
+
- - ">="
|
|
381
|
+
- !ruby/object:Gem::Version
|
|
382
|
+
version: '0'
|
|
383
|
+
type: :development
|
|
384
|
+
prerelease: false
|
|
385
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
386
|
+
requirements:
|
|
387
|
+
- - ">="
|
|
388
|
+
- !ruby/object:Gem::Version
|
|
389
|
+
version: '0'
|
|
239
390
|
executables:
|
|
240
391
|
- ssbase
|
|
241
392
|
extensions: []
|
|
@@ -247,8 +398,11 @@ files:
|
|
|
247
398
|
- lib/stack-service-base/command_line.rb
|
|
248
399
|
- lib/stack-service-base/database.rb
|
|
249
400
|
- lib/stack-service-base/debugger.rb
|
|
401
|
+
- lib/stack-service-base/examples/mcp_config.ru
|
|
250
402
|
- lib/stack-service-base/fiber_pool.rb
|
|
251
403
|
- lib/stack-service-base/logging.rb
|
|
404
|
+
- lib/stack-service-base/mcp_processor.rb
|
|
405
|
+
- lib/stack-service-base/mcp_tool_registry.rb
|
|
252
406
|
- lib/stack-service-base/nats_patch_1.rb
|
|
253
407
|
- lib/stack-service-base/nats_service.rb
|
|
254
408
|
- lib/stack-service-base/open_telemetry.rb
|
|
@@ -290,10 +444,8 @@ files:
|
|
|
290
444
|
- lib/stack-service-base/stack_template/home/stack/stack.drs
|
|
291
445
|
- lib/stack-service-base/version.rb
|
|
292
446
|
- lib/stack-service-base/views/ssbase_info.slim
|
|
293
|
-
homepage:
|
|
294
447
|
licenses: []
|
|
295
448
|
metadata: {}
|
|
296
|
-
post_install_message:
|
|
297
449
|
rdoc_options: []
|
|
298
450
|
require_paths:
|
|
299
451
|
- lib
|
|
@@ -301,15 +453,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
301
453
|
requirements:
|
|
302
454
|
- - ">="
|
|
303
455
|
- !ruby/object:Gem::Version
|
|
304
|
-
version: 3.
|
|
456
|
+
version: 3.4.4
|
|
305
457
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
306
458
|
requirements:
|
|
307
459
|
- - ">="
|
|
308
460
|
- !ruby/object:Gem::Version
|
|
309
461
|
version: '0'
|
|
310
462
|
requirements: []
|
|
311
|
-
rubygems_version: 3.
|
|
312
|
-
signing_key:
|
|
463
|
+
rubygems_version: 3.6.7
|
|
313
464
|
specification_version: 4
|
|
314
465
|
summary: Common files
|
|
315
466
|
test_files: []
|