midnight-mcp 0.1.40 → 0.2.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.
Files changed (100) hide show
  1. package/README.md +34 -0
  2. package/dist/bin.d.ts +1 -0
  3. package/dist/bin.js +10764 -0
  4. package/dist/index.d.ts +205 -3
  5. package/dist/index.js +10722 -15
  6. package/package.json +16 -6
  7. package/dist/config/compact-version.d.ts +0 -183
  8. package/dist/config/compact-version.js +0 -423
  9. package/dist/db/index.d.ts +0 -3
  10. package/dist/db/index.js +0 -2
  11. package/dist/db/vectorStore.d.ts +0 -69
  12. package/dist/db/vectorStore.js +0 -196
  13. package/dist/pipeline/embeddings.d.ts +0 -25
  14. package/dist/pipeline/embeddings.js +0 -103
  15. package/dist/pipeline/github.d.ts +0 -84
  16. package/dist/pipeline/github.js +0 -399
  17. package/dist/pipeline/index.d.ts +0 -11
  18. package/dist/pipeline/index.js +0 -6
  19. package/dist/pipeline/indexer.d.ts +0 -41
  20. package/dist/pipeline/indexer.js +0 -254
  21. package/dist/pipeline/parser.d.ts +0 -46
  22. package/dist/pipeline/parser.js +0 -436
  23. package/dist/pipeline/releases.d.ts +0 -112
  24. package/dist/pipeline/releases.js +0 -298
  25. package/dist/pipeline/repository.d.ts +0 -372
  26. package/dist/pipeline/repository.js +0 -520
  27. package/dist/prompts/index.d.ts +0 -3
  28. package/dist/prompts/index.js +0 -2
  29. package/dist/prompts/templates.d.ts +0 -26
  30. package/dist/prompts/templates.js +0 -443
  31. package/dist/resources/code.d.ts +0 -15
  32. package/dist/resources/code.js +0 -122
  33. package/dist/resources/content/code-content.d.ts +0 -6
  34. package/dist/resources/content/code-content.js +0 -802
  35. package/dist/resources/content/docs-content.d.ts +0 -14
  36. package/dist/resources/content/docs-content.js +0 -1202
  37. package/dist/resources/content/index.d.ts +0 -6
  38. package/dist/resources/content/index.js +0 -6
  39. package/dist/resources/docs.d.ts +0 -15
  40. package/dist/resources/docs.js +0 -98
  41. package/dist/resources/index.d.ts +0 -6
  42. package/dist/resources/index.js +0 -13
  43. package/dist/resources/schemas.d.ts +0 -16
  44. package/dist/resources/schemas.js +0 -407
  45. package/dist/scripts/index-repos.d.ts +0 -12
  46. package/dist/scripts/index-repos.js +0 -53
  47. package/dist/server.d.ts +0 -43
  48. package/dist/server.js +0 -693
  49. package/dist/services/index.d.ts +0 -6
  50. package/dist/services/index.js +0 -6
  51. package/dist/services/sampling.d.ts +0 -62
  52. package/dist/services/sampling.js +0 -277
  53. package/dist/tools/analyze.d.ts +0 -106
  54. package/dist/tools/analyze.js +0 -431
  55. package/dist/tools/generation.d.ts +0 -9
  56. package/dist/tools/generation.js +0 -285
  57. package/dist/tools/health.d.ts +0 -120
  58. package/dist/tools/health.js +0 -362
  59. package/dist/tools/index.d.ts +0 -14
  60. package/dist/tools/index.js +0 -22
  61. package/dist/tools/meta.d.ts +0 -61
  62. package/dist/tools/meta.js +0 -282
  63. package/dist/tools/repository/constants.d.ts +0 -19
  64. package/dist/tools/repository/constants.js +0 -324
  65. package/dist/tools/repository/handlers.d.ts +0 -373
  66. package/dist/tools/repository/handlers.js +0 -724
  67. package/dist/tools/repository/index.d.ts +0 -9
  68. package/dist/tools/repository/index.js +0 -13
  69. package/dist/tools/repository/schemas.d.ts +0 -153
  70. package/dist/tools/repository/schemas.js +0 -106
  71. package/dist/tools/repository/tools.d.ts +0 -7
  72. package/dist/tools/repository/tools.js +0 -484
  73. package/dist/tools/repository/validation.d.ts +0 -106
  74. package/dist/tools/repository/validation.js +0 -820
  75. package/dist/tools/repository.d.ts +0 -6
  76. package/dist/tools/repository.js +0 -7
  77. package/dist/tools/search.d.ts +0 -76
  78. package/dist/tools/search.js +0 -423
  79. package/dist/types/index.d.ts +0 -2
  80. package/dist/types/index.js +0 -2
  81. package/dist/types/mcp.d.ts +0 -187
  82. package/dist/types/mcp.js +0 -6
  83. package/dist/utils/cache.d.ts +0 -77
  84. package/dist/utils/cache.js +0 -172
  85. package/dist/utils/config.d.ts +0 -70
  86. package/dist/utils/config.js +0 -294
  87. package/dist/utils/errors.d.ts +0 -111
  88. package/dist/utils/errors.js +0 -165
  89. package/dist/utils/health.d.ts +0 -29
  90. package/dist/utils/health.js +0 -132
  91. package/dist/utils/hosted-api.d.ts +0 -67
  92. package/dist/utils/hosted-api.js +0 -119
  93. package/dist/utils/index.d.ts +0 -16
  94. package/dist/utils/index.js +0 -15
  95. package/dist/utils/logger.d.ts +0 -48
  96. package/dist/utils/logger.js +0 -124
  97. package/dist/utils/rate-limit.d.ts +0 -61
  98. package/dist/utils/rate-limit.js +0 -148
  99. package/dist/utils/validation.d.ts +0 -52
  100. package/dist/utils/validation.js +0 -255
