midnight-mcp 0.0.4 → 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
24
+ ## How It Works
31
25
 
32
- ChromaDB is a local vector database—no account needed, just Docker:
26
+ By default, the MCP uses a **hosted API** for semantic search:
33
27
 
34
- ```bash
35
- docker run -d -p 8000:8000 chromadb/chroma
36
- ```
28
+ - ✅ **Zero configuration** — just install and use
29
+ - **Semantic search** works immediately
30
+ - ✅ **No API keys** needed
37
31
 
38
- ### 2. Get an OpenAI API key
32
+ ### Local Mode (Optional)
39
33
 
40
- Needed for generating embeddings. Get one at [platform.openai.com/api-keys](https://platform.openai.com/api-keys).
41
-
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,15 +49,17 @@ 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.
53
+
54
+ ### GitHub Token (Optional)
60
55
 
61
- Add `"GITHUB_TOKEN": "ghp_..."` to increase API rate limits from 60 to 5000 requests/hour.
56
+ Add `"GITHUB_TOKEN": "ghp_..."` for higher GitHub API rate limits (60 5000 requests/hour).
62
57
 
63
58
  ---
64
59
 
65
- ## What's Included
60
+ ## Features
66
61
 
67
- ### Tools (14 total)
62
+ ### Tools (16)
68
63
 
69
64
  | Tool | Description |
70
65
  | --------------------------------- | --------------------------------------- |
@@ -82,10 +77,12 @@ Add `"GITHUB_TOKEN": "ghp_..."` to increase API rate limits from 60 to 5000 requ
82
77
  | `midnight-get-file-at-version` | Get file at specific version |
83
78
  | `midnight-compare-syntax` | Compare files between versions |
84
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 |
85
82
 
86
- ### Resources (20 total)
83
+ ### Resources (20)
87
84
 
88
- - `midnight://docs/*` — Documentation (Compact reference, SDK API, ZK concepts, OpenZeppelin patterns)
85
+ - `midnight://docs/*` — Documentation (Compact reference, SDK API, ZK concepts)
89
86
  - `midnight://code/*` — Examples, patterns, and templates
90
87
  - `midnight://schema/*` — AST, transaction, and proof schemas
91
88
 
@@ -94,27 +91,14 @@ Add `"GITHUB_TOKEN": "ghp_..."` to increase API rate limits from 60 to 5000 requ
94
91
  - `midnight-create-contract` — Create new contracts
95
92
  - `midnight-review-contract` — Security review
96
93
  - `midnight-explain-concept` — Learn Midnight concepts
94
+ - `midnight-compare-approaches` — Compare implementation approaches
97
95
  - `midnight-debug-contract` — Debug issues
98
96
 
99
97
  ---
100
98
 
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.
112
-
113
- ---
114
-
115
99
  ## Developer Setup
116
100
 
117
- For contributors who want to modify or extend the MCP server.
101
+ For contributors:
118
102
 
119
103
  ```bash
120
104
  git clone https://github.com/Olanetsoft/midnight-mcp.git
@@ -124,26 +108,23 @@ npm run build
124
108
  npm test
125
109
  ```
126
110
 
127
- ### Index Midnight repos (for search)
111
+ ### Testing with Local API
112
+
113
+ To test against a local API server instead of production:
128
114
 
129
115
  ```bash
130
- docker run -d -p 8000:8000 chromadb/chroma
131
- 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
132
123
  ```
133
124
 
134
- ### Project Structure
125
+ ### API Backend
135
126
 
136
- ```
137
- src/
138
- ├── index.ts # Entry point
139
- ├── server.ts # MCP server handlers
140
- ├── tools/ # Search, analysis, repository tools
141
- ├── resources/ # Docs, code, schema providers
142
- ├── prompts/ # Prompt templates
143
- ├── pipeline/ # GitHub sync & parsing
144
- ├── db/ # ChromaDB integration
145
- └── utils/ # Config & logging
146
- ```
127
+ The hosted API runs on Cloudflare Workers + Vectorize. See [api/README.md](./api/README.md) for deployment and development instructions.
147
128
 
148
129
  ## License
149
130
 
@@ -50,11 +50,11 @@ export declare const SearchDocsInputSchema: z.ZodObject<{
50
50
  }, "strip", z.ZodTypeAny, {
51
51
  query: string;
52
52
  limit: number;
53
- category: "guides" | "api" | "concepts" | "all";
53
+ category: "all" | "guides" | "api" | "concepts";
54
54
  }, {
55
55
  query: string;
56
56
  limit?: number | undefined;
57
- category?: "guides" | "api" | "concepts" | "all" | undefined;
57
+ category?: "all" | "guides" | "api" | "concepts" | undefined;
58
58
  }>;
59
59
  export type SearchCompactInput = z.infer<typeof SearchCompactInputSchema>;
60
60
  export type SearchTypeScriptInput = z.infer<typeof SearchTypeScriptInputSchema>;
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { vectorStore } from "../db/index.js";
3
- import { logger, validateQuery, validateNumber, searchCache, createCacheKey, } from "../utils/index.js";
3
+ import { logger, validateQuery, validateNumber, searchCache, createCacheKey, isHostedMode, searchCompactHosted, searchTypeScriptHosted, searchDocsHosted, } from "../utils/index.js";
4
4
  // Schema definitions for tool inputs
5
5
  export const SearchCompactInputSchema = z.object({
6
6
  query: z.string().describe("Natural language search query for Compact code"),
@@ -62,7 +62,7 @@ export async function searchCompact(input) {
62
62
  const limit = limitValidation.value;
63
63
  logger.debug("Searching Compact code", {
64
64
  query: sanitizedQuery,
65
- originalQuery: input.query,
65
+ mode: isHostedMode() ? "hosted" : "local",
66
66
  });
67
67
  // Check cache first
68
68
  const cacheKey = createCacheKey("compact", sanitizedQuery, limit, input.filter?.repository);
@@ -71,6 +71,26 @@ export async function searchCompact(input) {
71
71
  logger.debug("Search cache hit", { cacheKey });
72
72
  return cached;
73
73
  }
74
+ // Use hosted API if in hosted mode
75
+ if (isHostedMode()) {
76
+ try {
77
+ const response = await searchCompactHosted(sanitizedQuery, limit);
78
+ searchCache.set(cacheKey, response);
79
+ return {
80
+ ...response,
81
+ ...(queryValidation.warnings.length > 0 && {
82
+ warnings: queryValidation.warnings,
83
+ }),
84
+ };
85
+ }
86
+ catch (error) {
87
+ logger.warn("Hosted API search failed, falling back to local", {
88
+ error: String(error),
89
+ });
90
+ // Fall through to local search
91
+ }
92
+ }
93
+ // Local search (fallback or when in local mode)
74
94
  const filter = {
75
95
  language: "compact",
76
96
  ...input.filter,
@@ -118,7 +138,10 @@ export async function searchTypeScript(input) {
118
138
  });
119
139
  const sanitizedQuery = queryValidation.sanitized;
120
140
  const limit = limitValidation.value;
121
- logger.debug("Searching TypeScript code", { query: sanitizedQuery });
141
+ logger.debug("Searching TypeScript code", {
142
+ query: sanitizedQuery,
143
+ mode: isHostedMode() ? "hosted" : "local",
144
+ });
122
145
  // Check cache
123
146
  const cacheKey = createCacheKey("typescript", sanitizedQuery, limit, input.includeTypes, input.includeExamples);
124
147
  const cached = searchCache.get(cacheKey);
@@ -126,6 +149,26 @@ export async function searchTypeScript(input) {
126
149
  logger.debug("Search cache hit", { cacheKey });
127
150
  return cached;
128
151
  }
152
+ // Use hosted API if in hosted mode
153
+ if (isHostedMode()) {
154
+ try {
155
+ const response = await searchTypeScriptHosted(sanitizedQuery, limit, input.includeTypes);
156
+ searchCache.set(cacheKey, response);
157
+ return {
158
+ ...response,
159
+ ...(queryValidation.warnings.length > 0 && {
160
+ warnings: queryValidation.warnings,
161
+ }),
162
+ };
163
+ }
164
+ catch (error) {
165
+ logger.warn("Hosted API search failed, falling back to local", {
166
+ error: String(error),
167
+ });
168
+ // Fall through to local search
169
+ }
170
+ }
171
+ // Local search (fallback or when in local mode)
129
172
  const filter = {
130
173
  language: "typescript",
131
174
  };
@@ -177,7 +220,10 @@ export async function searchDocs(input) {
177
220
  });
178
221
  const sanitizedQuery = queryValidation.sanitized;
179
222
  const limit = limitValidation.value;
180
- logger.debug("Searching documentation", { query: sanitizedQuery });
223
+ logger.debug("Searching documentation", {
224
+ query: sanitizedQuery,
225
+ mode: isHostedMode() ? "hosted" : "local",
226
+ });
181
227
  // Check cache
182
228
  const cacheKey = createCacheKey("docs", sanitizedQuery, limit, input.category);
183
229
  const cached = searchCache.get(cacheKey);
@@ -185,6 +231,26 @@ export async function searchDocs(input) {
185
231
  logger.debug("Search cache hit", { cacheKey });
186
232
  return cached;
187
233
  }
234
+ // Use hosted API if in hosted mode
235
+ if (isHostedMode()) {
236
+ try {
237
+ const response = await searchDocsHosted(sanitizedQuery, limit, input.category);
238
+ searchCache.set(cacheKey, response);
239
+ return {
240
+ ...response,
241
+ ...(queryValidation.warnings.length > 0 && {
242
+ warnings: queryValidation.warnings,
243
+ }),
244
+ };
245
+ }
246
+ catch (error) {
247
+ logger.warn("Hosted API search failed, falling back to local", {
248
+ error: String(error),
249
+ });
250
+ // Fall through to local search
251
+ }
252
+ }
253
+ // Local search (fallback or when in local mode)
188
254
  const filter = {
189
255
  language: "markdown",
190
256
  };
@@ -1,10 +1,9 @@
1
1
  import { z } from "zod";
2
2
  declare const ConfigSchema: z.ZodObject<{
3
+ mode: z.ZodDefault<z.ZodEnum<["hosted", "local"]>>;
4
+ hostedApiUrl: z.ZodDefault<z.ZodString>;
3
5
  githubToken: z.ZodOptional<z.ZodString>;
4
6
  chromaUrl: z.ZodDefault<z.ZodString>;
5
- qdrantUrl: z.ZodOptional<z.ZodString>;
6
- pineconeApiKey: z.ZodOptional<z.ZodString>;
7
- pineconeIndex: z.ZodOptional<z.ZodString>;
8
7
  openaiApiKey: z.ZodOptional<z.ZodString>;
9
8
  embeddingModel: z.ZodDefault<z.ZodString>;
10
9
  logLevel: z.ZodDefault<z.ZodEnum<["debug", "info", "warn", "error"]>>;
@@ -13,6 +12,8 @@ declare const ConfigSchema: z.ZodObject<{
13
12
  dataDir: z.ZodDefault<z.ZodString>;
14
13
  cacheDir: z.ZodDefault<z.ZodString>;
15
14
  }, "strip", z.ZodTypeAny, {
15
+ mode: "hosted" | "local";
16
+ hostedApiUrl: string;
16
17
  chromaUrl: string;
17
18
  embeddingModel: string;
18
19
  logLevel: "debug" | "info" | "warn" | "error";
@@ -21,16 +22,12 @@ declare const ConfigSchema: z.ZodObject<{
21
22
  dataDir: string;
22
23
  cacheDir: string;
23
24
  githubToken?: string | undefined;
24
- qdrantUrl?: string | undefined;
25
- pineconeApiKey?: string | undefined;
26
- pineconeIndex?: string | undefined;
27
25
  openaiApiKey?: string | undefined;
28
26
  }, {
27
+ mode?: "hosted" | "local" | undefined;
28
+ hostedApiUrl?: string | undefined;
29
29
  githubToken?: string | undefined;
30
30
  chromaUrl?: string | undefined;
31
- qdrantUrl?: string | undefined;
32
- pineconeApiKey?: string | undefined;
33
- pineconeIndex?: string | undefined;
34
31
  openaiApiKey?: string | undefined;
35
32
  embeddingModel?: string | undefined;
36
33
  logLevel?: "debug" | "info" | "warn" | "error" | undefined;
@@ -41,6 +38,8 @@ declare const ConfigSchema: z.ZodObject<{
41
38
  }>;
42
39
  export type Config = z.infer<typeof ConfigSchema>;
43
40
  export declare const config: {
41
+ mode: "hosted" | "local";
42
+ hostedApiUrl: string;
44
43
  chromaUrl: string;
45
44
  embeddingModel: string;
46
45
  logLevel: "debug" | "info" | "warn" | "error";
@@ -49,11 +48,16 @@ export declare const config: {
49
48
  dataDir: string;
50
49
  cacheDir: string;
51
50
  githubToken?: string | undefined;
52
- qdrantUrl?: string | undefined;
53
- pineconeApiKey?: string | undefined;
54
- pineconeIndex?: string | undefined;
55
51
  openaiApiKey?: string | undefined;
56
52
  };
53
+ /**
54
+ * Check if running in hosted mode (default)
55
+ */
56
+ export declare function isHostedMode(): boolean;
57
+ /**
58
+ * Check if running in local mode
59
+ */
60
+ export declare function isLocalMode(): boolean;
57
61
  export interface RepositoryConfig {
58
62
  owner: string;
59
63
  repo: string;
@@ -2,14 +2,17 @@ import { z } from "zod";
2
2
  import dotenv from "dotenv";
3
3
  dotenv.config();
4
4
  const ConfigSchema = z.object({
5
+ // Mode: 'hosted' (default) or 'local'
6
+ mode: z.enum(["hosted", "local"]).default("hosted"),
7
+ // Hosted API URL (used when mode is 'hosted')
8
+ hostedApiUrl: z
9
+ .string()
10
+ .default("https://midnight-mcp-api.midnightmcp.workers.dev"),
5
11
  // GitHub
6
12
  githubToken: z.string().optional(),
7
- // Vector Database
13
+ // Vector Database (only needed for local mode)
8
14
  chromaUrl: z.string().default("http://localhost:8000"),
9
- qdrantUrl: z.string().optional(),
10
- pineconeApiKey: z.string().optional(),
11
- pineconeIndex: z.string().optional(),
12
- // Embeddings
15
+ // Embeddings (only needed for local mode)
13
16
  openaiApiKey: z.string().optional(),
14
17
  embeddingModel: z.string().default("text-embedding-3-small"),
15
18
  // Server
@@ -21,12 +24,14 @@ const ConfigSchema = z.object({
21
24
  cacheDir: z.string().default("./cache"),
22
25
  });
23
26
  function loadConfig() {
27
+ // Determine mode: local if MIDNIGHT_LOCAL=true or if OPENAI_API_KEY is set
28
+ const isLocalMode = process.env.MIDNIGHT_LOCAL === "true" ||
29
+ (process.env.OPENAI_API_KEY && process.env.CHROMA_URL);
24
30
  const rawConfig = {
31
+ mode: isLocalMode ? "local" : "hosted",
32
+ hostedApiUrl: process.env.MIDNIGHT_API_URL,
25
33
  githubToken: process.env.GITHUB_TOKEN,
26
34
  chromaUrl: process.env.CHROMA_URL,
27
- qdrantUrl: process.env.QDRANT_URL,
28
- pineconeApiKey: process.env.PINECONE_API_KEY,
29
- pineconeIndex: process.env.PINECONE_INDEX,
30
35
  openaiApiKey: process.env.OPENAI_API_KEY,
31
36
  embeddingModel: process.env.EMBEDDING_MODEL,
32
37
  logLevel: process.env.LOG_LEVEL,
@@ -42,6 +47,18 @@ function loadConfig() {
42
47
  return ConfigSchema.parse(cleanConfig);
43
48
  }
44
49
  export const config = loadConfig();
50
+ /**
51
+ * Check if running in hosted mode (default)
52
+ */
53
+ export function isHostedMode() {
54
+ return config.mode === "hosted";
55
+ }
56
+ /**
57
+ * Check if running in local mode
58
+ */
59
+ export function isLocalMode() {
60
+ return config.mode === "local";
61
+ }
45
62
  export const DEFAULT_REPOSITORIES = [
46
63
  // Core Language & SDK
47
64
  {
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Client for the hosted Midnight MCP API
3
+ * Used when running in hosted mode (default)
4
+ */
5
+ export interface HostedSearchResult {
6
+ code?: string;
7
+ content?: string;
8
+ relevanceScore: number;
9
+ source: {
10
+ repository: string;
11
+ filePath: string;
12
+ lines?: string;
13
+ section?: string;
14
+ };
15
+ codeType?: string;
16
+ name?: string;
17
+ isExported?: boolean;
18
+ }
19
+ export interface HostedSearchResponse {
20
+ results: HostedSearchResult[];
21
+ totalResults: number;
22
+ query: string;
23
+ category?: string;
24
+ warnings?: string[];
25
+ }
26
+ export interface HostedSearchFilter {
27
+ language?: string;
28
+ repository?: string;
29
+ }
30
+ /**
31
+ * Search Compact code via hosted API
32
+ */
33
+ export declare function searchCompactHosted(query: string, limit?: number): Promise<HostedSearchResponse>;
34
+ /**
35
+ * Search TypeScript code via hosted API
36
+ */
37
+ export declare function searchTypeScriptHosted(query: string, limit?: number, includeTypes?: boolean): Promise<HostedSearchResponse>;
38
+ /**
39
+ * Search documentation via hosted API
40
+ */
41
+ export declare function searchDocsHosted(query: string, limit?: number, category?: string): Promise<HostedSearchResponse>;
42
+ /**
43
+ * Generic search via hosted API
44
+ */
45
+ export declare function searchHosted(query: string, limit?: number, filter?: HostedSearchFilter): Promise<HostedSearchResponse>;
46
+ /**
47
+ * Check if the hosted API is available
48
+ */
49
+ export declare function checkHostedApiHealth(): Promise<{
50
+ available: boolean;
51
+ documentsIndexed?: number;
52
+ error?: string;
53
+ }>;
54
+ /**
55
+ * Get hosted API stats
56
+ */
57
+ export declare function getHostedApiStats(): Promise<{
58
+ documentsIndexed: number;
59
+ repositories: number;
60
+ }>;
61
+ //# sourceMappingURL=hosted-api.d.ts.map
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Client for the hosted Midnight MCP API
3
+ * Used when running in hosted mode (default)
4
+ */
5
+ import { config, logger } from "./index.js";
6
+ const API_TIMEOUT = 10000; // 10 seconds
7
+ /**
8
+ * Make a request to the hosted API
9
+ */
10
+ async function apiRequest(endpoint, options = {}) {
11
+ const url = `${config.hostedApiUrl}${endpoint}`;
12
+ const controller = new AbortController();
13
+ const timeout = setTimeout(() => controller.abort(), API_TIMEOUT);
14
+ try {
15
+ const response = await fetch(url, {
16
+ ...options,
17
+ signal: controller.signal,
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ "User-Agent": "midnight-mcp",
21
+ ...options.headers,
22
+ },
23
+ });
24
+ if (!response.ok) {
25
+ const errorData = (await response
26
+ .json()
27
+ .catch(() => ({ error: "Unknown error" })));
28
+ throw new Error(errorData.error || `API error: ${response.status}`);
29
+ }
30
+ return (await response.json());
31
+ }
32
+ catch (error) {
33
+ if (error instanceof Error && error.name === "AbortError") {
34
+ throw new Error("API request timed out. The hosted service may be unavailable.");
35
+ }
36
+ throw error;
37
+ }
38
+ finally {
39
+ clearTimeout(timeout);
40
+ }
41
+ }
42
+ /**
43
+ * Search Compact code via hosted API
44
+ */
45
+ export async function searchCompactHosted(query, limit = 10) {
46
+ logger.debug("Searching Compact code via hosted API", { query });
47
+ return apiRequest("/v1/search/compact", {
48
+ method: "POST",
49
+ body: JSON.stringify({ query, limit }),
50
+ });
51
+ }
52
+ /**
53
+ * Search TypeScript code via hosted API
54
+ */
55
+ export async function searchTypeScriptHosted(query, limit = 10, includeTypes = true) {
56
+ logger.debug("Searching TypeScript code via hosted API", { query });
57
+ return apiRequest("/v1/search/typescript", {
58
+ method: "POST",
59
+ body: JSON.stringify({ query, limit, includeTypes }),
60
+ });
61
+ }
62
+ /**
63
+ * Search documentation via hosted API
64
+ */
65
+ export async function searchDocsHosted(query, limit = 10, category = "all") {
66
+ logger.debug("Searching documentation via hosted API", { query });
67
+ return apiRequest("/v1/search/docs", {
68
+ method: "POST",
69
+ body: JSON.stringify({ query, limit, category }),
70
+ });
71
+ }
72
+ /**
73
+ * Generic search via hosted API
74
+ */
75
+ export async function searchHosted(query, limit = 10, filter) {
76
+ logger.debug("Searching via hosted API", { query, filter });
77
+ return apiRequest("/v1/search", {
78
+ method: "POST",
79
+ body: JSON.stringify({ query, limit, filter }),
80
+ });
81
+ }
82
+ /**
83
+ * Check if the hosted API is available
84
+ */
85
+ export async function checkHostedApiHealth() {
86
+ try {
87
+ const response = await apiRequest("/health");
88
+ return {
89
+ available: response.status === "healthy",
90
+ documentsIndexed: response.vectorStore?.documentsIndexed,
91
+ };
92
+ }
93
+ catch (error) {
94
+ return {
95
+ available: false,
96
+ error: error instanceof Error ? error.message : String(error),
97
+ };
98
+ }
99
+ }
100
+ /**
101
+ * Get hosted API stats
102
+ */
103
+ export async function getHostedApiStats() {
104
+ return apiRequest("/v1/stats");
105
+ }
106
+ //# sourceMappingURL=hosted-api.js.map
@@ -1,4 +1,4 @@
1
- export { config } from "./config.js";
1
+ export { config, isHostedMode, isLocalMode } from "./config.js";
2
2
  export type { Config, RepositoryConfig } from "./config.js";
3
3
  export { DEFAULT_REPOSITORIES } from "./config.js";
4
4
  export { logger } from "./logger.js";
@@ -11,4 +11,6 @@ export { updateRateLimitFromHeaders, updateRateLimit, getRateLimitStatus, should
11
11
  export type { RateLimitInfo, RateLimitStatus } from "./rate-limit.js";
12
12
  export { Cache, createCacheKey, searchCache, fileCache, metadataCache, pruneAllCaches, } from "./cache.js";
13
13
  export type { CacheOptions, CacheEntry, CacheStats } from "./cache.js";
14
+ export { searchCompactHosted, searchTypeScriptHosted, searchDocsHosted, searchHosted, checkHostedApiHealth, getHostedApiStats, } from "./hosted-api.js";
15
+ export type { HostedSearchResult, HostedSearchResponse, HostedSearchFilter, } from "./hosted-api.js";
14
16
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,4 @@
1
- export { config } from "./config.js";
1
+ export { config, isHostedMode, isLocalMode } from "./config.js";
2
2
  export { DEFAULT_REPOSITORIES } from "./config.js";
3
3
  export { logger } from "./logger.js";
4
4
  export { MCPError, ErrorCodes, createUserError, formatErrorResponse, withErrorHandling, } from "./errors.js";
@@ -10,4 +10,6 @@ export { getHealthStatus, getQuickHealthStatus } from "./health.js";
10
10
  export { updateRateLimitFromHeaders, updateRateLimit, getRateLimitStatus, shouldProceedWithRequest, getTimeUntilReset, formatRateLimitStatus, decrementRemaining, } from "./rate-limit.js";
11
11
  // Caching utilities
12
12
  export { Cache, createCacheKey, searchCache, fileCache, metadataCache, pruneAllCaches, } from "./cache.js";
13
+ // Hosted API client
14
+ export { searchCompactHosted, searchTypeScriptHosted, searchDocsHosted, searchHosted, checkHostedApiHealth, getHostedApiStats, } from "./hosted-api.js";
13
15
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midnight-mcp",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Model Context Protocol Server for Midnight Blockchain Development",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,7 +11,6 @@
11
11
  "build": "tsc",
12
12
  "start": "node dist/index.js",
13
13
  "dev": "tsx watch src/index.ts",
14
- "index": "tsx src/scripts/index-repos.ts",
15
14
  "test": "vitest",
16
15
  "test:coverage": "vitest --coverage",
17
16
  "lint": "eslint src/**/*.ts",