legion-mcp 0.5.0 → 0.5.1
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/CHANGELOG.md +10 -0
- data/lib/legion/mcp/catalog_bridge.rb +56 -0
- data/lib/legion/mcp/override_broadcast.rb +64 -0
- data/lib/legion/mcp/server.rb +6 -0
- data/lib/legion/mcp/version.rb +1 -1
- data/lib/legion/mcp.rb +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a8bed0d14356dfa6586b1772e2acdfa01ef35448dfa7164bdf7199feebb837f1
|
|
4
|
+
data.tar.gz: 8c5465bbf00210c1fd32b2202cafaa99ddac6253a007b9ccf0947f953706befa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa488f06e2989c3439f13cbbd3e396fe8a56baaaabce415fb5104f83a19230c7200a6639996ef6b70e30c7b81c5a1fee4f5f9d4017805393ee3dc8ed3efd4f07
|
|
7
|
+
data.tar.gz: ece02d6f4ac15cc6c2348f9c898877752f9c4a4a02b171b76706b6ab8e477f883035dd48b77f90b0f867a48c6901b0c296df05e0e64429fe791b6bdf22ae50d6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# legion-mcp Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.1] - 2026-03-23
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Dynamic tool list from `Catalog::Registry` merged with static TOOL_CLASSES
|
|
7
|
+
- `dispatch_catalog_tool` routes Catalog-sourced MCP tool calls to extension runners
|
|
8
|
+
- `CatalogBridge` module extracted for catalog integration (hydration, listener, dispatch, dynamic tools)
|
|
9
|
+
- `OverrideBroadcast` for mesh-wide override confirmation via RabbitMQ
|
|
10
|
+
- Hydrate `OverrideConfidence` from SQLite (L2) and Apollo (L3) at server boot
|
|
11
|
+
- MCP server resets automatically when Catalog registry changes
|
|
12
|
+
|
|
3
13
|
## [0.5.0] - 2026-03-23
|
|
4
14
|
|
|
5
15
|
### Added
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module MCP
|
|
5
|
+
module CatalogBridge
|
|
6
|
+
def hydrate_override_confidence
|
|
7
|
+
return unless defined?(Legion::LLM::OverrideConfidence)
|
|
8
|
+
return unless Legion::LLM::OverrideConfidence.respond_to?(:hydrate_from_l2)
|
|
9
|
+
|
|
10
|
+
Legion::LLM::OverrideConfidence.hydrate_from_l2
|
|
11
|
+
Legion::LLM::OverrideConfidence.hydrate_from_apollo if Legion::LLM::OverrideConfidence.respond_to?(:hydrate_from_apollo)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def register_catalog_listener
|
|
15
|
+
return unless defined?(Legion::Extensions::Catalog::Registry)
|
|
16
|
+
return unless Legion::Extensions::Catalog::Registry.respond_to?(:on_change)
|
|
17
|
+
|
|
18
|
+
Legion::Extensions::Catalog::Registry.on_change { Legion::MCP.reset! }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def dispatch_catalog_tool(tool_name, arguments)
|
|
22
|
+
return nil unless defined?(Legion::Extensions::Catalog::Registry)
|
|
23
|
+
|
|
24
|
+
cap = Legion::Extensions::Catalog::Registry.find_by_mcp_name(tool_name)
|
|
25
|
+
return nil unless cap
|
|
26
|
+
|
|
27
|
+
segments = cap.extension.delete_prefix('lex-').split('-')
|
|
28
|
+
runner_path = (%w[Legion Extensions] + segments.map(&:capitalize) + ['Runners', cap.runner]).join('::')
|
|
29
|
+
runner = Kernel.const_get(runner_path)
|
|
30
|
+
fn = cap.function.to_sym
|
|
31
|
+
result = runner.send(fn, **(arguments || {}).transform_keys(&:to_sym))
|
|
32
|
+
{ status: :success, result: result, source: :catalog }
|
|
33
|
+
rescue NameError => e
|
|
34
|
+
Legion::Logging.warn("Catalog dispatch failed: #{e.message}") if defined?(Legion::Logging)
|
|
35
|
+
nil
|
|
36
|
+
rescue StandardError => e
|
|
37
|
+
{ status: :error, error: e.message, source: :catalog }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def dynamic_tool_list
|
|
41
|
+
static = Server::TOOL_CLASSES.map do |klass|
|
|
42
|
+
{ name: klass.tool_name, description: klass.description,
|
|
43
|
+
input_schema: klass.input_schema, source: :builtin, klass: klass }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
dynamic = if defined?(Legion::Extensions::Catalog::Registry)
|
|
47
|
+
Legion::Extensions::Catalog::Registry.for_mcp.map(&:to_mcp_tool)
|
|
48
|
+
else
|
|
49
|
+
[]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
static + dynamic
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module MCP
|
|
5
|
+
module OverrideBroadcast
|
|
6
|
+
EXCHANGE = 'legion.mesh'
|
|
7
|
+
ROUTING_KEY = 'override.confirmed'
|
|
8
|
+
CORROBORATION_BOOST = 0.3
|
|
9
|
+
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def publish_confirmation(tool:, lex:, confidence:, tests:)
|
|
13
|
+
return unless defined?(Legion::Transport::Messages::Dynamic)
|
|
14
|
+
|
|
15
|
+
node_id = Legion::Settings.dig(:node, :id) rescue 'unknown' # rubocop:disable Style/RescueModifier
|
|
16
|
+
Legion::Transport::Messages::Dynamic.new(
|
|
17
|
+
function: 'override_confirmed',
|
|
18
|
+
exchange: EXCHANGE,
|
|
19
|
+
routing_key: ROUTING_KEY,
|
|
20
|
+
opts: {
|
|
21
|
+
tool: tool, lex: lex, confidence: confidence,
|
|
22
|
+
tests: tests, node: node_id, timestamp: Time.now.iso8601
|
|
23
|
+
}
|
|
24
|
+
).publish
|
|
25
|
+
rescue StandardError => e
|
|
26
|
+
Legion::Logging.warn("Override broadcast failed: #{e.message}") if defined?(Legion::Logging)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def receive_confirmation(tool:, lex:, confidence:, tests:, node:)
|
|
30
|
+
return unless defined?(Legion::LLM::OverrideConfidence)
|
|
31
|
+
|
|
32
|
+
existing = Legion::LLM::OverrideConfidence.lookup(tool)
|
|
33
|
+
|
|
34
|
+
if existing
|
|
35
|
+
new_confidence = (existing[:confidence] + CORROBORATION_BOOST).clamp(0.0, 1.0)
|
|
36
|
+
Legion::LLM::OverrideConfidence.record(tool: tool, lex: lex, confidence: new_confidence)
|
|
37
|
+
else
|
|
38
|
+
Legion::LLM::OverrideConfidence.record(tool: tool, lex: lex, confidence: confidence * 0.8)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
store_to_apollo(tool: tool, lex: lex, confidence: confidence, tests: tests, node: node)
|
|
42
|
+
rescue StandardError => e
|
|
43
|
+
Legion::Logging.warn("Override receive failed: #{e.message}") if defined?(Legion::Logging)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def store_to_apollo(tool:, lex:, confidence:, tests:, node:)
|
|
47
|
+
return unless defined?(Legion::Extensions::Apollo::Runners::Knowledge)
|
|
48
|
+
|
|
49
|
+
Legion::Extensions::Apollo::Runners::Knowledge.handle_ingest(
|
|
50
|
+
content: "Override confirmed: #{tool} -> #{lex} (confidence: #{confidence}, tests: #{tests})",
|
|
51
|
+
content_type: 'fact',
|
|
52
|
+
tags: %w[override mesh_confirmed] + [tool],
|
|
53
|
+
source_agent: "mesh:#{node}",
|
|
54
|
+
knowledge_domain: 'system',
|
|
55
|
+
context: { tool: tool, lex: lex, confidence: confidence, tests: tests }
|
|
56
|
+
)
|
|
57
|
+
rescue StandardError
|
|
58
|
+
nil
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private_class_method :store_to_apollo
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
data/lib/legion/mcp/server.rb
CHANGED
|
@@ -55,6 +55,7 @@ require_relative 'tools/list_peers'
|
|
|
55
55
|
require_relative 'tools/notify_peer'
|
|
56
56
|
require_relative 'tools/broadcast_peers'
|
|
57
57
|
require_relative 'tools/mesh_status'
|
|
58
|
+
require_relative 'catalog_bridge'
|
|
58
59
|
require_relative 'resources/runner_catalog'
|
|
59
60
|
require_relative 'resources/extension_info'
|
|
60
61
|
|
|
@@ -115,6 +116,8 @@ module Legion
|
|
|
115
116
|
].freeze
|
|
116
117
|
|
|
117
118
|
class << self
|
|
119
|
+
include CatalogBridge
|
|
120
|
+
|
|
118
121
|
def build(identity: nil)
|
|
119
122
|
tools = if ToolGovernance.governance_enabled?
|
|
120
123
|
ToolGovernance.filter_tools(TOOL_CLASSES, identity)
|
|
@@ -153,6 +156,9 @@ module Legion
|
|
|
153
156
|
Resources::RunnerCatalog.register(server)
|
|
154
157
|
Resources::ExtensionInfo.register_read_handler(server)
|
|
155
158
|
|
|
159
|
+
register_catalog_listener
|
|
160
|
+
hydrate_override_confidence
|
|
161
|
+
|
|
156
162
|
server
|
|
157
163
|
end
|
|
158
164
|
|
data/lib/legion/mcp/version.rb
CHANGED
data/lib/legion/mcp.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: legion-mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -119,6 +119,7 @@ files:
|
|
|
119
119
|
- lib/legion/mcp.rb
|
|
120
120
|
- lib/legion/mcp/auth.rb
|
|
121
121
|
- lib/legion/mcp/capability_generator.rb
|
|
122
|
+
- lib/legion/mcp/catalog_bridge.rb
|
|
122
123
|
- lib/legion/mcp/client.rb
|
|
123
124
|
- lib/legion/mcp/client/connection.rb
|
|
124
125
|
- lib/legion/mcp/client/pool.rb
|
|
@@ -129,6 +130,7 @@ files:
|
|
|
129
130
|
- lib/legion/mcp/embedding_index.rb
|
|
130
131
|
- lib/legion/mcp/gap_detector.rb
|
|
131
132
|
- lib/legion/mcp/observer.rb
|
|
133
|
+
- lib/legion/mcp/override_broadcast.rb
|
|
132
134
|
- lib/legion/mcp/pattern_compiler.rb
|
|
133
135
|
- lib/legion/mcp/pattern_exchange.rb
|
|
134
136
|
- lib/legion/mcp/pattern_gossip.rb
|