From 0209acdaae14f22d592f68798236a4ab58526470 Mon Sep 17 00:00:00 2001 From: Ajay Krishnan Date: Sat, 25 Jul 2026 08:49:44 -0700 Subject: [PATCH] Preserve abandoned smoke-script refactor WIP --- README.md | 1 - bin/context-kit | 57 ----------- docs/configuration.md | 6 +- docs/troubleshooting.md | 13 --- scripts/mcp-smoke-client.mjs | 188 ----------------------------------- scripts/release-check | 156 ----------------------------- scripts/smoke-docs.mjs | 53 ---------- scripts/smoke-repomix.mjs | 30 ------ scripts/smoke-web-search.mjs | 63 ------------ 9 files changed, 2 insertions(+), 565 deletions(-) delete mode 100644 scripts/mcp-smoke-client.mjs delete mode 100755 scripts/release-check delete mode 100644 scripts/smoke-docs.mjs delete mode 100644 scripts/smoke-repomix.mjs delete mode 100644 scripts/smoke-web-search.mjs diff --git a/README.md b/README.md index 5cdc6c3..9d68fcb 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,6 @@ bin/context-kit status bin/context-kit doctor bin/context-kit install claude bin/context-kit install opencode -bin/context-kit redaction-check ``` MCP entrypoints: diff --git a/bin/context-kit b/bin/context-kit index d5b74c3..4fc5f6f 100755 --- a/bin/context-kit +++ b/bin/context-kit @@ -83,7 +83,6 @@ Usage: context-kit build Build MCP images context-kit status Show services, images, sources, and the docs HTTP endpoint context-kit doctor Check Docker, services, images, sources, and HTTP endpoints - context-kit redaction-check Scan this repo for local paths and secret patterns MCP server commands: context-kit web-search Per-call SearXNG-backed web-search MCP (stdio) @@ -168,17 +167,6 @@ warn() { printf 'warn: %s\n' "$*" >&2 } -print_relative_paths() { - local path - while IFS= read -r path; do - [[ -n "${path}" ]] || continue - if [[ "${path}" == "${ROOT}/"* ]]; then - path="${path#"${ROOT}/"}" - fi - printf '%s\n' "${path}" - done -} - json_escape() { local s="$1" s="${s//\\/\\\\}" @@ -550,50 +538,6 @@ cmd_install() { esac } -cmd_redaction_check() { - local bad=0 - local scan_paths=("${ROOT}") - if [[ "$#" -gt 0 ]]; then - scan_paths=("$@") - fi - local local_path_terms='/(home|Users)/[^/[:space:]]+|/data/(projects|opencode-mcp)[^[:space:]]*|[A-Za-z]:\\Users\\[^\\[:space:]]+' - local secret_terms='AKIA[0-9A-Z]{16}|BEGIN (RSA |OPENSSH |EC |DSA )?PRIVATE KEY|xox[baprs]-|sk-[A-Za-z0-9_-]{20,}|ghp_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|glpat-[A-Za-z0-9_-]{20,}|gitea_[A-Za-z0-9_-]{20,}' - - # Scan only what would be published: skip .git plus everything .gitignore - # excludes by convention (local .env files, caches, logs). - local grep_opts=( - -RInE - --exclude-dir=.git - --exclude-dir=.cache - --exclude-dir=tmp - --exclude=.env - --exclude=.env.local - --exclude=*.log - ) - - local matches - matches="$(grep "${grep_opts[@]}" --files-with-matches "${local_path_terms}" "${scan_paths[@]}" 2>/dev/null || true)" - if [[ -n "${matches}" ]]; then - printf 'fail redaction-check found local path patterns in:\n' >&2 - printf '%s\n' "${matches}" | print_relative_paths | sed 's/^/- /' >&2 - bad=1 - fi - - matches="$(grep "${grep_opts[@]}" --files-with-matches "${secret_terms}" "${scan_paths[@]}" 2>/dev/null || true)" - if [[ -n "${matches}" ]]; then - printf 'fail redaction-check found secret-like patterns in:\n' >&2 - printf '%s\n' "${matches}" | print_relative_paths | sed 's/^/- /' >&2 - bad=1 - fi - - if [[ "${bad}" -eq 0 ]]; then - printf 'pass redaction-check found no local absolute paths or common secret patterns\n' - else - printf 'fail redaction-check found blocked content\n' >&2 - fi - return "${bad}" -} - case "${1:-}" in start) shift; cmd_start "$@" ;; stop) shift; cmd_stop "$@" ;; @@ -605,7 +549,6 @@ case "${1:-}" in docs) shift; cmd_docs "$@" ;; repomix) shift; cmd_repomix "$@" ;; install) shift; cmd_install "$@" ;; - redaction-check) shift; cmd_redaction_check "$@" ;; -h|--help|help|"") usage ;; *) usage >&2; exit 64 ;; esac diff --git a/docs/configuration.md b/docs/configuration.md index 22c7eab..4c38233 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -17,8 +17,7 @@ Tracked public files: - `config/sources.*.txt`: optional public source profiles. - `snippets/`: portable assistant config snippets that use `context-kit` on `PATH`. -- `compose.yml`, `docker/`, `bin/`, and `scripts/`: generic runtime and release - logic. +- `compose.yml`, `docker/`, `bin/`, and `scripts/check`: generic runtime logic. Ignored or external local files: @@ -50,8 +49,7 @@ host. ## User-Facing Variables -Only the variables below are part of the public configuration surface. Other -`CONTEXT_KIT_*` variables used by scripts are release/test hooks and may change. +The variables below are the supported public configuration surface. | Variable | Default | Purpose | |---|---|---| diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 5930556..fa3748a 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -9,19 +9,6 @@ bin/context-kit doctor This checks Docker, Compose, images, the Docker network, SearXNG health, docs HTTP readiness, and docs source configuration. -For release-grade MCP protocol checks, run: - -```sh -scripts/release-check -``` - -Live provider checks are opt-in because search engines, remote docs, and model -downloads can fail independently of this repo: - -```sh -CONTEXT_KIT_LIVE_CHECKS=1 scripts/release-check -``` - ## SearXNG Is Not Responding Start it: diff --git a/scripts/mcp-smoke-client.mjs b/scripts/mcp-smoke-client.mjs deleted file mode 100644 index 1b6189f..0000000 --- a/scripts/mcp-smoke-client.mjs +++ /dev/null @@ -1,188 +0,0 @@ -import { spawn, spawnSync } from "node:child_process"; -import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; - -export function textFrom(result) { - return (result.content || []) - .filter(part => part.type === "text") - .map(part => part.text) - .join("\n"); -} - -export function requireToolSuccess(name, result) { - if (result?.isError) { - const payload = textFrom(result) || JSON.stringify(result); - throw new Error(`${name} returned an error: ${payload.slice(0, 500)}`); - } - return result; -} - -export async function runSmoke({ usage, tmpPrefix, timeoutMs, clientInfo, scenario }) { - const command = process.argv[2]; - const args = process.argv.slice(3); - - if (!command) { - throw new Error(usage); - } - - const client = new McpSmokeClient({ command, args, tmpPrefix }); - const timeout = setTimeout(async () => { - await client.stop(); - console.error(`MCP smoke timed out. stderr: ${client.stderrTail(2000)}`); - process.exit(1); - }, timeoutMs); - - try { - await client.initialize(clientInfo); - const result = await scenario(client); - clearTimeout(timeout); - await client.stop(); - console.log(JSON.stringify(result, null, 2)); - } catch (error) { - clearTimeout(timeout); - await client.stop(); - console.error(error.message); - const stderr = client.stderrTail(4000); - if (stderr) console.error(stderr); - process.exit(1); - } -} - -class McpSmokeClient { - constructor({ command, args, tmpPrefix }) { - this.tmpDir = mkdtempSync(join(tmpdir(), tmpPrefix)); - this.cidFile = join(this.tmpDir, "container.cid"); - this.nextId = 1; - this.pending = new Map(); - this.stdoutBuffer = ""; - this.stderrBuffer = ""; - this.exited = false; - - this.child = spawn(command, args, { - cwd: new URL("..", import.meta.url).pathname, - env: { ...process.env, CONTEXT_KIT_DOCKER_CIDFILE: this.cidFile }, - stdio: ["pipe", "pipe", "pipe"] - }); - - this.child.once("exit", (code, signal) => { - this.exited = true; - if (this.pending.size > 0) { - const error = new Error(`MCP child exited before responding (code=${code}, signal=${signal}). stderr: ${this.stderrTail(2000)}`); - for (const { reject } of this.pending.values()) reject(error); - this.pending.clear(); - } - }); - - this.child.stderr.on("data", chunk => { - this.stderrBuffer += chunk.toString(); - }); - - this.child.stdout.on("data", chunk => this.handleStdout(chunk)); - } - - stderrTail(length) { - return this.stderrBuffer.slice(-length); - } - - handleStdout(chunk) { - this.stdoutBuffer += chunk.toString(); - let newline; - while ((newline = this.stdoutBuffer.indexOf("\n")) >= 0) { - const line = this.stdoutBuffer.slice(0, newline).trim(); - this.stdoutBuffer = this.stdoutBuffer.slice(newline + 1); - if (!line) continue; - let message; - try { - message = JSON.parse(line); - } catch { - continue; - } - if (message.id && this.pending.has(message.id)) { - const { resolve, reject } = this.pending.get(message.id); - this.pending.delete(message.id); - if (message.error) reject(new Error(JSON.stringify(message.error))); - else resolve(message.result); - } - } - } - - request(method, params = {}) { - if (this.exited) { - return Promise.reject(new Error(`MCP child already exited. stderr: ${this.stderrTail(2000)}`)); - } - const id = this.nextId++; - this.child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}\n`); - return new Promise((resolve, reject) => this.pending.set(id, { resolve, reject })); - } - - notify(method, params = {}) { - this.child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", method, params })}\n`); - } - - async initialize(clientInfo) { - await this.request("initialize", { - protocolVersion: "2024-11-05", - capabilities: {}, - clientInfo - }); - this.notify("notifications/initialized"); - } - - async tools() { - const listed = await this.request("tools/list"); - return new Set((listed.tools || []).map(tool => tool.name)); - } - - async requireTools(names) { - const toolNames = await this.tools(); - for (const name of names) { - if (!toolNames.has(name)) throw new Error(`missing tool: ${name}`); - } - return toolNames; - } - - callTool(name, args = {}) { - return this.request("tools/call", { name, arguments: args }); - } - - stopContainer() { - if (!existsSync(this.cidFile)) return; - const containerId = readFileSync(this.cidFile, "utf8").trim(); - if (!containerId) return; - spawnSync("docker", ["stop", containerId], { stdio: "ignore" }); - } - - stop() { - return new Promise(resolve => { - if (this.exited) { - this.stopContainer(); - rmSync(this.tmpDir, { recursive: true, force: true }); - resolve(); - return; - } - - let stopTimer; - let termTimer; - let killTimer; - this.child.once("exit", () => { - this.stopContainer(); - clearTimeout(stopTimer); - clearTimeout(termTimer); - clearTimeout(killTimer); - rmSync(this.tmpDir, { recursive: true, force: true }); - resolve(); - }); - - stopTimer = setTimeout(() => this.stopContainer(), 1000); - termTimer = setTimeout(() => { - if (!this.exited) this.child.kill("SIGTERM"); - }, 3000); - killTimer = setTimeout(() => { - if (!this.exited) this.child.kill("SIGKILL"); - }, 6000); - - this.child.stdin.end(); - }); - } -} diff --git a/scripts/release-check b/scripts/release-check deleted file mode 100755 index 2aaf9f1..0000000 --- a/scripts/release-check +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -cd "${ROOT}" - -tmp_dir="$(mktemp -d)" -pick_port() { - python - <<'PY' -import socket - -with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: - sock.bind(("127.0.0.1", 0)) - print(sock.getsockname()[1]) -PY -} - -release_id="release-$$" -export CONTEXT_KIT_COMPOSE_PROJECT="context-kit-${release_id}" -export CONTEXT_KIT_DATA_DIR="${tmp_dir}/data" -export CONTEXT_KIT_PROJECT_DIR="${ROOT}" -export CONTEXT_KIT_SEARXNG_PORT="$(pick_port)" -export CONTEXT_KIT_DOCS_PORT="$(pick_port)" -export CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR="${tmp_dir}/local-sources" -export CONTEXT_KIT_DOCS_LOCAL_SOURCES_PORT="8769" -local_sources_profile="${tmp_dir}/sources.local.txt" -export CONTEXT_KIT_DOCS_SOURCES="config/sources.default.txt ${local_sources_profile}" -export CONTEXT_KIT_LOCAL_SOURCE_SMOKE_URL="http://127.0.0.1:${CONTEXT_KIT_DOCS_LOCAL_SOURCES_PORT}/release-fixture/llms.txt" -export CONTEXT_KIT_WEB_SEARCH_IMAGE="context-kit/web-search-mcp:${release_id}" -export CONTEXT_KIT_DOCS_IMAGE="context-kit/docs-mcp:${release_id}" - -mkdir -p "${CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR}/release-fixture" -printf '%s\n' \ - '# Release Check Local Source' \ - '' \ - '> Exercises machine-local llms.txt serving and refresh behavior.' \ - '' \ - '## MCP' \ - '' \ - '- [Model Context Protocol](https://modelcontextprotocol.io/)' \ - > "${CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR}/release-fixture/llms.txt" -printf '%s\n' "${CONTEXT_KIT_LOCAL_SOURCE_SMOKE_URL}" > "${local_sources_profile}" - -cleanup() { - docker compose -p "${CONTEXT_KIT_COMPOSE_PROJECT}" -f compose.yml down -v --remove-orphans >/dev/null 2>&1 || true - docker image rm "${CONTEXT_KIT_WEB_SEARCH_IMAGE}" "${CONTEXT_KIT_DOCS_IMAGE}" >/dev/null 2>&1 || true - rm -rf "${tmp_dir}" -} -trap cleanup EXIT - -check_node() { - local file - for file in "$@"; do - node --check "${file}" - done -} - -assert_redaction_check_does_not_disclose_matches() { - local fixture="${tmp_dir}/redaction-fixture.txt" - local output="${tmp_dir}/redaction-output.txt" - local blocked_path="/data/proj""ects/context-kit-private-fixture" - printf 'blocked=%s\n' "${blocked_path}" > "${fixture}" - if bin/context-kit redaction-check "${fixture}" >"${output}" 2>&1; then - printf 'redaction-check test unexpectedly passed\n' >&2 - return 1 - fi - if grep -F "${blocked_path}" "${output}" >/dev/null; then - printf 'redaction-check disclosed matched content\n' >&2 - return 1 - fi -} - -assert_web_search_image() { - docker run --rm --entrypoint node \ - -e EXPECTED_MAX_BYTES="${CONTEXT_KIT_WEB_SEARCH_MAX_BYTES:-52428800}" \ - "${CONTEXT_KIT_WEB_SEARCH_IMAGE}" \ - -e ' -const fs = require("node:fs"); -const expected = Number(process.env.EXPECTED_MAX_BYTES) || 0; -const actual = Number(process.env.MAX_BYTES) || 0; -if (process.getuid && process.getuid() === 0) process.exit(1); -if (actual !== expected) process.exit(1); - -const serverPath = "/usr/local/lib/node_modules/@zhafron/mcp-web-search/dist/src/server.js"; -const server = fs.readFileSync(serverPath, "utf8"); -if (!server.includes("max_download_bytes: z.number().int().min(1).max(MAX_BYTES).optional()")) process.exit(1); - -const bingPath = "/usr/local/lib/node_modules/@zhafron/mcp-web-search/dist/src/providers/bing.js"; -const bing = fs.readFileSync(bingPath, "utf8"); -if (!bing.includes("Context Kit override for @zhafron/mcp-web-search 1.3.0")) process.exit(1); -if (!bing.includes("waitForSelector")) process.exit(1); -if (!bing.includes("decodeBingRedirect")) process.exit(1); -' >/dev/null - - docker run --rm --entrypoint /usr/bin/test \ - "${CONTEXT_KIT_WEB_SEARCH_IMAGE}" \ - -x "${CONTEXT_KIT_WEB_SEARCH_CHROME_PATH:-/usr/bin/chromium}" -} - -git diff --check HEAD -git show --check --format= HEAD >/dev/null -git ls-files --cached --error-unmatch \ - docker/web-search/patch-mcp-web-search.mjs \ - docker/web-search/overrides/bing.js \ - docker/docs/constraints.txt \ - scripts/mcp-smoke-client.mjs \ - scripts/smoke-web-search.mjs \ - scripts/smoke-docs.mjs \ - scripts/smoke-repomix.mjs \ - scripts/release-check >/dev/null -bash -n bin/context-kit -bash -n scripts/release-check -sh -n docker/docs/entrypoint.sh -check_node docker/web-search/patch-mcp-web-search.mjs docker/web-search/overrides/bing.js scripts/mcp-smoke-client.mjs scripts/smoke-web-search.mjs scripts/smoke-docs.mjs scripts/smoke-repomix.mjs - -node -e 'const fs=require("node:fs"); JSON.parse(fs.readFileSync("snippets/opencode.json", "utf8")); JSON.parse(fs.readFileSync("snippets/claude.mcp.json", "utf8"));' -CONTEXT_KIT_DOCS_HTTP_URL="http://127.0.0.1:8776/mcp" bin/context-kit install opencode > "${tmp_dir}/opencode-default.json" -cmp -s snippets/opencode.json "${tmp_dir}/opencode-default.json" || { - printf 'snippets/opencode.json differs from bin/context-kit install opencode output\n' >&2 - diff -u snippets/opencode.json "${tmp_dir}/opencode-default.json" >&2 || true - exit 1 -} -CONTEXT_KIT_DOCS_HTTP_URL="http://127.0.0.1:8776/mcp" bin/context-kit install claude > "${tmp_dir}/claude-default.json" -cmp -s snippets/claude.mcp.json "${tmp_dir}/claude-default.json" || { - printf 'snippets/claude.mcp.json differs from bin/context-kit install claude output\n' >&2 - diff -u snippets/claude.mcp.json "${tmp_dir}/claude-default.json" >&2 || true - exit 1 -} -bin/context-kit install opencode > "${tmp_dir}/opencode.json" -bin/context-kit install opencode --absolute > "${tmp_dir}/opencode-absolute.json" -bin/context-kit install claude > "${tmp_dir}/claude.json" -bin/context-kit install claude --absolute > "${tmp_dir}/claude-absolute.json" -node -e 'const fs=require("node:fs"); for (const file of process.argv.slice(1)) JSON.parse(fs.readFileSync(file, "utf8"));' \ - "${tmp_dir}/opencode.json" \ - "${tmp_dir}/opencode-absolute.json" \ - "${tmp_dir}/claude.json" \ - "${tmp_dir}/claude-absolute.json" -bin/context-kit redaction-check "${tmp_dir}/opencode.json" "${tmp_dir}/claude.json" -assert_redaction_check_does_not_disclose_matches - -bin/context-kit redaction-check -docker compose -p "${CONTEXT_KIT_COMPOSE_PROJECT}" -f compose.yml config >/dev/null -if env -u HOME -u CONTEXT_KIT_DATA_DIR -u CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR docker compose --env-file /dev/null -p context-kit-release-home-check -f compose.yml config >"${tmp_dir}/compose-no-home.out" 2>"${tmp_dir}/compose-no-home.err"; then - printf 'compose config unexpectedly succeeded without HOME or CONTEXT_KIT_DATA_DIR\n' >&2 - exit 1 -fi -CONTEXT_KIT_DATA_DIR="${tmp_dir}/compose-data" env -u HOME docker compose --env-file /dev/null -p context-kit-release-home-check -f compose.yml config >/dev/null -bin/context-kit build -assert_web_search_image -bin/context-kit restart -bin/context-kit doctor -node scripts/smoke-web-search.mjs bin/context-kit web-search -node scripts/smoke-docs.mjs bin/context-kit docs -node scripts/smoke-repomix.mjs bin/context-kit repomix - -printf 'pass release-check\n' diff --git a/scripts/smoke-docs.mjs b/scripts/smoke-docs.mjs deleted file mode 100644 index 75d59cb..0000000 --- a/scripts/smoke-docs.mjs +++ /dev/null @@ -1,53 +0,0 @@ -import { requireToolSuccess, runSmoke } from "./mcp-smoke-client.mjs"; - -const live = process.env.CONTEXT_KIT_LIVE_CHECKS === "1"; -const localSourceSmokeUrl = process.env.CONTEXT_KIT_LOCAL_SOURCE_SMOKE_URL; - -runSmoke({ - usage: "usage: node scripts/smoke-docs.mjs [args...]", - tmpPrefix: "context-kit-docs-smoke-", - timeoutMs: 300000, - clientInfo: { name: "context-kit-docs-smoke", version: "0.0.0" }, - scenario: async client => { - const toolNames = await client.requireTools(["docs_query", "docs_sources"]); - - const sources = requireToolSuccess("docs_sources", await client.callTool("docs_sources")); - if (!Array.isArray(sources?.structuredContent?.result)) { - const sourcesText = JSON.stringify(sources); - throw new Error(`docs_sources returned unexpected payload: ${sourcesText.slice(0, 500)}`); - } - - const result = { - tools: Array.from(toolNames).sort(), - docs_sources: "pass" - }; - - if (localSourceSmokeUrl) { - requireToolSuccess("docs_refresh/local_source_first", await client.callTool("docs_refresh", { - source: localSourceSmokeUrl - })); - requireToolSuccess("docs_refresh/local_source_second", await client.callTool("docs_refresh", { - source: localSourceSmokeUrl - })); - result.local_source_refresh = "pass"; - } - - if (live) { - const query = requireToolSuccess("docs_query", await client.callTool("docs_query", { - query: "Model Context Protocol documentation", - limit: 3, - auto_retrieve: true, - auto_retrieve_threshold: 0.1, - auto_retrieve_limit: 1, - max_bytes: 12000 - })); - const queryText = JSON.stringify(query); - if (!queryText.includes("search_results") && !queryText.includes("Model Context Protocol")) { - throw new Error(`docs_query returned unexpected payload: ${queryText.slice(0, 500)}`); - } - result.docs_query = "pass"; - } - - return result; - } -}); diff --git a/scripts/smoke-repomix.mjs b/scripts/smoke-repomix.mjs deleted file mode 100644 index 5fccc6e..0000000 --- a/scripts/smoke-repomix.mjs +++ /dev/null @@ -1,30 +0,0 @@ -import { requireToolSuccess, runSmoke, textFrom } from "./mcp-smoke-client.mjs"; - -runSmoke({ - usage: "usage: node scripts/smoke-repomix.mjs [args...]", - tmpPrefix: "context-kit-repomix-smoke-", - timeoutMs: 120000, - clientInfo: { name: "context-kit-repomix-smoke", version: "0.0.0" }, - scenario: async client => { - const toolNames = await client.requireTools(["pack_codebase"]); - - const pack = requireToolSuccess("pack_codebase", await client.callTool("pack_codebase", { - directory: process.cwd(), - compress: true, - includePatterns: "README.md,snippets/opencode.json", - ignorePatterns: "", - topFilesLength: 2, - style: "xml" - })); - - const packText = textFrom(pack) || JSON.stringify(pack); - if (!packText.includes("Successfully packed codebase") && !packText.includes("outputId")) { - throw new Error(`pack_codebase returned unexpected payload: ${packText.slice(0, 500)}`); - } - - return { - tools: Array.from(toolNames).sort(), - pack_codebase: "pass" - }; - } -}); diff --git a/scripts/smoke-web-search.mjs b/scripts/smoke-web-search.mjs deleted file mode 100644 index 91af049..0000000 --- a/scripts/smoke-web-search.mjs +++ /dev/null @@ -1,63 +0,0 @@ -import { requireToolSuccess, runSmoke, textFrom } from "./mcp-smoke-client.mjs"; - -const live = process.env.CONTEXT_KIT_LIVE_CHECKS === "1"; - -runSmoke({ - usage: "usage: node scripts/smoke-web-search.mjs [args...]", - tmpPrefix: "context-kit-web-search-smoke-", - timeoutMs: 120000, - clientInfo: { name: "context-kit-web-search-smoke", version: "0.0.0" }, - scenario: async client => { - const toolNames = await client.requireTools(["search_web", "fetch_url"]); - - const localResult = await client.callTool("fetch_url", { - url: "http://127.0.0.1:1/", - max_download_bytes: 52428800 - }); - const localBlocked = Boolean(localResult.isError) && textFrom(localResult).includes("Blocked localhost/private URL"); - if (!localBlocked) throw new Error("localhost/private URL was not blocked as expected"); - - const result = { - tools: Array.from(toolNames).sort(), - localhost_guard: "pass" - }; - - if (live) { - const searxng = textFrom(requireToolSuccess("search_web/searxng", await client.callTool("search_web", { - q: "Model Context Protocol", - limit: 2, - provider: "searxng" - }))); - if (!searxng.includes("Model")) throw new Error(`SearXNG smoke returned unexpected text: ${searxng.slice(0, 500)}`); - - const bing = textFrom(requireToolSuccess("search_web/bing", await client.callTool("search_web", { - q: "Model Context Protocol", - limit: 2, - provider: "bing" - }))); - if (!bing.includes("Model")) throw new Error(`Bing smoke returned unexpected text: ${bing.slice(0, 500)}`); - - const fetch = textFrom(requireToolSuccess("fetch_url/http", await client.callTool("fetch_url", { - url: "https://example.com/", - format: "markdown", - max_download_bytes: 52428800 - }))); - if (!fetch.includes("Example Domain")) throw new Error(`fetch smoke returned unexpected text: ${fetch.slice(0, 500)}`); - - const browserFetch = textFrom(requireToolSuccess("fetch_url/browser", await client.callTool("fetch_url", { - url: "https://example.com/", - format: "markdown", - engine: "browser", - max_download_bytes: 52428800 - }))); - if (!browserFetch.includes("Example Domain")) throw new Error(`browser fetch smoke returned unexpected text: ${browserFetch.slice(0, 500)}`); - - result.searxng = "pass"; - result.bing = "pass"; - result.fetch_url = "pass"; - result.fetch_url_browser_engine_currently_http = "pass"; - } - - return result; - } -});