dataquery-sdk 1.2.1__tar.gz → 1.2.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.
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/CHANGELOG.md +2 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/PKG-INFO +8 -5
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/__init__.py +2 -2
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/cli.py +66 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery_sdk.egg-info/PKG-INFO +8 -5
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery_sdk.egg-info/requires.txt +4 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/pyproject.toml +10 -4
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/CONTRIBUTING.md +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/LICENSE +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/MANIFEST.in +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/README.md +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/config/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/config/env.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/config/logging.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/constants/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/constants/api.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/constants/download.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/constants/rate_limit.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/constants/sse.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/core/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/core/_mixins.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/core/_sync.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/core/client.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/data/function.json +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/dataquery.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/download/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/download/parallel.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/download/utils.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/export.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/function_registry.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/py.typed +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/sse/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/sse/client.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/sse/event_store.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/sse/subscriber.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/transport/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/transport/auth.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/transport/connection_pool.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/transport/rate_limiter.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/transport/retry.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/types/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/types/exceptions.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/types/models.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery/utils.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery_sdk.egg-info/SOURCES.txt +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery_sdk.egg-info/dependency_links.txt +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery_sdk.egg-info/entry_points.txt +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/dataquery_sdk.egg-info/top_level.txt +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.2}/setup.cfg +0 -0
|
@@ -44,5 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
44
44
|
- Written research: new `download_zip_async` helper that downloads a group over a date range (split into calendar-month windows to fit the available-files endpoint limit) and safely extracts ZIP archives as each download completes, overlapping unzip with in-flight downloads
|
|
45
45
|
- Group downloads: `run_group_download_async` accepts an `on_file_complete` async callback awaited per file on `completed`/`already_exists`
|
|
46
46
|
- Extraction is Zip Slip-guarded, skips current-day archives, and surfaces failures via `extraction_errors` (downgrading overall status to `partial`); date windows with no available files no longer mark a multi-window run as `partial`
|
|
47
|
+
## [1.2.2] - 2026-07-18
|
|
48
|
+
- MCP: new `mcp-connect` CLI command
|
|
47
49
|
|
|
48
50
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataquery-sdk
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Python SDK for DATAQUERY Data API - Query, download, and check availability of economic data files
|
|
5
5
|
Author-email: DATAQUERY SDK Team <dataquery_support@jpmorgan.com>
|
|
6
|
-
Project-URL: Homepage, https://github.com/
|
|
7
|
-
Project-URL: Bug Tracker, https://github.com/
|
|
8
|
-
Project-URL: Documentation, https://github.com/
|
|
9
|
-
Project-URL: Source Code, https://github.com/
|
|
6
|
+
Project-URL: Homepage, https://github.com/jpmorganchase/dataquery-sdk
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/jpmorganchase/dataquery-sdk/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/jpmorganchase/dataquery-sdk/wiki
|
|
9
|
+
Project-URL: Source Code, https://github.com/jpmorganchase/dataquery-sdk
|
|
10
10
|
Keywords: dataquery,data,api,economic,financial,download,async,oauth,rate-limiting,sdk
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -49,6 +49,8 @@ Requires-Dist: mike>=1.1.0; extra == "docs"
|
|
|
49
49
|
Requires-Dist: pymdown-extensions>=10.21.3; extra == "docs"
|
|
50
50
|
Provides-Extra: pandas
|
|
51
51
|
Requires-Dist: pandas>=2.0.0; extra == "pandas"
|
|
52
|
+
Provides-Extra: mcp
|
|
53
|
+
Requires-Dist: fastmcp>=2.14; extra == "mcp"
|
|
52
54
|
Provides-Extra: all
|
|
53
55
|
Requires-Dist: pytest>=7.0.0; extra == "all"
|
|
54
56
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "all"
|
|
@@ -61,6 +63,7 @@ Requires-Dist: mkdocs-material>=9.0.0; extra == "all"
|
|
|
61
63
|
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "all"
|
|
62
64
|
Requires-Dist: mike>=1.1.0; extra == "all"
|
|
63
65
|
Requires-Dist: pandas>=2.0.0; extra == "all"
|
|
66
|
+
Requires-Dist: fastmcp>=2.14; extra == "all"
|
|
64
67
|
Requires-Dist: pip-audit>=2.7.0; extra == "all"
|
|
65
68
|
Requires-Dist: build>=1.3.0; extra == "all"
|
|
66
69
|
Requires-Dist: urllib3>=2.7.0; extra == "all"
|
|
@@ -11,10 +11,10 @@ Quick Start:
|
|
|
11
11
|
... groups = await dq.list_groups_async()
|
|
12
12
|
... print(f"Found {len(groups)} groups")
|
|
13
13
|
|
|
14
|
-
For more information, visit: https://github.com/
|
|
14
|
+
For more information, visit: https://github.com/jpmorganchase/dataquery-sdk
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
-
__version__ = "1.2.
|
|
17
|
+
__version__ = "1.2.2"
|
|
18
18
|
__author__ = "DATAQUERY SDK Team"
|
|
19
19
|
__email__ = "dataquery_support@jpmorgan.com"
|
|
20
20
|
__license__ = "MIT"
|
|
@@ -4,6 +4,7 @@ import argparse
|
|
|
4
4
|
import asyncio
|
|
5
5
|
import json
|
|
6
6
|
import sys
|
|
7
|
+
from collections.abc import AsyncGenerator
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
from typing import Any, Dict, List, Optional
|
|
9
10
|
|
|
@@ -290,6 +291,20 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
290
291
|
|
|
291
292
|
subparsers.add_parser("heartbeat", help="Check if DataQuery is running")
|
|
292
293
|
|
|
294
|
+
p_connect = subparsers.add_parser(
|
|
295
|
+
"mcp-connect",
|
|
296
|
+
help="Connect a local stdio MCP client to a remote MCP server (AuthE OAuth)",
|
|
297
|
+
description=(
|
|
298
|
+
"Bridge a desktop MCP client (stdio) to a remote streamable-HTTP MCP\n"
|
|
299
|
+
"server, authenticating with an OAuth client-credentials (AuthE) token\n"
|
|
300
|
+
"minted from the DATAQUERY_* environment. Point your MCP client's\n"
|
|
301
|
+
"`command` at: dataquery mcp-connect --url <MCP_URL>"
|
|
302
|
+
),
|
|
303
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
304
|
+
)
|
|
305
|
+
p_connect.add_argument("--url", required=True, help="Remote MCP endpoint URL")
|
|
306
|
+
p_connect.add_argument("--name", default="dataquery-mcp", help="Proxy server name (default: dataquery-mcp)")
|
|
307
|
+
|
|
293
308
|
return parser
|
|
294
309
|
|
|
295
310
|
|
|
@@ -716,6 +731,56 @@ def cmd_function_help(args: argparse.Namespace) -> int:
|
|
|
716
731
|
return 0
|
|
717
732
|
|
|
718
733
|
|
|
734
|
+
async def cmd_mcp_connect(args: argparse.Namespace) -> int:
|
|
735
|
+
"""Bridge a desktop MCP client (stdio) to a remote streamable-HTTP MCP server.
|
|
736
|
+
|
|
737
|
+
Mints an OAuth client-credentials (AuthE) token with the SDK's own
|
|
738
|
+
TokenManager from the ``DATAQUERY_*`` environment and attaches a fresh bearer
|
|
739
|
+
token to every upstream request. Launched by an MCP client as its stdio
|
|
740
|
+
``command``; stdout carries only the MCP JSON-RPC stream, so all diagnostics
|
|
741
|
+
go to stderr.
|
|
742
|
+
"""
|
|
743
|
+
try:
|
|
744
|
+
import httpx
|
|
745
|
+
from fastmcp import FastMCP
|
|
746
|
+
from fastmcp.client.transports import StreamableHttpTransport
|
|
747
|
+
except ImportError:
|
|
748
|
+
print(
|
|
749
|
+
"The MCP bridge requires the 'mcp' extra. Install it with:\n"
|
|
750
|
+
" pip install 'dataquery-sdk[mcp]'\n"
|
|
751
|
+
"or run it directly with:\n"
|
|
752
|
+
" uvx --from 'dataquery-sdk[mcp]' dataquery mcp-connect --url <MCP_URL>",
|
|
753
|
+
file=sys.stderr,
|
|
754
|
+
)
|
|
755
|
+
return 1
|
|
756
|
+
|
|
757
|
+
from dataquery.config import EnvConfig
|
|
758
|
+
from dataquery.transport.auth import TokenManager
|
|
759
|
+
|
|
760
|
+
config = EnvConfig.create_client_config(env_file=Path(args.env_file) if getattr(args, "env_file", None) else None)
|
|
761
|
+
token_manager = TokenManager(config)
|
|
762
|
+
|
|
763
|
+
class _AutheAuth(httpx.Auth):
|
|
764
|
+
"""Stamp a fresh AuthE bearer token (from the SDK TokenManager) per request."""
|
|
765
|
+
|
|
766
|
+
async def async_auth_flow(self, request: httpx.Request) -> AsyncGenerator[httpx.Request, httpx.Response]:
|
|
767
|
+
header = await token_manager.get_valid_token() # "Bearer <jwt>"
|
|
768
|
+
if not header:
|
|
769
|
+
raise DataQueryError(
|
|
770
|
+
"Could not obtain an OAuth token \u2014 check DATAQUERY_CLIENT_ID, "
|
|
771
|
+
"DATAQUERY_CLIENT_SECRET, DATAQUERY_OAUTH_TOKEN_URL and "
|
|
772
|
+
"DATAQUERY_OAUTH_AUD."
|
|
773
|
+
)
|
|
774
|
+
request.headers["Authorization"] = header
|
|
775
|
+
yield request
|
|
776
|
+
|
|
777
|
+
transport = StreamableHttpTransport(args.url, auth=_AutheAuth())
|
|
778
|
+
proxy = FastMCP.as_proxy(transport, name=args.name)
|
|
779
|
+
# stdout is reserved for the MCP JSON-RPC stream; keep the banner off it.
|
|
780
|
+
await proxy.run_async(transport="stdio", show_banner=False)
|
|
781
|
+
return 0
|
|
782
|
+
|
|
783
|
+
|
|
719
784
|
def main_sync(ns: argparse.Namespace) -> int:
|
|
720
785
|
if ns.command == "config":
|
|
721
786
|
if ns.config_command == "show":
|
|
@@ -745,6 +810,7 @@ _ASYNC_COMMANDS = {
|
|
|
745
810
|
"expression-timeseries": cmd_expression_timeseries,
|
|
746
811
|
"grid-data": cmd_grid_data,
|
|
747
812
|
"heartbeat": cmd_heartbeat,
|
|
813
|
+
"mcp-connect": cmd_mcp_connect,
|
|
748
814
|
}
|
|
749
815
|
|
|
750
816
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataquery-sdk
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Python SDK for DATAQUERY Data API - Query, download, and check availability of economic data files
|
|
5
5
|
Author-email: DATAQUERY SDK Team <dataquery_support@jpmorgan.com>
|
|
6
|
-
Project-URL: Homepage, https://github.com/
|
|
7
|
-
Project-URL: Bug Tracker, https://github.com/
|
|
8
|
-
Project-URL: Documentation, https://github.com/
|
|
9
|
-
Project-URL: Source Code, https://github.com/
|
|
6
|
+
Project-URL: Homepage, https://github.com/jpmorganchase/dataquery-sdk
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/jpmorganchase/dataquery-sdk/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/jpmorganchase/dataquery-sdk/wiki
|
|
9
|
+
Project-URL: Source Code, https://github.com/jpmorganchase/dataquery-sdk
|
|
10
10
|
Keywords: dataquery,data,api,economic,financial,download,async,oauth,rate-limiting,sdk
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -49,6 +49,8 @@ Requires-Dist: mike>=1.1.0; extra == "docs"
|
|
|
49
49
|
Requires-Dist: pymdown-extensions>=10.21.3; extra == "docs"
|
|
50
50
|
Provides-Extra: pandas
|
|
51
51
|
Requires-Dist: pandas>=2.0.0; extra == "pandas"
|
|
52
|
+
Provides-Extra: mcp
|
|
53
|
+
Requires-Dist: fastmcp>=2.14; extra == "mcp"
|
|
52
54
|
Provides-Extra: all
|
|
53
55
|
Requires-Dist: pytest>=7.0.0; extra == "all"
|
|
54
56
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "all"
|
|
@@ -61,6 +63,7 @@ Requires-Dist: mkdocs-material>=9.0.0; extra == "all"
|
|
|
61
63
|
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "all"
|
|
62
64
|
Requires-Dist: mike>=1.1.0; extra == "all"
|
|
63
65
|
Requires-Dist: pandas>=2.0.0; extra == "all"
|
|
66
|
+
Requires-Dist: fastmcp>=2.14; extra == "all"
|
|
64
67
|
Requires-Dist: pip-audit>=2.7.0; extra == "all"
|
|
65
68
|
Requires-Dist: build>=1.3.0; extra == "all"
|
|
66
69
|
Requires-Dist: urllib3>=2.7.0; extra == "all"
|
|
@@ -16,6 +16,7 @@ mkdocs-material>=9.0.0
|
|
|
16
16
|
mkdocstrings[python]>=0.24.0
|
|
17
17
|
mike>=1.1.0
|
|
18
18
|
pandas>=2.0.0
|
|
19
|
+
fastmcp>=2.14
|
|
19
20
|
pip-audit>=2.7.0
|
|
20
21
|
build>=1.3.0
|
|
21
22
|
urllib3>=2.7.0
|
|
@@ -40,5 +41,8 @@ mkdocstrings[python]>=0.24.0
|
|
|
40
41
|
mike>=1.1.0
|
|
41
42
|
pymdown-extensions>=10.21.3
|
|
42
43
|
|
|
44
|
+
[mcp]
|
|
45
|
+
fastmcp>=2.14
|
|
46
|
+
|
|
43
47
|
[pandas]
|
|
44
48
|
pandas>=2.0.0
|
|
@@ -48,10 +48,10 @@ keywords = [
|
|
|
48
48
|
]
|
|
49
49
|
|
|
50
50
|
[project.urls]
|
|
51
|
-
Homepage = "https://github.com/
|
|
52
|
-
"Bug Tracker" = "https://github.com/
|
|
53
|
-
Documentation = "https://github.com/
|
|
54
|
-
"Source Code" = "https://github.com/
|
|
51
|
+
Homepage = "https://github.com/jpmorganchase/dataquery-sdk"
|
|
52
|
+
"Bug Tracker" = "https://github.com/jpmorganchase/dataquery-sdk/issues"
|
|
53
|
+
Documentation = "https://github.com/jpmorganchase/dataquery-sdk/wiki"
|
|
54
|
+
"Source Code" = "https://github.com/jpmorganchase/dataquery-sdk"
|
|
55
55
|
|
|
56
56
|
[project.optional-dependencies]
|
|
57
57
|
dev = [
|
|
@@ -76,6 +76,9 @@ docs = [
|
|
|
76
76
|
pandas = [
|
|
77
77
|
"pandas>=2.0.0",
|
|
78
78
|
]
|
|
79
|
+
mcp = [
|
|
80
|
+
"fastmcp>=2.14",
|
|
81
|
+
]
|
|
79
82
|
all = [
|
|
80
83
|
"pytest>=7.0.0",
|
|
81
84
|
"pytest-asyncio>=0.21.0",
|
|
@@ -88,6 +91,7 @@ all = [
|
|
|
88
91
|
"mkdocstrings[python]>=0.24.0",
|
|
89
92
|
"mike>=1.1.0",
|
|
90
93
|
"pandas>=2.0.0",
|
|
94
|
+
"fastmcp>=2.14",
|
|
91
95
|
"pip-audit>=2.7.0",
|
|
92
96
|
"build>=1.3.0",
|
|
93
97
|
"urllib3>=2.7.0",
|
|
@@ -150,6 +154,8 @@ module = [
|
|
|
150
154
|
"structlog.*",
|
|
151
155
|
"dotenv.*",
|
|
152
156
|
"pytest.*",
|
|
157
|
+
"fastmcp.*",
|
|
158
|
+
"httpx.*",
|
|
153
159
|
]
|
|
154
160
|
ignore_missing_imports = true
|
|
155
161
|
|
|
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
|
|
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
|
|
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
|
|
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
|