docpull 4.4.0__tar.gz → 4.4.1__tar.gz
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.
- docpull-4.4.1/PKG-INFO +398 -0
- docpull-4.4.1/README.md +298 -0
- {docpull-4.4.0 → docpull-4.4.1}/pyproject.toml +5 -3
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/__init__.py +1 -1
- docpull-4.4.1/src/docpull.egg-info/PKG-INFO +398 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull.egg-info/requires.txt +4 -2
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_ci_policy.py +7 -2
- docpull-4.4.0/PKG-INFO +0 -818
- docpull-4.4.0/README.md +0 -720
- docpull-4.4.0/src/docpull.egg-info/PKG-INFO +0 -818
- {docpull-4.4.0 → docpull-4.4.1}/LICENSE +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/setup.cfg +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/__main__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/benchmark.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/cache/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/cache/frontier.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/cache/manager.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/cache/streaming_dedup.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/cli.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/conversion/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/conversion/chunking.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/conversion/extractor.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/conversion/filings.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/conversion/markdown.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/conversion/protocols.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/conversion/special_cases.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/conversion/trafilatura_extractor.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/core/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/core/fetcher.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/_fetch.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/composite.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/crawler.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/filters.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/link_extractors/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/link_extractors/enhanced.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/link_extractors/protocols.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/link_extractors/static.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/protocols.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/discovery/sitemap.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/doctor.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/evidence_pack.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/fixtures/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/fixtures/parallel-search-extract.json +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/http/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/http/client.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/http/protocols.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/http/rate_limiter.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/judge.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/mcp/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/mcp/server.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/mcp/sources.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/mcp/tools.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/metadata_extractor.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/models/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/models/config.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/models/document.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/models/events.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/models/profiles.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/models/run.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pack_tools.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/parallel_workflows.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/passk.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/base.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/manifest.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/chunk.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/convert.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/dedup.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/fetch.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/metadata.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/save.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/save_json.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/save_ndjson.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/save_okf.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/save_sqlite.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/pipeline/steps/validate.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/provider_cli.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/provider_keys.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/py.typed +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/scraper.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/security/__init__.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/security/download_policy.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/security/robots.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/security/url_validator.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/source_scoring.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull/time_utils.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull.egg-info/SOURCES.txt +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull.egg-info/dependency_links.txt +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull.egg-info/entry_points.txt +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/src/docpull.egg-info/top_level.txt +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_benchmark.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_cache_conditional_get.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_chunking.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_cli.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_conversion.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_convert_step_new.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_discovery.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_document_record.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_evidence_pack.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_frontier_resume.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_integration.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_judge.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_link_extractors.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_mcp_server.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_mcp_tools.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_naming.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_outputs_e2e.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_pack_tools.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_parallel_workflows.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_passk.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_pipeline.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_provider_cli.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_real_site_regressions.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_save_ndjson.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_save_sqlite.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_security_hardening.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_special_cases.py +0 -0
- {docpull-4.4.0 → docpull-4.4.1}/tests/test_time_utils.py +0 -0
docpull-4.4.1/PKG-INFO
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: docpull
|
|
3
|
+
Version: 4.4.1
|
|
4
|
+
Summary: Convert public web pages into clean Markdown for AI agents and RAG
|
|
5
|
+
Author-email: Zachary Roth <support@raintree.technology>
|
|
6
|
+
Maintainer-email: Raintree Technology <support@raintree.technology>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://docpull.raintree.technology
|
|
9
|
+
Project-URL: Documentation, https://docpull.raintree.technology
|
|
10
|
+
Project-URL: Repository, https://github.com/raintree-technology/docpull
|
|
11
|
+
Project-URL: Source Code, https://github.com/raintree-technology/docpull
|
|
12
|
+
Project-URL: Bug Tracker, https://github.com/raintree-technology/docpull/issues
|
|
13
|
+
Project-URL: Releases, https://github.com/raintree-technology/docpull/releases
|
|
14
|
+
Project-URL: MCP Plugin, https://github.com/raintree-technology/docpull/tree/main/plugin
|
|
15
|
+
Project-URL: Comparison Guide, https://github.com/raintree-technology/docpull/blob/main/docs/alternatives.md
|
|
16
|
+
Project-URL: Download Stats, https://pepy.tech/project/docpull
|
|
17
|
+
Project-URL: Changelog, https://github.com/raintree-technology/docpull/blob/main/docs/CHANGELOG.md
|
|
18
|
+
Keywords: python,markdown,documentation,web-extraction,web-scraping,web-crawler,crawler,developer-tools,cli,rag,llm,mcp,ai-agents,context-engineering,claude,ai-training-data
|
|
19
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
20
|
+
Classifier: Intended Audience :: Developers
|
|
21
|
+
Classifier: Intended Audience :: Information Technology
|
|
22
|
+
Classifier: Intended Audience :: Science/Research
|
|
23
|
+
Classifier: Intended Audience :: Education
|
|
24
|
+
Classifier: Environment :: Console
|
|
25
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
26
|
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
27
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
28
|
+
Classifier: Topic :: Utilities
|
|
29
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
30
|
+
Classifier: Natural Language :: English
|
|
31
|
+
Classifier: Operating System :: OS Independent
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
38
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
39
|
+
Classifier: Typing :: Typed
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
44
|
+
Requires-Dist: html2text>=2020.1.16
|
|
45
|
+
Requires-Dist: defusedxml>=0.7.1
|
|
46
|
+
Requires-Dist: extruct>=0.15.0
|
|
47
|
+
Requires-Dist: aiohttp>=3.14.0
|
|
48
|
+
Requires-Dist: idna>=3.15
|
|
49
|
+
Requires-Dist: regex>=2024.11.6
|
|
50
|
+
Requires-Dist: rich>=13.0.0
|
|
51
|
+
Requires-Dist: pyyaml>=6.0
|
|
52
|
+
Requires-Dist: pydantic>=2.0
|
|
53
|
+
Requires-Dist: urllib3>=2.7.0
|
|
54
|
+
Provides-Extra: proxy
|
|
55
|
+
Requires-Dist: aiohttp-socks>=0.11.0; extra == "proxy"
|
|
56
|
+
Provides-Extra: normalize
|
|
57
|
+
Requires-Dist: url-normalize>=1.4.0; extra == "normalize"
|
|
58
|
+
Provides-Extra: trafilatura
|
|
59
|
+
Requires-Dist: trafilatura>=1.12.0; extra == "trafilatura"
|
|
60
|
+
Provides-Extra: tokens
|
|
61
|
+
Requires-Dist: tiktoken>=0.7.0; extra == "tokens"
|
|
62
|
+
Provides-Extra: mcp
|
|
63
|
+
Requires-Dist: cryptography>=48.0.1; extra == "mcp"
|
|
64
|
+
Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
65
|
+
Requires-Dist: pyjwt>=2.13.0; extra == "mcp"
|
|
66
|
+
Requires-Dist: python-multipart>=0.0.27; extra == "mcp"
|
|
67
|
+
Requires-Dist: starlette>=1.3.1; extra == "mcp"
|
|
68
|
+
Provides-Extra: parallel
|
|
69
|
+
Requires-Dist: parallel-web>=1.0.1; extra == "parallel"
|
|
70
|
+
Provides-Extra: observability
|
|
71
|
+
Requires-Dist: raindrop-ai>=0.0.50; extra == "observability"
|
|
72
|
+
Provides-Extra: llm
|
|
73
|
+
Requires-Dist: tiktoken>=0.7.0; extra == "llm"
|
|
74
|
+
Provides-Extra: all
|
|
75
|
+
Requires-Dist: aiohttp-socks>=0.11.0; extra == "all"
|
|
76
|
+
Requires-Dist: url-normalize>=1.4.0; extra == "all"
|
|
77
|
+
Requires-Dist: trafilatura>=1.12.0; extra == "all"
|
|
78
|
+
Requires-Dist: tiktoken>=0.7.0; extra == "all"
|
|
79
|
+
Requires-Dist: cryptography>=48.0.1; extra == "all"
|
|
80
|
+
Requires-Dist: mcp>=1.0.0; extra == "all"
|
|
81
|
+
Requires-Dist: pyjwt>=2.13.0; extra == "all"
|
|
82
|
+
Requires-Dist: python-multipart>=0.0.27; extra == "all"
|
|
83
|
+
Requires-Dist: starlette>=1.3.1; extra == "all"
|
|
84
|
+
Requires-Dist: parallel-web>=1.0.1; extra == "all"
|
|
85
|
+
Requires-Dist: raindrop-ai>=0.0.50; extra == "all"
|
|
86
|
+
Provides-Extra: dev
|
|
87
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
88
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
89
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
90
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
91
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
92
|
+
Requires-Dist: bandit>=1.7.0; extra == "dev"
|
|
93
|
+
Requires-Dist: pip-audit>=2.0.0; extra == "dev"
|
|
94
|
+
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
|
|
95
|
+
Requires-Dist: types-requests>=2.31.0; extra == "dev"
|
|
96
|
+
Requires-Dist: types-beautifulsoup4>=4.12.0; extra == "dev"
|
|
97
|
+
Requires-Dist: types-defusedxml>=0.7.0; extra == "dev"
|
|
98
|
+
Requires-Dist: types-pyyaml>=6.0.0; extra == "dev"
|
|
99
|
+
Dynamic: license-file
|
|
100
|
+
|
|
101
|
+
# docpull
|
|
102
|
+
|
|
103
|
+
**Turn public documentation sites into local Markdown, NDJSON, and agent-ready context packs. No browser required.**
|
|
104
|
+
|
|
105
|
+
[](https://www.python.org/downloads/)
|
|
106
|
+
[](https://badge.fury.io/py/docpull)
|
|
107
|
+
[](https://pepy.tech/project/docpull)
|
|
108
|
+
[](https://github.com/raintree-technology/docpull/stargazers)
|
|
109
|
+
[](https://github.com/raintree-technology/docpull/blob/main/LICENSE)
|
|
110
|
+
|
|
111
|
+
docpull is a Python CLI, SDK, and MCP server that fetches public static or
|
|
112
|
+
server-rendered web pages and converts them into clean, auditable local
|
|
113
|
+
artifacts for LLMs, retrieval-augmented generation (RAG), offline research, and
|
|
114
|
+
agent workflows.
|
|
115
|
+
|
|
116
|
+
It works best on documentation sites, blogs, API references, OpenAPI specs,
|
|
117
|
+
vendor pages, and other public pages where the useful content is available in
|
|
118
|
+
HTML or embedded page data.
|
|
119
|
+
|
|
120
|
+
docpull is not a browser and does not render JavaScript. JS-only pages are
|
|
121
|
+
skipped with a clear reason. See [Scraping Boundary](docs/scraping-boundary.md)
|
|
122
|
+
and [Alternatives](docs/alternatives.md) for the full boundary.
|
|
123
|
+
|
|
124
|
+
## Install
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
pip install docpull
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Install optional extras as needed:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pip install 'docpull[llm]' # tiktoken for token-accurate chunking
|
|
134
|
+
pip install 'docpull[trafilatura]' # alternative extractor for noisy pages
|
|
135
|
+
pip install 'docpull[mcp]' # stdio MCP server
|
|
136
|
+
pip install 'docpull[parallel]' # Parallel context packs
|
|
137
|
+
pip install 'docpull[observability]' # Raindrop benchmark tracing
|
|
138
|
+
pip install 'docpull[all]' # all optional extras
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 30-Second Usage
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
docpull https://docs.python.org/3/library/asyncio.html --single -o ./asyncio-docs
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Example output:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
asyncio-docs/
|
|
151
|
+
index.md
|
|
152
|
+
corpus.manifest.json
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Markdown includes source metadata and readable page content:
|
|
156
|
+
|
|
157
|
+
```markdown
|
|
158
|
+
---
|
|
159
|
+
title: "asyncio - Asynchronous I/O"
|
|
160
|
+
source: https://docs.python.org/3/library/asyncio.html
|
|
161
|
+
source_type: "sphinx"
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
# asyncio - Asynchronous I/O
|
|
165
|
+
|
|
166
|
+
asyncio is a library to write concurrent code using the async/await syntax.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Stream chunked NDJSON for agents and RAG:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
docpull https://docs.python.org/3/library/asyncio.html \
|
|
173
|
+
--single \
|
|
174
|
+
--profile llm \
|
|
175
|
+
--stream | jq .
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Each line is a JSON document:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{"schema_version":1,"document_id":"doc_...","chunk_id":"chunk_...","url":"https://docs.python.org/3/library/asyncio.html","title":"asyncio - Asynchronous I/O","content":"asyncio is a library to write concurrent code...","source_type":"sphinx","chunk_index":0,"token_count":842}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Common Workflows
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Crawl a site and write Markdown files
|
|
188
|
+
docpull https://docs.example.com -o ./docs-example
|
|
189
|
+
|
|
190
|
+
# Stream LLM-ready NDJSON chunks from a site
|
|
191
|
+
docpull https://docs.example.com --profile llm --stream | jq .
|
|
192
|
+
|
|
193
|
+
# Write SQLite with an FTS5 search index
|
|
194
|
+
docpull https://docs.example.com --format sqlite -o ./docs-db
|
|
195
|
+
|
|
196
|
+
# Build an Open Knowledge Format (OKF) bundle for portable source packs
|
|
197
|
+
docpull https://example.com --profile okf -o ./site-okf
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
More examples live in [CLI Recipes](docs/examples/README.md).
|
|
201
|
+
|
|
202
|
+
Use docpull when you need to:
|
|
203
|
+
|
|
204
|
+
- Convert public docs, blogs, API references, vendor pages, and OpenAPI specs
|
|
205
|
+
into Markdown or chunked NDJSON for LLM and RAG pipelines.
|
|
206
|
+
- Give an agent a local tool for fetching, caching, grepping, and reading web
|
|
207
|
+
sources.
|
|
208
|
+
- Build repeatable context packs with stable IDs, hashes, manifests, and source
|
|
209
|
+
metadata.
|
|
210
|
+
- Mirror public web content for offline work while preserving attribution.
|
|
211
|
+
|
|
212
|
+
## Why docpull?
|
|
213
|
+
|
|
214
|
+
docpull is designed for agent and RAG workflows, not just downloading pages.
|
|
215
|
+
|
|
216
|
+
| Need | docpull gives you |
|
|
217
|
+
| --- | --- |
|
|
218
|
+
| Clean Markdown | Article-focused extraction with source metadata |
|
|
219
|
+
| LLM chunks | NDJSON streaming and optional token-aware chunking |
|
|
220
|
+
| Repeatability | Stable document IDs, chunk IDs, hashes, and manifests |
|
|
221
|
+
| Offline work | Cached archives and mirrored source artifacts |
|
|
222
|
+
| Agent access | Local CLI, Python SDK, and stdio MCP server |
|
|
223
|
+
| Safer fetching | HTTPS defaults, robots.txt compliance, SSRF protections, and redirect guards |
|
|
224
|
+
|
|
225
|
+
## Supported Sources
|
|
226
|
+
|
|
227
|
+
docpull uses async HTTP instead of browser automation and includes special
|
|
228
|
+
handling for common documentation and API surfaces.
|
|
229
|
+
|
|
230
|
+
| Source shape | Support |
|
|
231
|
+
| --- | --- |
|
|
232
|
+
| Static HTML / SSR docs | Extracts article or document regions |
|
|
233
|
+
| Next.js / Mintlify | Parses static HTML and `__NEXT_DATA__` when available |
|
|
234
|
+
| OpenAPI / Swagger | Renders specs into Markdown |
|
|
235
|
+
| Docusaurus / Sphinx / MkDocs | Extracts static article or document regions |
|
|
236
|
+
| VitePress / VuePress / Astro Starlight | Extracts static docs content |
|
|
237
|
+
| GitBook / ReadMe.io | Extracts available article or content regions |
|
|
238
|
+
| Redoc / Scalar | Extracts static API reference regions |
|
|
239
|
+
| JS-only apps | Skipped unless useful content is present in HTML or embedded data |
|
|
240
|
+
|
|
241
|
+
Use `--strict-js-required` when an agent should treat JS-only pages as hard
|
|
242
|
+
errors instead of normal skips.
|
|
243
|
+
|
|
244
|
+
## Output Formats
|
|
245
|
+
|
|
246
|
+
| Output | Use it for |
|
|
247
|
+
| --- | --- |
|
|
248
|
+
| Markdown | Local readable source snapshots with YAML frontmatter |
|
|
249
|
+
| NDJSON | Streamed records or chunked records for agents and RAG |
|
|
250
|
+
| SQLite | Local retrieval with an FTS5 index |
|
|
251
|
+
| OKF | Portable Open Knowledge Format bundles with indexes and manifests |
|
|
252
|
+
| Archive / mirror | Cached offline source snapshots |
|
|
253
|
+
|
|
254
|
+
Every file-backed run writes `corpus.manifest.json` with stable document IDs,
|
|
255
|
+
chunk IDs, hashes, output paths, and chunk counts. See
|
|
256
|
+
[Corpus Manifest](docs/corpus-manifest.md).
|
|
257
|
+
|
|
258
|
+
## Profiles
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
docpull https://site.com --profile rag # Default. Dedup + metadata.
|
|
262
|
+
docpull https://site.com --profile llm # NDJSON chunks for agents/RAG.
|
|
263
|
+
docpull https://site.com --profile okf # Portable Open Knowledge Format bundle.
|
|
264
|
+
docpull https://site.com --profile mirror # Cached archive.
|
|
265
|
+
docpull https://site.com --profile quick # Small sampling crawl.
|
|
266
|
+
docpull https://site.com --profile sec-filing # EDGAR-friendly evidence chunks.
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Run `docpull --help` for the full option list.
|
|
270
|
+
|
|
271
|
+
## When Not to Use docpull
|
|
272
|
+
|
|
273
|
+
docpull intentionally does not use a browser. It is not the right tool for:
|
|
274
|
+
|
|
275
|
+
- JS-only pages that require client-side rendering.
|
|
276
|
+
- Authenticated dashboards or private apps.
|
|
277
|
+
- Pages behind CAPTCHA or bot challenges.
|
|
278
|
+
- Workflows that require clicking, scrolling, or browser state.
|
|
279
|
+
|
|
280
|
+
For those cases, use browser automation, such as Playwright, then pass the
|
|
281
|
+
rendered HTML or exported content into your pipeline.
|
|
282
|
+
|
|
283
|
+
## How It Compares
|
|
284
|
+
|
|
285
|
+
| Tool type | Best for | Tradeoff |
|
|
286
|
+
| --- | --- | --- |
|
|
287
|
+
| `wget` / site mirroring | Downloading raw files | Not agent/RAG-oriented |
|
|
288
|
+
| Browser automation | JS-heavy pages and interactions | Slower, heavier, more stateful |
|
|
289
|
+
| Hosted extraction APIs | Managed extraction at scale | External dependency and cost |
|
|
290
|
+
| docpull | Local public-doc extraction and context packs | No JavaScript rendering |
|
|
291
|
+
|
|
292
|
+
## Python SDK
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
from docpull import fetch_one
|
|
296
|
+
|
|
297
|
+
ctx = fetch_one("https://docs.python.org/3/library/asyncio.html")
|
|
298
|
+
print(ctx.title)
|
|
299
|
+
print(ctx.markdown[:500])
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
import asyncio
|
|
304
|
+
from docpull import Fetcher, DocpullConfig, EventType, ProfileName
|
|
305
|
+
|
|
306
|
+
async def main():
|
|
307
|
+
cfg = DocpullConfig(url="https://docs.example.com", profile=ProfileName.LLM)
|
|
308
|
+
async with Fetcher(cfg) as fetcher:
|
|
309
|
+
async for event in fetcher.run():
|
|
310
|
+
if event.type == EventType.FETCH_PROGRESS:
|
|
311
|
+
print(f"{event.current}/{event.total}: {event.url}")
|
|
312
|
+
|
|
313
|
+
asyncio.run(main())
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## MCP Server
|
|
317
|
+
|
|
318
|
+
docpull can run as a stdio MCP server for agent clients:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
pip install 'docpull[mcp]'
|
|
322
|
+
docpull mcp
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Claude Code:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
claude mcp add --transport stdio docpull -- docpull mcp
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Cursor and Claude Desktop use the same `mcpServers` shape:
|
|
332
|
+
|
|
333
|
+
```json
|
|
334
|
+
{
|
|
335
|
+
"mcpServers": {
|
|
336
|
+
"docpull": {
|
|
337
|
+
"type": "stdio",
|
|
338
|
+
"command": "docpull",
|
|
339
|
+
"args": ["mcp"]
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
The supported MCP path is the Python stdio server started by `docpull mcp`.
|
|
346
|
+
The repository's `mcp/` directory is an internal TypeScript/Bun lab and is not
|
|
347
|
+
part of the package release contract.
|
|
348
|
+
|
|
349
|
+
## Advanced Workflows
|
|
350
|
+
|
|
351
|
+
- `docpull[parallel]` can discover, extract, enrich, score, diff, and archive
|
|
352
|
+
live web sources with your own Parallel API key. See
|
|
353
|
+
[Parallel Integration](docs/parallel.md).
|
|
354
|
+
- Optional provider workflows can use Parallel, Tavily, and Exa when configured.
|
|
355
|
+
See [CLI Recipes](docs/examples/README.md#parallel-context-pack).
|
|
356
|
+
- SEC filing evidence packs use rule profiles such as
|
|
357
|
+
[vendor-dependency-rules.yml](docs/examples/vendor-dependency-rules.yml).
|
|
358
|
+
|
|
359
|
+
## Security Defaults
|
|
360
|
+
|
|
361
|
+
- HTTPS-only fetching with robots.txt compliance.
|
|
362
|
+
- SSRF protections, private network blocking, DNS rebinding protection, and
|
|
363
|
+
connect-time address pinning.
|
|
364
|
+
- XXE protection for sitemaps.
|
|
365
|
+
- Path traversal and CRLF header injection guards.
|
|
366
|
+
- Auth headers stripped on cross-origin redirects.
|
|
367
|
+
|
|
368
|
+
When running with `--proxy`, DNS pinning is delegated to the proxy. Pass
|
|
369
|
+
`--require-pinned-dns` to refuse that configuration.
|
|
370
|
+
|
|
371
|
+
## Troubleshooting
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
docpull --doctor
|
|
375
|
+
docpull URL --verbose
|
|
376
|
+
docpull URL --dry-run
|
|
377
|
+
docpull URL --preview-urls
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Documentation
|
|
381
|
+
|
|
382
|
+
- [CLI Recipes](docs/examples/README.md) - common commands and advanced workflows.
|
|
383
|
+
- [Scraping Boundary](docs/scraping-boundary.md) - what docpull does and does not fetch.
|
|
384
|
+
- [Alternatives](docs/alternatives.md) - when to use browser automation or hosted extraction.
|
|
385
|
+
- [Corpus Manifest](docs/corpus-manifest.md) - stable IDs, hashes, and source maps.
|
|
386
|
+
- [Parallel Integration](docs/parallel.md) - live-source context pack workflows.
|
|
387
|
+
- [Changelog](docs/CHANGELOG.md) - release history.
|
|
388
|
+
|
|
389
|
+
## Links
|
|
390
|
+
|
|
391
|
+
- [Website](https://docpull.raintree.technology)
|
|
392
|
+
- [PyPI](https://pypi.org/project/docpull/)
|
|
393
|
+
- [GitHub](https://github.com/raintree-technology/docpull)
|
|
394
|
+
- [Metrics](METRICS.md)
|
|
395
|
+
|
|
396
|
+
## License
|
|
397
|
+
|
|
398
|
+
MIT
|
docpull-4.4.1/README.md
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# docpull
|
|
2
|
+
|
|
3
|
+
**Turn public documentation sites into local Markdown, NDJSON, and agent-ready context packs. No browser required.**
|
|
4
|
+
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
[](https://badge.fury.io/py/docpull)
|
|
7
|
+
[](https://pepy.tech/project/docpull)
|
|
8
|
+
[](https://github.com/raintree-technology/docpull/stargazers)
|
|
9
|
+
[](https://github.com/raintree-technology/docpull/blob/main/LICENSE)
|
|
10
|
+
|
|
11
|
+
docpull is a Python CLI, SDK, and MCP server that fetches public static or
|
|
12
|
+
server-rendered web pages and converts them into clean, auditable local
|
|
13
|
+
artifacts for LLMs, retrieval-augmented generation (RAG), offline research, and
|
|
14
|
+
agent workflows.
|
|
15
|
+
|
|
16
|
+
It works best on documentation sites, blogs, API references, OpenAPI specs,
|
|
17
|
+
vendor pages, and other public pages where the useful content is available in
|
|
18
|
+
HTML or embedded page data.
|
|
19
|
+
|
|
20
|
+
docpull is not a browser and does not render JavaScript. JS-only pages are
|
|
21
|
+
skipped with a clear reason. See [Scraping Boundary](docs/scraping-boundary.md)
|
|
22
|
+
and [Alternatives](docs/alternatives.md) for the full boundary.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install docpull
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Install optional extras as needed:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install 'docpull[llm]' # tiktoken for token-accurate chunking
|
|
34
|
+
pip install 'docpull[trafilatura]' # alternative extractor for noisy pages
|
|
35
|
+
pip install 'docpull[mcp]' # stdio MCP server
|
|
36
|
+
pip install 'docpull[parallel]' # Parallel context packs
|
|
37
|
+
pip install 'docpull[observability]' # Raindrop benchmark tracing
|
|
38
|
+
pip install 'docpull[all]' # all optional extras
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 30-Second Usage
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
docpull https://docs.python.org/3/library/asyncio.html --single -o ./asyncio-docs
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Example output:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
asyncio-docs/
|
|
51
|
+
index.md
|
|
52
|
+
corpus.manifest.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Markdown includes source metadata and readable page content:
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
---
|
|
59
|
+
title: "asyncio - Asynchronous I/O"
|
|
60
|
+
source: https://docs.python.org/3/library/asyncio.html
|
|
61
|
+
source_type: "sphinx"
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
# asyncio - Asynchronous I/O
|
|
65
|
+
|
|
66
|
+
asyncio is a library to write concurrent code using the async/await syntax.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Stream chunked NDJSON for agents and RAG:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
docpull https://docs.python.org/3/library/asyncio.html \
|
|
73
|
+
--single \
|
|
74
|
+
--profile llm \
|
|
75
|
+
--stream | jq .
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Each line is a JSON document:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{"schema_version":1,"document_id":"doc_...","chunk_id":"chunk_...","url":"https://docs.python.org/3/library/asyncio.html","title":"asyncio - Asynchronous I/O","content":"asyncio is a library to write concurrent code...","source_type":"sphinx","chunk_index":0,"token_count":842}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Common Workflows
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Crawl a site and write Markdown files
|
|
88
|
+
docpull https://docs.example.com -o ./docs-example
|
|
89
|
+
|
|
90
|
+
# Stream LLM-ready NDJSON chunks from a site
|
|
91
|
+
docpull https://docs.example.com --profile llm --stream | jq .
|
|
92
|
+
|
|
93
|
+
# Write SQLite with an FTS5 search index
|
|
94
|
+
docpull https://docs.example.com --format sqlite -o ./docs-db
|
|
95
|
+
|
|
96
|
+
# Build an Open Knowledge Format (OKF) bundle for portable source packs
|
|
97
|
+
docpull https://example.com --profile okf -o ./site-okf
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
More examples live in [CLI Recipes](docs/examples/README.md).
|
|
101
|
+
|
|
102
|
+
Use docpull when you need to:
|
|
103
|
+
|
|
104
|
+
- Convert public docs, blogs, API references, vendor pages, and OpenAPI specs
|
|
105
|
+
into Markdown or chunked NDJSON for LLM and RAG pipelines.
|
|
106
|
+
- Give an agent a local tool for fetching, caching, grepping, and reading web
|
|
107
|
+
sources.
|
|
108
|
+
- Build repeatable context packs with stable IDs, hashes, manifests, and source
|
|
109
|
+
metadata.
|
|
110
|
+
- Mirror public web content for offline work while preserving attribution.
|
|
111
|
+
|
|
112
|
+
## Why docpull?
|
|
113
|
+
|
|
114
|
+
docpull is designed for agent and RAG workflows, not just downloading pages.
|
|
115
|
+
|
|
116
|
+
| Need | docpull gives you |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| Clean Markdown | Article-focused extraction with source metadata |
|
|
119
|
+
| LLM chunks | NDJSON streaming and optional token-aware chunking |
|
|
120
|
+
| Repeatability | Stable document IDs, chunk IDs, hashes, and manifests |
|
|
121
|
+
| Offline work | Cached archives and mirrored source artifacts |
|
|
122
|
+
| Agent access | Local CLI, Python SDK, and stdio MCP server |
|
|
123
|
+
| Safer fetching | HTTPS defaults, robots.txt compliance, SSRF protections, and redirect guards |
|
|
124
|
+
|
|
125
|
+
## Supported Sources
|
|
126
|
+
|
|
127
|
+
docpull uses async HTTP instead of browser automation and includes special
|
|
128
|
+
handling for common documentation and API surfaces.
|
|
129
|
+
|
|
130
|
+
| Source shape | Support |
|
|
131
|
+
| --- | --- |
|
|
132
|
+
| Static HTML / SSR docs | Extracts article or document regions |
|
|
133
|
+
| Next.js / Mintlify | Parses static HTML and `__NEXT_DATA__` when available |
|
|
134
|
+
| OpenAPI / Swagger | Renders specs into Markdown |
|
|
135
|
+
| Docusaurus / Sphinx / MkDocs | Extracts static article or document regions |
|
|
136
|
+
| VitePress / VuePress / Astro Starlight | Extracts static docs content |
|
|
137
|
+
| GitBook / ReadMe.io | Extracts available article or content regions |
|
|
138
|
+
| Redoc / Scalar | Extracts static API reference regions |
|
|
139
|
+
| JS-only apps | Skipped unless useful content is present in HTML or embedded data |
|
|
140
|
+
|
|
141
|
+
Use `--strict-js-required` when an agent should treat JS-only pages as hard
|
|
142
|
+
errors instead of normal skips.
|
|
143
|
+
|
|
144
|
+
## Output Formats
|
|
145
|
+
|
|
146
|
+
| Output | Use it for |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| Markdown | Local readable source snapshots with YAML frontmatter |
|
|
149
|
+
| NDJSON | Streamed records or chunked records for agents and RAG |
|
|
150
|
+
| SQLite | Local retrieval with an FTS5 index |
|
|
151
|
+
| OKF | Portable Open Knowledge Format bundles with indexes and manifests |
|
|
152
|
+
| Archive / mirror | Cached offline source snapshots |
|
|
153
|
+
|
|
154
|
+
Every file-backed run writes `corpus.manifest.json` with stable document IDs,
|
|
155
|
+
chunk IDs, hashes, output paths, and chunk counts. See
|
|
156
|
+
[Corpus Manifest](docs/corpus-manifest.md).
|
|
157
|
+
|
|
158
|
+
## Profiles
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
docpull https://site.com --profile rag # Default. Dedup + metadata.
|
|
162
|
+
docpull https://site.com --profile llm # NDJSON chunks for agents/RAG.
|
|
163
|
+
docpull https://site.com --profile okf # Portable Open Knowledge Format bundle.
|
|
164
|
+
docpull https://site.com --profile mirror # Cached archive.
|
|
165
|
+
docpull https://site.com --profile quick # Small sampling crawl.
|
|
166
|
+
docpull https://site.com --profile sec-filing # EDGAR-friendly evidence chunks.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Run `docpull --help` for the full option list.
|
|
170
|
+
|
|
171
|
+
## When Not to Use docpull
|
|
172
|
+
|
|
173
|
+
docpull intentionally does not use a browser. It is not the right tool for:
|
|
174
|
+
|
|
175
|
+
- JS-only pages that require client-side rendering.
|
|
176
|
+
- Authenticated dashboards or private apps.
|
|
177
|
+
- Pages behind CAPTCHA or bot challenges.
|
|
178
|
+
- Workflows that require clicking, scrolling, or browser state.
|
|
179
|
+
|
|
180
|
+
For those cases, use browser automation, such as Playwright, then pass the
|
|
181
|
+
rendered HTML or exported content into your pipeline.
|
|
182
|
+
|
|
183
|
+
## How It Compares
|
|
184
|
+
|
|
185
|
+
| Tool type | Best for | Tradeoff |
|
|
186
|
+
| --- | --- | --- |
|
|
187
|
+
| `wget` / site mirroring | Downloading raw files | Not agent/RAG-oriented |
|
|
188
|
+
| Browser automation | JS-heavy pages and interactions | Slower, heavier, more stateful |
|
|
189
|
+
| Hosted extraction APIs | Managed extraction at scale | External dependency and cost |
|
|
190
|
+
| docpull | Local public-doc extraction and context packs | No JavaScript rendering |
|
|
191
|
+
|
|
192
|
+
## Python SDK
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from docpull import fetch_one
|
|
196
|
+
|
|
197
|
+
ctx = fetch_one("https://docs.python.org/3/library/asyncio.html")
|
|
198
|
+
print(ctx.title)
|
|
199
|
+
print(ctx.markdown[:500])
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
import asyncio
|
|
204
|
+
from docpull import Fetcher, DocpullConfig, EventType, ProfileName
|
|
205
|
+
|
|
206
|
+
async def main():
|
|
207
|
+
cfg = DocpullConfig(url="https://docs.example.com", profile=ProfileName.LLM)
|
|
208
|
+
async with Fetcher(cfg) as fetcher:
|
|
209
|
+
async for event in fetcher.run():
|
|
210
|
+
if event.type == EventType.FETCH_PROGRESS:
|
|
211
|
+
print(f"{event.current}/{event.total}: {event.url}")
|
|
212
|
+
|
|
213
|
+
asyncio.run(main())
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## MCP Server
|
|
217
|
+
|
|
218
|
+
docpull can run as a stdio MCP server for agent clients:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
pip install 'docpull[mcp]'
|
|
222
|
+
docpull mcp
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Claude Code:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
claude mcp add --transport stdio docpull -- docpull mcp
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Cursor and Claude Desktop use the same `mcpServers` shape:
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"mcpServers": {
|
|
236
|
+
"docpull": {
|
|
237
|
+
"type": "stdio",
|
|
238
|
+
"command": "docpull",
|
|
239
|
+
"args": ["mcp"]
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The supported MCP path is the Python stdio server started by `docpull mcp`.
|
|
246
|
+
The repository's `mcp/` directory is an internal TypeScript/Bun lab and is not
|
|
247
|
+
part of the package release contract.
|
|
248
|
+
|
|
249
|
+
## Advanced Workflows
|
|
250
|
+
|
|
251
|
+
- `docpull[parallel]` can discover, extract, enrich, score, diff, and archive
|
|
252
|
+
live web sources with your own Parallel API key. See
|
|
253
|
+
[Parallel Integration](docs/parallel.md).
|
|
254
|
+
- Optional provider workflows can use Parallel, Tavily, and Exa when configured.
|
|
255
|
+
See [CLI Recipes](docs/examples/README.md#parallel-context-pack).
|
|
256
|
+
- SEC filing evidence packs use rule profiles such as
|
|
257
|
+
[vendor-dependency-rules.yml](docs/examples/vendor-dependency-rules.yml).
|
|
258
|
+
|
|
259
|
+
## Security Defaults
|
|
260
|
+
|
|
261
|
+
- HTTPS-only fetching with robots.txt compliance.
|
|
262
|
+
- SSRF protections, private network blocking, DNS rebinding protection, and
|
|
263
|
+
connect-time address pinning.
|
|
264
|
+
- XXE protection for sitemaps.
|
|
265
|
+
- Path traversal and CRLF header injection guards.
|
|
266
|
+
- Auth headers stripped on cross-origin redirects.
|
|
267
|
+
|
|
268
|
+
When running with `--proxy`, DNS pinning is delegated to the proxy. Pass
|
|
269
|
+
`--require-pinned-dns` to refuse that configuration.
|
|
270
|
+
|
|
271
|
+
## Troubleshooting
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
docpull --doctor
|
|
275
|
+
docpull URL --verbose
|
|
276
|
+
docpull URL --dry-run
|
|
277
|
+
docpull URL --preview-urls
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Documentation
|
|
281
|
+
|
|
282
|
+
- [CLI Recipes](docs/examples/README.md) - common commands and advanced workflows.
|
|
283
|
+
- [Scraping Boundary](docs/scraping-boundary.md) - what docpull does and does not fetch.
|
|
284
|
+
- [Alternatives](docs/alternatives.md) - when to use browser automation or hosted extraction.
|
|
285
|
+
- [Corpus Manifest](docs/corpus-manifest.md) - stable IDs, hashes, and source maps.
|
|
286
|
+
- [Parallel Integration](docs/parallel.md) - live-source context pack workflows.
|
|
287
|
+
- [Changelog](docs/CHANGELOG.md) - release history.
|
|
288
|
+
|
|
289
|
+
## Links
|
|
290
|
+
|
|
291
|
+
- [Website](https://docpull.raintree.technology)
|
|
292
|
+
- [PyPI](https://pypi.org/project/docpull/)
|
|
293
|
+
- [GitHub](https://github.com/raintree-technology/docpull)
|
|
294
|
+
- [Metrics](METRICS.md)
|
|
295
|
+
|
|
296
|
+
## License
|
|
297
|
+
|
|
298
|
+
MIT
|