diff --git a/bench/uv.lock b/bench/uv.lock index ce263c6..75713a2 100644 --- a/bench/uv.lock +++ b/bench/uv.lock @@ -848,7 +848,7 @@ wheels = [ [[package]] name = "docpull" -version = "6.5.1" +version = "6.5.2" source = { editable = "../" } dependencies = [ { name = "aiohttp" }, diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 37695e3..daa3c08 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [6.5.2] - 2026-09-04 + +### Fixed +- Add a dependency-free plugin launcher that reports the exact `pipx` setup + command when the `docpull` executable is unavailable. + ## [6.5.1] - 2026-09-04 ### Fixed diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index 0ff39e3..ad670a8 100644 --- a/plugin/.claude-plugin/plugin.json +++ b/plugin/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "docpull", - "version": "6.5.1", + "version": "6.5.2", "description": "Pull public web sources into Claude Code. Indexes static and server-rendered sites as local Markdown with conditional-GET caching, then exposes them as MCP tools. Local, browser-free, no API keys.", "author": { "name": "Raintree Technology", diff --git a/plugin/.codex-plugin/plugin.json b/plugin/.codex-plugin/plugin.json index 6afc67b..9df5e27 100644 --- a/plugin/.codex-plugin/plugin.json +++ b/plugin/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "id": "docpull", "name": "docpull", - "version": "6.5.1", + "version": "6.5.2", "description": "Pull public web sources into Codex as local, searchable Markdown through docpull's MCP server.", "skills": "./skills/", "mcpServers": "./.mcp.json", diff --git a/plugin/.mcp.json b/plugin/.mcp.json index 68cf2b3..56586ae 100644 --- a/plugin/.mcp.json +++ b/plugin/.mcp.json @@ -1,8 +1,9 @@ { "mcpServers": { "docpull": { - "command": "docpull", - "args": ["mcp"] + "command": "node", + "args": ["./scripts/launch-docpull-mcp.mjs"], + "cwd": "." } } } diff --git a/plugin/README.md b/plugin/README.md index 08ebe1d..8dedf3c 100644 --- a/plugin/README.md +++ b/plugin/README.md @@ -20,12 +20,13 @@ for the boundary between the plugin's MCP tools and the broader CLI/SDK. The plugin wraps the `docpull` CLI. Install the MCP extra first: ```bash -pip install 'docpull[mcp]' # or: pipx install 'docpull[mcp]' -docpull --version # should print 6.5.1 or newer +pipx install 'docpull[mcp]==6.5.2' +docpull --version # should print 6.5.2 or newer docpull mcp --help ``` -The plain `pip install docpull` does not include the MCP dependency. +The plain `pip install docpull` does not include the MCP dependency. If the +executable is missing, the plugin exits with the exact `pipx` setup command. In Claude Code: diff --git a/plugin/scripts/launch-docpull-mcp.mjs b/plugin/scripts/launch-docpull-mcp.mjs new file mode 100644 index 0000000..0fa8b30 --- /dev/null +++ b/plugin/scripts/launch-docpull-mcp.mjs @@ -0,0 +1,29 @@ +#!/usr/bin/env node + +import { spawn } from "node:child_process"; + +const child = spawn("docpull", ["mcp", ...process.argv.slice(2)], { + stdio: "inherit", +}); + +child.on("error", (error) => { + if (error.code === "ENOENT") { + console.error( + "DocPull is not installed. Run: pipx install 'docpull[mcp]==6.5.2'", + ); + process.exitCode = 127; + return; + } + + console.error(`DocPull could not start: ${error.message}`); + process.exitCode = 1; +}); + +child.on("exit", (code, signal) => { + if (signal) { + process.kill(process.pid, signal); + return; + } + + process.exitCode = code ?? 1; +}); diff --git a/pyproject.toml b/pyproject.toml index 51e1e9b..1a78ae4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "docpull" -version = "6.5.1" +version = "6.5.2" dynamic = [] description = "Declare, sync, diff, and lock context dependencies for AI agents" readme = {file = "README.md", content-type = "text/markdown"} diff --git a/sdk/js/package.json b/sdk/js/package.json index 3dd4571..d52128b 100644 --- a/sdk/js/package.json +++ b/sdk/js/package.json @@ -1,6 +1,6 @@ { "name": "@raintree-technology/docpull-sdk", - "version": "6.5.1", + "version": "6.5.2", "description": "TypeScript SDK for reading docpull context packs and running the docpull CLI", "license": "MIT", "type": "module", diff --git a/server.json b/server.json index 2d563c3..bf96ac3 100644 --- a/server.json +++ b/server.json @@ -8,12 +8,12 @@ "source": "github" }, "websiteUrl": "https://github.com/raintree-technology/docpull", - "version": "6.5.1", + "version": "6.5.2", "packages": [ { "registryType": "pypi", "identifier": "docpull", - "version": "6.5.1", + "version": "6.5.2", "transport": { "type": "stdio" } diff --git a/src/docpull/__init__.py b/src/docpull/__init__.py index f5bd8ac..d307651 100644 --- a/src/docpull/__init__.py +++ b/src/docpull/__init__.py @@ -15,7 +15,7 @@ from .surface import PUBLIC_SDK_EXPORTS -__version__ = "6.5.1" +__version__ = "6.5.2" _LAZY_EXPORTS: dict[str, tuple[str, str]] = { **{ diff --git a/tests/test_ci_policy.py b/tests/test_ci_policy.py index 49fb641..12005ee 100644 --- a/tests/test_ci_policy.py +++ b/tests/test_ci_policy.py @@ -4,6 +4,7 @@ import json import re +import shutil import subprocess # nosec B404 import sys from pathlib import Path @@ -309,6 +310,22 @@ def test_plugin_manifest_versions_match_project_version() -> None: assert manifest["version"] == project_version() +def test_plugin_launcher_reports_actionable_setup_when_docpull_is_missing() -> None: + launcher = REPO_ROOT / "plugin" / "scripts" / "launch-docpull-mcp.mjs" + node = shutil.which("node") + assert node is not None + proc = subprocess.run( # nosec B603 + [node, str(launcher)], + check=False, + text=True, + env={"PATH": ""}, + capture_output=True, + ) + + assert proc.returncode == 127 + assert "pipx install 'docpull[mcp]==6.5.2'" in proc.stderr + + def test_mcp_registry_manifest_versions_match_project_version() -> None: manifest = json.loads((REPO_ROOT / "server.json").read_text(encoding="utf-8")) diff --git a/uv.lock b/uv.lock index b36d9c9..e60bca5 100644 --- a/uv.lock +++ b/uv.lock @@ -1305,7 +1305,7 @@ wheels = [ [[package]] name = "docpull" -version = "6.5.1" +version = "6.5.2" source = { editable = "." } dependencies = [ { name = "aiohttp" },