package/dist/server.js DELETED
@@ -1,693 +0,0 @@
1
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
- import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourceTemplatesRequestSchema, SubscribeRequestSchema, UnsubscribeRequestSchema, SetLevelRequestSchema, CompleteRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
- import { logger, formatErrorResponse, setMCPLogCallback, trackToolCall, } from "./utils/index.js";
5
- import { vectorStore } from "./db/index.js";
6
- import { allTools } from "./tools/index.js";
7
- import { allResources, getDocumentation, getCode, getSchema, } from "./resources/index.js";
8
- import { promptDefinitions, generatePrompt } from "./prompts/index.js";
9
- import { registerSamplingCallback } from "./services/index.js";
10
- // Server information - version should match package.json
11
- const CURRENT_VERSION = "0.1.33";
12
- const SERVER_INFO = {
13
- name: "midnight-mcp",
14
- version: CURRENT_VERSION,
15
- description: "MCP Server for Midnight Blockchain Development",
16
- };
17
- // Version check state
18
- let versionCheckResult = {
19
- isOutdated: false,
20
- latestVersion: CURRENT_VERSION,
21
- updateMessage: null,
22
- };
23
- /**
24
- * Check for updates against npm registry (runs at startup)
25
- */
26
- async function checkForUpdates() {
27
- try {
28
- const controller = new AbortController();
29
- const timeoutId = setTimeout(() => controller.abort(), 5000); // 5s timeout
30
- const response = await fetch("https://registry.npmjs.org/midnight-mcp/latest", { signal: controller.signal });
31
- clearTimeout(timeoutId);
32
- if (!response.ok)
33
- return;
34
- const data = (await response.json());
35
- const latestVersion = data.version;
36
- if (latestVersion !== CURRENT_VERSION) {
37
- versionCheckResult = {
38
- isOutdated: true,
39
- latestVersion,
40
- updateMessage: `⚠️ UPDATE AVAILABLE: v${latestVersion} (you have v${CURRENT_VERSION}). ` +
41
- `Run: rm -rf ~/.npm/_npx && restart Claude Desktop. ` +
42
- `Or update config to use: "midnight-mcp@latest"`,
43
- };
44
- logger.warn(`Outdated version detected: v${CURRENT_VERSION} -> v${latestVersion}`);
45
- }
46
- }
47
- catch {
48
- // Silently ignore version check failures (offline, timeout, etc.)
49
- }
50
- }
51
- /**
52
- * Get update warning if outdated (to include in responses)
53
- */
54
- export function getUpdateWarning() {
55
- return versionCheckResult.updateMessage;
56
- }
57
- // Resource subscriptions tracking
58
- const resourceSubscriptions = new Set();
59
- /**
60
- * Clear all subscriptions (useful for server restart/testing)
61
- */
62
- export function clearSubscriptions() {
63
- resourceSubscriptions.clear();
64
- logger.debug("Subscriptions cleared");
65
- }
66
- // Resource templates for parameterized resources (RFC 6570 URI Templates)
67
- const resourceTemplates = [
68
- {
69
- uriTemplate: "midnight://code/{owner}/{repo}/{path}",
70
- name: "Repository Code",
71
- title: "📄 Repository Code Files",
72
- description: "Access code files from any Midnight repository by specifying owner, repo, and file path",
73
- mimeType: "text/plain",
74
- },
75
- {
76
- uriTemplate: "midnight://docs/{section}/{topic}",
77
- name: "Documentation",
78
- title: "📚 Documentation Sections",
79
- description: "Access documentation by section (guides, api, concepts) and topic",
80
- mimeType: "text/markdown",
81
- },
82
- {
83
- uriTemplate: "midnight://examples/{category}/{name}",
84
- name: "Example Contracts",
85
- title: "📝 Example Contracts",
86
- description: "Access example contracts by category (counter, bboard, token, voting) and name",
87
- mimeType: "text/x-compact",
88
- },
89
- {
90
- uriTemplate: "midnight://schema/{type}",
91
- name: "Schema Definitions",
92
- title: "🔧 Schema Definitions",
93
- description: "Access JSON schemas for contract AST, transactions, and proofs",
94
- mimeType: "application/json",
95
- },
96
- ];
97
- /**
98
- * Create and configure the MCP server
99
- */
100
- // Current MCP logging level (controlled by client)
101
- let mcpLogLevel = "info";
102
- // Server instance for sending notifications
103
- let serverInstance = null;
104
- // Track if server is connected (can send notifications)
105
- let isConnected = false;
106
- /**
107
- * Mark server as connected (safe to send notifications)
108
- */
109
- export function setServerConnected(connected) {
110
- isConnected = connected;
111
- }
112
- /**
113
- * Send a log message to the MCP client
114
- * This allows clients to see server logs for debugging
115
- */
116
- export function sendLogToClient(level, loggerName, data) {
117
- // Only send if server exists AND is connected
118
- if (!serverInstance || !isConnected)
119
- return;
120
- // Map levels to numeric values for comparison
121
- const levelValues = {
122
- debug: 0,
123
- info: 1,
124
- notice: 2,
125
- warning: 3,
126
- error: 4,
127
- critical: 5,
128
- alert: 6,
129
- emergency: 7,
130
- };
131
- // Only send if level meets threshold
132
- if (levelValues[level] < levelValues[mcpLogLevel])
133
- return;
134
- try {
135
- serverInstance.notification({
136
- method: "notifications/message",
137
- params: {
138
- level,
139
- logger: loggerName,
140
- data,
141
- },
142
- });
143
- }
144
- catch {
145
- // Ignore notification errors
146
- }
147
- }
148
- /**
149
- * Send a progress notification to the MCP client
150
- * Used for long-running operations like compound tools
151
- */
152
- export function sendProgressNotification(progressToken, progress, total, message) {
153
- if (!serverInstance)
154
- return;
155
- try {
156
- serverInstance.notification({
157
- method: "notifications/progress",
158
- params: {
159
- progressToken,
160
- progress,
161
- ...(total !== undefined && { total }),
162
- ...(message && { message }),
163
- },
164
- });
165
- }
166
- catch {
167
- // Ignore notification errors
168
- }
169
- }
170
- export function createServer() {
171
- const server = new Server(SERVER_INFO, {
172
- capabilities: {
173
- tools: {
174
- listChanged: true,
175
- },
176
- resources: {
177
- subscribe: true,
178
- listChanged: true,
179
- },
180
- prompts: {
181
- listChanged: true,
182
- },
183
- logging: {},
184
- completions: {},
185
- },
186
- });
187
- // Store server instance for logging notifications
188
- serverInstance = server;
189
- // Wire up MCP logging - send logger output to client
190
- setMCPLogCallback((level, loggerName, data) => {
191
- sendLogToClient(level, loggerName, data);
192
- });
193
- // Register tool handlers
194
- registerToolHandlers(server);
195
- // Register resource handlers
196
- registerResourceHandlers(server);
197
- // Register prompt handlers
198
- registerPromptHandlers(server);
199
- // Register subscription handlers
200
- registerSubscriptionHandlers(server);
201
- // Register logging handler
202
- registerLoggingHandler(server);
203
- // Register completions handler
204
- registerCompletionsHandler(server);
205
- // Setup sampling callback if available
206
- setupSampling(server);
207
- return server;
208
- }
209
- /**
210
- * Register logging handler for MCP logging capability
211
- */
212
- function registerLoggingHandler(server) {
213
- server.setRequestHandler(SetLevelRequestSchema, async (request) => {
214
- const { level } = request.params;
215
- mcpLogLevel = level;
216
- logger.info(`MCP log level set to: ${level}`);
217
- sendLogToClient("info", "midnight-mcp", {
218
- message: `Log level changed to ${level}`,
219
- });
220
- return {};
221
- });
222
- }
223
- // Completion suggestions for prompt arguments
224
- const COMPLETION_VALUES = {
225
- "midnight:create-contract": {
226
- contractType: [
227
- "token",
228
- "voting",
229
- "credential",
230
- "auction",
231
- "escrow",
232
- "custom",
233
- ],
234
- privacyLevel: ["full", "partial", "public"],
235
- complexity: ["beginner", "intermediate", "advanced"],
236
- },
237
- "midnight:review-contract": {
238
- focusAreas: [
239
- "security",
240
- "performance",
241
- "privacy",
242
- "readability",
243
- "gas-optimization",
244
- ],
245
- },
246
- "midnight:explain-concept": {
247
- concept: [
248
- "zk-proofs",
249
- "circuits",
250
- "witnesses",
251
- "ledger",
252
- "state-management",
253
- "privacy-model",
254
- "token-transfers",
255
- "merkle-trees",
256
- ],
257
- level: ["beginner", "intermediate", "advanced"],
258
- },
259
- "midnight:compare-approaches": {
260
- approaches: [
261
- "token-standards",
262
- "state-management",
263
- "privacy-patterns",
264
- "circuit-design",
265
- ],
266
- },
267
- "midnight:debug-contract": {
268
- errorType: [
269
- "compilation",
270
- "runtime",
271
- "logic",
272
- "privacy-leak",
273
- "state-corruption",
274
- ],
275
- },
276
- };
277
- /**
278
- * Register completions handler for argument autocompletion
279
- */
280
- function registerCompletionsHandler(server) {
281
- server.setRequestHandler(CompleteRequestSchema, async (request) => {
282
- const { ref, argument } = request.params;
283
- if (ref.type !== "ref/prompt") {
284
- return { completion: { values: [], hasMore: false } };
285
- }
286
- const promptName = ref.name;
287
- const argName = argument.name;
288
- const currentValue = argument.value?.toLowerCase() || "";
289
- // Get completion values for this prompt/argument
290
- const promptCompletions = COMPLETION_VALUES[promptName];
291
- if (!promptCompletions) {
292
- return { completion: { values: [], hasMore: false } };
293
- }
294
- const argValues = promptCompletions[argName];
295
- if (!argValues) {
296
- return { completion: { values: [], hasMore: false } };
297
- }
298
- // Filter by current input
299
- const filtered = argValues.filter((v) => v.toLowerCase().includes(currentValue));
300
- return {
301
- completion: {
302
- values: filtered.slice(0, 20),
303
- total: filtered.length,
304
- hasMore: filtered.length > 20,
305
- },
306
- };
307
- });
308
- }
309
- /**
310
- * Register tool handlers
311
- */
312
- function registerToolHandlers(server) {
313
- // List available tools with annotations and output schemas
314
- server.setRequestHandler(ListToolsRequestSchema, async () => {
315
- logger.debug("Listing tools");
316
- return {
317
- tools: allTools.map((tool) => ({
318
- name: tool.name,
319
- description: tool.description,
320
- inputSchema: tool.inputSchema,
321
- // Include output schema if defined
322
- ...(tool.outputSchema && { outputSchema: tool.outputSchema }),
323
- // Include annotations if defined
324
- ...(tool.annotations && { annotations: tool.annotations }),
325
- })),
326
- };
327
- });
328
- // Handle tool calls
329
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
330
- const { name, arguments: args } = request.params;
331
- logger.info(`Tool called: ${name}`, { args });
332
- const startTime = Date.now();
333
- const tool = allTools.find((t) => t.name === name);
334
- if (!tool) {
335
- const availableTools = allTools
336
- .map((t) => t.name)
337
- .slice(0, 5)
338
- .join(", ");
339
- // Track failed tool call (unknown tool)
340
- trackToolCall(name, false, Date.now() - startTime, CURRENT_VERSION);
341
- return {
342
- content: [
343
- {
344
- type: "text",
345
- text: JSON.stringify({
346
- error: `Unknown tool: ${name}`,
347
- suggestion: `Available tools include: ${availableTools}...`,
348
- hint: "Use ListTools to see all available tools",
349
- }, null, 2),
350
- },
351
- ],
352
- isError: true,
353
- };
354
- }
355
- try {
356
- const result = await tool.handler(args);
357
- const durationMs = Date.now() - startTime;
358
- // Track successful tool call (fire-and-forget, won't block response)
359
- trackToolCall(name, true, durationMs, CURRENT_VERSION);
360
- // Include prominent update prompt in ALL responses when outdated
361
- const updateWarning = getUpdateWarning();
362
- if (updateWarning && versionCheckResult.isOutdated) {
363
- // Prepend update notice with MANUAL instructions (auto-update not possible in sandbox)
364
- const updatePrompt = {
365
- "🚨 UPDATE AVAILABLE": {
366
- message: `You are using v${CURRENT_VERSION} but v${versionCheckResult.latestVersion} is available.`,
367
- userAction: {
368
- instruction: "Tell the user to update manually. Auto-update is NOT possible because you run in a sandboxed environment without access to local files.",
369
- steps: [
370
- "1. Edit config file to use 'midnight-mcp@latest' instead of 'midnight-mcp'",
371
- "2. Run: rm -rf ~/.npm/_npx (to clear npm cache)",
372
- "3. Restart the editor completely (Cmd+Q on Mac, then reopen)",
373
- ],
374
- configLocations: {
375
- claudeDesktop: "~/Library/Application Support/Claude/claude_desktop_config.json",
376
- cursor: ".cursor/mcp.json",
377
- vscode: ".vscode/mcp.json",
378
- windsurf: "~/.codeium/windsurf/mcp_config.json",
379
- },
380
- },
381
- note: "If user already has @latest in config, they just need to clear cache (rm -rf ~/.npm/_npx) and restart.",
382
- },
383
- result,
384
- };
385
- return {
386
- content: [
387
- {
388
- type: "text",
389
- text: JSON.stringify(updatePrompt, null, 2),
390
- },
391
- ],
392
- };
393
- }
394
- return {
395
- content: [
396
- {
397
- type: "text",
398
- text: JSON.stringify(result, null, 2),
399
- },
400
- ],
401
- // Include structured content for machine-readable responses
402
- // This allows clients to parse results without JSON.parse()
403
- structuredContent: result,
404
- };
405
- }
406
- catch (error) {
407
- const durationMs = Date.now() - startTime;
408
- logger.error(`Tool error: ${name}`, { error: String(error) });
409
- // Track failed tool call
410
- trackToolCall(name, false, durationMs, CURRENT_VERSION);
411
- const errorResponse = formatErrorResponse(error, `tool:${name}`);
412
- return {
413
- content: [
414
- {
415
- type: "text",
416
- text: JSON.stringify(errorResponse, null, 2),
417
- },
418
- ],
419
- isError: true,
420
- };
421
- }
422
- });
423
- }
424
- /**
425
- * Register resource handlers
426
- */
427
- function registerResourceHandlers(server) {
428
- // List available resources
429
- server.setRequestHandler(ListResourcesRequestSchema, async () => {
430
- logger.debug("Listing resources");
431
- return {
432
- resources: allResources.map((resource) => ({
433
- uri: resource.uri,
434
- name: resource.name,
435
- description: resource.description,
436
- mimeType: resource.mimeType,
437
- })),
438
- };
439
- });
440
- // List resource templates (RFC 6570 URI Templates)
441
- server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
442
- logger.debug("Listing resource templates");
443
- return {
444
- resourceTemplates: resourceTemplates.map((template) => ({
445
- uriTemplate: template.uriTemplate,
446
- name: template.name,
447
- title: template.title,
448
- description: template.description,
449
- mimeType: template.mimeType,
450
- })),
451
- };
452
- });
453
- // Read resource content
454
- server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
455
- const { uri } = request.params;
456
- logger.info(`Resource requested: ${uri}`);
457
- try {
458
- let content = null;
459
- let mimeType = "text/plain";
460
- if (uri.startsWith("midnight://docs/")) {
461
- content = await getDocumentation(uri);
462
- mimeType = "text/markdown";
463
- }
464
- else if (uri.startsWith("midnight://code/")) {
465
- content = await getCode(uri);
466
- mimeType = "text/x-compact";
467
- }
468
- else if (uri.startsWith("midnight://schema/")) {
469
- const schema = getSchema(uri);
470
- content = schema ? JSON.stringify(schema, null, 2) : null;
471
- mimeType = "application/json";
472
- }
473
- if (!content) {
474
- const resourceTypes = [
475
- "midnight://docs/",
476
- "midnight://code/",
477
- "midnight://schema/",
478
- ];
479
- const validPrefix = resourceTypes.find((p) => uri.startsWith(p));
480
- return {
481
- contents: [
482
- {
483
- uri,
484
- mimeType: "application/json",
485
- text: JSON.stringify({
486
- error: `Resource not found: ${uri}`,
487
- suggestion: validPrefix
488
- ? `Check the resource path after '${validPrefix}'`
489
- : `Valid resource prefixes: ${resourceTypes.join(", ")}`,
490
- hint: "Use ListResources to see all available resources",
491
- }, null, 2),
492
- },
493
- ],
494
- };
495
- }
496
- return {
497
- contents: [
498
- {
499
- uri,
500
- mimeType,
501
- text: content,
502
- },
503
- ],
504
- };
505
- }
506
- catch (error) {
507
- logger.error(`Resource error: ${uri}`, { error: String(error) });
508
- const errorResponse = formatErrorResponse(error, `resource:${uri}`);
509
- return {
510
- contents: [
511
- {
512
- uri,
513
- mimeType: "application/json",
514
- text: JSON.stringify(errorResponse, null, 2),
515
- },
516
- ],
517
- };
518
- }
519
- });
520
- }
521
- /**
522
- * Register prompt handlers
523
- */
524
- function registerPromptHandlers(server) {
525
- // List available prompts
526
- server.setRequestHandler(ListPromptsRequestSchema, async () => {
527
- logger.debug("Listing prompts");
528
- return {
529
- prompts: promptDefinitions.map((prompt) => ({
530
- name: prompt.name,
531
- description: prompt.description,
532
- arguments: prompt.arguments,
533
- })),
534
- };
535
- });
536
- // Get prompt content
537
- server.setRequestHandler(GetPromptRequestSchema, async (request) => {
538
- const { name, arguments: args } = request.params;
539
- logger.info(`Prompt requested: ${name}`, { args });
540
- const prompt = promptDefinitions.find((p) => p.name === name);
541
- if (!prompt) {
542
- return {
543
- description: `Unknown prompt: ${name}`,
544
- messages: [],
545
- };
546
- }
547
- const messages = generatePrompt(name, args || {});
548
- return {
549
- description: prompt.description,
550
- messages: messages.map((m) => ({
551
- role: m.role,
552
- content: m.content,
553
- })),
554
- };
555
- });
556
- }
557
- /**
558
- * Register resource subscription handlers
559
- */
560
- function registerSubscriptionHandlers(server) {
561
- // Handle subscribe requests
562
- server.setRequestHandler(SubscribeRequestSchema, async (request) => {
563
- const { uri } = request.params;
564
- logger.info(`Subscribing to resource: ${uri}`);
565
- // Validate that the URI is a valid resource
566
- const validPrefixes = [
567
- "midnight://docs/",
568
- "midnight://code/",
569
- "midnight://schema/",
570
- ];
571
- const isValid = validPrefixes.some((prefix) => uri.startsWith(prefix));
572
- if (!isValid) {
573
- logger.warn(`Invalid subscription URI: ${uri}`);
574
- throw new Error(`Invalid subscription URI: ${uri}. Valid prefixes: ${validPrefixes.join(", ")}`);
575
- }
576
- resourceSubscriptions.add(uri);
577
- logger.debug(`Active subscriptions: ${resourceSubscriptions.size}`);
578
- return {};
579
- });
580
- // Handle unsubscribe requests
581
- server.setRequestHandler(UnsubscribeRequestSchema, async (request) => {
582
- const { uri } = request.params;
583
- logger.info(`Unsubscribing from resource: ${uri}`);
584
- resourceSubscriptions.delete(uri);
585
- logger.debug(`Active subscriptions: ${resourceSubscriptions.size}`);
586
- return {};
587
- });
588
- }
589
- /**
590
- * Notify subscribers when a resource changes
591
- * Call this when re-indexing or when docs are updated
592
- */
593
- export function notifyResourceUpdate(server, uri) {
594
- if (resourceSubscriptions.has(uri)) {
595
- logger.info(`Notifying subscribers of update: ${uri}`);
596
- // Send notification via the server
597
- server.notification({
598
- method: "notifications/resources/updated",
599
- params: { uri },
600
- });
601
- }
602
- }
603
- /**
604
- * Get the list of active subscriptions
605
- */
606
- export function getActiveSubscriptions() {
607
- return Array.from(resourceSubscriptions);
608
- }
609
- /**
610
- * Setup sampling capability
611
- * Registers a callback that allows the server to request LLM completions
612
- */
613
- function setupSampling(server) {
614
- // Create a sampling callback that uses the server's request method
615
- const samplingCallback = async (request) => {
616
- logger.debug("Requesting sampling from client", {
617
- messageCount: request.messages.length,
618
- maxTokens: request.maxTokens,
619
- });
620
- try {
621
- // Request completion from the client
622
- const response = await server.request({
623
- method: "sampling/createMessage",
624
- params: {
625
- messages: request.messages,
626
- systemPrompt: request.systemPrompt,
627
- maxTokens: request.maxTokens || 2048,
628
- temperature: request.temperature,
629
- modelPreferences: request.modelPreferences,
630
- },
631
- },
632
- // Use a schema that matches the expected response
633
- {
634
- parse: (data) => {
635
- const response = data;
636
- // Basic validation of expected response structure
637
- if (!response || typeof response !== "object") {
638
- throw new Error("Invalid sampling response: expected object");
639
- }
640
- if (!response.content || typeof response.content !== "object") {
641
- throw new Error("Invalid sampling response: missing content");
642
- }
643
- return response;
644
- },
645
- _def: { typeName: "SamplingResponse" },
646
- });
647
- return response;
648
- }
649
- catch (error) {
650
- logger.error("Sampling request failed", { error: String(error) });
651
- throw error;
652
- }
653
- };
654
- // Register the callback
655
- registerSamplingCallback(samplingCallback);
656
- logger.info("Sampling capability configured");
657
- }
658
- /**
659
- * Initialize the server and vector store
660
- */
661
- export async function initializeServer() {
662
- logger.info("Initializing Midnight MCP Server...");
663
- // Check for updates in background (non-blocking)
664
- checkForUpdates().catch(() => {
665
- // Ignore errors - version check is best-effort
666
- });
667
- // Initialize vector store
668
- try {
669
- await vectorStore.initialize();
670
- logger.info("Vector store initialized");
671
- }
672
- catch (error) {
673
- logger.warn("Vector store initialization failed, continuing without it", {
674
- error: String(error),
675
- });
676
- }
677
- // Create and return server
678
- const server = createServer();
679
- logger.info(`Server v${CURRENT_VERSION} created successfully`);
680
- return server;
681
- }
682
- /**
683
- * Start the server with stdio transport
684
- */
685
- export async function startServer() {
686
- const server = await initializeServer();
687
- const transport = new StdioServerTransport();
688
- await server.connect(transport);
689
- // Now safe to send notifications
690
- setServerConnected(true);
691
- logger.info("Midnight MCP Server running on stdio");
692
- }
693
- //# sourceMappingURL=server.js.map
@@ -1,6 +0,0 @@
1
- /**
2
- * Services index
3
- * Export all service modules
4
- */
5
- export { isSamplingAvailable, registerSamplingCallback, requestCompletion, generateContract, reviewContract, generateDocumentation, } from "./sampling.js";
6
- //# sourceMappingURL=index.d.ts.map