docpull 3.0.1__tar.gz → 3.0.2__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.
Files changed (88) hide show
  1. {docpull-3.0.1/src/docpull.egg-info → docpull-3.0.2}/PKG-INFO +12 -2
  2. {docpull-3.0.1 → docpull-3.0.2}/README.md +11 -1
  3. {docpull-3.0.1 → docpull-3.0.2}/pyproject.toml +1 -1
  4. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/__init__.py +1 -1
  5. {docpull-3.0.1 → docpull-3.0.2/src/docpull.egg-info}/PKG-INFO +12 -2
  6. {docpull-3.0.1 → docpull-3.0.2}/src/docpull.egg-info/SOURCES.txt +1 -0
  7. {docpull-3.0.1 → docpull-3.0.2}/tests/test_cli.py +7 -0
  8. docpull-3.0.2/tests/test_mcp_server.py +51 -0
  9. {docpull-3.0.1 → docpull-3.0.2}/LICENSE +0 -0
  10. {docpull-3.0.1 → docpull-3.0.2}/setup.cfg +0 -0
  11. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/__main__.py +0 -0
  12. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/cache/__init__.py +0 -0
  13. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/cache/manager.py +0 -0
  14. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/cache/streaming_dedup.py +0 -0
  15. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/cli.py +0 -0
  16. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/concurrency/__init__.py +0 -0
  17. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/concurrency/manager.py +0 -0
  18. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/conversion/__init__.py +0 -0
  19. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/conversion/chunking.py +0 -0
  20. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/conversion/extractor.py +0 -0
  21. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/conversion/markdown.py +0 -0
  22. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/conversion/protocols.py +0 -0
  23. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/conversion/special_cases.py +0 -0
  24. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/conversion/trafilatura_extractor.py +0 -0
  25. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/core/__init__.py +0 -0
  26. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/core/fetcher.py +0 -0
  27. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/__init__.py +0 -0
  28. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/composite.py +0 -0
  29. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/crawler.py +0 -0
  30. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/filters.py +0 -0
  31. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/link_extractors/__init__.py +0 -0
  32. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/link_extractors/enhanced.py +0 -0
  33. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/link_extractors/protocols.py +0 -0
  34. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/link_extractors/static.py +0 -0
  35. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/protocols.py +0 -0
  36. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/discovery/sitemap.py +0 -0
  37. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/doctor.py +0 -0
  38. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/http/__init__.py +0 -0
  39. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/http/client.py +0 -0
  40. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/http/protocols.py +0 -0
  41. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/http/rate_limiter.py +0 -0
  42. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/logging_config.py +0 -0
  43. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/mcp/__init__.py +0 -0
  44. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/mcp/server.py +0 -0
  45. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/mcp/sources.py +0 -0
  46. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/mcp/tools.py +0 -0
  47. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/metadata_extractor.py +0 -0
  48. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/models/__init__.py +0 -0
  49. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/models/config.py +0 -0
  50. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/models/events.py +0 -0
  51. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/models/profiles.py +0 -0
  52. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/__init__.py +0 -0
  53. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/base.py +0 -0
  54. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/__init__.py +0 -0
  55. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/chunk.py +0 -0
  56. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/convert.py +0 -0
  57. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/dedup.py +0 -0
  58. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/fetch.py +0 -0
  59. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/metadata.py +0 -0
  60. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/save.py +0 -0
  61. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/save_json.py +0 -0
  62. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/save_ndjson.py +0 -0
  63. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/save_sqlite.py +0 -0
  64. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/pipeline/steps/validate.py +0 -0
  65. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/py.typed +0 -0
  66. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/security/__init__.py +0 -0
  67. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/security/robots.py +0 -0
  68. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/security/url_validator.py +0 -0
  69. {docpull-3.0.1 → docpull-3.0.2}/src/docpull/time_utils.py +0 -0
  70. {docpull-3.0.1 → docpull-3.0.2}/src/docpull.egg-info/dependency_links.txt +0 -0
  71. {docpull-3.0.1 → docpull-3.0.2}/src/docpull.egg-info/entry_points.txt +0 -0
  72. {docpull-3.0.1 → docpull-3.0.2}/src/docpull.egg-info/requires.txt +0 -0
  73. {docpull-3.0.1 → docpull-3.0.2}/src/docpull.egg-info/top_level.txt +0 -0
  74. {docpull-3.0.1 → docpull-3.0.2}/tests/test_cache_conditional_get.py +0 -0
  75. {docpull-3.0.1 → docpull-3.0.2}/tests/test_chunking.py +0 -0
  76. {docpull-3.0.1 → docpull-3.0.2}/tests/test_conversion.py +0 -0
  77. {docpull-3.0.1 → docpull-3.0.2}/tests/test_convert_step_new.py +0 -0
  78. {docpull-3.0.1 → docpull-3.0.2}/tests/test_discovery.py +0 -0
  79. {docpull-3.0.1 → docpull-3.0.2}/tests/test_integration.py +0 -0
  80. {docpull-3.0.1 → docpull-3.0.2}/tests/test_link_extractors.py +0 -0
  81. {docpull-3.0.1 → docpull-3.0.2}/tests/test_mcp_tools.py +0 -0
  82. {docpull-3.0.1 → docpull-3.0.2}/tests/test_naming.py +0 -0
  83. {docpull-3.0.1 → docpull-3.0.2}/tests/test_pipeline.py +0 -0
  84. {docpull-3.0.1 → docpull-3.0.2}/tests/test_real_site_regressions.py +0 -0
  85. {docpull-3.0.1 → docpull-3.0.2}/tests/test_save_ndjson.py +0 -0
  86. {docpull-3.0.1 → docpull-3.0.2}/tests/test_security_hardening.py +0 -0
  87. {docpull-3.0.1 → docpull-3.0.2}/tests/test_special_cases.py +0 -0
  88. {docpull-3.0.1 → docpull-3.0.2}/tests/test_time_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docpull
