midnight-mcp 0.0.2 → 0.0.4

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
@@ -64,31 +64,51 @@ Add `"GITHUB_TOKEN": "ghp_..."` to increase API rate limits from 60 to 5000 requ
64
64
 
65
65
  ## What's Included
66
66
 
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 |
79
-
80
- ### Resources
81
-
82
- - `midnight://docs/*` Documentation (Compact reference, SDK API, ZK concepts)
67
+ ### Tools (14 total)
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 |
79
+ | `midnight-get-version-info` | Get version and release info |
80
+ | `midnight-check-breaking-changes` | Check for breaking changes |
81
+ | `midnight-get-migration-guide` | Migration guides between versions |
82
+ | `midnight-get-file-at-version` | Get file at specific version |
83
+ | `midnight-compare-syntax` | Compare files between versions |
84
+ | `midnight-get-latest-syntax` | Latest syntax reference |
85
+
86
+ ### Resources (20 total)
87
+
88
+ - `midnight://docs/*` — Documentation (Compact reference, SDK API, ZK concepts, OpenZeppelin patterns)
83
89
  - `midnight://code/*` — Examples, patterns, and templates
84
90
  - `midnight://schema/*` — AST, transaction, and proof schemas
85
91
 
86
92
  ### Prompts
87
93
 
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
94
+ - `midnight-create-contract` — Create new contracts
95
+ - `midnight-review-contract` — Security review
96
+ - `midnight-explain-concept` — Learn Midnight concepts
97
+ - `midnight-debug-contract` — Debug issues
98
+
99
+ ---
100
+
101
+ ## How Environment Variables Work
102
+
103
+ The npm package contains no secrets. **You provide your own credentials** via the `env` block in your config:
104
+
105
+ | Variable | Required | Without It | With It |
106
+ | ---------------- | -------- | -------------------------------------- | -------------------- |
107
+ | `GITHUB_TOKEN` | No | 60 API calls/hour, may hit rate limits | 5,000 calls/hour |
108
+ | `OPENAI_API_KEY` | No | Keyword search only (no embeddings) | Semantic search |
109
+ | `CHROMA_URL` | No | In-memory search, no persistence | Persistent vector DB |
110
+
111
+ Your tokens stay on your machine and are only used to access services on your behalf.
92
112
 
93
113
  ---
94
114
 
@@ -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
@@ -1,9 +1,11 @@
1
- export { searchTools, searchCompact, searchTypeScript, searchDocs } from "./search.js";
2
- export type { SearchCompactInput, SearchTypeScriptInput, SearchDocsInput } from "./search.js";
1
+ export { searchTools, searchCompact, searchTypeScript, searchDocs, } from "./search.js";
2
+ export type { SearchCompactInput, SearchTypeScriptInput, SearchDocsInput, } from "./search.js";
3
3
  export { analyzeTools, analyzeContract, explainCircuit } from "./analyze.js";
4
4
  export type { AnalyzeContractInput, ExplainCircuitInput } from "./analyze.js";
5
- export { repositoryTools, getFile, listExamples, getLatestUpdates } from "./repository.js";
6
- export type { GetFileInput, ListExamplesInput, GetLatestUpdatesInput } from "./repository.js";
5
+ export { repositoryTools, getFile, listExamples, getLatestUpdates, } from "./repository.js";
6
+ export type { GetFileInput, ListExamplesInput, GetLatestUpdatesInput, } from "./repository.js";
7
+ export { healthTools, healthCheck, getStatus } from "./health.js";
8
+ export type { HealthCheckInput, GetStatusInput } from "./health.js";
7
9
  export declare const allTools: ({
8
10
  name: string;
9
11
  description: string;
@@ -388,5 +390,29 @@ export declare const allTools: ({
388
390
  required: never[];
389
391
  };
390
392
  handler: typeof import("./repository.js").getLatestSyntax;
393
+ } | {
394
+ name: string;
395
+ description: string;
396
+ inputSchema: {
397
+ type: "object";
398
+ properties: {
399
+ detailed: {
400
+ type: string;
401
+ description: string;
402
+ default: boolean;
403
+ };
404
+ };
405
+ };
406
+ handler: typeof import("./health.js").healthCheck;
407
+ } | {
408
+ name: string;
409
+ description: string;
410
+ inputSchema: {
411
+ type: "object";
412
+ properties: {
413
+ detailed?: undefined;
414
+ };
415
+ };
416
+ handler: typeof import("./health.js").getStatus;
391
417
  })[];
392
418
  //# sourceMappingURL=index.d.ts.map
@@ -1,9 +1,16 @@
1
- export { searchTools, searchCompact, searchTypeScript, searchDocs } from "./search.js";
1
+ export { searchTools, searchCompact, searchTypeScript, searchDocs, } from "./search.js";
2
2
  export { analyzeTools, analyzeContract, explainCircuit } from "./analyze.js";
3
- export { repositoryTools, getFile, listExamples, getLatestUpdates } from "./repository.js";
3
+ export { repositoryTools, getFile, listExamples, getLatestUpdates, } from "./repository.js";
4
+ export { healthTools, healthCheck, getStatus } from "./health.js";
4
5
  // Combined tool list for MCP server
5
6
  import { searchTools } from "./search.js";
6
7
  import { analyzeTools } from "./analyze.js";
7
8
  import { repositoryTools } from "./repository.js";
8
- export const allTools = [...searchTools, ...analyzeTools, ...repositoryTools];
9
+ import { healthTools } from "./health.js";
10
+ export const allTools = [
11
+ ...searchTools,
12
+ ...analyzeTools,
13
+ ...repositoryTools,
14
+ ...healthTools,
15
+ ];
9
16
  //# sourceMappingURL=index.js.map