legion-mcp 0.5.9 → 0.6.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/CLAUDE.md +15 -10
- data/README.md +14 -4
- data/lib/legion/mcp/server.rb +3 -1
- data/lib/legion/mcp/tools/knowledge_context.rb +104 -0
- data/lib/legion/mcp/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 19e316cc546a5fae512d371abccff4f2b6eef90d2902ee7df75a97eb5680dc01
|
|
4
|
+
data.tar.gz: 0b9d4d42b3a3677e66d289454e5d496c0535f8d99e71c1a20a9a2d718c18305a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c15a8d8c104f8fbbfeccbc50e6a58363a7989ca84e28c13d9b8199fe6ea700733e3f449cb619ecc4c5948ca947f9f9b756eda51a707705f765504145faa64543
|
|
7
|
+
data.tar.gz: 3001f29ecd4a9da497c4ee5824086bdb7288a99db51202d017d031df38a0f987f4db0ba123cf61e527f1e961be5422307aac394001b55250c3a461514e20c466
|
data/CHANGELOG.md
CHANGED
data/CLAUDE.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
Standalone gem providing the Model Context Protocol (MCP) server for LegionIO. Extracted from LegionIO to enable independent versioning and reuse. Includes semantic tool matching, observation pipeline, context compilation, tiered inference (Tier 0/1/2), and tool governance.
|
|
8
8
|
|
|
9
9
|
**GitHub**: https://github.com/LegionIO/legion-mcp
|
|
10
|
-
**Version**: 0.
|
|
10
|
+
**Version**: 0.6.0
|
|
11
11
|
**License**: Apache-2.0
|
|
12
12
|
**Ruby**: >= 3.4
|
|
13
13
|
|
|
@@ -25,7 +25,7 @@ Legion::MCP
|
|
|
25
25
|
├── PatternStore # 4-layer degrading storage (L0 memory, L1 cache, L2 local SQLite)
|
|
26
26
|
├── TierRouter # Confidence-gated tier selection (Tier 0/1/2)
|
|
27
27
|
├── ContextGuard # Staleness, rapid-fire, anomaly detection guards
|
|
28
|
-
├── Tools/ #
|
|
28
|
+
├── Tools/ # 59 MCP::Tool subclasses (legion.* namespace)
|
|
29
29
|
└── Resources/ # RunnerCatalog, ExtensionInfo
|
|
30
30
|
```
|
|
31
31
|
|
|
@@ -75,16 +75,21 @@ All optional dependencies use `defined?()` guards:
|
|
|
75
75
|
| `lib/legion/mcp/pattern_store.rb` | 4-layer degrading storage (L0/L1/L2) with thread-safe access |
|
|
76
76
|
| `lib/legion/mcp/tier_router.rb` | Confidence-gated tier selection, tool chain execution |
|
|
77
77
|
| `lib/legion/mcp/context_guard.rb` | Staleness, rapid-fire, anomaly detection |
|
|
78
|
-
| `lib/legion/mcp/tools/` |
|
|
78
|
+
| `lib/legion/mcp/tools/` | 59 MCP::Tool subclasses (legion.* namespace) |
|
|
79
79
|
| `lib/legion/mcp/tools/do_action.rb` | Natural language intent routing with Tier 0 fast path |
|
|
80
80
|
| `lib/legion/mcp/tools/discover_tools.rb` | Dynamic tool discovery with context |
|
|
81
81
|
| `lib/legion/mcp/tools/run_task.rb` | Execute runner function via dot notation |
|
|
82
|
-
| `legion.
|
|
83
|
-
| `legion.
|
|
84
|
-
| `legion.
|
|
85
|
-
| `legion
|
|
86
|
-
| `legion.
|
|
87
|
-
| `legion
|
|
82
|
+
| `lib/legion/mcp/tools/query_knowledge.rb` | Query Apollo knowledge store |
|
|
83
|
+
| `lib/legion/mcp/tools/knowledge_health.rb` | Knowledge store health and quality report |
|
|
84
|
+
| `lib/legion/mcp/tools/knowledge_context.rb` | Scoped RAG query (local/global/all) for current-task context |
|
|
85
|
+
| `lib/legion/mcp/tools/eval_*.rb` | Evaluation management (list/run/results) |
|
|
86
|
+
| `lib/legion/mcp/tools/experiment_results.rb` | A/B experiment result comparison |
|
|
87
|
+
| `lib/legion/mcp/tools/dataset_*.rb` | Dataset browsing (list/show) |
|
|
88
|
+
| `lib/legion/mcp/tools/prompt_*.rb` | Prompt template management (list/show/run) |
|
|
89
|
+
| `lib/legion/mcp/tools/plan_action.rb` | Agentic planning with action decomposition |
|
|
90
|
+
| `lib/legion/mcp/tools/ask_peer.rb` / `notify_peer.rb` / `broadcast_peers.rb` / `list_peers.rb` | Agent mesh communication |
|
|
91
|
+
| `lib/legion/mcp/tools/mesh_status.rb` | Mesh topology status |
|
|
92
|
+
| `lib/legion/mcp/tools/mind_growth_*.rb` | Mind growth tools (status/propose/approve/build_queue/cognitive_profile/health) |
|
|
88
93
|
| `lib/legion/mcp/resources/runner_catalog.rb` | `legion://runners` resource |
|
|
89
94
|
| `lib/legion/mcp/resources/extension_info.rb` | `legion://extensions/{name}` resource template |
|
|
90
95
|
|
|
@@ -92,7 +97,7 @@ All optional dependencies use `defined?()` guards:
|
|
|
92
97
|
|
|
93
98
|
```bash
|
|
94
99
|
bundle install
|
|
95
|
-
bundle exec rspec #
|
|
100
|
+
bundle exec rspec # 0 failures
|
|
96
101
|
bundle exec rubocop -A # auto-fix
|
|
97
102
|
bundle exec rubocop # lint check
|
|
98
103
|
```
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
MCP (Model Context Protocol) server for the LegionIO framework. Provides semantic tool matching, observation pipeline, context compilation, and tiered behavioral intelligence (Tier 0/1/2 routing).
|
|
4
4
|
|
|
5
|
-
**Version**: 0.
|
|
5
|
+
**Version**: 0.6.0
|
|
6
6
|
|
|
7
7
|
Extracted from [LegionIO](https://github.com/LegionIO/LegionIO) for independent versioning and reuse.
|
|
8
8
|
|
|
@@ -32,7 +32,7 @@ Legion::MCP
|
|
|
32
32
|
├── PatternStore # 4-layer degrading storage (L0 memory → L1 cache → L2 SQLite)
|
|
33
33
|
├── TierRouter # Confidence-gated tier selection (0/1/2)
|
|
34
34
|
├── ContextGuard # Staleness, rapid-fire, anomaly detection
|
|
35
|
-
├── Tools/ #
|
|
35
|
+
├── Tools/ # 59 MCP::Tool subclasses (legion.* namespace)
|
|
36
36
|
└── Resources/ # RunnerCatalog, ExtensionInfo
|
|
37
37
|
```
|
|
38
38
|
|
|
@@ -77,7 +77,7 @@ All persistence wraps in `begin/rescue => nil` — failed writes never block Tie
|
|
|
77
77
|
|
|
78
78
|
## Tools
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
59 MCP tools in the `legion.*` namespace:
|
|
81
81
|
|
|
82
82
|
| Tool | Purpose |
|
|
83
83
|
|------|---------|
|
|
@@ -97,6 +97,16 @@ All persistence wraps in `begin/rescue => nil` — failed writes never block Tie
|
|
|
97
97
|
| `legion.rbac_assignments` / `rbac_check` / `rbac_grants` | Access control |
|
|
98
98
|
| `legion.mind_growth_status` / `mind_growth_propose` / `mind_growth_approve` | Cognitive architecture growth |
|
|
99
99
|
| `legion.mind_growth_build_queue` / `mind_growth_cognitive_profile` / `mind_growth_health` | Growth analysis and health |
|
|
100
|
+
| `legion.query_knowledge` | Query Apollo knowledge store |
|
|
101
|
+
| `legion.knowledge_health` | Knowledge store health and quality report |
|
|
102
|
+
| `legion.knowledge_context` | Scoped RAG knowledge retrieval (local/global/all) |
|
|
103
|
+
| `legion.eval_list` / `eval_run` / `eval_results` | Evaluation management |
|
|
104
|
+
| `legion.experiment_results` | A/B experiment result comparison |
|
|
105
|
+
| `legion.dataset_list` / `dataset_show` | Dataset browsing |
|
|
106
|
+
| `legion.prompt_list` / `prompt_show` / `prompt_run` | Prompt template management |
|
|
107
|
+
| `legion.plan_action` | Agentic planning with action decomposition |
|
|
108
|
+
| `legion.ask_peer` / `notify_peer` / `broadcast_peers` / `list_peers` | Agent mesh communication |
|
|
109
|
+
| `legion.mesh_status` | Mesh topology status |
|
|
100
110
|
|
|
101
111
|
## Resources
|
|
102
112
|
|
|
@@ -176,7 +186,7 @@ All configuration is optional and read via `Legion::Settings` when available:
|
|
|
176
186
|
|
|
177
187
|
```bash
|
|
178
188
|
bundle install
|
|
179
|
-
bundle exec rspec #
|
|
189
|
+
bundle exec rspec # 0 failures
|
|
180
190
|
bundle exec rubocop -A # auto-fix
|
|
181
191
|
bundle exec rubocop # lint check
|
|
182
192
|
```
|
data/lib/legion/mcp/server.rb
CHANGED
|
@@ -66,6 +66,7 @@ require_relative 'tools/mind_growth_cognitive_profile'
|
|
|
66
66
|
require_relative 'tools/mind_growth_health'
|
|
67
67
|
require_relative 'tools/query_knowledge'
|
|
68
68
|
require_relative 'tools/knowledge_health'
|
|
69
|
+
require_relative 'tools/knowledge_context'
|
|
69
70
|
require_relative 'catalog_bridge'
|
|
70
71
|
require_relative 'resources/runner_catalog'
|
|
71
72
|
require_relative 'resources/extension_info'
|
|
@@ -131,7 +132,8 @@ module Legion
|
|
|
131
132
|
Tools::MindGrowthCognitiveProfile,
|
|
132
133
|
Tools::MindGrowthHealth,
|
|
133
134
|
Tools::QueryKnowledge,
|
|
134
|
-
Tools::KnowledgeHealth
|
|
135
|
+
Tools::KnowledgeHealth,
|
|
136
|
+
Tools::KnowledgeContext
|
|
135
137
|
].freeze
|
|
136
138
|
|
|
137
139
|
class << self
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module MCP
|
|
5
|
+
module Tools
|
|
6
|
+
class KnowledgeContext < ::MCP::Tool
|
|
7
|
+
tool_name 'legion.knowledge_context'
|
|
8
|
+
description 'Retrieve knowledge relevant to the current task. Call this when you need context about ' \
|
|
9
|
+
'the codebase, architecture, past decisions, or known gotchas.'
|
|
10
|
+
|
|
11
|
+
input_schema(
|
|
12
|
+
properties: {
|
|
13
|
+
question: { type: 'string', description: 'What do you need to know?' },
|
|
14
|
+
scope: { type: 'string', description: 'Knowledge scope: local (this node), global (shared), all (merged). Default: all',
|
|
15
|
+
enum: %w[local global all] },
|
|
16
|
+
top_k: { type: 'integer', description: 'Number of source chunks to retrieve (default 5)' }
|
|
17
|
+
},
|
|
18
|
+
required: %w[question]
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
def call(question:, scope: 'all', top_k: 5)
|
|
23
|
+
return error_response('lex-knowledge is not available') unless knowledge_available?(scope)
|
|
24
|
+
|
|
25
|
+
result = case scope
|
|
26
|
+
when 'local' then query_local(question: question, top_k: top_k)
|
|
27
|
+
when 'global' then query_global(question: question, top_k: top_k)
|
|
28
|
+
else query_all(question: question, top_k: top_k)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
text_response(result)
|
|
32
|
+
rescue StandardError => e
|
|
33
|
+
Legion::Logging.warn("KnowledgeContext#call failed: #{e.message}") if defined?(Legion::Logging)
|
|
34
|
+
error_response("Knowledge context failed: #{e.message}")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def knowledge_available?(scope = 'all')
|
|
40
|
+
return defined?(Legion::Apollo::Local) || defined?(Legion::Extensions::Knowledge::Runners::Query) if scope == 'local'
|
|
41
|
+
|
|
42
|
+
defined?(Legion::Extensions::Knowledge::Runners::Query)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def query_global(question:, top_k:)
|
|
46
|
+
result = Legion::Extensions::Knowledge::Runners::Query.query(
|
|
47
|
+
question: question,
|
|
48
|
+
top_k: top_k,
|
|
49
|
+
synthesize: true
|
|
50
|
+
)
|
|
51
|
+
result.merge(scope: 'global')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def query_local(question:, top_k:)
|
|
55
|
+
if defined?(Legion::Apollo::Local)
|
|
56
|
+
result = Legion::Apollo::Local.query(question: question, top_k: top_k)
|
|
57
|
+
result.merge(scope: 'local')
|
|
58
|
+
else
|
|
59
|
+
Legion::Logging.warn('KnowledgeContext: Apollo::Local not available, falling back to global') if defined?(Legion::Logging)
|
|
60
|
+
query_global(question: question, top_k: top_k)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def query_all(question:, top_k:)
|
|
65
|
+
global = query_global(question: question, top_k: top_k)
|
|
66
|
+
return global unless defined?(Legion::Apollo::Local)
|
|
67
|
+
|
|
68
|
+
local = Legion::Apollo::Local.query(question: question, top_k: top_k)
|
|
69
|
+
merge_results(global, local)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def merge_results(global, local)
|
|
73
|
+
global_sources = Array(global[:sources] || global['sources'])
|
|
74
|
+
local_sources = Array(local[:sources] || local['sources'])
|
|
75
|
+
|
|
76
|
+
seen = {}
|
|
77
|
+
deduped = []
|
|
78
|
+
(local_sources + global_sources).each do |src|
|
|
79
|
+
key = src[:content_hash] || src['content_hash'] || src[:content] || src['content']
|
|
80
|
+
next if seen[key]
|
|
81
|
+
|
|
82
|
+
seen[key] = true
|
|
83
|
+
deduped << src
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
global_answer = global[:answer] || global['answer']
|
|
87
|
+
local_answer = local[:answer] || local['answer']
|
|
88
|
+
answer = global_answer.nil? || global_answer.to_s.empty? ? local_answer : global_answer
|
|
89
|
+
{ answer: answer, sources: deduped, scope: 'all' }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def text_response(data)
|
|
93
|
+
::MCP::Tool::Response.new([{ type: 'text', text: Legion::JSON.dump(data) }])
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def error_response(msg)
|
|
97
|
+
body = { error: msg }
|
|
98
|
+
::MCP::Tool::Response.new([{ type: 'text', text: Legion::JSON.dump(body) }], error: true)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
data/lib/legion/mcp/version.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.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -171,6 +171,7 @@ files:
|
|
|
171
171
|
- lib/legion/mcp/tools/get_status.rb
|
|
172
172
|
- lib/legion/mcp/tools/get_task.rb
|
|
173
173
|
- lib/legion/mcp/tools/get_task_logs.rb
|
|
174
|
+
- lib/legion/mcp/tools/knowledge_context.rb
|
|
174
175
|
- lib/legion/mcp/tools/knowledge_health.rb
|
|
175
176
|
- lib/legion/mcp/tools/list_chains.rb
|
|
176
177
|
- lib/legion/mcp/tools/list_extensions.rb
|