midnight-mcp 0.0.2 → 0.0.5

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 CHANGED
@@ -17,29 +17,21 @@ Add to your `claude_desktop_config.json`:
17
17
  }
18
18
  ```
19
19
 
20
- Restart Claude Desktop. You can now use analysis tools, prompts, and access resources.
21
-
22
- > **Note:** Search features won't work well without the full setup below.
20
+ Restart Claude Desktop. All features work out of the box—no API keys or setup required.
23
21
 
24
22
  ---
25
23
 
26
- ## Full Setup (for search)
27
-
28
- To enable semantic search across Midnight contracts and docs:
29
-
30
- ### 1. Start ChromaDB
31
-
32
- ChromaDB is a local vector database—no account needed, just Docker:
24
+ ## How It Works
33
25
 
34
- ```bash
35
- docker run -d -p 8000:8000 chromadb/chroma
36
- ```
26
+ By default, the MCP uses a **hosted API** for semantic search:
37
27
 
38
- ### 2. Get an OpenAI API key
28
+ - **Zero configuration** just install and use
29
+ - ✅ **Semantic search** works immediately
30
+ - ✅ **No API keys** needed
39
31
 
40
- Needed for generating embeddings. Get one at [platform.openai.com/api-keys](https://platform.openai.com/api-keys).
32
+ ### Local Mode (Optional)
41
33
 
42
- ### 3. Update your config
34
+ Run everything locally for privacy or offline use:
43
35
 
44
36
  ```json
45
37
  {
@@ -48,6 +40,7 @@ Needed for generating embeddings. Get one at [platform.openai.com/api-keys](http
48
40
  "command": "npx",
49
41
  "args": ["-y", "midnight-mcp"],
50
42
  "env": {
43
+ "MIDNIGHT_LOCAL": "true",
51
44
  "OPENAI_API_KEY": "sk-...",
52
45
  "CHROMA_URL": "http://localhost:8000"
53
46
  }
@@ -56,28 +49,38 @@ Needed for generating embeddings. Get one at [platform.openai.com/api-keys](http
56
49
  }
57
50
  ```
58
51
 
59
- ### Optional: GitHub token
52
+ Local mode requires ChromaDB (`docker run -d -p 8000:8000 chromadb/chroma`) and an OpenAI API key.
60
53
 
61
- Add `"GITHUB_TOKEN": "ghp_..."` to increase API rate limits from 60 to 5000 requests/hour.
62
-
63
- ---
54
+ ### GitHub Token (Optional)
64
55
 
65
- ## What's Included
56
+ Add `"GITHUB_TOKEN": "ghp_..."` for higher GitHub API rate limits (60 → 5000 requests/hour).
66
57
 
67
- ### Tools
68
-
69
- | Tool | Description |
70
- | ----------------------------- | --------------------------------------- |
71
- | `midnight:search-compact` | Search Compact contract code |
72
- | `midnight:search-typescript` | Search TypeScript SDK |
73
- | `midnight:search-docs` | Search documentation |
74
- | `midnight:analyze-contract` | Analyze contract structure and security |
75
- | `midnight:explain-circuit` | Explain circuits in plain language |
76
- | `midnight:get-file` | Get files from Midnight repos |
77
- | `midnight:list-examples` | List example contracts |
78
- | `midnight:get-latest-updates` | Recent repo changes |
58
+ ---
79
59
 
80
- ### Resources
60
+ ## Features
61
+
62
+ ### Tools (16)
63
+
64
+ | Tool | Description |
65
+ | --------------------------------- | --------------------------------------- |
66
+ | `midnight-search-compact` | Search Compact contract code |
67
+ | `midnight-search-typescript` | Search TypeScript SDK |
68
+ | `midnight-search-docs` | Search documentation |
69
+ | `midnight-analyze-contract` | Analyze contract structure and security |
70
+ | `midnight-explain-circuit` | Explain circuits in plain language |
71
+ | `midnight-get-file` | Get files from Midnight repos |
72
+ | `midnight-list-examples` | List example contracts |
73
+ | `midnight-get-latest-updates` | Recent repo changes |
74
+ | `midnight-get-version-info` | Get version and release info |
75
+ | `midnight-check-breaking-changes` | Check for breaking changes |
76
+ | `midnight-get-migration-guide` | Migration guides between versions |
77
+ | `midnight-get-file-at-version` | Get file at specific version |
78
+ | `midnight-compare-syntax` | Compare files between versions |
79
+ | `midnight-get-latest-syntax` | Latest syntax reference |
80
+ | `midnight-health-check` | Check server health status |
81
+ | `midnight-get-status` | Get rate limits and cache stats |
82
+
83
+ ### Resources (20)
81
84
 
82
85
  - `midnight://docs/*` — Documentation (Compact reference, SDK API, ZK concepts)
83
86
  - `midnight://code/*` — Examples, patterns, and templates
@@ -85,16 +88,17 @@ Add `"GITHUB_TOKEN": "ghp_..."` to increase API rate limits from 60 to 5000 requ
85
88
 
86
89
  ### Prompts
87
90
 
88
- - `midnight:create-contract` — Create new contracts
89
- - `midnight:review-contract` — Security review
90
- - `midnight:explain-concept` — Learn Midnight concepts
91
- - `midnight:debug-contract` — Debug issues
91
+ - `midnight-create-contract` — Create new contracts
92
+ - `midnight-review-contract` — Security review
93
+ - `midnight-explain-concept` — Learn Midnight concepts
94
+ - `midnight-compare-approaches` — Compare implementation approaches
95
+ - `midnight-debug-contract` — Debug issues
92
96
 
93
97
  ---
94
98
 
95
99
  ## Developer Setup
96
100
 
97
- For contributors who want to modify or extend the MCP server.
101
+ For contributors:
98
102
 
99
103
  ```bash
100
104
  git clone https://github.com/Olanetsoft/midnight-mcp.git
@@ -104,26 +108,23 @@ npm run build
104
108
  npm test
105
109
  ```
106
110
 
107
- ### Index Midnight repos (for search)
111
+ ### Testing with Local API
112
+
113
+ To test against a local API server instead of production:
108
114
 
109
115
  ```bash
110
- docker run -d -p 8000:8000 chromadb/chroma
111
- npm run index
116
+ # Terminal 1: Start local API
117
+ cd api
118
+ npm install
119
+ npm run dev # Starts at http://localhost:8787
120
+
121
+ # Terminal 2: Run MCP with local API
122
+ MIDNIGHT_API_URL=http://localhost:8787 npm start
112
123
  ```
113
124
 
114
- ### Project Structure
125
+ ### API Backend
115
126
 
116
- ```
117
- src/
118
- ├── index.ts # Entry point
119
- ├── server.ts # MCP server handlers
120
- ├── tools/ # Search, analysis, repository tools
121
- ├── resources/ # Docs, code, schema providers
122
- ├── prompts/ # Prompt templates
123
- ├── pipeline/ # GitHub sync & parsing
124
- ├── db/ # ChromaDB integration
125
- └── utils/ # Config & logging
126
- ```
127
+ The hosted API runs on Cloudflare Workers + Vectorize. See [api/README.md](./api/README.md) for deployment and development instructions.
127
128
 
128
129
  ## License
129
130
 
@@ -1,4 +1,4 @@
1
- import { RepositoryConfig } from "../utils/index.js";
1
+ import { RepositoryConfig, getRateLimitStatus } from "../utils/index.js";
2
2
  export interface GitHubFile {
3
3
  path: string;
4
4
  content: string;
@@ -62,6 +62,23 @@ export declare class GitHubClient {
62
62
  repository: string;
63
63
  url: string;
64
64
  }>>;
65
+ /**
66
+ * Get current rate limit status from GitHub API
67
+ */
68
+ getRateLimit(): Promise<{
69
+ limit: number;
70
+ remaining: number;
71
+ reset: Date;
72
+ used: number;
73
+ }>;
74
+ /**
75
+ * Check if it's safe to make API requests
76
+ */
77
+ checkRateLimit(): {
78
+ proceed: boolean;
79
+ reason?: string;
80
+ status: ReturnType<typeof getRateLimitStatus>;
81
+ };
65
82
  }
66
83
  export declare const githubClient: GitHubClient;
67
84
  //# sourceMappingURL=github.d.ts.map
@@ -1,5 +1,87 @@
1
1
  import { Octokit } from "octokit";
2
- import { config, logger } from "../utils/index.js";
2
+ import { config, logger, updateRateLimit, shouldProceedWithRequest, getRateLimitStatus, } from "../utils/index.js";
3
+ // Retry configuration
4
+ const RETRY_CONFIG = {
5
+ maxRetries: 3,
6
+ baseDelayMs: 1000,
7
+ maxDelayMs: 10000,
8
+ };
9
+ /**
10
+ * Retry wrapper with exponential backoff
11
+ */
12
+ async function withRetry(operation, operationName) {
13
+ let lastError = null;
14
+ for (let attempt = 1; attempt <= RETRY_CONFIG.maxRetries; attempt++) {
15
+ try {
16
+ return await operation();
17
+ }
18
+ catch (error) {
19
+ lastError = error;
20
+ const isRetryable = isRetryableError(error);
21
+ if (!isRetryable || attempt === RETRY_CONFIG.maxRetries) {
22
+ logger.error(`${operationName} failed after ${attempt} attempt(s)`, {
23
+ error: String(error),
24
+ attempt,
25
+ });
26
+ throw enhanceError(error, operationName);
27
+ }
28
+ const delay = Math.min(RETRY_CONFIG.baseDelayMs * Math.pow(2, attempt - 1), RETRY_CONFIG.maxDelayMs);
29
+ logger.warn(`${operationName} failed, retrying in ${delay}ms...`, {
30
+ attempt,
31
+ error: String(error),
32
+ });
33
+ await sleep(delay);
34
+ }
35
+ }
36
+ throw lastError;
37
+ }
38
+ /**
39
+ * Check if an error is retryable
40
+ */
41
+ function isRetryableError(error) {
42
+ if (error instanceof Error) {
43
+ const message = error.message.toLowerCase();
44
+ // Retry on network errors, rate limits, and server errors
45
+ return (message.includes("network") ||
46
+ message.includes("timeout") ||
47
+ message.includes("econnreset") ||
48
+ message.includes("rate limit") ||
49
+ message.includes("403") ||
50
+ message.includes("500") ||
51
+ message.includes("502") ||
52
+ message.includes("503") ||
53
+ message.includes("504"));
54
+ }
55
+ return false;
56
+ }
57
+ /**
58
+ * Enhance error with more context
59
+ */
60
+ function enhanceError(error, operation) {
61
+ const originalMessage = error instanceof Error ? error.message : String(error);
62
+ // Provide user-friendly error messages
63
+ if (originalMessage.includes("rate limit") ||
64
+ originalMessage.includes("403")) {
65
+ return new Error(`GitHub API rate limit exceeded during ${operation}. ` +
66
+ `Add a GITHUB_TOKEN to your config to increase limits from 60 to 5000 requests/hour.`);
67
+ }
68
+ if (originalMessage.includes("404")) {
69
+ return new Error(`Resource not found during ${operation}. ` +
70
+ `Check that the repository/file exists and is accessible.`);
71
+ }
72
+ if (originalMessage.includes("timeout") ||
73
+ originalMessage.includes("network")) {
74
+ return new Error(`Network error during ${operation}. ` +
75
+ `Check your internet connection and try again.`);
76
+ }
77
+ return new Error(`${operation} failed: ${originalMessage}`);
78
+ }
79
+ /**
80
+ * Sleep for a given number of milliseconds
81
+ */
82
+ function sleep(ms) {
83
+ return new Promise((resolve) => setTimeout(resolve, ms));
84
+ }
3
85
  class SimpleCache {
4
86
  cache = new Map();
5
87
  ttlMs;
@@ -47,15 +129,8 @@ export class GitHubClient {
47
129
  return cached;
48
130
  }
49
131
  try {
50
- const { data: repoData } = await this.octokit.rest.repos.get({
51
- owner,
52
- repo,
53
- });
54
- const { data: commits } = await this.octokit.rest.repos.listCommits({
55
- owner,
56
- repo,
57
- per_page: 1,
58
- });
132
+ const { data: repoData } = await withRetry(() => this.octokit.rest.repos.get({ owner, repo }), `getRepositoryInfo(${owner}/${repo})`);
133
+ const { data: commits } = await withRetry(() => this.octokit.rest.repos.listCommits({ owner, repo, per_page: 1 }), `getCommits(${owner}/${repo})`);
59
134
  const lastCommit = commits[0]
60
135
  ? {
61
136
  sha: commits[0].sha,
@@ -93,12 +168,7 @@ export class GitHubClient {
93
168
  return cached;
94
169
  }
95
170
  try {
96
- const { data } = await this.octokit.rest.repos.getContent({
97
- owner,
98
- repo,
99
- path,
100
- ref,
101
- });
171
+ const { data } = await withRetry(() => this.octokit.rest.repos.getContent({ owner, repo, path, ref }), `getFileContent(${owner}/${repo}/${path})`);
102
172
  if (Array.isArray(data) || data.type !== "file") {
103
173
  return null;
104
174
  }
@@ -133,17 +203,17 @@ export class GitHubClient {
133
203
  return cached;
134
204
  }
135
205
  try {
136
- const { data: refData } = await this.octokit.rest.git.getRef({
206
+ const { data: refData } = await withRetry(() => this.octokit.rest.git.getRef({
137
207
  owner,
138
208
  repo,
139
209
  ref: `heads/${ref || "main"}`,
140
- });
141
- const { data: treeData } = await this.octokit.rest.git.getTree({
210
+ }), `getRef(${owner}/${repo})`);
211
+ const { data: treeData } = await withRetry(() => this.octokit.rest.git.getTree({
142
212
  owner,
143
213
  repo,
144
214
  tree_sha: refData.object.sha,
145
215
  recursive: "true",
146
- });
216
+ }), `getTree(${owner}/${repo})`);
147
217
  const result = treeData.tree
148
218
  .filter((item) => item.type === "blob" && item.path)
149
219
  .map((item) => item.path);
@@ -282,6 +352,48 @@ export class GitHubClient {
282
352
  return [];
283
353
  }
284
354
  }
355
+ /**
356
+ * Get current rate limit status from GitHub API
357
+ */
358
+ async getRateLimit() {
359
+ try {
360
+ const { data } = await this.octokit.rest.rateLimit.get();
361
+ const rateLimit = {
362
+ limit: data.rate.limit,
363
+ remaining: data.rate.remaining,
364
+ reset: new Date(data.rate.reset * 1000),
365
+ used: data.rate.used,
366
+ };
367
+ // Update the global rate limit tracker
368
+ updateRateLimit(rateLimit);
369
+ return rateLimit;
370
+ }
371
+ catch (error) {
372
+ logger.warn("Failed to get rate limit", { error: String(error) });
373
+ // Return defaults if we can't get rate limit
374
+ return {
375
+ limit: 60,
376
+ remaining: 60,
377
+ reset: new Date(Date.now() + 3600000),
378
+ used: 0,
379
+ };
380
+ }
381
+ }
382
+ /**
383
+ * Check if it's safe to make API requests
384
+ */
385
+ checkRateLimit() {
386
+ const check = shouldProceedWithRequest();
387
+ const status = getRateLimitStatus();
388
+ if (!check.proceed) {
389
+ logger.warn("Rate limit check failed", { reason: check.reason });
390
+ }
391
+ return {
392
+ proceed: check.proceed,
393
+ reason: check.reason,
394
+ status,
395
+ };
396
+ }
285
397
  }
286
398
  export const githubClient = new GitHubClient();
287
399
  //# sourceMappingURL=github.js.map
package/dist/server.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
- import { logger } from "./utils/index.js";
4
+ import { logger, formatErrorResponse } from "./utils/index.js";
5
5
  import { vectorStore } from "./db/index.js";
6
6
  import { allTools } from "./tools/index.js";
7
7
  import { allResources, getDocumentation, getCode, getSchema, } from "./resources/index.js";
@@ -57,11 +57,19 @@ function registerToolHandlers(server) {
57
57
  logger.info(`Tool called: ${name}`, { args });
58
58
  const tool = allTools.find((t) => t.name === name);
59
59
  if (!tool) {
60
+ const availableTools = allTools
61
+ .map((t) => t.name)
62
+ .slice(0, 5)
63
+ .join(", ");
60
64
  return {
61
65
  content: [
62
66
  {
63
67
  type: "text",
64
- text: `Unknown tool: ${name}`,
68
+ text: JSON.stringify({
69
+ error: `Unknown tool: ${name}`,
70
+ suggestion: `Available tools include: ${availableTools}...`,
71
+ hint: "Use ListTools to see all available tools",
72
+ }, null, 2),
65
73
  },
66
74
  ],
67
75
  isError: true,
@@ -80,11 +88,12 @@ function registerToolHandlers(server) {
80
88
  }
81
89
  catch (error) {
82
90
  logger.error(`Tool error: ${name}`, { error: String(error) });
91
+ const errorResponse = formatErrorResponse(error, `tool:${name}`);
83
92
  return {
84
93
  content: [
85
94
  {
86
95
  type: "text",
87
- text: `Error executing ${name}: ${error}`,
96
+ text: JSON.stringify(errorResponse, null, 2),
88
97
  },
89
98
  ],
90
99
  isError: true,
@@ -129,12 +138,24 @@ function registerResourceHandlers(server) {
129
138
  mimeType = "application/json";
130
139
  }
131
140
  if (!content) {
141
+ const resourceTypes = [
142
+ "midnight://docs/",
143
+ "midnight://code/",
144
+ "midnight://schema/",
145
+ ];
146
+ const validPrefix = resourceTypes.find((p) => uri.startsWith(p));
132
147
  return {
133
148
  contents: [
134
149
  {
135
150
  uri,
136
- mimeType: "text/plain",
137
- text: `Resource not found: ${uri}`,
151
+ mimeType: "application/json",
152
+ text: JSON.stringify({
153
+ error: `Resource not found: ${uri}`,
154
+ suggestion: validPrefix
155
+ ? `Check the resource path after '${validPrefix}'`
156
+ : `Valid resource prefixes: ${resourceTypes.join(", ")}`,
157
+ hint: "Use ListResources to see all available resources",
158
+ }, null, 2),
138
159
  },
139
160
  ],
140
161
  };
@@ -151,12 +172,13 @@ function registerResourceHandlers(server) {
151
172
  }
152
173
  catch (error) {
153
174
  logger.error(`Resource error: ${uri}`, { error: String(error) });
175
+ const errorResponse = formatErrorResponse(error, `resource:${uri}`);
154
176
  return {
155
177
  contents: [
156
178
  {
157
179
  uri,
158
- mimeType: "text/plain",
159
- text: `Error reading resource: ${error}`,
180
+ mimeType: "application/json",
181
+ text: JSON.stringify(errorResponse, null, 2),
160
182
  },
161
183
  ],
162
184
  };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Health check and diagnostic tools for MCP server
3
+ */
4
+ import { z } from "zod";
5
+ export declare const HealthCheckInputSchema: z.ZodObject<{
6
+ detailed: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ detailed: boolean;
9
+ }, {
10
+ detailed?: boolean | undefined;
11
+ }>;
12
+ export declare const GetStatusInputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
13
+ export type HealthCheckInput = z.infer<typeof HealthCheckInputSchema>;
14
+ export type GetStatusInput = z.infer<typeof GetStatusInputSchema>;
15
+ /**
16
+ * Perform health check on the MCP server
17
+ */
18
+ export declare function healthCheck(input: HealthCheckInput): Promise<{
19
+ rateLimit: string;
20
+ cacheStats: {
21
+ search: import("../utils/cache.js").CacheStats;
22
+ file: import("../utils/cache.js").CacheStats;
23
+ metadata: import("../utils/cache.js").CacheStats;
24
+ };
25
+ status: "healthy" | "degraded" | "unhealthy";
26
+ timestamp: string;
27
+ version: string;
28
+ uptime: number;
29
+ checks: {
30
+ name: string;
31
+ status: "pass" | "warn" | "fail";
32
+ message?: string;
33
+ latency?: number;
34
+ }[];
35
+ } | {
36
+ rateLimit: string;
37
+ status: "healthy" | "degraded" | "unhealthy";
38
+ version: string;
39
+ timestamp: string;
40
+ uptime: number;
41
+ checks: {
42
+ name: string;
43
+ status: "pass";
44
+ }[];
45
+ }>;
46
+ /**
47
+ * Get current server status and statistics
48
+ */
49
+ export declare function getStatus(_input: GetStatusInput): Promise<{
50
+ server: string;
51
+ status: string;
52
+ timestamp: string;
53
+ rateLimit: {
54
+ remaining: number;
55
+ limit: number;
56
+ percentUsed: number;
57
+ status: string;
58
+ message: string;
59
+ };
60
+ cache: {
61
+ search: import("../utils/cache.js").CacheStats;
62
+ file: import("../utils/cache.js").CacheStats;
63
+ metadata: import("../utils/cache.js").CacheStats;
64
+ };
65
+ }>;
66
+ export declare const healthTools: ({
67
+ name: string;
68
+ description: string;
69
+ inputSchema: {
70
+ type: "object";
71
+ properties: {
72
+ detailed: {
73
+ type: string;
74
+ description: string;
75
+ default: boolean;
76
+ };
77
+ };
78
+ };
79
+ handler: typeof healthCheck;
80
+ } | {
81
+ name: string;
82
+ description: string;
83
+ inputSchema: {
84
+ type: "object";
85
+ properties: {
86
+ detailed?: undefined;
87
+ };
88
+ };
89
+ handler: typeof getStatus;
90
+ })[];
91
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Health check and diagnostic tools for MCP server
3
+ */
4
+ import { z } from "zod";
5
+ import { getHealthStatus, getQuickHealthStatus, getRateLimitStatus, formatRateLimitStatus, } from "../utils/index.js";
6
+ import { searchCache, fileCache, metadataCache } from "../utils/cache.js";
7
+ // Schema definitions
8
+ export const HealthCheckInputSchema = z.object({
9
+ detailed: z
10
+ .boolean()
11
+ .optional()
12
+ .default(false)
13
+ .describe("Include detailed checks (slower but more comprehensive)"),
14
+ });
15
+ export const GetStatusInputSchema = z.object({});
16
+ /**
17
+ * Perform health check on the MCP server
18
+ */
19
+ export async function healthCheck(input) {
20
+ if (input.detailed) {
21
+ const status = await getHealthStatus();
22
+ return {
23
+ ...status,
24
+ rateLimit: formatRateLimitStatus(),
25
+ cacheStats: {
26
+ search: searchCache.getStats(),
27
+ file: fileCache.getStats(),
28
+ metadata: metadataCache.getStats(),
29
+ },
30
+ };
31
+ }
32
+ return {
33
+ ...getQuickHealthStatus(),
34
+ rateLimit: formatRateLimitStatus(),
35
+ };
36
+ }
37
+ /**
38
+ * Get current server status and statistics
39
+ */
40
+ export async function getStatus(_input) {
41
+ const rateLimitStatus = getRateLimitStatus();
42
+ return {
43
+ server: "midnight-mcp",
44
+ status: "running",
45
+ timestamp: new Date().toISOString(),
46
+ rateLimit: {
47
+ remaining: rateLimitStatus.remaining,
48
+ limit: rateLimitStatus.limit,
49
+ percentUsed: rateLimitStatus.percentUsed,
50
+ status: rateLimitStatus.isLimited
51
+ ? "limited"
52
+ : rateLimitStatus.isWarning
53
+ ? "warning"
54
+ : "ok",
55
+ message: rateLimitStatus.message,
56
+ },
57
+ cache: {
58
+ search: searchCache.getStats(),
59
+ file: fileCache.getStats(),
60
+ metadata: metadataCache.getStats(),
61
+ },
62
+ };
63
+ }
64
+ // Tool definitions for MCP server
65
+ export const healthTools = [
66
+ {
67
+ name: "midnight-health-check",
68
+ description: "Check the health status of the Midnight MCP server. Returns server status, API connectivity, and resource availability.",
69
+ inputSchema: {
70
+ type: "object",
71
+ properties: {
72
+ detailed: {
73
+ type: "boolean",
74
+ description: "Include detailed checks including GitHub API and vector store status (slower)",
75
+ default: false,
76
+ },
77
+ },
78
+ },
79
+ handler: healthCheck,
80
+ },
81
+ {
82
+ name: "midnight-get-status",
83
+ description: "Get current server status including rate limits and cache statistics. Quick status check without external API calls.",
84
+ inputSchema: {
85
+ type: "object",
86
+ properties: {},
87
+ },
88
+ handler: getStatus,
89
+ },
90
+ ];
91
+ //# sourceMappingURL=health.js.map