kairos-chain 1.2.0 → 2.0.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 +146 -0
- data/lib/kairos_mcp/http_server.rb +27 -1
- data/lib/kairos_mcp/meeting_router.rb +89 -7
- data/lib/kairos_mcp/protocol.rb +38 -1
- data/lib/kairos_mcp/version.rb +1 -1
- data/lib/kairos_mcp.rb +17 -10
- data/templates/knowledge/hestiachain_meeting_place/hestiachain_meeting_place.md +147 -0
- data/templates/knowledge/hestiachain_meeting_place_jp/hestiachain_meeting_place_jp.md +147 -0
- data/templates/skills/config.yml +6 -0
- data/templates/skills/kairos.md +30 -0
- data/templates/skills/kairos_quickguide.md +34 -0
- data/templates/skillsets/hestia/config/hestia.yml +34 -0
- data/templates/skillsets/hestia/knowledge/hestia_meeting_place/hestia_meeting_place.md +237 -0
- data/templates/skillsets/hestia/lib/hestia/agent_registry.rb +204 -0
- data/templates/skillsets/hestia/lib/hestia/chain/backend/base.rb +78 -0
- data/templates/skillsets/hestia/lib/hestia/chain/backend/in_memory.rb +107 -0
- data/templates/skillsets/hestia/lib/hestia/chain/backend/private.rb +190 -0
- data/templates/skillsets/hestia/lib/hestia/chain/core/anchor.rb +138 -0
- data/templates/skillsets/hestia/lib/hestia/chain/core/batch_processor.rb +107 -0
- data/templates/skillsets/hestia/lib/hestia/chain/core/client.rb +104 -0
- data/templates/skillsets/hestia/lib/hestia/chain/core/config.rb +102 -0
- data/templates/skillsets/hestia/lib/hestia/chain/integrations/base.rb +44 -0
- data/templates/skillsets/hestia/lib/hestia/chain/integrations/meeting_protocol.rb +121 -0
- data/templates/skillsets/hestia/lib/hestia/chain/migration/migrator.rb +161 -0
- data/templates/skillsets/hestia/lib/hestia/chain/protocol/observation_log.rb +152 -0
- data/templates/skillsets/hestia/lib/hestia/chain/protocol/philosophy_declaration.rb +127 -0
- data/templates/skillsets/hestia/lib/hestia/chain/protocol/types.rb +36 -0
- data/templates/skillsets/hestia/lib/hestia/chain/protocol.rb +29 -0
- data/templates/skillsets/hestia/lib/hestia/chain_migrator.rb +140 -0
- data/templates/skillsets/hestia/lib/hestia/heartbeat_manager.rb +112 -0
- data/templates/skillsets/hestia/lib/hestia/hestia_chain_adapter.rb +90 -0
- data/templates/skillsets/hestia/lib/hestia/place_router.rb +312 -0
- data/templates/skillsets/hestia/lib/hestia/skill_board.rb +85 -0
- data/templates/skillsets/hestia/lib/hestia.rb +79 -0
- data/templates/skillsets/hestia/skillset.json +19 -0
- data/templates/skillsets/hestia/tools/chain_migrate_execute.rb +75 -0
- data/templates/skillsets/hestia/tools/chain_migrate_status.rb +55 -0
- data/templates/skillsets/hestia/tools/meeting_place_start.rb +86 -0
- data/templates/skillsets/hestia/tools/meeting_place_status.rb +73 -0
- data/templates/skillsets/hestia/tools/philosophy_anchor.rb +105 -0
- data/templates/skillsets/hestia/tools/record_observation.rb +105 -0
- data/templates/skillsets/mmp/lib/mmp/meeting_session_store.rb +136 -0
- data/templates/skillsets/mmp/lib/mmp/peer_manager.rb +29 -22
- data/templates/skillsets/mmp/lib/mmp/place_client.rb +27 -3
- data/templates/skillsets/mmp/lib/mmp/skill_exchange.rb +4 -0
- metadata +41 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5fd71b1e5a02a3c56628d6af5a0e45eba34b8e345c44d82dd58be023e8eb9f2e
|
|
4
|
+
data.tar.gz: d8f57a9f80bd3338d7c329aca088b6f0185da9c21f4558c4fabab8c571e54872
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3aa8ae7abfdbbf2c7353ab223cf2b1ed472225ce636c6ce698fb8c899d10d74347cbccbf0163c7e4775228496ff5ba75afcc7728e764cda0615f676979a03783
|
|
7
|
+
data.tar.gz: 30eebdc840a2c65c8321bacd9610899fc89d15c47ee86dd4912db619ca3ad6405ca1fa6f15ef8d14efea5791e01061ff20b7ea82233841a63e97495c1851fd63
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `kairos-chain` gem will be documented in this file.
|
|
4
|
+
|
|
5
|
+
This project follows [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [2.0.1] - 2026-02-23
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **MCP Instructions**: `instructions` field in `initialize` response delivers
|
|
12
|
+
KairosChain philosophy or quick guide to LLM on connection
|
|
13
|
+
- `instructions_mode` config: `developer` (full kairos.md), `user` (quick guide), `none`
|
|
14
|
+
- New template: `kairos_quickguide.md` — concise user-facing operational guide
|
|
15
|
+
- **L0-A Philosophy**: Added PHILOSOPHY-001 (Generative Principle) and
|
|
16
|
+
PHILOSOPHY-005 (Five Propositions) to `kairos.md`
|
|
17
|
+
- **Agent Instruction Sync**: `scripts/sync_agent_instructions.sh` syncs CLAUDE.md
|
|
18
|
+
to `.cursor/rules/kairos.mdc` for Cursor IDE support
|
|
19
|
+
- **Test**: Initialize instructions test (Test 0) in `test_local.rb`
|
|
20
|
+
|
|
21
|
+
## [2.0.0] - 2026-02-23
|
|
22
|
+
|
|
23
|
+
### Breaking Changes
|
|
24
|
+
|
|
25
|
+
- **HestiaChain Meeting Place Server**: New `/place/v1/*` HTTP endpoints require
|
|
26
|
+
the `hestia` SkillSet to be installed. Existing MMP P2P endpoints (`/meeting/v1/*`)
|
|
27
|
+
are unchanged.
|
|
28
|
+
- **SkillSet versioning**: `depends_on` now supports semantic version constraints
|
|
29
|
+
(e.g., `{name: "mmp", version: ">= 1.0.0"}`). Old array format still accepted.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- **Phase 4.pre**: Authentication and hardening for HTTP server
|
|
34
|
+
- Admin token rotation via `token_manage` tool
|
|
35
|
+
- Session-based authentication for P2P endpoints
|
|
36
|
+
- **Phase 4A**: HestiaChain Foundation — Self-contained SkillSet + DEE Protocol
|
|
37
|
+
- `Hestia::Chain::Core` (Anchor, Client, Config, BatchProcessor)
|
|
38
|
+
- `Hestia::Chain::Backend` (InMemory stage 0, PrivateJSON stage 1)
|
|
39
|
+
- `Hestia::Chain::Protocol` (DEE types, PhilosophyDeclaration, ObservationLog)
|
|
40
|
+
- `Hestia::Chain::Integrations::MeetingProtocol`
|
|
41
|
+
- `Hestia::HestiaChainAdapter` implementing `MMP::ChainAdapter`
|
|
42
|
+
- `Hestia::ChainMigrator` with stage-gate migration (0→1)
|
|
43
|
+
- MCP tools: `chain_migrate_status`, `chain_migrate_execute`,
|
|
44
|
+
`philosophy_anchor`, `record_observation`
|
|
45
|
+
- 77 new test assertions
|
|
46
|
+
- **Phase 4B**: Meeting Place Server
|
|
47
|
+
- `Hestia::AgentRegistry` — JSON-persisted, Mutex thread-safe, self_register
|
|
48
|
+
- `Hestia::SkillBoard` — Random sampling (DEE D3: no ranking)
|
|
49
|
+
- `Hestia::HeartbeatManager` — TTL-based fadeout with ObservationLog recording
|
|
50
|
+
- `Hestia::PlaceRouter` — Rack-compatible HTTP routing for `/place/v1/*`
|
|
51
|
+
- HTTP endpoints: `/place/v1/info`, `register`, `unregister`, `agents`,
|
|
52
|
+
`board/browse`, `keys/:id`
|
|
53
|
+
- MCP tools: `meeting_place_start`, `meeting_place_status`
|
|
54
|
+
- PlaceRouter integrated into existing HttpServer (same pattern as MeetingRouter)
|
|
55
|
+
- 70 new test assertions
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- Add missing `require 'uri'` in MeetingRouter (query string parsing)
|
|
60
|
+
- Rakefile now includes Phase 4A/4B integration tests via `rake test_all`
|
|
61
|
+
|
|
62
|
+
### Test Results
|
|
63
|
+
|
|
64
|
+
- **Total**: 356 assertions passed, 0 failed
|
|
65
|
+
- Phase 1–3.85 (existing): 170, Phase 4A: 77, Phase 4B: 70, SkillSet manager: 37
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## [1.2.0] - 2026-02-22
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
|
|
73
|
+
- **Phase 1**: SkillSet Plugin Infrastructure
|
|
74
|
+
- `SkillSetManager` for installing/uninstalling SkillSet packages
|
|
75
|
+
- SkillSet manifest format (`skillset.json`)
|
|
76
|
+
- Namespace isolation for SkillSet tools and knowledge
|
|
77
|
+
- **Phase 2**: MMP SkillSet packaging + P2P direct mode
|
|
78
|
+
- MMP packaged as a self-contained SkillSet
|
|
79
|
+
- `/meeting/v1/*` HTTP endpoints for P2P communication
|
|
80
|
+
- `MMP::Identity`, `MMP::MeetingSessionStore`
|
|
81
|
+
- **Phase 3**: Knowledge-only SkillSet exchange via MMP P2P
|
|
82
|
+
- `SkillExchange` with content hash verification and provenance tracking
|
|
83
|
+
- `knowledge_only` mode for safe skill sharing
|
|
84
|
+
- **Phase 3.5**: Security fixes and MMP wire protocol specification
|
|
85
|
+
- Name sanitization, path traversal guard
|
|
86
|
+
- Extended `knowledge_only` integrity check
|
|
87
|
+
- MMP wire protocol spec document
|
|
88
|
+
- **Phase 3.7**: Pre-Phase 4 hardening
|
|
89
|
+
- RSA signature verification for handshake (`Identity#introduce`)
|
|
90
|
+
- `depends_on` semantic version constraints (`Gem::Requirement`)
|
|
91
|
+
- `PeerManager` persistence with TOFU trust model
|
|
92
|
+
- **Phase 3.75**: MMP extension infrastructure
|
|
93
|
+
- Collision detection, extension advertise, core action guard
|
|
94
|
+
- **Phase 3.85**: Pre-merge hardening
|
|
95
|
+
- `.gitignore`: `*.pem`, `*.pem.pub`, `keys/`
|
|
96
|
+
- Error message sanitization in HTTP responses
|
|
97
|
+
- `DEFAULT_HOST` changed from `0.0.0.0` to `127.0.0.1`
|
|
98
|
+
|
|
99
|
+
### Test Results
|
|
100
|
+
|
|
101
|
+
- **Total**: 170 assertions passed, 0 failed
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## [1.0.0] - 2026-02-14
|
|
106
|
+
|
|
107
|
+
### Added
|
|
108
|
+
|
|
109
|
+
- Renamed gem from `kairos_mcp` to `kairos-chain`
|
|
110
|
+
- Bundle official L1 knowledge in gem
|
|
111
|
+
- Upgrade migration system (`system_upgrade` tool)
|
|
112
|
+
- htmx-based Admin UI for Streamable HTTP server
|
|
113
|
+
- Claude Code plugin marketplace support
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## [0.9.0] - 2026-02-12
|
|
118
|
+
|
|
119
|
+
### Added
|
|
120
|
+
|
|
121
|
+
- Streamable HTTP transport with Bearer token authentication
|
|
122
|
+
- Puma web server integration
|
|
123
|
+
- Admin UI with L2 Context viewer
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## [0.1.0] - 2026-01-15
|
|
128
|
+
|
|
129
|
+
### Added
|
|
130
|
+
|
|
131
|
+
- Initial release
|
|
132
|
+
- Layered skill architecture (L0/L1/L2)
|
|
133
|
+
- Private blockchain for auditability
|
|
134
|
+
- Skills DSL with Ruby AST
|
|
135
|
+
- MCP (Model Context Protocol) server via stdio
|
|
136
|
+
- Vector search for skills and knowledge (optional RAG)
|
|
137
|
+
- SQLite storage backend (optional)
|
|
138
|
+
- StateCommit for cross-layer auditability
|
|
139
|
+
- Skill promotion with Persona Assembly
|
|
140
|
+
- Tool guide and metadata system
|
|
141
|
+
|
|
142
|
+
[2.0.0]: https://github.com/masaomi/KairosChain_2026/compare/v1.2.0...v2.0.0
|
|
143
|
+
[1.2.0]: https://github.com/masaomi/KairosChain_2026/compare/v1.0.0...v1.2.0
|
|
144
|
+
[1.0.0]: https://github.com/masaomi/KairosChain_2026/compare/v0.9.0...v1.0.0
|
|
145
|
+
[0.9.0]: https://github.com/masaomi/KairosChain_2026/compare/v0.1.0...v0.9.0
|
|
146
|
+
[0.1.0]: https://github.com/masaomi/KairosChain_2026/releases/tag/v0.1.0
|
|
@@ -38,7 +38,7 @@ module KairosMcp
|
|
|
38
38
|
'Cache-Control' => 'no-cache'
|
|
39
39
|
}.freeze
|
|
40
40
|
|
|
41
|
-
attr_reader :port, :host, :token_store, :authenticator, :admin_router, :meeting_router
|
|
41
|
+
attr_reader :port, :host, :token_store, :authenticator, :admin_router, :meeting_router, :place_router
|
|
42
42
|
|
|
43
43
|
def initialize(port: nil, host: nil, token_store_path: nil)
|
|
44
44
|
http_config = SkillsConfig.load['http'] || {}
|
|
@@ -53,6 +53,7 @@ module KairosMcp
|
|
|
53
53
|
@authenticator = Auth::Authenticator.new(@token_store)
|
|
54
54
|
@admin_router = Admin::Router.new(token_store: @token_store, authenticator: @authenticator)
|
|
55
55
|
@meeting_router = MeetingRouter.new
|
|
56
|
+
@place_router = nil # Initialized lazily via meeting_place_start tool
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
# Start the HTTP server with Puma
|
|
@@ -119,6 +120,11 @@ module KairosMcp
|
|
|
119
120
|
return server.meeting_router.call(env)
|
|
120
121
|
end
|
|
121
122
|
|
|
123
|
+
# Hestia Meeting Place endpoints
|
|
124
|
+
if path.start_with?('/place/')
|
|
125
|
+
return server.handle_place(env)
|
|
126
|
+
end
|
|
127
|
+
|
|
122
128
|
case [request_method, path]
|
|
123
129
|
when ['GET', '/health']
|
|
124
130
|
server.handle_health
|
|
@@ -190,6 +196,26 @@ module KairosMcp
|
|
|
190
196
|
message: "Internal server error: #{e.message}")
|
|
191
197
|
end
|
|
192
198
|
|
|
199
|
+
# Handle /place/* routes via Hestia PlaceRouter
|
|
200
|
+
def handle_place(env)
|
|
201
|
+
unless @place_router
|
|
202
|
+
return json_response(503, error: 'place_not_started',
|
|
203
|
+
message: 'Meeting Place is not started. Use meeting_place_start tool first.')
|
|
204
|
+
end
|
|
205
|
+
@place_router.call(env)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Start the Meeting Place (called by meeting_place_start tool)
|
|
209
|
+
def start_place(identity:, trust_anchor_client: nil)
|
|
210
|
+
require 'hestia'
|
|
211
|
+
@place_router = ::Hestia::PlaceRouter.new
|
|
212
|
+
@place_router.start(
|
|
213
|
+
identity: identity,
|
|
214
|
+
session_store: @meeting_router.session_store,
|
|
215
|
+
trust_anchor_client: trust_anchor_client
|
|
216
|
+
)
|
|
217
|
+
end
|
|
218
|
+
|
|
193
219
|
# -----------------------------------------------------------------------
|
|
194
220
|
# Helpers
|
|
195
221
|
# -----------------------------------------------------------------------
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
|
+
require 'uri'
|
|
4
5
|
|
|
5
6
|
module KairosMcp
|
|
6
7
|
# MeetingRouter handles MMP (Model Meeting Protocol) HTTP endpoints
|
|
@@ -18,6 +19,7 @@ module KairosMcp
|
|
|
18
19
|
@protocol = nil
|
|
19
20
|
@identity = nil
|
|
20
21
|
@exchange = nil
|
|
22
|
+
@session_store = nil
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def call(env)
|
|
@@ -26,11 +28,21 @@ module KairosMcp
|
|
|
26
28
|
request_method = env['REQUEST_METHOD']
|
|
27
29
|
path = env['PATH_INFO']
|
|
28
30
|
|
|
31
|
+
# Unauthenticated endpoints
|
|
29
32
|
case [request_method, path]
|
|
30
33
|
when ['GET', '/meeting/v1/introduce']
|
|
31
|
-
handle_get_introduce
|
|
34
|
+
return handle_get_introduce
|
|
32
35
|
when ['POST', '/meeting/v1/introduce']
|
|
33
|
-
handle_post_introduce(env)
|
|
36
|
+
return handle_post_introduce(env)
|
|
37
|
+
when ['POST', '/meeting/v1/goodbye']
|
|
38
|
+
return handle_goodbye(env)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# All other endpoints require Bearer token authentication
|
|
42
|
+
auth_result = authenticate_meeting_request!(env)
|
|
43
|
+
return auth_result unless auth_result.nil?
|
|
44
|
+
|
|
45
|
+
case [request_method, path]
|
|
34
46
|
when ['POST', '/meeting/v1/message']
|
|
35
47
|
handle_message(env)
|
|
36
48
|
when ['GET', '/meeting/v1/skills']
|
|
@@ -62,6 +74,14 @@ module KairosMcp
|
|
|
62
74
|
@protocol = nil
|
|
63
75
|
end
|
|
64
76
|
|
|
77
|
+
# Public accessor for session store (testing)
|
|
78
|
+
def session_store
|
|
79
|
+
@session_store ||= begin
|
|
80
|
+
require_relative '../../templates/skillsets/mmp/lib/mmp/meeting_session_store'
|
|
81
|
+
MMP::MeetingSessionStore.new
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
65
85
|
private
|
|
66
86
|
|
|
67
87
|
def mmp_available?
|
|
@@ -137,16 +157,20 @@ module KairosMcp
|
|
|
137
157
|
end
|
|
138
158
|
|
|
139
159
|
# POST /meeting/v1/introduce - Receive introduction from peer
|
|
160
|
+
# If RSA signature verification succeeds, a session token is issued.
|
|
140
161
|
def handle_post_introduce(env)
|
|
141
162
|
body = parse_body(env)
|
|
142
163
|
|
|
143
164
|
# Signature verification (H2 fix: verify identity if signed)
|
|
144
165
|
verified = false
|
|
145
|
-
|
|
166
|
+
peer_id = body.dig('identity', 'instance_id')
|
|
167
|
+
public_key = body['public_key']
|
|
168
|
+
|
|
169
|
+
if public_key && body['identity_signature'] && body['identity']
|
|
146
170
|
begin
|
|
147
171
|
canonical = JSON.generate(body['identity'], sort_keys: true)
|
|
148
172
|
crypto = MMP::Crypto.new(auto_generate: false)
|
|
149
|
-
verified = crypto.verify_signature(canonical, body['identity_signature'],
|
|
173
|
+
verified = crypto.verify_signature(canonical, body['identity_signature'], public_key)
|
|
150
174
|
rescue StandardError => e
|
|
151
175
|
$stderr.puts "[MeetingRouter] Signature verification failed: #{e.message}"
|
|
152
176
|
end
|
|
@@ -154,12 +178,31 @@ module KairosMcp
|
|
|
154
178
|
|
|
155
179
|
result = protocol.process_message(body.merge('action' => 'introduce'))
|
|
156
180
|
|
|
157
|
-
|
|
181
|
+
response = {
|
|
158
182
|
status: 'received',
|
|
159
183
|
peer_identity: identity.introduce,
|
|
160
184
|
identity_verified: verified,
|
|
161
185
|
result: result
|
|
162
|
-
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
# Issue session token if signature was verified
|
|
189
|
+
if verified && peer_id
|
|
190
|
+
token = session_store.create_session(peer_id, public_key)
|
|
191
|
+
response[:session_token] = token
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
json_response(200, response)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# POST /meeting/v1/goodbye - Revoke session token
|
|
198
|
+
def handle_goodbye(env)
|
|
199
|
+
token = extract_bearer_token(env)
|
|
200
|
+
if token
|
|
201
|
+
session_store.revoke(token)
|
|
202
|
+
json_response(200, { status: 'goodbye', message: 'Session ended' })
|
|
203
|
+
else
|
|
204
|
+
json_response(400, { error: 'no_token', message: 'No session token provided' })
|
|
205
|
+
end
|
|
163
206
|
end
|
|
164
207
|
|
|
165
208
|
# POST /meeting/v1/message - Generic MMP message handler
|
|
@@ -381,7 +424,46 @@ module KairosMcp
|
|
|
381
424
|
})
|
|
382
425
|
end
|
|
383
426
|
|
|
384
|
-
#
|
|
427
|
+
# --- Authentication ---
|
|
428
|
+
|
|
429
|
+
# Authenticate a meeting request via Bearer token.
|
|
430
|
+
# Returns nil if authenticated, or an error response triple if not.
|
|
431
|
+
def authenticate_meeting_request!(env)
|
|
432
|
+
token = extract_bearer_token(env)
|
|
433
|
+
|
|
434
|
+
unless token
|
|
435
|
+
return json_response(401, {
|
|
436
|
+
error: 'authentication_required',
|
|
437
|
+
message: 'Bearer token required. Use POST /meeting/v1/introduce to obtain a session token.'
|
|
438
|
+
})
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
peer_id = session_store.validate(token)
|
|
442
|
+
unless peer_id
|
|
443
|
+
return json_response(401, {
|
|
444
|
+
error: 'invalid_or_expired_token',
|
|
445
|
+
message: 'Session token is invalid or has expired. Re-introduce to obtain a new token.'
|
|
446
|
+
})
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
unless session_store.check_rate_limit(token)
|
|
450
|
+
return json_response(429, {
|
|
451
|
+
error: 'rate_limited',
|
|
452
|
+
message: 'Too many requests. Please wait before retrying.'
|
|
453
|
+
})
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
nil # Authentication passed
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def extract_bearer_token(env)
|
|
460
|
+
auth_header = env['HTTP_AUTHORIZATION'] || ''
|
|
461
|
+
return nil unless auth_header.start_with?('Bearer ')
|
|
462
|
+
|
|
463
|
+
auth_header.sub('Bearer ', '').strip
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# --- Helpers ---
|
|
385
467
|
|
|
386
468
|
def parse_body(env)
|
|
387
469
|
body = env['rack.input']&.read
|
data/lib/kairos_mcp/protocol.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
require_relative 'tool_registry'
|
|
3
|
+
require_relative 'skills_config'
|
|
3
4
|
require_relative 'version'
|
|
4
5
|
|
|
5
6
|
module KairosMcp
|
|
@@ -59,7 +60,7 @@ module KairosMcp
|
|
|
59
60
|
@tool_registry.set_workspace(roots)
|
|
60
61
|
@initialized = true
|
|
61
62
|
|
|
62
|
-
{
|
|
63
|
+
result = {
|
|
63
64
|
protocolVersion: protocol_version,
|
|
64
65
|
capabilities: {
|
|
65
66
|
tools: {
|
|
@@ -72,6 +73,42 @@ module KairosMcp
|
|
|
72
73
|
version: KairosMcp::VERSION
|
|
73
74
|
}
|
|
74
75
|
}
|
|
76
|
+
|
|
77
|
+
# Add instructions based on config mode (developer/user/none)
|
|
78
|
+
instructions = load_instructions
|
|
79
|
+
result[:instructions] = instructions if instructions
|
|
80
|
+
|
|
81
|
+
result
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Load instructions based on instructions_mode in config.yml
|
|
85
|
+
#
|
|
86
|
+
# @return [String, nil] Instructions text or nil
|
|
87
|
+
def load_instructions
|
|
88
|
+
mode = SkillsConfig.load['instructions_mode'] || 'user'
|
|
89
|
+
|
|
90
|
+
path = case mode
|
|
91
|
+
when 'developer'
|
|
92
|
+
KairosMcp.md_path # Full philosophy (kairos.md)
|
|
93
|
+
when 'user'
|
|
94
|
+
KairosMcp.quickguide_path # Quick guide (kairos_quickguide.md)
|
|
95
|
+
when 'none'
|
|
96
|
+
nil
|
|
97
|
+
else
|
|
98
|
+
KairosMcp.quickguide_path # Default to user mode
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
return nil unless path
|
|
102
|
+
|
|
103
|
+
read_if_exists(path)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Read file content if it exists
|
|
107
|
+
#
|
|
108
|
+
# @param path [String] File path
|
|
109
|
+
# @return [String, nil] File content or nil
|
|
110
|
+
def read_if_exists(path)
|
|
111
|
+
File.exist?(path) ? File.read(path) : nil
|
|
75
112
|
end
|
|
76
113
|
|
|
77
114
|
def handle_tools_list
|
data/lib/kairos_mcp/version.rb
CHANGED
data/lib/kairos_mcp.rb
CHANGED
|
@@ -13,20 +13,22 @@ module KairosMcp
|
|
|
13
13
|
# Format: [template_relative_path, data_dir_accessor_symbol]
|
|
14
14
|
#
|
|
15
15
|
TEMPLATE_FILES = [
|
|
16
|
-
['skills/kairos.rb',
|
|
17
|
-
['skills/kairos.md',
|
|
18
|
-
['skills/
|
|
19
|
-
['config
|
|
20
|
-
['config/
|
|
16
|
+
['skills/kairos.rb', :dsl_path],
|
|
17
|
+
['skills/kairos.md', :md_path],
|
|
18
|
+
['skills/kairos_quickguide.md', :quickguide_path],
|
|
19
|
+
['skills/config.yml', :skills_config_path],
|
|
20
|
+
['config/safety.yml', :safety_config_path],
|
|
21
|
+
['config/tool_metadata.yml', :tool_metadata_path]
|
|
21
22
|
].freeze
|
|
22
23
|
|
|
23
24
|
# File type classification for upgrade conflict resolution
|
|
24
25
|
TEMPLATE_FILE_TYPES = {
|
|
25
|
-
'skills/kairos.rb'
|
|
26
|
-
'skills/kairos.md'
|
|
27
|
-
'skills/
|
|
28
|
-
'config
|
|
29
|
-
'config/
|
|
26
|
+
'skills/kairos.rb' => :l0_dsl,
|
|
27
|
+
'skills/kairos.md' => :l0_doc,
|
|
28
|
+
'skills/kairos_quickguide.md' => :l0_doc,
|
|
29
|
+
'skills/config.yml' => :config_yaml,
|
|
30
|
+
'config/safety.yml' => :config_yaml,
|
|
31
|
+
'config/tool_metadata.yml' => :config_yaml
|
|
30
32
|
}.freeze
|
|
31
33
|
|
|
32
34
|
# =========================================================================
|
|
@@ -85,6 +87,11 @@ module KairosMcp
|
|
|
85
87
|
File.join(skills_dir, 'kairos.md')
|
|
86
88
|
end
|
|
87
89
|
|
|
90
|
+
# L0 skills quick guide file path (user-facing instructions)
|
|
91
|
+
def quickguide_path
|
|
92
|
+
File.join(skills_dir, 'kairos_quickguide.md')
|
|
93
|
+
end
|
|
94
|
+
|
|
88
95
|
# L0 skills config file path
|
|
89
96
|
def skills_config_path
|
|
90
97
|
File.join(skills_dir, 'config.yml')
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hestiachain_meeting_place
|
|
3
|
+
description: "HestiaChain Meeting Place — user guide for agent discovery, skill exchange, and trust anchoring"
|
|
4
|
+
version: 2.0
|
|
5
|
+
layer: L1
|
|
6
|
+
tags: [documentation, readme, hestia, meeting-place, p2p, deployment, trust-anchor]
|
|
7
|
+
readme_order: 4.5
|
|
8
|
+
readme_lang: en
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## HestiaChain Meeting Place (v2.0.0)
|
|
12
|
+
|
|
13
|
+
### What is HestiaChain?
|
|
14
|
+
|
|
15
|
+
HestiaChain is a **trust anchor and meeting place** for KairosChain agents. It is implemented entirely as a SkillSet (the `hestia` SkillSet), preserving KairosChain's principle that new capabilities are expressed as SkillSets rather than core modifications.
|
|
16
|
+
|
|
17
|
+
HestiaChain provides two functions:
|
|
18
|
+
|
|
19
|
+
1. **Trust Anchor** — A witness chain that records *that* interactions occurred, without enforcing judgments or determining canonical state
|
|
20
|
+
2. **Meeting Place Server** — A hosted environment where agents discover each other, browse skills, and exchange knowledge via HTTP endpoints
|
|
21
|
+
|
|
22
|
+
### Architecture
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
KairosChain (MCP Server)
|
|
26
|
+
├── [core] L0/L1/L2 + private blockchain
|
|
27
|
+
├── [SkillSet: mmp] P2P direct mode, /meeting/v1/*
|
|
28
|
+
└── [SkillSet: hestia] Meeting Place + trust anchor
|
|
29
|
+
├── chain/ ← Trust anchor (self-contained, no external gem dependency)
|
|
30
|
+
├── PlaceRouter ← /place/v1/* HTTP endpoints
|
|
31
|
+
├── AgentRegistry ← Agent registration with JSON persistence
|
|
32
|
+
├── SkillBoard ← Skill discovery (random sampling, no ranking)
|
|
33
|
+
├── HeartbeatManager ← TTL-based liveness with fadeout recording
|
|
34
|
+
└── tools/ ← 6 MCP tools
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
A KairosChain instance with the hestia SkillSet is simultaneously an MCP server, a P2P agent, a Meeting Place host, and a participant in other Meeting Places. This embodies the DEE principle of subject-object undifferentiation (主客未分).
|
|
38
|
+
|
|
39
|
+
### Quick Start
|
|
40
|
+
|
|
41
|
+
#### 1. Install the hestia SkillSet
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# The hestia SkillSet is bundled with the gem.
|
|
45
|
+
# It is installed automatically when you install mmp.
|
|
46
|
+
# To install manually:
|
|
47
|
+
kairos-chain # Start KairosChain
|
|
48
|
+
# Then in Claude Code / Cursor:
|
|
49
|
+
"Install the hestia SkillSet"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
#### 2. Start the Meeting Place
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Start HTTP server
|
|
56
|
+
kairos-chain --http --port 8080
|
|
57
|
+
|
|
58
|
+
# Then in Claude Code / Cursor:
|
|
59
|
+
"Start the Meeting Place"
|
|
60
|
+
# This calls the meeting_place_start tool
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### 3. Test with curl
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Place info (no auth required)
|
|
67
|
+
curl -s http://localhost:8080/place/v1/info | python3 -m json.tool
|
|
68
|
+
|
|
69
|
+
# Register an agent
|
|
70
|
+
curl -s -X POST http://localhost:8080/place/v1/register \
|
|
71
|
+
-H 'Content-Type: application/json' \
|
|
72
|
+
-d '{"id":"agent-alpha","name":"Agent Alpha","capabilities":{"supported_actions":["test"]}}'
|
|
73
|
+
|
|
74
|
+
# Browse the skill board (Bearer token required)
|
|
75
|
+
curl -s -H "Authorization: Bearer $TOKEN" \
|
|
76
|
+
http://localhost:8080/place/v1/board/browse | python3 -m json.tool
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### HTTP Endpoints
|
|
80
|
+
|
|
81
|
+
| Method | Path | Auth | Description |
|
|
82
|
+
|--------|------|------|-------------|
|
|
83
|
+
| GET | `/place/v1/info` | None | Place metadata and identity |
|
|
84
|
+
| POST | `/place/v1/register` | RSA signature (optional) | Register an agent |
|
|
85
|
+
| POST | `/place/v1/unregister` | Bearer | Unregister an agent |
|
|
86
|
+
| GET | `/place/v1/agents` | Bearer | List registered agents |
|
|
87
|
+
| GET | `/place/v1/board/browse` | Bearer | Browse skill board (random order) |
|
|
88
|
+
| GET | `/place/v1/keys/:id` | Bearer | Retrieve agent's public key |
|
|
89
|
+
|
|
90
|
+
### MCP Tools
|
|
91
|
+
|
|
92
|
+
| Tool | Description |
|
|
93
|
+
|------|-------------|
|
|
94
|
+
| `chain_migrate_status` | Show current backend stage and available migrations |
|
|
95
|
+
| `chain_migrate_execute` | Migrate chain to next backend stage |
|
|
96
|
+
| `philosophy_anchor` | Declare exchange philosophy (hash recorded on chain) |
|
|
97
|
+
| `record_observation` | Record subjective observation of interaction |
|
|
98
|
+
| `meeting_place_start` | Start the Meeting Place, initialize components |
|
|
99
|
+
| `meeting_place_status` | Show Meeting Place configuration and status |
|
|
100
|
+
|
|
101
|
+
### Trust Anchor: Chain Migration
|
|
102
|
+
|
|
103
|
+
HestiaChain's trust anchor supports a 4-stage backend progression:
|
|
104
|
+
|
|
105
|
+
| Stage | Backend | Use Case |
|
|
106
|
+
|-------|---------|----------|
|
|
107
|
+
| 0 | In-memory | Development and testing |
|
|
108
|
+
| 1 | Private JSON file | Production-ready, self-hosted |
|
|
109
|
+
| 2 | Public testnet (Base Sepolia) | Cross-instance verification |
|
|
110
|
+
| 3 | Public mainnet | Full decentralization |
|
|
111
|
+
|
|
112
|
+
Use `chain_migrate_status` to check and `chain_migrate_execute` to advance.
|
|
113
|
+
|
|
114
|
+
### DEE Philosophy Protocol
|
|
115
|
+
|
|
116
|
+
HestiaChain implements the Decentralized Event Exchange (DEE) protocol:
|
|
117
|
+
|
|
118
|
+
- **PhilosophyDeclaration**: Agents declare their exchange philosophy (observable, not enforceable). Only the hash is recorded on chain.
|
|
119
|
+
- **ObservationLog**: Agents record subjective observations. Multiple agents can have different observations of the same interaction — "meaning coexists."
|
|
120
|
+
- **Fadeout**: When an agent's heartbeat expires, this is recorded as a first-class event (not an error). Silent departure is a natural part of the protocol.
|
|
121
|
+
- **Random Sampling**: The SkillBoard returns skills in random order. There is no ranking, no scoring, no popularity metric.
|
|
122
|
+
|
|
123
|
+
### EC2 Deployment
|
|
124
|
+
|
|
125
|
+
To host a public Meeting Place on AWS EC2:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Install
|
|
129
|
+
gem install kairos-chain
|
|
130
|
+
|
|
131
|
+
# Initialize
|
|
132
|
+
kairos-chain init ~/.kairos
|
|
133
|
+
|
|
134
|
+
# Start (bind to all interfaces for external access)
|
|
135
|
+
KAIROS_HOST=0.0.0.0 KAIROS_PORT=8080 kairos-chain --http
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
For production, use a reverse proxy (Caddy/nginx) for TLS:
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
# Caddyfile example
|
|
142
|
+
kairos.example.com {
|
|
143
|
+
reverse_proxy localhost:8080
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
For detailed DEE protocol internals, install the hestia SkillSet and refer to its bundled knowledge (`hestia_meeting_place`).
|