3
- Version: 3.0.1
3
+ Version: 3.0.2
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>
@@ -228,12 +228,19 @@ pip install 'docpull[mcp]'
228
228
  docpull mcp # starts the stdio server
229
229
  ```
230
230
 
231
- Add to Claude Desktop or Claude Code manually:
231
+ Claude Code:
232
+
233
+ ```bash
234
+ claude mcp add --transport stdio docpull -- docpull mcp
235
+ ```
236
+
237
+ Cursor (`.cursor/mcp.json` in a project, or `~/.cursor/mcp.json` globally):
232
238
 
233
239
  ```json
234
240
  {
235
241
  "mcpServers": {
236
242
  "docpull": {
243
+ "type": "stdio",
237
244
  "command": "docpull",
238
245
  "args": ["mcp"]
239
246
  }
@@ -241,6 +248,9 @@ Add to Claude Desktop or Claude Code manually:
241
248
  }
242
249
  ```
243
250
 
251
+ Claude Desktop uses the same `mcpServers` shape in
252
+ `claude_desktop_config.json`.
253
+
244
254
  Or, if you use Claude Code, install the plugin instead — it bundles the MCP
245
255
  server, five slash commands (`/docs-add`, `/docs-search`, `/docs-list`,
246
256
  `/docs-refresh`, `/docs-remove`), and a meta-skill that teaches Claude
@@ -140,12 +140,19 @@ pip install 'docpull[mcp]'
140
140
  docpull mcp # starts the stdio server
141
141
  ```
142
142
 
143
- Add to Claude Desktop or Claude Code manually:
143
+ Claude Code:
144
+
145
+ ```bash
146
+ claude mcp add --transport stdio docpull -- docpull mcp
147
+ ```
148
+
149
+ Cursor (`.cursor/mcp.json` in a project, or `~/.cursor/mcp.json` globally):
144
150
 
145
151
  ```json
146
152
  {
147
153
  "mcpServers": {
148
154
  "docpull": {
155
+ "type": "stdio",
149
156
  "command": "docpull",
150
157
  "args": ["mcp"]
151
158
  }
@@ -153,6 +160,9 @@ Add to Claude Desktop or Claude Code manually:
153
160
  }
154
161
  ```
155
162
 
163
+ Claude Desktop uses the same `mcpServers` shape in
164
+ `claude_desktop_config.json`.
165
+
156
166
  Or, if you use Claude Code, install the plugin instead — it bundles the MCP
157
167
  server, five slash commands (`/docs-add`, `/docs-search`, `/docs-list`,
158
168
  `/docs-refresh`, `/docs-remove`), and a meta-skill that teaches Claude
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "docpull"
7
- version = "3.0.1"
7
+ version = "3.0.2"
8
8
  dynamic = []
9
9
  description = "Pull documentation from the web and convert to clean markdown"
10
10
  readme = {file = "README.md", content-type = "text/markdown"}
@@ -14,7 +14,7 @@ Usage:
14
14
  print(event)
15
15
  """
16
16
 
17
- __version__ = "3.0.0"
17
+ __version__ = "3.0.2"
18
18
 
19
19
  from .cache import CacheManager, StreamingDeduplicator
20
20
  from .conversion.chunking import Chunk, TokenCounter, chunk_markdown
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docpull
3
- Version: 3.0.1
3
+ Version: 3.0.2
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>
@@ -228,12 +228,19 @@ pip install 'docpull[mcp]'
228
228
  docpull mcp # starts the stdio server
229
229
  ```
230
230
 
231
- Add to Claude Desktop or Claude Code manually:
231
+ Claude Code:
232
+
233
+ ```bash
234
+ claude mcp add --transport stdio docpull -- docpull mcp
235
+ ```
236
+
237
+ Cursor (`.cursor/mcp.json` in a project, or `~/.cursor/mcp.json` globally):
232
238
 
233
239
  ```json
234
240
  {
235
241
  "mcpServers": {
236
242
  "docpull": {
243
+ "type": "stdio",
237
244
  "command": "docpull",
238
245
  "args": ["mcp"]
239
246
  }
@@ -241,6 +248,9 @@ Add to Claude Desktop or Claude Code manually:
241
248
  }
242
249
  ```
243
250
 
251
+ Claude Desktop uses the same `mcpServers` shape in
252
+ `claude_desktop_config.json`.
253
+
244
254
  Or, if you use Claude Code, install the plugin instead — it bundles the MCP
245
255
  server, five slash commands (`/docs-add`, `/docs-search`, `/docs-list`,
246
256
  `/docs-refresh`, `/docs-remove`), and a meta-skill that teaches Claude
@@ -75,6 +75,7 @@ tests/test_convert_step_new.py
75
75
  tests/test_discovery.py
76
76
  tests/test_integration.py
77
77
  tests/test_link_extractors.py
78
+ tests/test_mcp_server.py
78
79
  tests/test_mcp_tools.py
79
80
  tests/test_naming.py
80
81
  tests/test_pipeline.py
@@ -1,10 +1,17 @@
1
1
  """CLI regression tests."""
2
2
 
3
+ from importlib.metadata import version
4
+
3
5
  import pytest
4
6
 
7
+ import docpull
5
8
  from docpull.cli import create_parser
6
9
 
7
10
 
11
+ def test_runtime_version_matches_package_metadata():
12
+ assert docpull.__version__ == version("docpull")
13
+
14
+
8
15
  def test_parser_rejects_removed_js_flag():
9
16
  """Ensure the removed JavaScript flag stays unavailable."""
10
17
  parser = create_parser()
@@ -0,0 +1,51 @@
1
+ """End-to-end tests for the stdio MCP server."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import sys
7
+
8
+ import pytest
9
+
10
+ pytest.importorskip("mcp")
11
+ pytest.importorskip("mcp.client.stdio")
12
+
13
+ from mcp.client.stdio import stdio_client
14
+
15
+ from mcp import ClientSession, StdioServerParameters
16
+
17
+
18
+ @pytest.mark.asyncio
19
+ async def test_stdio_server_lists_and_calls_tools(tmp_path):
20
+ env = os.environ.copy()
21
+ env["XDG_CONFIG_HOME"] = str(tmp_path / "config")
22
+ env["XDG_DATA_HOME"] = str(tmp_path / "data")
23
+
24
+ server = StdioServerParameters(
25
+ command=sys.executable,
26
+ args=["-m", "docpull", "mcp"],
27
+ env=env,
28
+ )
29
+ async with stdio_client(server) as (read, write), ClientSession(read, write) as session:
30
+ await session.initialize()
31
+
32
+ tools = await session.list_tools()
33
+ names = {tool.name for tool in tools.tools}
34
+ assert names == {
35
+ "fetch_url",
36
+ "ensure_docs",
37
+ "list_sources",
38
+ "list_indexed",
39
+ "grep_docs",
40
+ "read_doc",
41
+ "add_source",
42
+ "remove_source",
43
+ }
44
+
45
+ result = await session.call_tool("list_sources", {})
46
+ assert result.isError is False
47
+ assert result.structuredContent is not None
48
+ assert any(source["name"] == "react" for source in result.structuredContent["sources"])
49
+
50
+ rejected = await session.call_tool("fetch_url", {"url": "https://localhost/admin"})
51
+ assert rejected.isError is True
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes