claude-brain 0.30.2 → 0.30.3
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.
- package/README.md +241 -191
- package/VERSION +1 -1
- package/assets/CLAUDE-unified.md +11 -11
- package/assets/CLAUDE.md +29 -29
- package/package.json +7 -3
- package/packs/backend/node.json +173 -173
- package/packs/core/javascript.json +176 -176
- package/packs/core/typescript.json +222 -222
- package/packs/frontend/react.json +254 -254
- package/packs/meta/testing.json +172 -172
- package/scripts/postinstall.mjs +531 -531
- package/src/automation/decision-detector.ts +452 -452
- package/src/automation/phase12-manager.ts +456 -456
- package/src/automation/proactive-recall.ts +373 -373
- package/src/automation/project-detector.ts +310 -310
- package/src/automation/repo-scanner.ts +210 -205
- package/src/cli/auto-setup.ts +75 -75
- package/src/cli/auto-start.ts +266 -266
- package/src/cli/bin.ts +264 -264
- package/src/cli/commands/autostart.ts +90 -90
- package/src/cli/commands/chroma.ts +578 -577
- package/src/cli/commands/export-training.ts +70 -70
- package/src/cli/commands/export.ts +130 -130
- package/src/cli/commands/git-hook.ts +183 -183
- package/src/cli/commands/hooks.ts +217 -217
- package/src/cli/commands/init.ts +123 -123
- package/src/cli/commands/install-mcp.ts +122 -111
- package/src/cli/commands/models.ts +979 -979
- package/src/cli/commands/pack.ts +200 -200
- package/src/cli/commands/refresh.ts +344 -339
- package/src/cli/commands/reindex.ts +120 -120
- package/src/cli/commands/serve.ts +466 -463
- package/src/cli/commands/start.ts +44 -44
- package/src/cli/commands/status.ts +220 -203
- package/src/cli/commands/uninstall-mcp.ts +45 -41
- package/src/cli/commands/update.ts +130 -124
- package/src/cli/migrate-chroma.ts +106 -106
- package/src/cli/ui/animations.ts +80 -80
- package/src/cli/ui/components.ts +82 -82
- package/src/cli/ui/index.ts +4 -4
- package/src/cli/ui/logo.ts +36 -36
- package/src/cli/ui/theme.ts +55 -55
- package/src/code-intelligence/indexer.ts +352 -352
- package/src/code-intelligence/linker.ts +178 -178
- package/src/code-intelligence/parser.ts +484 -484
- package/src/code-intelligence/query.ts +291 -291
- package/src/code-intelligence/schema.ts +83 -83
- package/src/code-intelligence/types.ts +95 -95
- package/src/config/defaults.ts +52 -52
- package/src/config/home.ts +56 -56
- package/src/config/index.ts +5 -5
- package/src/config/loader.ts +192 -192
- package/src/config/schema.ts +446 -415
- package/src/config/validator.ts +182 -182
- package/src/context/assembler.ts +407 -400
- package/src/context/index.ts +79 -79
- package/src/context/progress-tracker.ts +174 -174
- package/src/context/standards-manager.ts +287 -287
- package/src/context/validator.ts +58 -58
- package/src/diagnostics/index.ts +122 -121
- package/src/health/index.ts +233 -232
- package/src/hooks/brain-hook.ts +134 -131
- package/src/hooks/capture.ts +168 -168
- package/src/hooks/claude-code-mastery.md +112 -112
- package/src/hooks/context-hook.ts +260 -245
- package/src/hooks/deduplicator.ts +72 -72
- package/src/hooks/git-capture.ts +109 -109
- package/src/hooks/git-hook-installer.ts +211 -207
- package/src/hooks/index.ts +20 -20
- package/src/hooks/installer.ts +306 -288
- package/src/hooks/interceptor-hook.ts +204 -201
- package/src/hooks/passive-classifier.ts +397 -397
- package/src/hooks/queue.ts +160 -129
- package/src/hooks/session-tracker.ts +312 -312
- package/src/hooks/types.ts +52 -52
- package/src/index.ts +7 -7
- package/src/intelligence/cross-project/generalizer.ts +283 -283
- package/src/intelligence/cross-project/index.ts +7 -7
- package/src/intelligence/hf-downloader.ts +222 -222
- package/src/intelligence/hf-manifest.json +78 -78
- package/src/intelligence/index.ts +24 -24
- package/src/intelligence/inference-router.ts +762 -762
- package/src/intelligence/model-manager.ts +263 -245
- package/src/intelligence/optimization/index.ts +10 -10
- package/src/intelligence/optimization/precompute.ts +202 -202
- package/src/intelligence/optimization/semantic-cache.ts +213 -207
- package/src/intelligence/prediction/index.ts +7 -7
- package/src/intelligence/prediction/recommender.ts +276 -268
- package/src/intelligence/reasoning/chain-retrieval.ts +243 -247
- package/src/intelligence/reasoning/index.ts +7 -7
- package/src/intelligence/temporal/evolution.ts +193 -197
- package/src/intelligence/temporal/index.ts +16 -16
- package/src/intelligence/temporal/query-processor.ts +190 -190
- package/src/intelligence/temporal/timeline.ts +272 -259
- package/src/intelligence/temporal/trends.ts +263 -263
- package/src/intelligence/tokenizer.ts +118 -118
- package/src/knowledge/entity-extractor.ts +447 -443
- package/src/knowledge/graph/builder.ts +185 -185
- package/src/knowledge/graph/linker.ts +201 -201
- package/src/knowledge/graph/memory-graph.ts +359 -359
- package/src/knowledge/graph/schema.ts +99 -99
- package/src/knowledge/graph/search.ts +166 -166
- package/src/knowledge/relationship-extractor.ts +108 -108
- package/src/memory/chroma/client.ts +211 -192
- package/src/memory/chroma/collection-manager.ts +92 -92
- package/src/memory/chroma/config.ts +57 -57
- package/src/memory/chroma/embeddings.ts +177 -175
- package/src/memory/chroma/index.ts +82 -82
- package/src/memory/chroma/migration.ts +270 -270
- package/src/memory/chroma/schemas.ts +69 -69
- package/src/memory/chroma/search.ts +319 -315
- package/src/memory/chroma/store.ts +755 -747
- package/src/memory/compression.ts +121 -121
- package/src/memory/consolidation/archiver.ts +162 -165
- package/src/memory/consolidation/merger.ts +182 -186
- package/src/memory/consolidation/scorer.ts +136 -136
- package/src/memory/database.ts +9 -0
- package/src/memory/dual-write.ts +145 -0
- package/src/memory/embeddings.ts +226 -226
- package/src/memory/episodic/detector.ts +108 -108
- package/src/memory/episodic/manager.ts +347 -351
- package/src/memory/episodic/summarizer.ts +179 -179
- package/src/memory/episodic/types.ts +52 -52
- package/src/memory/fts5-search.ts +692 -633
- package/src/memory/index.ts +943 -1060
- package/src/memory/migrations/add-fts5.ts +118 -108
- package/src/memory/patterns.ts +438 -438
- package/src/memory/pruning.ts +60 -60
- package/src/memory/schema.ts +88 -88
- package/src/memory/store.ts +911 -787
- package/src/orchestrator/handlers/decision-handler.ts +204 -204
- package/src/packs/index.ts +9 -9
- package/src/packs/loader.ts +134 -134
- package/src/packs/manager.ts +204 -204
- package/src/packs/ranker.ts +78 -78
- package/src/packs/types.ts +81 -81
- package/src/phase12/index.ts +5 -5
- package/src/retrieval/bm25/index.ts +300 -297
- package/src/retrieval/bm25/tokenizer.ts +184 -184
- package/src/retrieval/feedback/adaptive.ts +221 -221
- package/src/retrieval/feedback/index.ts +16 -16
- package/src/retrieval/feedback/metrics.ts +221 -221
- package/src/retrieval/feedback/store.ts +283 -283
- package/src/retrieval/fusion/index.ts +194 -194
- package/src/retrieval/fusion/rrf.ts +165 -165
- package/src/retrieval/index.ts +12 -12
- package/src/retrieval/pipeline.ts +375 -375
- package/src/retrieval/query/expander.ts +203 -203
- package/src/retrieval/query/index.ts +27 -27
- package/src/retrieval/query/intent-classifier.ts +252 -252
- package/src/retrieval/query/temporal-parser.ts +295 -295
- package/src/retrieval/reranker/index.ts +189 -188
- package/src/retrieval/reranker/model.ts +99 -95
- package/src/retrieval/service.ts +125 -125
- package/src/retrieval/types.ts +162 -162
- package/src/routing/entity-extractor.ts +454 -454
- package/src/routing/handlers/exploration-handler.ts +369 -0
- package/src/routing/handlers/index.ts +19 -0
- package/src/routing/handlers/memory-handler.ts +273 -0
- package/src/routing/handlers/mutation-handler.ts +241 -0
- package/src/routing/handlers/recall-handler.ts +642 -0
- package/src/routing/handlers/shared.ts +515 -0
- package/src/routing/handlers/types.ts +48 -0
- package/src/routing/intent-classifier.ts +552 -552
- package/src/routing/response-filter.ts +399 -391
- package/src/routing/router.ts +245 -2193
- package/src/routing/search-engine.ts +521 -514
- package/src/routing/types.ts +104 -94
- package/src/scripts/health-check.ts +118 -118
- package/src/scripts/setup.ts +122 -122
- package/src/server/auto-updater.ts +283 -276
- package/src/server/handlers/call-tool.ts +159 -159
- package/src/server/handlers/list-tools.ts +35 -35
- package/src/server/handlers/tools/auto-remember.ts +165 -165
- package/src/server/handlers/tools/brain.ts +86 -86
- package/src/server/handlers/tools/create-project.ts +135 -135
- package/src/server/handlers/tools/get-code-standards.ts +123 -123
- package/src/server/handlers/tools/get-corrections.ts +152 -152
- package/src/server/handlers/tools/get-patterns.ts +156 -156
- package/src/server/handlers/tools/get-project-context.ts +75 -75
- package/src/server/handlers/tools/index.ts +30 -30
- package/src/server/handlers/tools/init-project.ts +756 -756
- package/src/server/handlers/tools/list-projects.ts +126 -126
- package/src/server/handlers/tools/recall-similar.ts +87 -87
- package/src/server/handlers/tools/recognize-pattern.ts +132 -132
- package/src/server/handlers/tools/record-correction.ts +131 -131
- package/src/server/handlers/tools/remember-decision.ts +168 -168
- package/src/server/handlers/tools/schemas.ts +179 -179
- package/src/server/handlers/tools/search-code.ts +122 -122
- package/src/server/handlers/tools/smart-context.ts +146 -146
- package/src/server/handlers/tools/update-progress.ts +131 -131
- package/src/server/http-api.ts +215 -1229
- package/src/server/mcp-proxy.ts +85 -84
- package/src/server/mcp-server.ts +285 -284
- package/src/server/middleware/auth.ts +39 -0
- package/src/server/middleware/error-handler.ts +37 -0
- package/src/server/middleware/rate-limit.ts +53 -0
- package/src/server/middleware/validate.ts +42 -0
- package/src/server/pid-manager.ts +137 -136
- package/src/server/providers/resources.ts +581 -581
- package/src/server/routes/code.ts +228 -0
- package/src/server/routes/context.ts +26 -0
- package/src/server/routes/health.ts +19 -0
- package/src/server/routes/helpers.ts +100 -0
- package/src/server/routes/hooks.ts +197 -0
- package/src/server/routes/mcp.ts +47 -0
- package/src/server/routes/memory.ts +397 -0
- package/src/server/routes/models.ts +96 -0
- package/src/server/routes/projects.ts +89 -0
- package/src/server/routes/types.ts +21 -0
- package/src/server/schemas/api-schemas.ts +202 -0
- package/src/server/services.ts +720 -720
- package/src/server/utils/memory-indicator.ts +84 -84
- package/src/server/utils/response-formatter.ts +129 -129
- package/src/server/web-viewer.ts +1145 -1115
- package/src/setup/index.ts +38 -38
- package/src/tools/registry.ts +115 -115
- package/src/tools/schemas.ts +666 -666
- package/src/tools/types.ts +412 -412
- package/src/training/data-store.ts +320 -298
- package/src/training/retrain-pipeline.ts +399 -394
- package/src/utils/error-handler.ts +136 -136
- package/src/utils/index.ts +58 -58
- package/src/utils/kill-port.ts +55 -53
- package/src/utils/phase12-helper.ts +56 -56
- package/src/utils/safe-path.ts +43 -0
- package/src/utils/timing.ts +47 -47
- package/src/utils/transaction.ts +63 -63
- package/src/vault/index.ts +4 -3
- package/src/vault/paths.ts +106 -106
- package/src/vault/query.ts +4 -1
- package/src/vault/reader.ts +44 -1
- package/src/vault/watcher.ts +24 -1
- package/src/vault/writer.ts +487 -413
- package/skills/persistent-memory/SKILL.md +0 -148
- package/skills/persistent-memory/references/tool-reference.md +0 -90
package/src/server/mcp-server.ts
CHANGED
|
@@ -1,284 +1,285 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Brain MCP Server
|
|
3
|
-
* Main MCP server implementation using the Model Context Protocol SDK
|
|
4
|
-
* Phase 6.5: Enhanced with system prompts and resources
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
|
8
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
9
|
-
import {
|
|
10
|
-
CallToolRequestSchema,
|
|
11
|
-
ListToolsRequestSchema,
|
|
12
|
-
ListPromptsRequestSchema,
|
|
13
|
-
GetPromptRequestSchema,
|
|
14
|
-
ListResourcesRequestSchema,
|
|
15
|
-
ReadResourceRequestSchema
|
|
16
|
-
} from '@modelcontextprotocol/sdk/types.js'
|
|
17
|
-
import type { Logger } from 'pino'
|
|
18
|
-
import type { Config } from '@/config'
|
|
19
|
-
import type { ConnectionState, ServerStatus, ServerOptions, ServerEvents } from './types'
|
|
20
|
-
import { PromptProvider } from './providers/prompts'
|
|
21
|
-
import { ResourceProvider } from './providers/resources'
|
|
22
|
-
|
|
23
|
-
export class ClaudeBrainMCPServer {
|
|
24
|
-
private server: Server
|
|
25
|
-
private logger: Logger
|
|
26
|
-
private config: Config
|
|
27
|
-
private isRunning: boolean = false
|
|
28
|
-
private connectionState: ConnectionState = 'disconnected'
|
|
29
|
-
private startedAt?: Date
|
|
30
|
-
private requestCount: number = 0
|
|
31
|
-
private events: ServerEvents
|
|
32
|
-
|
|
33
|
-
// Phase 6.5: Prompt and Resource providers
|
|
34
|
-
private promptProvider: PromptProvider
|
|
35
|
-
private resourceProvider: ResourceProvider
|
|
36
|
-
|
|
37
|
-
constructor(config: Config, logger: Logger, options: ServerOptions = {}) {
|
|
38
|
-
this.config = config
|
|
39
|
-
this.logger = logger.child({ component: 'mcp-server' })
|
|
40
|
-
this.events = options.events || {}
|
|
41
|
-
|
|
42
|
-
// Phase 6.5: Initialize providers
|
|
43
|
-
this.promptProvider = new PromptProvider(logger)
|
|
44
|
-
this.resourceProvider = new ResourceProvider(logger)
|
|
45
|
-
|
|
46
|
-
// Initialize MCP Server with metadata and enhanced capabilities
|
|
47
|
-
this.server = new Server(
|
|
48
|
-
{
|
|
49
|
-
name: config.serverName,
|
|
50
|
-
version: config.serverVersion
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
capabilities: {
|
|
54
|
-
tools: {},
|
|
55
|
-
prompts: {}, // Phase 6.5: Enable prompts
|
|
56
|
-
resources: {} // Phase 6.5: Enable resources
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
// Setup request handlers
|
|
62
|
-
this.setupHandlers()
|
|
63
|
-
|
|
64
|
-
// Setup error handling
|
|
65
|
-
this.setupErrorHandling()
|
|
66
|
-
|
|
67
|
-
this.logger.debug('MCP server instance created with Phase 6.5 enhancements')
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Setup MCP request handlers for tools, prompts, and resources
|
|
72
|
-
*/
|
|
73
|
-
private setupHandlers(): void {
|
|
74
|
-
// Handle tools/list request
|
|
75
|
-
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
76
|
-
this.logger.debug('Handling tools/list request')
|
|
77
|
-
|
|
78
|
-
// Import dynamically to avoid circular dependencies
|
|
79
|
-
const { handleListTools } = await import('./handlers/list-tools')
|
|
80
|
-
return await handleListTools()
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
// Handle tools/call request
|
|
84
|
-
// @ts-expect-error - SDK handler type expects extra param we don't use
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
this.connectionState
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
this.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
this.
|
|
211
|
-
this.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
this.
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
this.
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Claude Brain MCP Server
|
|
3
|
+
* Main MCP server implementation using the Model Context Protocol SDK
|
|
4
|
+
* Phase 6.5: Enhanced with system prompts and resources
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
|
8
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
9
|
+
import {
|
|
10
|
+
CallToolRequestSchema,
|
|
11
|
+
ListToolsRequestSchema,
|
|
12
|
+
ListPromptsRequestSchema,
|
|
13
|
+
GetPromptRequestSchema,
|
|
14
|
+
ListResourcesRequestSchema,
|
|
15
|
+
ReadResourceRequestSchema
|
|
16
|
+
} from '@modelcontextprotocol/sdk/types.js'
|
|
17
|
+
import type { Logger } from 'pino'
|
|
18
|
+
import type { Config } from '@/config'
|
|
19
|
+
import type { ConnectionState, ServerStatus, ServerOptions, ServerEvents } from './types'
|
|
20
|
+
import { PromptProvider } from './providers/prompts'
|
|
21
|
+
import { ResourceProvider } from './providers/resources'
|
|
22
|
+
|
|
23
|
+
export class ClaudeBrainMCPServer {
|
|
24
|
+
private server: Server
|
|
25
|
+
private logger: Logger
|
|
26
|
+
private config: Config
|
|
27
|
+
private isRunning: boolean = false
|
|
28
|
+
private connectionState: ConnectionState = 'disconnected'
|
|
29
|
+
private startedAt?: Date
|
|
30
|
+
private requestCount: number = 0
|
|
31
|
+
private events: ServerEvents
|
|
32
|
+
|
|
33
|
+
// Phase 6.5: Prompt and Resource providers
|
|
34
|
+
private promptProvider: PromptProvider
|
|
35
|
+
private resourceProvider: ResourceProvider
|
|
36
|
+
|
|
37
|
+
constructor(config: Config, logger: Logger, options: ServerOptions = {}) {
|
|
38
|
+
this.config = config
|
|
39
|
+
this.logger = logger.child({ component: 'mcp-server' })
|
|
40
|
+
this.events = options.events || {}
|
|
41
|
+
|
|
42
|
+
// Phase 6.5: Initialize providers
|
|
43
|
+
this.promptProvider = new PromptProvider(logger)
|
|
44
|
+
this.resourceProvider = new ResourceProvider(logger)
|
|
45
|
+
|
|
46
|
+
// Initialize MCP Server with metadata and enhanced capabilities
|
|
47
|
+
this.server = new Server(
|
|
48
|
+
{
|
|
49
|
+
name: config.serverName,
|
|
50
|
+
version: config.serverVersion
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
capabilities: {
|
|
54
|
+
tools: {},
|
|
55
|
+
prompts: {}, // Phase 6.5: Enable prompts
|
|
56
|
+
resources: {} // Phase 6.5: Enable resources
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
// Setup request handlers
|
|
62
|
+
this.setupHandlers()
|
|
63
|
+
|
|
64
|
+
// Setup error handling
|
|
65
|
+
this.setupErrorHandling()
|
|
66
|
+
|
|
67
|
+
this.logger.debug('MCP server instance created with Phase 6.5 enhancements')
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Setup MCP request handlers for tools, prompts, and resources
|
|
72
|
+
*/
|
|
73
|
+
private setupHandlers(): void {
|
|
74
|
+
// Handle tools/list request
|
|
75
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
76
|
+
this.logger.debug('Handling tools/list request')
|
|
77
|
+
|
|
78
|
+
// Import dynamically to avoid circular dependencies
|
|
79
|
+
const { handleListTools } = await import('./handlers/list-tools')
|
|
80
|
+
return await handleListTools()
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
// Handle tools/call request
|
|
84
|
+
// @ts-expect-error - SDK handler type expects extra param we don't use
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- MCP SDK request handler type
|
|
86
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request: any) => {
|
|
87
|
+
const toolName = request.params.name
|
|
88
|
+
const args = request.params.arguments || {}
|
|
89
|
+
|
|
90
|
+
this.requestCount++
|
|
91
|
+
const requestId = `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`
|
|
92
|
+
|
|
93
|
+
this.logger.debug({
|
|
94
|
+
tool: toolName,
|
|
95
|
+
args,
|
|
96
|
+
requestId
|
|
97
|
+
}, 'Handling tools/call request')
|
|
98
|
+
|
|
99
|
+
// Emit request event
|
|
100
|
+
this.events.onRequest?.(toolName, requestId)
|
|
101
|
+
|
|
102
|
+
const startTime = Date.now()
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
// Import dynamically to avoid circular dependencies
|
|
106
|
+
const { handleCallTool } = await import('./handlers/call-tool')
|
|
107
|
+
const result = await handleCallTool(toolName, args, this.logger)
|
|
108
|
+
|
|
109
|
+
const duration = Date.now() - startTime
|
|
110
|
+
this.logger.debug({
|
|
111
|
+
tool: toolName,
|
|
112
|
+
requestId,
|
|
113
|
+
durationMs: duration
|
|
114
|
+
}, 'Tool call completed')
|
|
115
|
+
|
|
116
|
+
// Emit response event
|
|
117
|
+
this.events.onResponse?.(toolName, requestId, duration)
|
|
118
|
+
|
|
119
|
+
return result
|
|
120
|
+
} catch (error) {
|
|
121
|
+
const duration = Date.now() - startTime
|
|
122
|
+
this.logger.error({
|
|
123
|
+
tool: toolName,
|
|
124
|
+
requestId,
|
|
125
|
+
durationMs: duration,
|
|
126
|
+
error: error instanceof Error ? error.message : String(error)
|
|
127
|
+
}, 'Tool call failed')
|
|
128
|
+
|
|
129
|
+
throw error
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
// Phase 6.5: Handle prompts/list request
|
|
134
|
+
this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
135
|
+
this.logger.debug('Handling prompts/list request')
|
|
136
|
+
return await this.promptProvider.listPrompts()
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
// Phase 6.5: Handle prompts/get request
|
|
140
|
+
this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
141
|
+
this.logger.debug({ name: request.params.name }, 'Handling prompts/get request')
|
|
142
|
+
return await this.promptProvider.getPrompt(request.params.name)
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
// Phase 6.5: Handle resources/list request
|
|
146
|
+
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
147
|
+
this.logger.debug('Handling resources/list request')
|
|
148
|
+
return await this.resourceProvider.listResources()
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
// Phase 6.5: Handle resources/read request
|
|
152
|
+
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
153
|
+
this.logger.debug({ uri: request.params.uri }, 'Handling resources/read request')
|
|
154
|
+
return await this.resourceProvider.readResource(request.params.uri)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
this.logger.debug('Request handlers configured (tools, prompts, resources)')
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Setup error handling for the server
|
|
162
|
+
*/
|
|
163
|
+
private setupErrorHandling(): void {
|
|
164
|
+
this.server.onerror = (error) => {
|
|
165
|
+
this.logger.error({
|
|
166
|
+
error: error instanceof Error ? {
|
|
167
|
+
message: error.message,
|
|
168
|
+
stack: error.stack,
|
|
169
|
+
name: error.name
|
|
170
|
+
} : error
|
|
171
|
+
}, 'MCP server error')
|
|
172
|
+
|
|
173
|
+
this.events.onError?.(error instanceof Error ? error : new Error(String(error)))
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Update connection state and emit events
|
|
179
|
+
*/
|
|
180
|
+
private setConnectionState(state: ConnectionState): void {
|
|
181
|
+
const previousState = this.connectionState
|
|
182
|
+
this.connectionState = state
|
|
183
|
+
|
|
184
|
+
if (previousState !== state) {
|
|
185
|
+
this.logger.info({
|
|
186
|
+
previousState,
|
|
187
|
+
newState: state
|
|
188
|
+
}, 'Connection state changed')
|
|
189
|
+
|
|
190
|
+
this.events.onConnectionStateChange?.(state)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Start the MCP server and connect via stdio transport
|
|
196
|
+
*/
|
|
197
|
+
async start(): Promise<void> {
|
|
198
|
+
if (this.isRunning) {
|
|
199
|
+
this.logger.warn('Server already running')
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
this.logger.info('Starting MCP server...')
|
|
205
|
+
this.setConnectionState('connecting')
|
|
206
|
+
|
|
207
|
+
const transport = new StdioServerTransport()
|
|
208
|
+
await this.server.connect(transport)
|
|
209
|
+
|
|
210
|
+
this.isRunning = true
|
|
211
|
+
this.startedAt = new Date()
|
|
212
|
+
this.setConnectionState('connected')
|
|
213
|
+
|
|
214
|
+
this.logger.info({
|
|
215
|
+
name: this.config.serverName,
|
|
216
|
+
version: this.config.serverVersion,
|
|
217
|
+
startedAt: this.startedAt.toISOString()
|
|
218
|
+
}, 'MCP server started successfully')
|
|
219
|
+
|
|
220
|
+
} catch (error) {
|
|
221
|
+
this.setConnectionState('disconnected')
|
|
222
|
+
this.logger.error({
|
|
223
|
+
error: error instanceof Error ? {
|
|
224
|
+
message: error.message,
|
|
225
|
+
stack: error.stack
|
|
226
|
+
} : error
|
|
227
|
+
}, 'Failed to start MCP server')
|
|
228
|
+
throw error
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Stop the MCP server gracefully
|
|
234
|
+
*/
|
|
235
|
+
async stop(): Promise<void> {
|
|
236
|
+
if (!this.isRunning) {
|
|
237
|
+
this.logger.debug('Server not running, skip stop')
|
|
238
|
+
return
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
this.logger.info('Stopping MCP server...')
|
|
243
|
+
await this.server.close()
|
|
244
|
+
|
|
245
|
+
this.isRunning = false
|
|
246
|
+
this.setConnectionState('disconnected')
|
|
247
|
+
|
|
248
|
+
this.logger.info({
|
|
249
|
+
totalRequests: this.requestCount,
|
|
250
|
+
uptimeMs: this.startedAt ? Date.now() - this.startedAt.getTime() : 0
|
|
251
|
+
}, 'MCP server stopped')
|
|
252
|
+
|
|
253
|
+
} catch (error) {
|
|
254
|
+
this.logger.error({
|
|
255
|
+
error: error instanceof Error ? {
|
|
256
|
+
message: error.message,
|
|
257
|
+
stack: error.stack
|
|
258
|
+
} : error
|
|
259
|
+
}, 'Error stopping MCP server')
|
|
260
|
+
throw error
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get current server status
|
|
266
|
+
*/
|
|
267
|
+
getStatus(): ServerStatus {
|
|
268
|
+
return {
|
|
269
|
+
running: this.isRunning,
|
|
270
|
+
name: this.config.serverName,
|
|
271
|
+
version: this.config.serverVersion,
|
|
272
|
+
connectionState: this.connectionState,
|
|
273
|
+
startedAt: this.startedAt,
|
|
274
|
+
requestCount: this.requestCount,
|
|
275
|
+
capabilities: ['tools', 'prompts', 'resources']
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Health check method
|
|
281
|
+
*/
|
|
282
|
+
isHealthy(): boolean {
|
|
283
|
+
return this.isRunning && this.connectionState === 'connected'
|
|
284
|
+
}
|
|
285
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Key Authentication Middleware
|
|
3
|
+
* Phase 1: Security Hardening
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Context, Next } from 'hono'
|
|
7
|
+
import { timingSafeEqual } from 'crypto'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Verify API key from X-API-Key header or Authorization: Bearer <key>
|
|
11
|
+
* Returns 401 if no key, 403 if invalid key.
|
|
12
|
+
*/
|
|
13
|
+
export function apiKeyAuth(apiKey: string | undefined) {
|
|
14
|
+
return async (c: Context, next: Next) => {
|
|
15
|
+
// If no API key configured, skip auth (local-only mode)
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
await next()
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Extract key from header
|
|
22
|
+
const headerKey = c.req.header('X-API-Key')
|
|
23
|
+
|| c.req.header('Authorization')?.replace('Bearer ', '')
|
|
24
|
+
|
|
25
|
+
if (!headerKey) {
|
|
26
|
+
return c.json({ error: 'Authentication required. Provide X-API-Key header.' }, 401)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Timing-safe comparison to prevent timing attacks
|
|
30
|
+
const expected = Buffer.from(apiKey)
|
|
31
|
+
const received = Buffer.from(headerKey)
|
|
32
|
+
|
|
33
|
+
if (expected.length !== received.length || !timingSafeEqual(expected, received)) {
|
|
34
|
+
return c.json({ error: 'Invalid API key' }, 403)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
await next()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Handler Middleware
|
|
3
|
+
* Phase 1: Security Hardening
|
|
4
|
+
*
|
|
5
|
+
* Catches unhandled errors and returns sanitized responses.
|
|
6
|
+
* Full error details are logged internally, only safe messages are returned to clients.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Context, Next } from 'hono'
|
|
10
|
+
import type { Logger } from 'pino'
|
|
11
|
+
|
|
12
|
+
export function errorHandler(logger: Logger) {
|
|
13
|
+
return async (c: Context, next: Next) => {
|
|
14
|
+
try {
|
|
15
|
+
await next()
|
|
16
|
+
} catch (error) {
|
|
17
|
+
const requestId = crypto.randomUUID().slice(0, 8)
|
|
18
|
+
|
|
19
|
+
// Log full error internally
|
|
20
|
+
logger.error({
|
|
21
|
+
error,
|
|
22
|
+
requestId,
|
|
23
|
+
method: c.req.method,
|
|
24
|
+
path: c.req.path,
|
|
25
|
+
}, 'Unhandled API error')
|
|
26
|
+
|
|
27
|
+
// Return sanitized error to client
|
|
28
|
+
const status = (error && typeof error === 'object' && 'status' in error && typeof (error as Record<string, unknown>).status === 'number')
|
|
29
|
+
? (error as Record<string, unknown>).status as number
|
|
30
|
+
: 500
|
|
31
|
+
return c.json({
|
|
32
|
+
error: status >= 500 ? 'Internal server error' : (error as Error).message,
|
|
33
|
+
requestId,
|
|
34
|
+
}, status)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|