docpull 4.0.0__tar.gz → 4.1.0__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.0.0/src/docpull.egg-info → docpull-4.1.0}/PKG-INFO +184 -27
- docpull-4.1.0/README.md +476 -0
- {docpull-4.0.0 → docpull-4.1.0}/pyproject.toml +6 -2
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/__init__.py +1 -6
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/cache/__init__.py +4 -0
- docpull-4.1.0/src/docpull/cache/frontier.py +199 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/cache/manager.py +140 -23
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/cli.py +44 -17
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/conversion/chunking.py +56 -23
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/conversion/extractor.py +129 -1
- docpull-4.1.0/src/docpull/conversion/markdown.py +516 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/conversion/special_cases.py +108 -3
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/core/fetcher.py +111 -53
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/__init__.py +0 -4
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/crawler.py +0 -19
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/filters.py +1 -6
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/sitemap.py +0 -4
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/doctor.py +0 -13
- docpull-4.1.0/src/docpull/fixtures/__init__.py +1 -0
- docpull-4.1.0/src/docpull/fixtures/parallel-search-extract.json +103 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/http/client.py +80 -11
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/mcp/server.py +299 -1
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/mcp/sources.py +1 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/mcp/tools.py +92 -17
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/models/__init__.py +16 -3
- docpull-4.1.0/src/docpull/models/document.py +78 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/models/events.py +41 -2
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/models/profiles.py +6 -8
- docpull-4.1.0/src/docpull/models/run.py +60 -0
- docpull-4.1.0/src/docpull/pack_tools.py +500 -0
- docpull-4.1.0/src/docpull/parallel_workflows.py +5809 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/base.py +60 -12
- docpull-4.1.0/src/docpull/pipeline/manifest.py +74 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/convert.py +46 -6
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/dedup.py +11 -4
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/fetch.py +20 -32
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/save.py +53 -6
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/save_json.py +30 -11
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/save_ndjson.py +39 -21
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/save_sqlite.py +68 -10
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/validate.py +10 -7
- docpull-4.1.0/src/docpull/security/__init__.py +13 -0
- docpull-4.1.0/src/docpull/security/download_policy.py +339 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/security/url_validator.py +0 -6
- docpull-4.1.0/src/docpull/source_scoring.py +98 -0
- {docpull-4.0.0 → docpull-4.1.0/src/docpull.egg-info}/PKG-INFO +184 -27
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull.egg-info/SOURCES.txt +15 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull.egg-info/requires.txt +4 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_chunking.py +24 -0
- docpull-4.1.0/tests/test_cli.py +116 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_conversion.py +88 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_convert_step_new.py +31 -8
- docpull-4.1.0/tests/test_frontier_resume.py +35 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_integration.py +67 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_mcp_server.py +13 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_mcp_tools.py +40 -1
- docpull-4.1.0/tests/test_outputs_e2e.py +120 -0
- docpull-4.1.0/tests/test_pack_tools.py +241 -0
- docpull-4.1.0/tests/test_parallel_workflows.py +2205 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_save_ndjson.py +2 -0
- docpull-4.1.0/tests/test_save_sqlite.py +52 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_security_hardening.py +299 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_special_cases.py +99 -1
- docpull-4.0.0/README.md +0 -322
- docpull-4.0.0/src/docpull/conversion/markdown.py +0 -280
- docpull-4.0.0/src/docpull/security/__init__.py +0 -6
- docpull-4.0.0/tests/test_cli.py +0 -20
- {docpull-4.0.0 → docpull-4.1.0}/LICENSE +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/setup.cfg +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/__main__.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/cache/streaming_dedup.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/conversion/__init__.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/conversion/protocols.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/conversion/trafilatura_extractor.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/core/__init__.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/_fetch.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/composite.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/link_extractors/__init__.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/link_extractors/enhanced.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/link_extractors/protocols.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/link_extractors/static.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/discovery/protocols.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/http/__init__.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/http/protocols.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/http/rate_limiter.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/mcp/__init__.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/metadata_extractor.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/models/config.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/__init__.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/__init__.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/chunk.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/pipeline/steps/metadata.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/py.typed +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/security/robots.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull/time_utils.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull.egg-info/dependency_links.txt +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull.egg-info/entry_points.txt +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/src/docpull.egg-info/top_level.txt +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_cache_conditional_get.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_ci_policy.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_discovery.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_link_extractors.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_naming.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_pipeline.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_real_site_regressions.py +0 -0
- {docpull-4.0.0 → docpull-4.1.0}/tests/test_time_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docpull
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.1.0
|
|
4
4
|
Summary: Pull documentation from the web and convert to clean markdown
|
|
5
5
|
Author-email: Zachary Roth <support@raintree.technology>
|
|
6
6
|
Maintainer-email: Raintree Technology <support@raintree.technology>
|
|
@@ -62,6 +62,8 @@ Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
|
62
62
|
Requires-Dist: pyjwt>=2.13.0; extra == "mcp"
|
|
63
63
|
Requires-Dist: python-multipart>=0.0.27; extra == "mcp"
|
|
64
64
|
Requires-Dist: starlette>=1.0.1; extra == "mcp"
|
|
65
|
+
Provides-Extra: parallel
|
|
66
|
+
Requires-Dist: parallel-web>=1.0.1; extra == "parallel"
|
|
65
67
|
Provides-Extra: llm
|
|
66
68
|
Requires-Dist: tiktoken>=0.7.0; extra == "llm"
|
|
67
69
|
Provides-Extra: all
|
|
@@ -73,6 +75,7 @@ Requires-Dist: mcp>=1.0.0; extra == "all"
|
|
|
73
75
|
Requires-Dist: pyjwt>=2.13.0; extra == "all"
|
|
74
76
|
Requires-Dist: python-multipart>=0.0.27; extra == "all"
|
|
75
77
|
Requires-Dist: starlette>=1.0.1; extra == "all"
|
|
78
|
+
Requires-Dist: parallel-web>=1.0.1; extra == "all"
|
|
76
79
|
Provides-Extra: dev
|
|
77
80
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
78
81
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -152,7 +155,7 @@ content directly from framework data feeds:
|
|
|
152
155
|
| Mintlify | `__NEXT_DATA__` with Mintlify tagging |
|
|
153
156
|
| OpenAPI | Renders `openapi.json` / `swagger.json` into Markdown |
|
|
154
157
|
| Docusaurus| Detected and tagged; generic extractor produces Markdown |
|
|
155
|
-
| Sphinx | Detected and tagged; generic extractor produces Markdown |
|
|
158
|
+
| Sphinx | Detected from generator metadata / Read the Docs hosts and tagged; generic extractor produces Markdown |
|
|
156
159
|
|
|
157
160
|
JS-only SPAs with no server-rendered content are detected and skipped with a
|
|
158
161
|
clear reason (or, with `--strict-js-required`, reported as an error so agents
|
|
@@ -215,11 +218,146 @@ async def tool_call(url: str) -> str:
|
|
|
215
218
|
|
|
216
219
|
```bash
|
|
217
220
|
docpull https://site.com --profile rag # Default. Dedup, rich metadata.
|
|
218
|
-
docpull https://site.com --profile llm # NDJSON + chunks + metadata.
|
|
219
|
-
docpull https://site.com --profile mirror # Full archive, polite, cached.
|
|
221
|
+
docpull https://site.com --profile llm # NDJSON + chunks + metadata; JS-only pages skip unless --strict-js-required is passed.
|
|
222
|
+
docpull https://site.com --profile mirror # Full archive, polite, cached, hierarchical paths.
|
|
220
223
|
docpull https://site.com --profile quick # Sampling: 50 pages, depth 2.
|
|
221
224
|
```
|
|
222
225
|
|
|
226
|
+
## Parallel context packs
|
|
227
|
+
|
|
228
|
+
`docpull[parallel]` adds an optional source-discovery and research layer on top
|
|
229
|
+
of Parallel web intelligence APIs. Use the core crawler when you already know
|
|
230
|
+
the docs URL. Use Parallel packs when an agent needs current web sources found,
|
|
231
|
+
extracted, researched, organized, and loaded as durable local context.
|
|
232
|
+
|
|
233
|
+
Parallel handles live Search, Extract, Task, Entity Search, FindAll, TaskGroup,
|
|
234
|
+
and Monitor calls. docpull turns those results into local, inspectable packs
|
|
235
|
+
with Markdown, NDJSON, manifests, hashes, source indexes, workflow metadata, and
|
|
236
|
+
an `AGENT_CONTEXT.md` load plan so agents do not need to reverse-engineer raw API
|
|
237
|
+
responses before using the pack.
|
|
238
|
+
|
|
239
|
+
Live calls use your own Parallel API key. docpull never proxies requests through
|
|
240
|
+
a shared account or writes the key into pack artifacts. For normal PyPI installs,
|
|
241
|
+
`docpull parallel init` stores the key in a local secrets file with restricted
|
|
242
|
+
permissions so it works across shells and agent sessions. Pack artifacts can
|
|
243
|
+
still contain source content, workflow inputs/outputs, selected URLs, and
|
|
244
|
+
metadata, so treat them as research data.
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
pip install 'docpull[parallel]'
|
|
248
|
+
|
|
249
|
+
# Recommended local setup. Prompts securely and writes ~/.config/docpull/secrets.env.
|
|
250
|
+
docpull parallel init
|
|
251
|
+
docpull parallel auth --json
|
|
252
|
+
|
|
253
|
+
# Optional project-local setup for agent worktrees. Writes .env.local and
|
|
254
|
+
# adds it to .gitignore.
|
|
255
|
+
docpull parallel init --project
|
|
256
|
+
|
|
257
|
+
# CI can still use a normal environment secret instead.
|
|
258
|
+
export PARALLEL_API_KEY="<your-parallel-api-key>"
|
|
259
|
+
|
|
260
|
+
docpull parallel context-pack "Compare AI web-search APIs for agents" \
|
|
261
|
+
--query "AI web search API" \
|
|
262
|
+
--query "agent web extraction API" \
|
|
263
|
+
--include-domain parallel.ai \
|
|
264
|
+
--exclude-domain onparallel.com \
|
|
265
|
+
--output-dir ./packs/ai-web-search \
|
|
266
|
+
--mode advanced \
|
|
267
|
+
--extract-limit 8 \
|
|
268
|
+
--max-estimated-cost 0.05 \
|
|
269
|
+
--task-brief
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`docpull parallel auth` checks local SDK/key presence without printing the key
|
|
273
|
+
value and reports the key source (`env`, `project_env`, `user_config`, or
|
|
274
|
+
`missing`). It does not make a live Parallel call or prove the key is valid. Use
|
|
275
|
+
`--json` when an agent or CI job needs machine-readable configuration status.
|
|
276
|
+
|
|
277
|
+
The pack contains:
|
|
278
|
+
|
|
279
|
+
- `AGENT_CONTEXT.md` — agent load plan with source order, pack signals, warnings, errors, and artifact map.
|
|
280
|
+
- `documents.ndjson` — chunked records for agents and RAG pipelines.
|
|
281
|
+
- `corpus.manifest.json` — stable docpull record manifest.
|
|
282
|
+
- `parallel.pack.json` — Parallel workflow metadata, selected URLs, errors, IDs, and usage.
|
|
283
|
+
- `sources.md` and `sources/*.md` — human-readable sources and extracted Markdown.
|
|
284
|
+
- `brief.md` when `--task-brief` is enabled.
|
|
285
|
+
|
|
286
|
+
That makes the Parallel layer more than a pass-through wrapper: Parallel finds
|
|
287
|
+
and enriches live web sources, while docpull normalizes them into a repeatable
|
|
288
|
+
context pack that can be scored, diffed, audited, and loaded offline.
|
|
289
|
+
|
|
290
|
+
For planning without spending credits, use `--dry-run`. For repeatable packs,
|
|
291
|
+
use `--include-domain`, `--exclude-domain`, `--after-date`, and `--max-search-results`
|
|
292
|
+
to pin the source policy that appears later in `parallel.pack.json`.
|
|
293
|
+
Use `--fetch-max-age-seconds`, `--fetch-timeout-seconds`,
|
|
294
|
+
`--disable-cache-fallback`, `--excerpt-chars-per-result`, and `--location`
|
|
295
|
+
when you need Parallel's freshness, excerpt-size, and geo controls.
|
|
296
|
+
|
|
297
|
+
Offline fixtures are supported for demos and tests without a Parallel account:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
docpull parallel demo --output-dir ./packs/demo
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
When working from the source checkout, the same fixture can also be imported
|
|
304
|
+
directly with `docpull parallel import ./docs/examples/parallel-search-extract.json`.
|
|
305
|
+
|
|
306
|
+
The core workflow is Search + Extract + optional Task. Broader pack workflows
|
|
307
|
+
cover Search-only snapshots, docs discovery plans, Extract-known-URL packs,
|
|
308
|
+
core-fetch-with-Parallel-fallback packs, diff briefs, Task lifecycle snapshots,
|
|
309
|
+
Entity Search, FindAll lifecycle actions, TaskGroup batches, Monitor
|
|
310
|
+
metadata/events, API specs, and local source scoring.
|
|
311
|
+
See [docs/parallel.md](docs/parallel.md) for the Parallel product cross-reference
|
|
312
|
+
and the boundary between docpull, Parallel MCP, and planned workflows.
|
|
313
|
+
|
|
314
|
+
Additional Parallel-backed artifact commands:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
# Readiness and API-key setup checks.
|
|
318
|
+
docpull parallel auth
|
|
319
|
+
docpull parallel init
|
|
320
|
+
docpull parallel init --project
|
|
321
|
+
|
|
322
|
+
# Search + Extract + optional Task brief.
|
|
323
|
+
docpull parallel context-pack "Compare AI web-search APIs for agents" \
|
|
324
|
+
--query "AI web search API" \
|
|
325
|
+
--include-domain parallel.ai \
|
|
326
|
+
--dry-run
|
|
327
|
+
|
|
328
|
+
# Search-only, docs-discovery, known-URL extract, fallback, and structured Task packs.
|
|
329
|
+
docpull parallel search-pack "Parallel Search API docs" --query "Parallel Search API" --dry-run
|
|
330
|
+
docpull parallel discover-docs "Find Parallel API docs" \
|
|
331
|
+
--query "Parallel Search API docs" \
|
|
332
|
+
--include-domain docs.parallel.ai \
|
|
333
|
+
--dry-run
|
|
334
|
+
docpull parallel extract-pack https://docs.parallel.ai/api-reference/search/search --dry-run
|
|
335
|
+
docpull parallel fallback-pack https://docs.parallel.ai/api-reference/search/search --dry-run
|
|
336
|
+
docpull parallel task-pack "Research Parallel Search API" \
|
|
337
|
+
--source-include-domain docs.parallel.ai \
|
|
338
|
+
--output-schema-json '{"type":"object","properties":{"summary":{"type":"string"}},"required":["summary"]}' \
|
|
339
|
+
--dry-run
|
|
340
|
+
|
|
341
|
+
# Entity dossiers, FindAll lifecycle, batch enrichment, monitors, and API specs.
|
|
342
|
+
docpull parallel entity-pack "AI developer infrastructure companies" --entity-type companies
|
|
343
|
+
docpull parallel findall-pack "AI developer infrastructure companies" --generator preview --dry-run
|
|
344
|
+
docpull parallel findall-ingest-pack "Find companies with public API docs"
|
|
345
|
+
docpull parallel findall-result-pack findall_123 --output-dir ./packs/findall-result
|
|
346
|
+
docpull parallel taskgroup-pack ./companies.json --prompt-template "Research {company}" --dry-run
|
|
347
|
+
docpull parallel taskgroup-pack ./companies.json --prompt-template "Research {company}" --wait
|
|
348
|
+
docpull parallel monitor-pack create "New vendor pricing changes" --dry-run
|
|
349
|
+
docpull parallel monitor-pack create --type snapshot --task-run-id run_123 --dry-run
|
|
350
|
+
docpull parallel monitor-pack list --status active --output-dir ./packs/monitors
|
|
351
|
+
docpull parallel monitor-pack events monitor_123 --cursor next_cursor --output-dir ./packs/events
|
|
352
|
+
docpull parallel api-pack https://docs.parallel.ai/public-openapi.json --output-dir ./packs/parallel-openapi
|
|
353
|
+
docpull parallel run ./docs/examples/parallel-llms-api-pack.yaml --dry-run
|
|
354
|
+
docpull parallel run ./docs/examples/parallel-openapi-api-pack.yaml --dry-run
|
|
355
|
+
docpull pack score ./packs/parallel-openapi
|
|
356
|
+
docpull pack sources ./packs/parallel-openapi --require-domain docs.parallel.ai
|
|
357
|
+
docpull pack diff ./packs/old ./packs/new --markdown ./packs/changes.md
|
|
358
|
+
docpull parallel diff-brief ./packs/old ./packs/new --dry-run
|
|
359
|
+
```
|
|
360
|
+
|
|
223
361
|
## MCP server
|
|
224
362
|
|
|
225
363
|
docpull ships an MCP (Model Context Protocol) server so AI agents can call it
|
|
@@ -271,21 +409,27 @@ pip install 'docpull[mcp]'
|
|
|
271
409
|
|
|
272
410
|
See [plugin/README.md](plugin/README.md) for details.
|
|
273
411
|
|
|
274
|
-
Tools exposed (
|
|
412
|
+
Tools exposed (12 total — read tools advertise `readOnlyHint` so hosts that auto-approve safe tools won't prompt):
|
|
275
413
|
|
|
276
414
|
Read:
|
|
277
415
|
- `fetch_url(url, max_tokens?)` — one-shot fetch, no crawl. HTTPS-only, SSRF-validated.
|
|
278
|
-
- `list_sources(category?)` — show available aliases (react, nextjs, fastapi, …)
|
|
416
|
+
- `list_sources(category?)` — show available aliases (react, nextjs, parallel, fastapi, …)
|
|
279
417
|
- `list_indexed()` — what has been fetched locally, with last-fetched age
|
|
280
418
|
- `grep_docs(pattern, library?, limit?, context?)` — regex search across fetched Markdown (length-capped + wall-clock budgeted to mitigate ReDoS)
|
|
281
419
|
- `read_doc(library, path, line_start?, line_end?)` — read a specific cached file, optionally line-sliced
|
|
420
|
+
- `pack_score(pack_dir, required_domains?)` — score a local context pack for agent readiness.
|
|
421
|
+
- `pack_diff(old_pack_dir, new_pack_dir)` — compare pack URL sets and content hashes.
|
|
282
422
|
|
|
283
423
|
Write:
|
|
284
424
|
- `ensure_docs(source, force?, profile?)` — fetch a named library (cached 7 days). Forwards progress to clients that supply a `progressToken`.
|
|
425
|
+
- `parallel_context_pack(...)` — build or dry-run a Parallel Search + Extract pack without shelling out.
|
|
426
|
+
- `parallel_api_pack(source, kind?, output_dir?)` — build a pack from `llms.txt` or OpenAPI.
|
|
285
427
|
- `add_source(name, url, description?, category?, max_pages?, force?)` — register a user alias (HTTPS-only, atomic write to `sources.yaml`).
|
|
286
428
|
- `remove_source(name, delete_cache?)` — drop a user alias and (optionally) its cached docs.
|
|
287
429
|
|
|
288
|
-
All tools
|
|
430
|
+
All schema-backed tools return `structuredContent` validated against an
|
|
431
|
+
`outputSchema` for clients that prefer typed output. `fetch_url` intentionally
|
|
432
|
+
returns Markdown text directly.
|
|
289
433
|
|
|
290
434
|
User-defined sources live in `~/.config/docpull-mcp/sources.yaml`:
|
|
291
435
|
|
|
@@ -298,16 +442,17 @@ sources:
|
|
|
298
442
|
maxPages: 200
|
|
299
443
|
```
|
|
300
444
|
|
|
301
|
-
###
|
|
445
|
+
### Supported MCP path
|
|
302
446
|
|
|
303
|
-
The
|
|
304
|
-
|
|
305
|
-
the
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
and
|
|
447
|
+
The supported MCP server is the Python stdio server started by `docpull mcp`.
|
|
448
|
+
That is the only MCP path covered by the `docpull` package release contract and
|
|
449
|
+
the one agents, plugin users, Claude Code, Cursor, and Claude Desktop should
|
|
450
|
+
use.
|
|
451
|
+
|
|
452
|
+
This repository also contains an `mcp/` directory with an internal TypeScript +
|
|
453
|
+
Bun lab for PostgreSQL/pgvector semantic search. It is not shipped by the Python
|
|
454
|
+
package, is not documented as a user install path, and should be ignored unless
|
|
455
|
+
you are explicitly developing that lab.
|
|
311
456
|
|
|
312
457
|
## Output
|
|
313
458
|
|
|
@@ -327,9 +472,14 @@ source_type: "nextjs"
|
|
|
327
472
|
NDJSON (one record per page or chunk):
|
|
328
473
|
|
|
329
474
|
```json
|
|
330
|
-
{"url": "...", "title": "...", "content": "...", "hash": "...", "token_count": 842, "chunk_index": 0}
|
|
475
|
+
{"document_id": "doc_...", "chunk_id": "chunk_...", "url": "...", "title": "...", "content": "...", "hash": "...", "token_count": 842, "chunk_index": 0}
|
|
331
476
|
```
|
|
332
477
|
|
|
478
|
+
Every output format also writes `corpus.manifest.json` next to the generated
|
|
479
|
+
documents. The manifest records the run identity, output format, stable
|
|
480
|
+
`document_id` / `chunk_id` values, content hashes, relative output paths, and
|
|
481
|
+
chunk counts so regenerated corpora can be diffed and cited by agents.
|
|
482
|
+
|
|
333
483
|
## Security
|
|
334
484
|
|
|
335
485
|
- HTTPS-only, mandatory robots.txt compliance
|
|
@@ -349,7 +499,7 @@ Run `docpull --help` for the full list. Highlights:
|
|
|
349
499
|
|
|
350
500
|
```
|
|
351
501
|
Core:
|
|
352
|
-
--profile {rag,mirror,quick,llm
|
|
502
|
+
--profile {rag,mirror,quick,llm}
|
|
353
503
|
--single Fetch one URL (no crawl)
|
|
354
504
|
--format {markdown,json,ndjson,sqlite}
|
|
355
505
|
--stream Stream NDJSON to stdout
|
|
@@ -368,27 +518,34 @@ Cache:
|
|
|
368
518
|
--cache Enable incremental updates
|
|
369
519
|
--cache-dir DIR
|
|
370
520
|
--cache-ttl DAYS
|
|
521
|
+
|
|
522
|
+
Crawl:
|
|
523
|
+
--max-concurrent N Global request concurrency
|
|
524
|
+
--per-host-concurrent N Per-host request concurrency
|
|
371
525
|
```
|
|
372
526
|
|
|
373
527
|
## Performance
|
|
374
528
|
|
|
375
529
|
End-to-end numbers from `tests/benchmarks/test_10k_pages.py` against a
|
|
376
530
|
synthetic 10,000-page localhost site (RAG profile, `max_concurrent=50`,
|
|
377
|
-
HTTP keep-alive, 5% injected duplicate content)
|
|
531
|
+
`per_host_concurrent=50`, HTTP keep-alive, 5% injected duplicate content).
|
|
532
|
+
The benchmark emits progress every 1,000 pages plus a final JSON report for
|
|
533
|
+
trend tooling. Wall time varies by machine; the value below is the latest
|
|
534
|
+
local audit run.
|
|
378
535
|
|
|
379
536
|
| Metric | Value |
|
|
380
537
|
|---|---|
|
|
381
|
-
| Total wall time | ~
|
|
382
|
-
|
|
|
383
|
-
|
|
|
384
|
-
| Per-page latency p50 / p95 / p99 | ~
|
|
385
|
-
| Peak RSS delta from baseline | ~
|
|
386
|
-
| Cache manifest size on disk | ~
|
|
538
|
+
| Total wall time | ~309 s |
|
|
539
|
+
| Pages fetched / skipped / failed | 9,501 / 499 / 0 |
|
|
540
|
+
| Time to first saved page | ~119 ms |
|
|
541
|
+
| Per-page latency p50 / p95 / p99 | ~0 / 168 / 271 ms |
|
|
542
|
+
| Peak RSS delta from baseline | ~93 MB |
|
|
543
|
+
| Cache manifest size on disk | ~8.9 MB |
|
|
387
544
|
| Duplicates detected (5% injected) | 499 / 500 |
|
|
388
545
|
|
|
389
546
|
Reproduce with `make benchmark` (requires `aiohttp`; runs the gated
|
|
390
|
-
benchmark in `tests/benchmarks/` and prints a JSON line you can
|
|
391
|
-
into trend tooling).
|
|
547
|
+
benchmark in `tests/benchmarks/` and prints progress plus a JSON line you can
|
|
548
|
+
pipe into trend tooling).
|
|
392
549
|
|
|
393
550
|
## Troubleshooting
|
|
394
551
|
|