nodebench-mcp 2.15.0 → 2.17.0
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/dist/__tests__/architectComplex.test.d.ts +1 -0
- package/dist/__tests__/architectComplex.test.js +375 -0
- package/dist/__tests__/architectComplex.test.js.map +1 -0
- package/dist/__tests__/architectSmoke.test.d.ts +1 -0
- package/dist/__tests__/architectSmoke.test.js +92 -0
- package/dist/__tests__/architectSmoke.test.js.map +1 -0
- package/dist/__tests__/evalHarness.test.js +6 -1
- package/dist/__tests__/evalHarness.test.js.map +1 -1
- package/dist/__tests__/gaiaCapabilityEval.test.js +229 -12
- package/dist/__tests__/gaiaCapabilityEval.test.js.map +1 -1
- package/dist/__tests__/gaiaCapabilityMediaEval.test.js +194 -109
- package/dist/__tests__/gaiaCapabilityMediaEval.test.js.map +1 -1
- package/dist/__tests__/presetRealWorldBench.test.js +2 -2
- package/dist/__tests__/presetRealWorldBench.test.js.map +1 -1
- package/dist/__tests__/tools.test.js +10 -4
- package/dist/__tests__/tools.test.js.map +1 -1
- package/dist/__tests__/toolsetGatingEval.test.js +3 -3
- package/dist/__tests__/toolsetGatingEval.test.js.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/tools/architectTools.d.ts +15 -0
- package/dist/tools/architectTools.js +304 -0
- package/dist/tools/architectTools.js.map +1 -0
- package/dist/tools/emailTools.d.ts +15 -0
- package/dist/tools/emailTools.js +664 -0
- package/dist/tools/emailTools.js.map +1 -0
- package/dist/tools/metaTools.js +660 -0
- package/dist/tools/metaTools.js.map +1 -1
- package/dist/tools/progressiveDiscoveryTools.js +2 -2
- package/dist/tools/progressiveDiscoveryTools.js.map +1 -1
- package/dist/tools/rssTools.d.ts +8 -0
- package/dist/tools/rssTools.js +833 -0
- package/dist/tools/rssTools.js.map +1 -0
- package/dist/tools/toolRegistry.js +171 -0
- package/dist/tools/toolRegistry.js.map +1 -1
- package/package.json +10 -3
package/dist/tools/metaTools.js
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
* findTools helps agents discover what's available.
|
|
4
4
|
* getMethodology teaches agents the development process.
|
|
5
5
|
*/
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
const _require = createRequire(import.meta.url);
|
|
8
|
+
function _isInstalled(pkg) {
|
|
9
|
+
try {
|
|
10
|
+
_require.resolve(pkg);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
6
17
|
const METHODOLOGY_CONTENT = {
|
|
7
18
|
verification: {
|
|
8
19
|
title: "6-Phase Iterative Deep-Dive Verification Process",
|
|
@@ -1585,6 +1596,655 @@ export function createMetaTools(allTools) {
|
|
|
1585
1596
|
return content;
|
|
1586
1597
|
},
|
|
1587
1598
|
},
|
|
1599
|
+
{
|
|
1600
|
+
name: "check_mcp_setup",
|
|
1601
|
+
description: "Comprehensive diagnostic wizard for the entire NodeBench MCP. Checks all env vars, API keys, optional npm packages, and external services across every domain. Returns a full readiness report with per-domain status and step-by-step setup instructions for anything missing. Run this FIRST to see what capabilities are available and what needs configuration.",
|
|
1602
|
+
inputSchema: {
|
|
1603
|
+
type: "object",
|
|
1604
|
+
properties: {
|
|
1605
|
+
domains: {
|
|
1606
|
+
type: "array",
|
|
1607
|
+
items: { type: "string" },
|
|
1608
|
+
description: "Specific domains to check (default: all). Options: web, vision, github, llm, embedding, email, flicker_detection, figma_flow, ui_capture, local_file, gaia_solvers",
|
|
1609
|
+
},
|
|
1610
|
+
test_connections: {
|
|
1611
|
+
type: "boolean",
|
|
1612
|
+
description: "Test reachability of Python servers (flicker on :8006, figma on :8007) and email SMTP/IMAP. Default: false",
|
|
1613
|
+
},
|
|
1614
|
+
generate_config: {
|
|
1615
|
+
type: "boolean",
|
|
1616
|
+
description: "Generate a complete MCP config snippet with all needed env vars (default: true)",
|
|
1617
|
+
},
|
|
1618
|
+
generate_setup: {
|
|
1619
|
+
type: "boolean",
|
|
1620
|
+
description: "Generate complete setup files that an agent can write to disk to self-enable every capability: .env.nodebench (env template), setup-nodebench.sh (bash), setup-nodebench.ps1 (powershell), docker-compose.nodebench.yml (Python servers). Default: false",
|
|
1621
|
+
},
|
|
1622
|
+
},
|
|
1623
|
+
required: [],
|
|
1624
|
+
},
|
|
1625
|
+
handler: async (args) => {
|
|
1626
|
+
const testConnections = args.test_connections === true;
|
|
1627
|
+
const generateConfig = args.generate_config !== false;
|
|
1628
|
+
const generateSetup = args.generate_setup === true;
|
|
1629
|
+
const targetDomains = args.domains;
|
|
1630
|
+
const reports = [];
|
|
1631
|
+
const envCheck = (name, hint) => {
|
|
1632
|
+
const val = process.env[name];
|
|
1633
|
+
return {
|
|
1634
|
+
item: name,
|
|
1635
|
+
status: val ? "ok" : "missing",
|
|
1636
|
+
value: val ? `${val.substring(0, 4)}***` : undefined,
|
|
1637
|
+
hint: !val ? hint : undefined,
|
|
1638
|
+
};
|
|
1639
|
+
};
|
|
1640
|
+
const anyEnv = (...names) => names.some((n) => !!process.env[n]);
|
|
1641
|
+
const pkgCheck = (name) => ({
|
|
1642
|
+
item: `npm: ${name}`,
|
|
1643
|
+
status: _isInstalled(name) ? "installed" : "not_installed",
|
|
1644
|
+
hint: !_isInstalled(name) ? `npm install ${name}` : undefined,
|
|
1645
|
+
});
|
|
1646
|
+
const shouldCheck = (d) => !targetDomains || targetDomains.includes(d);
|
|
1647
|
+
// ── WEB ──
|
|
1648
|
+
if (shouldCheck("web")) {
|
|
1649
|
+
const checks = [
|
|
1650
|
+
envCheck("GEMINI_API_KEY", "Google AI key (free at https://aistudio.google.com/apikey)"),
|
|
1651
|
+
envCheck("OPENAI_API_KEY", "OpenAI key from https://platform.openai.com/api-keys"),
|
|
1652
|
+
envCheck("PERPLEXITY_API_KEY", "Perplexity key from https://www.perplexity.ai/settings/api"),
|
|
1653
|
+
];
|
|
1654
|
+
const ok = anyEnv("GEMINI_API_KEY", "OPENAI_API_KEY", "PERPLEXITY_API_KEY");
|
|
1655
|
+
reports.push({
|
|
1656
|
+
domain: "web",
|
|
1657
|
+
ready: ok,
|
|
1658
|
+
status: ok ? "ready" : "not_configured",
|
|
1659
|
+
checks,
|
|
1660
|
+
tools: ["web_search", "fetch_url"],
|
|
1661
|
+
...(!ok
|
|
1662
|
+
? {
|
|
1663
|
+
setupInstructions: [
|
|
1664
|
+
"web_search needs at least ONE LLM API key.",
|
|
1665
|
+
"Easiest: Get a free Gemini key at https://aistudio.google.com/apikey",
|
|
1666
|
+
"Set GEMINI_API_KEY=your-key in your MCP config env vars.",
|
|
1667
|
+
"fetch_url works without any API keys (raw HTTP fetch).",
|
|
1668
|
+
],
|
|
1669
|
+
}
|
|
1670
|
+
: {}),
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
// ── VISION ──
|
|
1674
|
+
if (shouldCheck("vision")) {
|
|
1675
|
+
const pw = _isInstalled("playwright");
|
|
1676
|
+
const checks = [
|
|
1677
|
+
envCheck("GEMINI_API_KEY", "Needed for LLM-based image analysis"),
|
|
1678
|
+
envCheck("OPENAI_API_KEY", "Alternative: OpenAI vision models"),
|
|
1679
|
+
pkgCheck("playwright"),
|
|
1680
|
+
];
|
|
1681
|
+
const hasLlm = anyEnv("GEMINI_API_KEY", "OPENAI_API_KEY");
|
|
1682
|
+
reports.push({
|
|
1683
|
+
domain: "vision",
|
|
1684
|
+
ready: hasLlm,
|
|
1685
|
+
status: hasLlm ? (pw ? "ready" : "partial") : "not_configured",
|
|
1686
|
+
checks,
|
|
1687
|
+
tools: ["discover_vision_env", "analyze_screenshot", "manipulate_screenshot", "diff_screenshots"],
|
|
1688
|
+
...(!hasLlm
|
|
1689
|
+
? {
|
|
1690
|
+
setupInstructions: [
|
|
1691
|
+
"Vision tools need an LLM API key for image analysis.",
|
|
1692
|
+
"Set GEMINI_API_KEY or OPENAI_API_KEY.",
|
|
1693
|
+
"Optional: npm install playwright && npx playwright install chromium",
|
|
1694
|
+
],
|
|
1695
|
+
}
|
|
1696
|
+
: !pw
|
|
1697
|
+
? {
|
|
1698
|
+
setupInstructions: [
|
|
1699
|
+
"Vision LLM analysis is ready.",
|
|
1700
|
+
"Optional: npm install playwright && npx playwright install chromium (for browser screenshots)",
|
|
1701
|
+
],
|
|
1702
|
+
}
|
|
1703
|
+
: {}),
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
// ── GITHUB ──
|
|
1707
|
+
if (shouldCheck("github")) {
|
|
1708
|
+
const checks = [envCheck("GITHUB_TOKEN", "Fine-grained token from https://github.com/settings/tokens")];
|
|
1709
|
+
const ok = !!process.env.GITHUB_TOKEN;
|
|
1710
|
+
reports.push({
|
|
1711
|
+
domain: "github",
|
|
1712
|
+
ready: ok,
|
|
1713
|
+
status: ok ? "ready" : "not_configured",
|
|
1714
|
+
checks,
|
|
1715
|
+
tools: ["search_github", "analyze_repo", "monitor_repo"],
|
|
1716
|
+
...(!ok
|
|
1717
|
+
? {
|
|
1718
|
+
setupInstructions: [
|
|
1719
|
+
"1. Go to https://github.com/settings/tokens",
|
|
1720
|
+
"2. Generate fine-grained token with: Contents (read), Metadata (read)",
|
|
1721
|
+
"3. Set GITHUB_TOKEN=ghp_your-token",
|
|
1722
|
+
],
|
|
1723
|
+
}
|
|
1724
|
+
: {}),
|
|
1725
|
+
});
|
|
1726
|
+
}
|
|
1727
|
+
// ── LLM ──
|
|
1728
|
+
if (shouldCheck("llm")) {
|
|
1729
|
+
const checks = [
|
|
1730
|
+
envCheck("ANTHROPIC_API_KEY", "From https://console.anthropic.com/settings/keys"),
|
|
1731
|
+
envCheck("OPENAI_API_KEY", "OpenAI key"),
|
|
1732
|
+
envCheck("GEMINI_API_KEY", "Google AI key (free tier)"),
|
|
1733
|
+
];
|
|
1734
|
+
const ok = anyEnv("ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GEMINI_API_KEY");
|
|
1735
|
+
reports.push({
|
|
1736
|
+
domain: "llm",
|
|
1737
|
+
ready: ok,
|
|
1738
|
+
status: ok ? "ready" : "not_configured",
|
|
1739
|
+
checks,
|
|
1740
|
+
tools: ["call_llm", "extract_structured_data", "benchmark_models"],
|
|
1741
|
+
...(!ok
|
|
1742
|
+
? {
|
|
1743
|
+
setupInstructions: [
|
|
1744
|
+
"call_llm needs at least ONE LLM API key.",
|
|
1745
|
+
"ANTHROPIC_API_KEY (Claude), OPENAI_API_KEY (GPT), or GEMINI_API_KEY (Gemini, free).",
|
|
1746
|
+
"Easiest: Get a free Gemini key at https://aistudio.google.com/apikey",
|
|
1747
|
+
],
|
|
1748
|
+
}
|
|
1749
|
+
: {}),
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
// ── EMBEDDING ──
|
|
1753
|
+
if (shouldCheck("embedding")) {
|
|
1754
|
+
const hasHf = _isInstalled("@huggingface/transformers");
|
|
1755
|
+
const checks = [
|
|
1756
|
+
pkgCheck("@huggingface/transformers"),
|
|
1757
|
+
envCheck("GEMINI_API_KEY", "Fallback: Google text-embedding-004 (free)"),
|
|
1758
|
+
envCheck("OPENAI_API_KEY", "Fallback: OpenAI text-embedding-3-small"),
|
|
1759
|
+
];
|
|
1760
|
+
const ok = hasHf || anyEnv("GEMINI_API_KEY", "OPENAI_API_KEY");
|
|
1761
|
+
reports.push({
|
|
1762
|
+
domain: "embedding",
|
|
1763
|
+
ready: ok,
|
|
1764
|
+
status: ok ? "ready" : "not_configured",
|
|
1765
|
+
checks,
|
|
1766
|
+
tools: ["discover_tools (semantic mode)"],
|
|
1767
|
+
...(!ok
|
|
1768
|
+
? {
|
|
1769
|
+
setupInstructions: [
|
|
1770
|
+
"Embedding search enhances discover_tools with semantic understanding.",
|
|
1771
|
+
"Option 1 (recommended, free, local): npm install @huggingface/transformers",
|
|
1772
|
+
" Uses Xenova/all-MiniLM-L6-v2 (23MB INT8, no API key needed)",
|
|
1773
|
+
"Option 2: Set GEMINI_API_KEY (free Google text-embedding-004)",
|
|
1774
|
+
"Option 3: Set OPENAI_API_KEY (OpenAI text-embedding-3-small, paid)",
|
|
1775
|
+
"Without embedding, discover_tools still works with keyword/fuzzy search.",
|
|
1776
|
+
],
|
|
1777
|
+
}
|
|
1778
|
+
: {}),
|
|
1779
|
+
});
|
|
1780
|
+
}
|
|
1781
|
+
// ── EMAIL ──
|
|
1782
|
+
if (shouldCheck("email")) {
|
|
1783
|
+
const checks = [
|
|
1784
|
+
envCheck("EMAIL_USER", "Your email address (e.g., agent@gmail.com)"),
|
|
1785
|
+
envCheck("EMAIL_PASS", "App password (NOT regular password)"),
|
|
1786
|
+
];
|
|
1787
|
+
const ok = !!process.env.EMAIL_USER && !!process.env.EMAIL_PASS;
|
|
1788
|
+
reports.push({
|
|
1789
|
+
domain: "email",
|
|
1790
|
+
ready: ok,
|
|
1791
|
+
status: ok ? "ready" : "not_configured",
|
|
1792
|
+
checks,
|
|
1793
|
+
tools: ["send_email", "read_emails", "draft_email_reply", "check_email_setup"],
|
|
1794
|
+
...(!ok
|
|
1795
|
+
? {
|
|
1796
|
+
setupInstructions: [
|
|
1797
|
+
"For detailed per-provider setup, run check_email_setup instead.",
|
|
1798
|
+
"Quick start (Gmail):",
|
|
1799
|
+
"1. Enable 2FA at https://myaccount.google.com/security",
|
|
1800
|
+
"2. Create app password at https://myaccount.google.com/apppasswords",
|
|
1801
|
+
"3. Set EMAIL_USER=your.email@gmail.com",
|
|
1802
|
+
"4. Set EMAIL_PASS=your-16-char-app-password",
|
|
1803
|
+
],
|
|
1804
|
+
}
|
|
1805
|
+
: {}),
|
|
1806
|
+
});
|
|
1807
|
+
}
|
|
1808
|
+
// ── FLICKER DETECTION ──
|
|
1809
|
+
if (shouldCheck("flicker_detection")) {
|
|
1810
|
+
const checks = [
|
|
1811
|
+
{ item: "Python FastAPI server (port 8006)", status: "optional", hint: "docker compose up flicker_detection" },
|
|
1812
|
+
];
|
|
1813
|
+
let serverOk = false;
|
|
1814
|
+
if (testConnections) {
|
|
1815
|
+
try {
|
|
1816
|
+
const res = await fetch("http://localhost:8006/health", { signal: AbortSignal.timeout(3000) });
|
|
1817
|
+
serverOk = res.ok;
|
|
1818
|
+
checks[0] = { item: "Python FastAPI server (port 8006)", status: serverOk ? "ok" : "missing", hint: serverOk ? "Server running" : "Not reachable" };
|
|
1819
|
+
}
|
|
1820
|
+
catch {
|
|
1821
|
+
checks[0] = { item: "Python FastAPI server (port 8006)", status: "missing", hint: "Not reachable. Start with: docker compose up flicker_detection" };
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
reports.push({
|
|
1825
|
+
domain: "flicker_detection",
|
|
1826
|
+
ready: testConnections ? serverOk : true,
|
|
1827
|
+
status: testConnections ? (serverOk ? "ready" : "not_configured") : "partial",
|
|
1828
|
+
checks,
|
|
1829
|
+
tools: ["start_flicker_analysis", "get_flicker_status", "get_flicker_results", "compare_flicker_runs", "detect_flicker_frames"],
|
|
1830
|
+
setupInstructions: [
|
|
1831
|
+
"Flicker detection requires a Python FastAPI server:",
|
|
1832
|
+
"1. cd python-mcp-servers",
|
|
1833
|
+
"2. docker compose up flicker_detection",
|
|
1834
|
+
"3. Server starts on port 8006",
|
|
1835
|
+
"4. Requires ffmpeg installed on the server",
|
|
1836
|
+
"Run check_mcp_setup with test_connections=true to verify.",
|
|
1837
|
+
],
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
// ── FIGMA FLOW ──
|
|
1841
|
+
if (shouldCheck("figma_flow")) {
|
|
1842
|
+
const checks = [
|
|
1843
|
+
envCheck("FIGMA_ACCESS_TOKEN", "From https://www.figma.com/developers/api#access-tokens"),
|
|
1844
|
+
{ item: "Python FastAPI server (port 8007)", status: "optional", hint: "docker compose up figma_flow" },
|
|
1845
|
+
];
|
|
1846
|
+
let serverOk = false;
|
|
1847
|
+
if (testConnections) {
|
|
1848
|
+
try {
|
|
1849
|
+
const res = await fetch("http://localhost:8007/health", { signal: AbortSignal.timeout(3000) });
|
|
1850
|
+
serverOk = res.ok;
|
|
1851
|
+
checks[1] = { item: "Python FastAPI server (port 8007)", status: serverOk ? "ok" : "missing" };
|
|
1852
|
+
}
|
|
1853
|
+
catch {
|
|
1854
|
+
checks[1] = { item: "Python FastAPI server (port 8007)", status: "missing", hint: "Not reachable. Start with: docker compose up figma_flow" };
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
const hasToken = !!process.env.FIGMA_ACCESS_TOKEN;
|
|
1858
|
+
reports.push({
|
|
1859
|
+
domain: "figma_flow",
|
|
1860
|
+
ready: hasToken && (testConnections ? serverOk : true),
|
|
1861
|
+
status: hasToken ? (testConnections ? (serverOk ? "ready" : "partial") : "partial") : "not_configured",
|
|
1862
|
+
checks,
|
|
1863
|
+
tools: ["analyze_figma_flow", "get_figma_flow_status", "get_figma_flow_results", "compare_figma_flows"],
|
|
1864
|
+
...(!hasToken
|
|
1865
|
+
? {
|
|
1866
|
+
setupInstructions: [
|
|
1867
|
+
"1. Go to https://www.figma.com/developers/api#access-tokens",
|
|
1868
|
+
"2. Generate a personal access token",
|
|
1869
|
+
"3. Set FIGMA_ACCESS_TOKEN=your-token",
|
|
1870
|
+
"4. Start server: cd python-mcp-servers && docker compose up figma_flow (port 8007)",
|
|
1871
|
+
],
|
|
1872
|
+
}
|
|
1873
|
+
: {}),
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
// ── UI CAPTURE ──
|
|
1877
|
+
if (shouldCheck("ui_capture")) {
|
|
1878
|
+
const pw = _isInstalled("playwright");
|
|
1879
|
+
reports.push({
|
|
1880
|
+
domain: "ui_capture",
|
|
1881
|
+
ready: pw,
|
|
1882
|
+
status: pw ? "ready" : "not_configured",
|
|
1883
|
+
checks: [pkgCheck("playwright")],
|
|
1884
|
+
tools: ["capture_ui_screenshot", "capture_responsive_suite"],
|
|
1885
|
+
...(!pw
|
|
1886
|
+
? {
|
|
1887
|
+
setupInstructions: [
|
|
1888
|
+
"1. npm install playwright",
|
|
1889
|
+
"2. npx playwright install chromium",
|
|
1890
|
+
"Uses headless Chromium to screenshot URLs at multiple breakpoints.",
|
|
1891
|
+
],
|
|
1892
|
+
}
|
|
1893
|
+
: {}),
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
// ── LOCAL FILE ──
|
|
1897
|
+
if (shouldCheck("local_file")) {
|
|
1898
|
+
const deps = [
|
|
1899
|
+
{ name: "cheerio", use: "HTML parsing" },
|
|
1900
|
+
{ name: "pdf-parse", use: "PDF extraction" },
|
|
1901
|
+
{ name: "xlsx", use: "Excel/CSV parsing" },
|
|
1902
|
+
{ name: "sharp", use: "Image processing" },
|
|
1903
|
+
{ name: "tesseract.js", use: "OCR (text from images)" },
|
|
1904
|
+
{ name: "yauzl", use: "ZIP extraction" },
|
|
1905
|
+
{ name: "papaparse", use: "CSV parsing" },
|
|
1906
|
+
];
|
|
1907
|
+
const checks = deps.map((d) => ({
|
|
1908
|
+
...pkgCheck(d.name),
|
|
1909
|
+
hint: _isInstalled(d.name) ? `Used for: ${d.use}` : `npm install ${d.name} (for: ${d.use})`,
|
|
1910
|
+
}));
|
|
1911
|
+
const count = deps.filter((d) => _isInstalled(d.name)).length;
|
|
1912
|
+
reports.push({
|
|
1913
|
+
domain: "local_file",
|
|
1914
|
+
ready: true,
|
|
1915
|
+
status: count === deps.length ? "ready" : count > 0 ? "partial" : "not_configured",
|
|
1916
|
+
checks,
|
|
1917
|
+
tools: ["parse_html_file", "parse_pdf_file", "parse_excel_file", "parse_csv_file", "ocr_image", "extract_zip", "read_local_file"],
|
|
1918
|
+
setupInstructions: [
|
|
1919
|
+
"Core file tools (read, stat, list) always work. Optional deps extend capabilities:",
|
|
1920
|
+
...deps.filter((d) => !_isInstalled(d.name)).map((d) => ` npm install ${d.name} → ${d.use}`),
|
|
1921
|
+
deps.every((d) => _isInstalled(d.name))
|
|
1922
|
+
? "All optional file deps installed!"
|
|
1923
|
+
: "Install all: npm install cheerio pdf-parse xlsx sharp tesseract.js yauzl papaparse",
|
|
1924
|
+
],
|
|
1925
|
+
});
|
|
1926
|
+
}
|
|
1927
|
+
// ── GAIA SOLVERS ──
|
|
1928
|
+
if (shouldCheck("gaia_solvers")) {
|
|
1929
|
+
const checks = [
|
|
1930
|
+
envCheck("HF_TOKEN", "Hugging Face token from https://huggingface.co/settings/tokens"),
|
|
1931
|
+
pkgCheck("sharp"),
|
|
1932
|
+
pkgCheck("tesseract.js"),
|
|
1933
|
+
];
|
|
1934
|
+
const hasToken = !!process.env.HF_TOKEN;
|
|
1935
|
+
const hasDeps = _isInstalled("sharp") && _isInstalled("tesseract.js");
|
|
1936
|
+
reports.push({
|
|
1937
|
+
domain: "gaia_solvers",
|
|
1938
|
+
ready: hasToken && hasDeps,
|
|
1939
|
+
status: hasToken && hasDeps ? "ready" : hasToken || hasDeps ? "partial" : "not_configured",
|
|
1940
|
+
checks,
|
|
1941
|
+
tools: ["solve_red_green_deviation_average_from_image", "solve_green_polygon_area_from_image", "read_image_ocr_text", "count_shapes_in_image", "solve_chessboard_fen", "measure_angles_in_image"],
|
|
1942
|
+
...(!hasToken || !hasDeps
|
|
1943
|
+
? {
|
|
1944
|
+
setupInstructions: [
|
|
1945
|
+
...(!hasToken ? ["1. Get token at https://huggingface.co/settings/tokens", "2. Set HF_TOKEN=hf_your-token"] : []),
|
|
1946
|
+
...(!hasDeps ? ["3. npm install sharp tesseract.js"] : []),
|
|
1947
|
+
],
|
|
1948
|
+
}
|
|
1949
|
+
: {}),
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
// ── Summary ──
|
|
1953
|
+
const readyCount = reports.filter((r) => r.ready).length;
|
|
1954
|
+
const partialCount = reports.filter((r) => r.status === "partial").length;
|
|
1955
|
+
const missingCount = reports.filter((r) => r.status === "not_configured").length;
|
|
1956
|
+
// ── MCP config snippet ──
|
|
1957
|
+
let configSnippet;
|
|
1958
|
+
if (generateConfig) {
|
|
1959
|
+
const envVars = {};
|
|
1960
|
+
for (const report of reports) {
|
|
1961
|
+
for (const check of report.checks) {
|
|
1962
|
+
if (check.status === "missing" && !check.item.startsWith("npm:") && !check.item.includes("server")) {
|
|
1963
|
+
envVars[check.item] = check.hint || "your-value-here";
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
if (Object.keys(envVars).length > 0) {
|
|
1968
|
+
configSnippet = JSON.stringify({
|
|
1969
|
+
mcpServers: {
|
|
1970
|
+
nodebench: {
|
|
1971
|
+
command: "npx",
|
|
1972
|
+
args: ["-y", "nodebench-mcp"],
|
|
1973
|
+
env: Object.fromEntries(Object.entries(envVars).map(([k, v]) => [k, process.env[k] || v])),
|
|
1974
|
+
},
|
|
1975
|
+
},
|
|
1976
|
+
}, null, 2);
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
// ── Setup file generation ──
|
|
1980
|
+
let setupFiles;
|
|
1981
|
+
if (generateSetup) {
|
|
1982
|
+
// .env.nodebench — complete env var template
|
|
1983
|
+
const envTemplate = [
|
|
1984
|
+
"# ═══════════════════════════════════════════════════════════",
|
|
1985
|
+
"# NodeBench MCP — Environment Variables",
|
|
1986
|
+
"# Generated by check_mcp_setup. Fill in values and rename to .env",
|
|
1987
|
+
"# ═══════════════════════════════════════════════════════════",
|
|
1988
|
+
"",
|
|
1989
|
+
"# ── LLM / Web Search (at least ONE required) ──",
|
|
1990
|
+
`GEMINI_API_KEY=${process.env.GEMINI_API_KEY || ""} # Free at https://aistudio.google.com/apikey`,
|
|
1991
|
+
`OPENAI_API_KEY=${process.env.OPENAI_API_KEY || ""} # https://platform.openai.com/api-keys`,
|
|
1992
|
+
`ANTHROPIC_API_KEY=${process.env.ANTHROPIC_API_KEY || ""} # https://console.anthropic.com/settings/keys`,
|
|
1993
|
+
`PERPLEXITY_API_KEY=${process.env.PERPLEXITY_API_KEY || ""} # https://www.perplexity.ai/settings/api`,
|
|
1994
|
+
"",
|
|
1995
|
+
"# ── GitHub ──",
|
|
1996
|
+
`GITHUB_TOKEN=${process.env.GITHUB_TOKEN || ""} # Fine-grained: https://github.com/settings/tokens`,
|
|
1997
|
+
"",
|
|
1998
|
+
"# ── Email (SMTP/IMAP) ──",
|
|
1999
|
+
`EMAIL_USER=${process.env.EMAIL_USER || ""} # e.g. agent@gmail.com`,
|
|
2000
|
+
`EMAIL_PASS=${process.env.EMAIL_PASS || ""} # App password (NOT regular password)`,
|
|
2001
|
+
`EMAIL_SMTP_HOST=${process.env.EMAIL_SMTP_HOST || "smtp.gmail.com"} # Default: smtp.gmail.com`,
|
|
2002
|
+
`EMAIL_SMTP_PORT=${process.env.EMAIL_SMTP_PORT || "465"} # Default: 465 (TLS)`,
|
|
2003
|
+
`EMAIL_IMAP_HOST=${process.env.EMAIL_IMAP_HOST || "imap.gmail.com"} # Default: imap.gmail.com`,
|
|
2004
|
+
`EMAIL_IMAP_PORT=${process.env.EMAIL_IMAP_PORT || "993"} # Default: 993 (TLS)`,
|
|
2005
|
+
"",
|
|
2006
|
+
"# ── Figma ──",
|
|
2007
|
+
`FIGMA_ACCESS_TOKEN=${process.env.FIGMA_ACCESS_TOKEN || ""} # https://www.figma.com/developers/api#access-tokens`,
|
|
2008
|
+
"",
|
|
2009
|
+
"# ── Hugging Face (GAIA solvers + local embeddings) ──",
|
|
2010
|
+
`HF_TOKEN=${process.env.HF_TOKEN || ""} # https://huggingface.co/settings/tokens`,
|
|
2011
|
+
"",
|
|
2012
|
+
"# ── Python servers (flicker detection + figma flow) ──",
|
|
2013
|
+
"# These are started via docker compose, not env vars.",
|
|
2014
|
+
"# See docker-compose.nodebench.yml for configuration.",
|
|
2015
|
+
"",
|
|
2016
|
+
].join("\n");
|
|
2017
|
+
// setup-nodebench.sh — bash install script
|
|
2018
|
+
const bashScript = [
|
|
2019
|
+
"#!/usr/bin/env bash",
|
|
2020
|
+
"set -euo pipefail",
|
|
2021
|
+
"",
|
|
2022
|
+
"# ═══════════════════════════════════════════════════════════",
|
|
2023
|
+
"# NodeBench MCP — Setup Script (bash)",
|
|
2024
|
+
"# Generated by check_mcp_setup",
|
|
2025
|
+
"# ═══════════════════════════════════════════════════════════",
|
|
2026
|
+
"",
|
|
2027
|
+
'echo "=== NodeBench MCP Setup ==="',
|
|
2028
|
+
'echo ""',
|
|
2029
|
+
"",
|
|
2030
|
+
"# Step 1: Install required dependencies",
|
|
2031
|
+
'echo "→ Installing required npm packages..."',
|
|
2032
|
+
"npm install @modelcontextprotocol/sdk better-sqlite3 @toon-format/toon",
|
|
2033
|
+
"",
|
|
2034
|
+
"# Step 2: Install optional dependencies for extended capabilities",
|
|
2035
|
+
'echo "→ Installing optional dependencies..."',
|
|
2036
|
+
'echo " These unlock: HTML parsing, PDF extraction, Excel/CSV, OCR, images, ZIP, browser screenshots"',
|
|
2037
|
+
"npm install cheerio pdf-parse xlsx sharp tesseract.js yauzl papaparse || true",
|
|
2038
|
+
"",
|
|
2039
|
+
"# Step 3: Install embedding provider (local semantic search)",
|
|
2040
|
+
'echo "→ Installing local embedding model..."',
|
|
2041
|
+
'echo " Enables semantic search in discover_tools (23MB model, no API key needed)"',
|
|
2042
|
+
"npm install @huggingface/transformers || true",
|
|
2043
|
+
"",
|
|
2044
|
+
"# Step 4: Install Playwright for browser-based tools",
|
|
2045
|
+
'echo "→ Installing Playwright + Chromium..."',
|
|
2046
|
+
"npm install playwright || true",
|
|
2047
|
+
"npx playwright install chromium || true",
|
|
2048
|
+
"",
|
|
2049
|
+
"# Step 5: Install LLM SDKs",
|
|
2050
|
+
'echo "→ Installing LLM SDKs..."',
|
|
2051
|
+
"npm install @anthropic-ai/sdk @google/genai openai || true",
|
|
2052
|
+
"",
|
|
2053
|
+
"# Step 6: Set up Python servers (optional)",
|
|
2054
|
+
'echo ""',
|
|
2055
|
+
'echo "→ Python servers (flicker detection + figma flow):"',
|
|
2056
|
+
'echo " If you need these, run: docker compose -f docker-compose.nodebench.yml up -d"',
|
|
2057
|
+
"",
|
|
2058
|
+
"# Step 7: Environment variables",
|
|
2059
|
+
'echo ""',
|
|
2060
|
+
'echo "=== Setup Complete ==="',
|
|
2061
|
+
'echo ""',
|
|
2062
|
+
'echo "Next steps:"',
|
|
2063
|
+
'echo " 1. Copy .env.nodebench to .env and fill in your API keys"',
|
|
2064
|
+
'echo " 2. Add env vars to your MCP config (Claude Code / Cursor / etc)"',
|
|
2065
|
+
'echo " 3. Run: npx nodebench-mcp --preset full"',
|
|
2066
|
+
'echo " 4. Verify: call check_mcp_setup to see all domains"',
|
|
2067
|
+
"",
|
|
2068
|
+
].join("\n");
|
|
2069
|
+
// setup-nodebench.ps1 — PowerShell install script
|
|
2070
|
+
const psScript = [
|
|
2071
|
+
"# ═══════════════════════════════════════════════════════════",
|
|
2072
|
+
"# NodeBench MCP — Setup Script (PowerShell)",
|
|
2073
|
+
"# Generated by check_mcp_setup",
|
|
2074
|
+
"# ═══════════════════════════════════════════════════════════",
|
|
2075
|
+
"",
|
|
2076
|
+
'$ErrorActionPreference = "Continue"',
|
|
2077
|
+
"",
|
|
2078
|
+
'Write-Host "=== NodeBench MCP Setup ===" -ForegroundColor Cyan',
|
|
2079
|
+
'Write-Host ""',
|
|
2080
|
+
"",
|
|
2081
|
+
"# Step 1: Required dependencies",
|
|
2082
|
+
'Write-Host "-> Installing required npm packages..." -ForegroundColor Yellow',
|
|
2083
|
+
"npm install @modelcontextprotocol/sdk better-sqlite3 @toon-format/toon",
|
|
2084
|
+
"",
|
|
2085
|
+
"# Step 2: Optional dependencies",
|
|
2086
|
+
'Write-Host "-> Installing optional dependencies..." -ForegroundColor Yellow',
|
|
2087
|
+
"npm install cheerio pdf-parse xlsx sharp tesseract.js yauzl papaparse 2>$null",
|
|
2088
|
+
"",
|
|
2089
|
+
"# Step 3: Embedding provider",
|
|
2090
|
+
'Write-Host "-> Installing local embedding model..." -ForegroundColor Yellow',
|
|
2091
|
+
"npm install @huggingface/transformers 2>$null",
|
|
2092
|
+
"",
|
|
2093
|
+
"# Step 4: Playwright",
|
|
2094
|
+
'Write-Host "-> Installing Playwright + Chromium..." -ForegroundColor Yellow',
|
|
2095
|
+
"npm install playwright 2>$null",
|
|
2096
|
+
"npx playwright install chromium 2>$null",
|
|
2097
|
+
"",
|
|
2098
|
+
"# Step 5: LLM SDKs",
|
|
2099
|
+
'Write-Host "-> Installing LLM SDKs..." -ForegroundColor Yellow',
|
|
2100
|
+
"npm install @anthropic-ai/sdk @google/genai openai 2>$null",
|
|
2101
|
+
"",
|
|
2102
|
+
"# Step 6: Python servers",
|
|
2103
|
+
'Write-Host ""',
|
|
2104
|
+
'Write-Host "-> Python servers (flicker detection + figma flow):" -ForegroundColor Yellow',
|
|
2105
|
+
'Write-Host " If needed: docker compose -f docker-compose.nodebench.yml up -d"',
|
|
2106
|
+
"",
|
|
2107
|
+
'Write-Host ""',
|
|
2108
|
+
'Write-Host "=== Setup Complete ===" -ForegroundColor Green',
|
|
2109
|
+
'Write-Host ""',
|
|
2110
|
+
'Write-Host "Next steps:"',
|
|
2111
|
+
'Write-Host " 1. Copy .env.nodebench to .env and fill in your API keys"',
|
|
2112
|
+
'Write-Host " 2. Add env vars to your MCP config (Claude Code / Cursor / etc)"',
|
|
2113
|
+
'Write-Host " 3. Run: npx nodebench-mcp --preset full"',
|
|
2114
|
+
'Write-Host " 4. Verify: call check_mcp_setup to see all domains"',
|
|
2115
|
+
"",
|
|
2116
|
+
].join("\n");
|
|
2117
|
+
// docker-compose.nodebench.yml
|
|
2118
|
+
const dockerCompose = [
|
|
2119
|
+
"# ═══════════════════════════════════════════════════════════",
|
|
2120
|
+
"# NodeBench MCP — Docker Compose for Python Servers",
|
|
2121
|
+
"# Generated by check_mcp_setup",
|
|
2122
|
+
"# ═══════════════════════════════════════════════════════════",
|
|
2123
|
+
"# Usage: docker compose -f docker-compose.nodebench.yml up -d",
|
|
2124
|
+
"",
|
|
2125
|
+
"services:",
|
|
2126
|
+
" flicker_detection:",
|
|
2127
|
+
" build: ./python-mcp-servers/flicker_detection",
|
|
2128
|
+
" ports:",
|
|
2129
|
+
' - "8006:8006"',
|
|
2130
|
+
" volumes:",
|
|
2131
|
+
" - ./tmp/flicker:/app/tmp",
|
|
2132
|
+
" restart: unless-stopped",
|
|
2133
|
+
" healthcheck:",
|
|
2134
|
+
" test: curl -f http://localhost:8006/health || exit 1",
|
|
2135
|
+
" interval: 30s",
|
|
2136
|
+
" timeout: 5s",
|
|
2137
|
+
" retries: 3",
|
|
2138
|
+
"",
|
|
2139
|
+
" figma_flow:",
|
|
2140
|
+
" build: ./python-mcp-servers/figma_flow",
|
|
2141
|
+
" ports:",
|
|
2142
|
+
' - "8007:8007"',
|
|
2143
|
+
" environment:",
|
|
2144
|
+
" - FIGMA_ACCESS_TOKEN=${FIGMA_ACCESS_TOKEN:-}",
|
|
2145
|
+
" volumes:",
|
|
2146
|
+
" - ./tmp/figma:/app/tmp",
|
|
2147
|
+
" restart: unless-stopped",
|
|
2148
|
+
" healthcheck:",
|
|
2149
|
+
" test: curl -f http://localhost:8007/health || exit 1",
|
|
2150
|
+
" interval: 30s",
|
|
2151
|
+
" timeout: 5s",
|
|
2152
|
+
" retries: 3",
|
|
2153
|
+
"",
|
|
2154
|
+
].join("\n");
|
|
2155
|
+
// Full MCP config with ALL env vars
|
|
2156
|
+
const allEnvVars = {
|
|
2157
|
+
GEMINI_API_KEY: process.env.GEMINI_API_KEY || "your-gemini-api-key",
|
|
2158
|
+
OPENAI_API_KEY: process.env.OPENAI_API_KEY || "your-openai-api-key",
|
|
2159
|
+
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || "your-anthropic-api-key",
|
|
2160
|
+
PERPLEXITY_API_KEY: process.env.PERPLEXITY_API_KEY || "your-perplexity-api-key",
|
|
2161
|
+
GITHUB_TOKEN: process.env.GITHUB_TOKEN || "ghp_your-github-token",
|
|
2162
|
+
EMAIL_USER: process.env.EMAIL_USER || "your.email@gmail.com",
|
|
2163
|
+
EMAIL_PASS: process.env.EMAIL_PASS || "your-16-char-app-password",
|
|
2164
|
+
EMAIL_SMTP_HOST: process.env.EMAIL_SMTP_HOST || "smtp.gmail.com",
|
|
2165
|
+
EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || "465",
|
|
2166
|
+
EMAIL_IMAP_HOST: process.env.EMAIL_IMAP_HOST || "imap.gmail.com",
|
|
2167
|
+
EMAIL_IMAP_PORT: process.env.EMAIL_IMAP_PORT || "993",
|
|
2168
|
+
FIGMA_ACCESS_TOKEN: process.env.FIGMA_ACCESS_TOKEN || "your-figma-token",
|
|
2169
|
+
HF_TOKEN: process.env.HF_TOKEN || "hf_your-huggingface-token",
|
|
2170
|
+
};
|
|
2171
|
+
const fullMcpConfig = JSON.stringify({
|
|
2172
|
+
mcpServers: {
|
|
2173
|
+
nodebench: {
|
|
2174
|
+
command: "npx",
|
|
2175
|
+
args: ["-y", "nodebench-mcp", "--preset", "full"],
|
|
2176
|
+
env: allEnvVars,
|
|
2177
|
+
},
|
|
2178
|
+
},
|
|
2179
|
+
}, null, 2);
|
|
2180
|
+
setupFiles = {
|
|
2181
|
+
env: {
|
|
2182
|
+
filename: ".env.nodebench",
|
|
2183
|
+
content: envTemplate,
|
|
2184
|
+
description: "Environment variable template — copy to .env and fill in your API keys",
|
|
2185
|
+
},
|
|
2186
|
+
bash: {
|
|
2187
|
+
filename: "setup-nodebench.sh",
|
|
2188
|
+
content: bashScript,
|
|
2189
|
+
description: "Bash install script — chmod +x setup-nodebench.sh && ./setup-nodebench.sh",
|
|
2190
|
+
},
|
|
2191
|
+
powershell: {
|
|
2192
|
+
filename: "setup-nodebench.ps1",
|
|
2193
|
+
content: psScript,
|
|
2194
|
+
description: "PowerShell install script — .\\setup-nodebench.ps1",
|
|
2195
|
+
},
|
|
2196
|
+
docker: {
|
|
2197
|
+
filename: "docker-compose.nodebench.yml",
|
|
2198
|
+
content: dockerCompose,
|
|
2199
|
+
description: "Docker Compose for Python servers (flicker detection + figma flow)",
|
|
2200
|
+
},
|
|
2201
|
+
mcpConfig: {
|
|
2202
|
+
filename: "mcp-config.nodebench.json",
|
|
2203
|
+
content: fullMcpConfig,
|
|
2204
|
+
description: "Full MCP config with ALL env vars — paste into Claude Code / Cursor settings",
|
|
2205
|
+
},
|
|
2206
|
+
};
|
|
2207
|
+
}
|
|
2208
|
+
return {
|
|
2209
|
+
summary: {
|
|
2210
|
+
totalDomains: reports.length,
|
|
2211
|
+
ready: readyCount,
|
|
2212
|
+
partial: partialCount,
|
|
2213
|
+
notConfigured: missingCount,
|
|
2214
|
+
overallStatus: missingCount === 0
|
|
2215
|
+
? "fully_configured"
|
|
2216
|
+
: readyCount > 0
|
|
2217
|
+
? "partially_configured"
|
|
2218
|
+
: "needs_setup",
|
|
2219
|
+
},
|
|
2220
|
+
domains: reports,
|
|
2221
|
+
...(configSnippet ? { mcpConfigSnippet: configSnippet } : {}),
|
|
2222
|
+
...(setupFiles ? { setupFiles } : {}),
|
|
2223
|
+
nextSteps: readyCount === reports.length
|
|
2224
|
+
? [
|
|
2225
|
+
"All checked domains are configured! Start working.",
|
|
2226
|
+
"Run discover_tools to find the right tools for your task.",
|
|
2227
|
+
"Run getMethodology('overview') to see available methodologies.",
|
|
2228
|
+
]
|
|
2229
|
+
: generateSetup
|
|
2230
|
+
? [
|
|
2231
|
+
"Setup files generated! Write them to your project root:",
|
|
2232
|
+
" 1. Write .env.nodebench → fill in API keys → rename to .env",
|
|
2233
|
+
" 2. Run setup-nodebench.sh (bash) or setup-nodebench.ps1 (PowerShell) to install all deps",
|
|
2234
|
+
" 3. Optionally run docker-compose.nodebench.yml for Python servers",
|
|
2235
|
+
" 4. Copy mcp-config.nodebench.json content into your Claude Code / Cursor MCP settings",
|
|
2236
|
+
" 5. Re-run check_mcp_setup to verify everything is configured",
|
|
2237
|
+
]
|
|
2238
|
+
: [
|
|
2239
|
+
`${missingCount} domain(s) need configuration. See setupInstructions per domain.`,
|
|
2240
|
+
"Add env vars to your MCP config (see mcpConfigSnippet) or shell profile.",
|
|
2241
|
+
"Re-run check_mcp_setup to verify after configuration.",
|
|
2242
|
+
"Tip: Most capabilities work without ALL domains configured. Start with what you need.",
|
|
2243
|
+
"Tip: Run check_mcp_setup with generate_setup=true to get ready-to-write setup files.",
|
|
2244
|
+
],
|
|
2245
|
+
};
|
|
2246
|
+
},
|
|
2247
|
+
},
|
|
1588
2248
|
];
|
|
1589
2249
|
}
|
|
1590
2250
|
//# sourceMappingURL=metaTools.js.map
|