midnight-mcp 0.2.3 → 0.2.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 +3 -3
- package/dist/bin.js +3 -3
- package/dist/{chunk-EBFMM2DS.js → chunk-6BPO5SRQ.js} +58 -14
- package/dist/{chunk-ZYCQLQEX.js → chunk-E5HAMXS3.js} +263 -5
- package/dist/db-F27LE73N.js +7 -0
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/db-ILWTH42C.js +0 -7
package/README.md
CHANGED
|
@@ -104,11 +104,11 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
104
104
|
|
|
105
105
|
## What's Included
|
|
106
106
|
|
|
107
|
-
###
|
|
107
|
+
### 28 Tools
|
|
108
108
|
|
|
109
109
|
| Category | Tools | Description |
|
|
110
110
|
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
|
|
111
|
-
| **Search** | `search-compact`, `search-typescript`, `search-docs`
|
|
111
|
+
| **Search** | `search-compact`, `search-typescript`, `search-docs`, `fetch-docs` | Semantic search + live docs fetching |
|
|
112
112
|
| **Analysis** | `analyze-contract`, `explain-circuit`, `extract-contract-structure` | Static analysis with 15+ checks (P0-P2 severity) |
|
|
113
113
|
| **Repository** | `get-file`, `list-examples`, `get-latest-updates` | Access files and examples |
|
|
114
114
|
| **Versioning** | `get-version-info`, `check-breaking-changes`, `get-migration-guide`, `get-file-at-version`, `compare-syntax`, `get-latest-syntax` | Version tracking and migration |
|
|
@@ -123,7 +123,7 @@ All tools are prefixed with `midnight-` (e.g., `midnight-search-compact`).
|
|
|
123
123
|
|
|
124
124
|
| Capability | Feature |
|
|
125
125
|
| --------------- | ----------------------------------------------- |
|
|
126
|
-
| **Tools** |
|
|
126
|
+
| **Tools** | 28 tools with `listChanged` notifications |
|
|
127
127
|
| **Resources** | 9 embedded resources with subscription support |
|
|
128
128
|
| **Prompts** | 5 workflow prompts |
|
|
129
129
|
| **Logging** | Client-controllable log level |
|
package/dist/bin.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
startHttpServer,
|
|
4
4
|
startServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-E5HAMXS3.js";
|
|
6
6
|
import {
|
|
7
7
|
setOutputFormat
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-6BPO5SRQ.js";
|
|
9
9
|
|
|
10
10
|
// src/bin.ts
|
|
11
11
|
import { config } from "dotenv";
|
|
@@ -13,7 +13,7 @@ import { resolve } from "path";
|
|
|
13
13
|
import yargs from "yargs";
|
|
14
14
|
import { hideBin } from "yargs/helpers";
|
|
15
15
|
config({ path: resolve(process.cwd(), ".env") });
|
|
16
|
-
var CURRENT_VERSION = "0.2.
|
|
16
|
+
var CURRENT_VERSION = "0.2.5";
|
|
17
17
|
process.on("uncaughtException", (error) => {
|
|
18
18
|
console.error("Uncaught exception:", error);
|
|
19
19
|
process.exit(1);
|
|
@@ -1594,7 +1594,7 @@ async function checkGitHubAPI() {
|
|
|
1594
1594
|
}
|
|
1595
1595
|
async function checkVectorStore() {
|
|
1596
1596
|
try {
|
|
1597
|
-
const { vectorStore: vectorStore2 } = await import("./db-
|
|
1597
|
+
const { vectorStore: vectorStore2 } = await import("./db-F27LE73N.js");
|
|
1598
1598
|
if (vectorStore2) {
|
|
1599
1599
|
return {
|
|
1600
1600
|
status: "pass",
|
|
@@ -1898,7 +1898,9 @@ function pruneAllCaches() {
|
|
|
1898
1898
|
setInterval(pruneAllCaches, 5 * 60 * 1e3);
|
|
1899
1899
|
|
|
1900
1900
|
// src/utils/hosted-api.ts
|
|
1901
|
-
var API_TIMEOUT =
|
|
1901
|
+
var API_TIMEOUT = 15e3;
|
|
1902
|
+
var MAX_RETRIES = 2;
|
|
1903
|
+
var RETRY_DELAY_MS = 1e3;
|
|
1902
1904
|
function getActionableErrorMessage(status, endpoint, serverMessage) {
|
|
1903
1905
|
const baseMessages = {
|
|
1904
1906
|
400: `Bad request to ${endpoint}. Check your query parameters are valid.`,
|
|
@@ -1932,8 +1934,17 @@ async function parseApiError(response, endpoint) {
|
|
|
1932
1934
|
);
|
|
1933
1935
|
return new Error(actionableMessage);
|
|
1934
1936
|
}
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
+
function isRetryableError2(error) {
|
|
1938
|
+
if (error instanceof Error) {
|
|
1939
|
+
const message = error.message.toLowerCase();
|
|
1940
|
+
return error.name === "AbortError" || message.includes("timeout") || message.includes("network") || message.includes("econnreset") || message.includes("502") || message.includes("503") || message.includes("504") || message.includes("bad gateway") || message.includes("service unavailable") || message.includes("gateway timeout");
|
|
1941
|
+
}
|
|
1942
|
+
return false;
|
|
1943
|
+
}
|
|
1944
|
+
function sleep2(ms) {
|
|
1945
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1946
|
+
}
|
|
1947
|
+
async function makeRequest(url, endpoint, options) {
|
|
1937
1948
|
const controller = new AbortController();
|
|
1938
1949
|
const timeout = setTimeout(() => controller.abort(), API_TIMEOUT);
|
|
1939
1950
|
try {
|
|
@@ -1953,21 +1964,54 @@ async function apiRequest(endpoint, options = {}) {
|
|
|
1953
1964
|
} catch (error) {
|
|
1954
1965
|
if (error instanceof Error && error.name === "AbortError") {
|
|
1955
1966
|
throw new Error(
|
|
1956
|
-
`Request to ${endpoint} timed out after ${API_TIMEOUT / 1e3}s
|
|
1967
|
+
`Request to ${endpoint} timed out after ${API_TIMEOUT / 1e3}s.`
|
|
1957
1968
|
);
|
|
1958
1969
|
}
|
|
1959
|
-
|
|
1960
|
-
|
|
1970
|
+
throw error;
|
|
1971
|
+
} finally {
|
|
1972
|
+
clearTimeout(timeout);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
async function apiRequest(endpoint, options = {}) {
|
|
1976
|
+
const url = `${config.hostedApiUrl}${endpoint}`;
|
|
1977
|
+
let lastError = null;
|
|
1978
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
1979
|
+
try {
|
|
1980
|
+
return await makeRequest(url, endpoint, options);
|
|
1981
|
+
} catch (error) {
|
|
1982
|
+
lastError = error;
|
|
1983
|
+
if (!isRetryableError2(error)) {
|
|
1984
|
+
break;
|
|
1985
|
+
}
|
|
1986
|
+
if (attempt === MAX_RETRIES) {
|
|
1987
|
+
logger.warn(`Hosted API request failed after ${attempt + 1} attempts`, {
|
|
1988
|
+
endpoint,
|
|
1989
|
+
error: String(error)
|
|
1990
|
+
});
|
|
1991
|
+
break;
|
|
1992
|
+
}
|
|
1993
|
+
const delay = RETRY_DELAY_MS * Math.pow(2, attempt);
|
|
1994
|
+
logger.debug(
|
|
1995
|
+
`Retrying hosted API request in ${delay}ms (attempt ${attempt + 1}/${MAX_RETRIES + 1})`,
|
|
1996
|
+
{ endpoint }
|
|
1997
|
+
);
|
|
1998
|
+
await sleep2(delay);
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
if (lastError) {
|
|
2002
|
+
if (lastError.message.includes("github.com/Olanetsoft")) {
|
|
2003
|
+
throw lastError;
|
|
1961
2004
|
}
|
|
1962
|
-
if (
|
|
2005
|
+
if (lastError.message.includes("timed out")) {
|
|
1963
2006
|
throw new Error(
|
|
1964
|
-
`
|
|
2007
|
+
`Request to ${endpoint} timed out after ${MAX_RETRIES + 1} attempts. The hosted service may be slow or unavailable. Try a simpler query or set MIDNIGHT_LOCAL=true for local search.`
|
|
1965
2008
|
);
|
|
1966
2009
|
}
|
|
1967
|
-
throw
|
|
1968
|
-
|
|
1969
|
-
|
|
2010
|
+
throw new Error(
|
|
2011
|
+
`Failed to connect to hosted API after ${MAX_RETRIES + 1} attempts: ${lastError.message}. Check your internet connection or set MIDNIGHT_LOCAL=true for local search.`
|
|
2012
|
+
);
|
|
1970
2013
|
}
|
|
2014
|
+
throw new Error("Unknown error in API request");
|
|
1971
2015
|
}
|
|
1972
2016
|
async function searchCompactHosted(query, limit = 10) {
|
|
1973
2017
|
logger.debug("Searching Compact code via hosted API", { query });
|
|
@@ -2025,7 +2069,7 @@ function serialize(data) {
|
|
|
2025
2069
|
}
|
|
2026
2070
|
|
|
2027
2071
|
// src/utils/version.ts
|
|
2028
|
-
var CURRENT_VERSION = "0.2.
|
|
2072
|
+
var CURRENT_VERSION = "0.2.5";
|
|
2029
2073
|
|
|
2030
2074
|
// src/db/vectorStore.ts
|
|
2031
2075
|
var VectorStore = class {
|
|
@@ -2234,4 +2278,4 @@ export {
|
|
|
2234
2278
|
serialize,
|
|
2235
2279
|
CURRENT_VERSION
|
|
2236
2280
|
};
|
|
2237
|
-
//# sourceMappingURL=chunk-
|
|
2281
|
+
//# sourceMappingURL=chunk-6BPO5SRQ.js.map
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
validateNumber,
|
|
26
26
|
validateQuery,
|
|
27
27
|
vectorStore
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-6BPO5SRQ.js";
|
|
29
29
|
|
|
30
30
|
// src/tools/search/schemas.ts
|
|
31
31
|
import { z } from "zod";
|
|
@@ -48,6 +48,14 @@ var SearchDocsInputSchema = z.object({
|
|
|
48
48
|
category: z.enum(["guides", "api", "concepts", "all"]).optional().default("all").describe("Filter by documentation category"),
|
|
49
49
|
limit: z.number().optional().default(10)
|
|
50
50
|
});
|
|
51
|
+
var FetchDocsInputSchema = z.object({
|
|
52
|
+
path: z.string().describe(
|
|
53
|
+
"Documentation page path (e.g., '/develop/faq', '/getting-started/installation', '/compact')"
|
|
54
|
+
),
|
|
55
|
+
extractSection: z.string().optional().describe(
|
|
56
|
+
"Optional: Extract only a specific section by heading (e.g., 'General questions')"
|
|
57
|
+
)
|
|
58
|
+
});
|
|
51
59
|
|
|
52
60
|
// src/tools/search/handlers.ts
|
|
53
61
|
function validateSearchInput(query, limit) {
|
|
@@ -235,13 +243,16 @@ async function searchDocs(input) {
|
|
|
235
243
|
);
|
|
236
244
|
const cached = checkSearchCache(cacheKey);
|
|
237
245
|
if (cached) return cached;
|
|
246
|
+
const freshnessHint = "For guaranteed freshness, use midnight-fetch-docs with the path from these results (e.g., /develop/faq)";
|
|
238
247
|
const hostedResult = await tryHostedSearch(
|
|
239
248
|
"docs",
|
|
240
249
|
() => searchDocsHosted(sanitizedQuery, limit, input.category),
|
|
241
250
|
cacheKey,
|
|
242
251
|
warnings
|
|
243
252
|
);
|
|
244
|
-
if (hostedResult)
|
|
253
|
+
if (hostedResult) {
|
|
254
|
+
return { ...hostedResult.result, hint: freshnessHint };
|
|
255
|
+
}
|
|
245
256
|
const filter = {
|
|
246
257
|
language: "markdown"
|
|
247
258
|
};
|
|
@@ -261,10 +272,169 @@ async function searchDocs(input) {
|
|
|
261
272
|
})),
|
|
262
273
|
totalResults: results.length,
|
|
263
274
|
query: sanitizedQuery,
|
|
264
|
-
category: input.category
|
|
275
|
+
category: input.category,
|
|
276
|
+
hint: "For guaranteed freshness, use midnight-fetch-docs with the path from these results (e.g., /develop/faq)"
|
|
265
277
|
};
|
|
266
278
|
return finalizeResponse(response, cacheKey, warnings);
|
|
267
279
|
}
|
|
280
|
+
var DOCS_BASE_URL = "https://docs.midnight.network";
|
|
281
|
+
var FETCH_TIMEOUT = 15e3;
|
|
282
|
+
var KNOWN_DOC_PATHS = [
|
|
283
|
+
"/develop/faq",
|
|
284
|
+
"/develop/getting-help",
|
|
285
|
+
"/develop/tutorial/building",
|
|
286
|
+
"/develop/how-midnight-works",
|
|
287
|
+
"/getting-started/installation",
|
|
288
|
+
"/getting-started/create-mn-app",
|
|
289
|
+
"/getting-started/deploy-mn-app",
|
|
290
|
+
"/getting-started/interact-with-mn-app",
|
|
291
|
+
"/compact",
|
|
292
|
+
"/learn/what-is-midnight",
|
|
293
|
+
"/learn/glossary",
|
|
294
|
+
"/develop/reference/midnight-api",
|
|
295
|
+
"/relnotes/overview",
|
|
296
|
+
"/blog"
|
|
297
|
+
];
|
|
298
|
+
function extractContentFromHtml(html, extractSection) {
|
|
299
|
+
const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
300
|
+
const title = titleMatch ? titleMatch[1].replace(" | Midnight Docs", "").trim() : "Unknown";
|
|
301
|
+
const lastUpdatedMatch = html.match(
|
|
302
|
+
/<time[^>]*datetime="([^"]+)"[^>]*itemprop="dateModified"/i
|
|
303
|
+
);
|
|
304
|
+
const lastUpdated = lastUpdatedMatch ? lastUpdatedMatch[1] : void 0;
|
|
305
|
+
const articleMatch = html.match(/<article[^>]*>([\s\S]*?)<\/article>/i);
|
|
306
|
+
const articleHtml = articleMatch ? articleMatch[1] : html;
|
|
307
|
+
const headings = [];
|
|
308
|
+
const headingRegex = /<h([1-6])[^>]*class="[^"]*anchor[^"]*"[^>]*id="([^"]*)"[^>]*>([^<]*(?:<[^/][^>]*>[^<]*<\/[^>]+>)*[^<]*)/gi;
|
|
309
|
+
let headingMatch;
|
|
310
|
+
while ((headingMatch = headingRegex.exec(articleHtml)) !== null) {
|
|
311
|
+
const text = headingMatch[3].replace(/<[^>]+>/g, "").replace(/\u200B/g, "").replace(//g, "").trim();
|
|
312
|
+
if (text) {
|
|
313
|
+
headings.push({
|
|
314
|
+
level: parseInt(headingMatch[1]),
|
|
315
|
+
text,
|
|
316
|
+
id: headingMatch[2]
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
let content = articleHtml.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<svg[^>]*>[\s\S]*?<\/svg>/gi, "").replace(/<nav[^>]*class="[^"]*breadcrumb[^"]*"[^>]*>[\s\S]*?<\/nav>/gi, "").replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, "").replace(/<a[^>]*class="[^"]*hash-link[^"]*"[^>]*>[\s\S]*?<\/a>/gi, "").replace(/<button[^>]*>[\s\S]*?<\/button>/gi, "");
|
|
321
|
+
content = content.replace(/<h1[^>]*>/gi, "\n# ").replace(/<\/h1>/gi, "\n").replace(/<h2[^>]*>/gi, "\n## ").replace(/<\/h2>/gi, "\n").replace(/<h3[^>]*>/gi, "\n### ").replace(/<\/h3>/gi, "\n").replace(/<h4[^>]*>/gi, "\n#### ").replace(/<\/h4>/gi, "\n").replace(/<p[^>]*>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<ul[^>]*>/gi, "\n").replace(/<\/ul>/gi, "\n").replace(/<ol[^>]*>/gi, "\n").replace(/<\/ol>/gi, "\n").replace(/<li[^>]*>/gi, "\u2022 ").replace(/<\/li>/gi, "\n").replace(/<pre[^>]*><code[^>]*>/gi, "\n```\n").replace(/<\/code><\/pre>/gi, "\n```\n").replace(/<code[^>]*>/gi, "`").replace(/<\/code>/gi, "`").replace(/<a[^>]*href="([^"]*)"[^>]*>([^<]*)<\/a>/gi, "$2 ($1)").replace(/<strong[^>]*>/gi, "**").replace(/<\/strong>/gi, "**").replace(/<em[^>]*>/gi, "_").replace(/<\/em>/gi, "_").replace(/<[^>]+>/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ").replace(/\n{3,}/g, "\n\n").trim();
|
|
322
|
+
if (extractSection) {
|
|
323
|
+
const sectionLower = extractSection.toLowerCase();
|
|
324
|
+
const lines = content.split("\n");
|
|
325
|
+
const result = [];
|
|
326
|
+
let inSection = false;
|
|
327
|
+
let sectionLevel = 0;
|
|
328
|
+
for (const line of lines) {
|
|
329
|
+
const headerMatch = line.match(/^(#{1,4})\s+(.+)$/);
|
|
330
|
+
if (headerMatch) {
|
|
331
|
+
const level = headerMatch[1].length;
|
|
332
|
+
const headerText = headerMatch[2].toLowerCase();
|
|
333
|
+
if (headerText.includes(sectionLower)) {
|
|
334
|
+
inSection = true;
|
|
335
|
+
sectionLevel = level;
|
|
336
|
+
result.push(line);
|
|
337
|
+
} else if (inSection && level <= sectionLevel) {
|
|
338
|
+
break;
|
|
339
|
+
} else if (inSection) {
|
|
340
|
+
result.push(line);
|
|
341
|
+
}
|
|
342
|
+
} else if (inSection) {
|
|
343
|
+
result.push(line);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (result.length > 0) {
|
|
347
|
+
content = result.join("\n").trim();
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return { title, content, headings, lastUpdated };
|
|
351
|
+
}
|
|
352
|
+
async function fetchDocs(input) {
|
|
353
|
+
const { path: path2, extractSection } = input;
|
|
354
|
+
let normalizedPath = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
355
|
+
normalizedPath = normalizedPath.replace(/\/$/, "");
|
|
356
|
+
if (/[<>"\s]/.test(normalizedPath)) {
|
|
357
|
+
return {
|
|
358
|
+
error: "Invalid path",
|
|
359
|
+
details: ["Path contains invalid characters"],
|
|
360
|
+
suggestion: `Use a clean path like '/develop/faq' or '/getting-started/installation'`
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
const url = `${DOCS_BASE_URL}${normalizedPath}`;
|
|
364
|
+
logger.debug("Fetching live documentation", { url, extractSection });
|
|
365
|
+
try {
|
|
366
|
+
const controller = new AbortController();
|
|
367
|
+
const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT);
|
|
368
|
+
const response = await fetch(url, {
|
|
369
|
+
signal: controller.signal,
|
|
370
|
+
headers: {
|
|
371
|
+
"User-Agent": "midnight-mcp/1.0 (Documentation Fetcher)",
|
|
372
|
+
Accept: "text/html"
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
clearTimeout(timeoutId);
|
|
376
|
+
if (!response.ok) {
|
|
377
|
+
if (response.status === 404) {
|
|
378
|
+
return {
|
|
379
|
+
error: "Page not found",
|
|
380
|
+
path: normalizedPath,
|
|
381
|
+
suggestion: `Try one of these known paths: ${KNOWN_DOC_PATHS.slice(0, 5).join(", ")}`,
|
|
382
|
+
knownPaths: KNOWN_DOC_PATHS
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
error: `Failed to fetch documentation: ${response.status} ${response.statusText}`,
|
|
387
|
+
path: normalizedPath,
|
|
388
|
+
suggestion: "Try again later or check if the URL is correct"
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
const html = await response.text();
|
|
392
|
+
if (!html.includes("<article") && !html.includes("<main")) {
|
|
393
|
+
return {
|
|
394
|
+
error: "Page returned but content not found",
|
|
395
|
+
path: normalizedPath,
|
|
396
|
+
suggestion: "The page may not have main content. Try a different path."
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
const { title, content, headings, lastUpdated } = extractContentFromHtml(
|
|
400
|
+
html,
|
|
401
|
+
extractSection
|
|
402
|
+
);
|
|
403
|
+
const MAX_CONTENT_LENGTH = 15e3;
|
|
404
|
+
const truncated = content.length > MAX_CONTENT_LENGTH;
|
|
405
|
+
const finalContent = truncated ? content.slice(0, MAX_CONTENT_LENGTH) + "\n\n[Content truncated...]" : content;
|
|
406
|
+
return {
|
|
407
|
+
title,
|
|
408
|
+
path: normalizedPath,
|
|
409
|
+
url,
|
|
410
|
+
content: finalContent,
|
|
411
|
+
headings: headings.length > 0 ? headings : void 0,
|
|
412
|
+
lastUpdated,
|
|
413
|
+
truncated,
|
|
414
|
+
contentLength: content.length,
|
|
415
|
+
note: extractSection ? `Extracted section matching: "${extractSection}"` : "Full page content"
|
|
416
|
+
};
|
|
417
|
+
} catch (error) {
|
|
418
|
+
if (error instanceof Error) {
|
|
419
|
+
if (error.name === "AbortError") {
|
|
420
|
+
return {
|
|
421
|
+
error: "Request timed out",
|
|
422
|
+
path: normalizedPath,
|
|
423
|
+
suggestion: "The documentation site may be slow. Try again or use midnight-search-docs for cached content."
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
error: `Failed to fetch: ${error.message}`,
|
|
428
|
+
path: normalizedPath,
|
|
429
|
+
suggestion: "Check your network connection or try midnight-search-docs for cached content."
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
return {
|
|
433
|
+
error: "Unknown error fetching documentation",
|
|
434
|
+
path: normalizedPath
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
}
|
|
268
438
|
|
|
269
439
|
// src/tools/search/tools.ts
|
|
270
440
|
var searchResultSchema = {
|
|
@@ -429,6 +599,80 @@ USAGE GUIDANCE:
|
|
|
429
599
|
title: "Search Documentation"
|
|
430
600
|
},
|
|
431
601
|
handler: searchDocs
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
name: "midnight-fetch-docs",
|
|
605
|
+
description: `\u{1F310} LIVE FETCH: Retrieve latest documentation directly from docs.midnight.network (SSG-enabled).
|
|
606
|
+
|
|
607
|
+
Unlike midnight-search-docs which uses pre-indexed content, this tool fetches LIVE documentation pages in real-time. Use when you need:
|
|
608
|
+
\u2022 The absolute latest content (just updated docs)
|
|
609
|
+
\u2022 A specific page you know the path to
|
|
610
|
+
\u2022 Full page content rather than search snippets
|
|
611
|
+
|
|
612
|
+
COMMON PATHS:
|
|
613
|
+
\u2022 /develop/faq - Frequently asked questions
|
|
614
|
+
\u2022 /getting-started/installation - Installation guide
|
|
615
|
+
\u2022 /getting-started/create-mn-app - Create an MN app
|
|
616
|
+
\u2022 /compact - Compact language reference
|
|
617
|
+
\u2022 /develop/tutorial/building - Build guide
|
|
618
|
+
\u2022 /develop/reference/midnight-api - API documentation
|
|
619
|
+
\u2022 /learn/what-is-midnight - What is Midnight
|
|
620
|
+
\u2022 /blog - Dev diaries
|
|
621
|
+
|
|
622
|
+
USAGE GUIDANCE:
|
|
623
|
+
\u2022 Use extractSection to get only a specific heading (e.g., "Developer questions")
|
|
624
|
+
\u2022 Prefer midnight-search-docs for discovery, use this for known pages
|
|
625
|
+
\u2022 Content is truncated at 15KB for token efficiency`,
|
|
626
|
+
inputSchema: {
|
|
627
|
+
type: "object",
|
|
628
|
+
properties: {
|
|
629
|
+
path: {
|
|
630
|
+
type: "string",
|
|
631
|
+
description: "Documentation page path (e.g., '/develop/faq', '/getting-started/installation')"
|
|
632
|
+
},
|
|
633
|
+
extractSection: {
|
|
634
|
+
type: "string",
|
|
635
|
+
description: "Optional: Extract only a specific section by heading text"
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
required: ["path"]
|
|
639
|
+
},
|
|
640
|
+
outputSchema: {
|
|
641
|
+
type: "object",
|
|
642
|
+
properties: {
|
|
643
|
+
title: { type: "string", description: "Page title" },
|
|
644
|
+
path: { type: "string", description: "Normalized path" },
|
|
645
|
+
url: { type: "string", description: "Full URL" },
|
|
646
|
+
content: { type: "string", description: "Extracted page content" },
|
|
647
|
+
headings: {
|
|
648
|
+
type: "array",
|
|
649
|
+
description: "Page headings/table of contents",
|
|
650
|
+
items: {
|
|
651
|
+
type: "object",
|
|
652
|
+
properties: {
|
|
653
|
+
level: { type: "number" },
|
|
654
|
+
text: { type: "string" },
|
|
655
|
+
id: { type: "string" }
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
lastUpdated: { type: "string", description: "Last update timestamp" },
|
|
660
|
+
truncated: {
|
|
661
|
+
type: "boolean",
|
|
662
|
+
description: "Whether content was truncated"
|
|
663
|
+
}
|
|
664
|
+
},
|
|
665
|
+
required: ["title", "path", "content"],
|
|
666
|
+
description: "Live documentation page content"
|
|
667
|
+
},
|
|
668
|
+
annotations: {
|
|
669
|
+
readOnlyHint: true,
|
|
670
|
+
openWorldHint: true,
|
|
671
|
+
// Fetches from external URL
|
|
672
|
+
title: "\u{1F310} Fetch Live Docs",
|
|
673
|
+
category: "search"
|
|
674
|
+
},
|
|
675
|
+
handler: fetchDocs
|
|
432
676
|
}
|
|
433
677
|
];
|
|
434
678
|
|
|
@@ -8483,6 +8727,20 @@ var INTENT_TO_TOOL = [
|
|
|
8483
8727
|
tool: "midnight-search-docs",
|
|
8484
8728
|
reason: "Search official Midnight documentation"
|
|
8485
8729
|
},
|
|
8730
|
+
{
|
|
8731
|
+
patterns: [
|
|
8732
|
+
"fetch docs",
|
|
8733
|
+
"get docs",
|
|
8734
|
+
"latest docs",
|
|
8735
|
+
"live docs",
|
|
8736
|
+
"docs page",
|
|
8737
|
+
"faq",
|
|
8738
|
+
"installation guide",
|
|
8739
|
+
"getting started page"
|
|
8740
|
+
],
|
|
8741
|
+
tool: "midnight-fetch-docs",
|
|
8742
|
+
reason: "Fetch live documentation directly from docs.midnight.network"
|
|
8743
|
+
},
|
|
8486
8744
|
// Code Generation
|
|
8487
8745
|
{
|
|
8488
8746
|
patterns: [
|
|
@@ -8918,7 +9176,7 @@ var suggestToolOutputSchema = {
|
|
|
8918
9176
|
var metaTools = [
|
|
8919
9177
|
{
|
|
8920
9178
|
name: "midnight-list-tool-categories",
|
|
8921
|
-
description: "\u{1F4CB} DISCOVERY TOOL: List available tool categories for progressive exploration. Use this FIRST to understand what capabilities are available, then drill into specific categories with midnight-list-category-tools. Reduces cognitive load by organizing
|
|
9179
|
+
description: "\u{1F4CB} DISCOVERY TOOL: List available tool categories for progressive exploration. Use this FIRST to understand what capabilities are available, then drill into specific categories with midnight-list-category-tools. Reduces cognitive load by organizing 28 tools into 7 logical groups.",
|
|
8922
9180
|
inputSchema: {
|
|
8923
9181
|
type: "object",
|
|
8924
9182
|
properties: {
|
|
@@ -9034,4 +9292,4 @@ export {
|
|
|
9034
9292
|
startServer,
|
|
9035
9293
|
startHttpServer
|
|
9036
9294
|
};
|
|
9037
|
-
//# sourceMappingURL=chunk-
|
|
9295
|
+
//# sourceMappingURL=chunk-E5HAMXS3.js.map
|
package/dist/index.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
promptDefinitions,
|
|
10
10
|
startHttpServer,
|
|
11
11
|
startServer
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-E5HAMXS3.js";
|
|
13
13
|
import {
|
|
14
14
|
logger
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-6BPO5SRQ.js";
|
|
16
16
|
export {
|
|
17
17
|
allResources,
|
|
18
18
|
allTools,
|
package/package.json
CHANGED