dataquery-sdk 1.2.4__tar.gz → 1.2.6__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.4 → dataquery_sdk-1.2.6}/CHANGELOG.md +5 -2
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/PKG-INFO +159 -5
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/README.md +156 -2
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/__init__.py +1 -1
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/cli.py +20 -4
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/mcp_proxy.py +12 -2
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/types/models.py +4 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/utils.py +4 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery_sdk.egg-info/PKG-INFO +159 -5
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery_sdk.egg-info/requires.txt +2 -2
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/pyproject.toml +2 -2
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/CONTRIBUTING.md +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/LICENSE +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/MANIFEST.in +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/config/__init__.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/config/env.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/config/logging.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/constants/__init__.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/constants/api.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/constants/download.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/constants/rate_limit.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/constants/sse.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/core/__init__.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/core/_mixins.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/core/_sync.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/core/client.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/data/function.json +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/dataquery.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/download/__init__.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/download/parallel.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/download/utils.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/export.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/function_registry.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/py.typed +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/sse/__init__.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/sse/client.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/sse/event_store.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/sse/subscriber.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/transport/__init__.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/transport/auth.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/transport/connection_pool.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/transport/rate_limiter.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/transport/retry.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/types/__init__.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery/types/exceptions.py +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery_sdk.egg-info/SOURCES.txt +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery_sdk.egg-info/dependency_links.txt +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery_sdk.egg-info/entry_points.txt +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/dataquery_sdk.egg-info/top_level.txt +0 -0
- {dataquery_sdk-1.2.4 → dataquery_sdk-1.2.6}/setup.cfg +0 -0
|
@@ -53,5 +53,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
53
53
|
- Exports: `Paginated`, `Link`, `APIResponseError` are now part of the public API
|
|
54
54
|
## [1.2.4] - 2026-08-12
|
|
55
55
|
- MCP: `mcp-connect` accepts `--client-id`, `--client-secret` and `--bearer-token` and exports them into the `DATAQUERY_*` environment of the process, so the MCP bridge and the SDK share one credential set instead of each needing its own setup
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
## [1.2.5] - 2026-08-21
|
|
57
|
+
- MCP: `mcp-connect --url` is now optional
|
|
58
|
+
## [1.2.6] - 2026-09-24
|
|
59
|
+
- Bug fixes
|
|
60
|
+
- MCP: capped the `mcp` extra to `fastmcp>=2.14,<4` — fastmcp 4.x repackages onto `httpx2` and drops `FastMCP.as_proxy()`, which broke `mcp-connect`; installs now resolve to the 3.x line
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataquery-sdk
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
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
6
|
Project-URL: Homepage, https://github.com/jpmorganchase/dataquery-sdk
|
|
@@ -50,7 +50,7 @@ Requires-Dist: pymdown-extensions>=11.0.0; extra == "docs"
|
|
|
50
50
|
Provides-Extra: pandas
|
|
51
51
|
Requires-Dist: pandas>=2.0.0; extra == "pandas"
|
|
52
52
|
Provides-Extra: mcp
|
|
53
|
-
Requires-Dist: fastmcp
|
|
53
|
+
Requires-Dist: fastmcp<4,>=2.14; extra == "mcp"
|
|
54
54
|
Provides-Extra: all
|
|
55
55
|
Requires-Dist: pytest>=7.0.0; extra == "all"
|
|
56
56
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "all"
|
|
@@ -63,7 +63,7 @@ Requires-Dist: mkdocs-material>=9.0.0; extra == "all"
|
|
|
63
63
|
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "all"
|
|
64
64
|
Requires-Dist: mike>=1.1.0; extra == "all"
|
|
65
65
|
Requires-Dist: pandas>=2.0.0; extra == "all"
|
|
66
|
-
Requires-Dist: fastmcp
|
|
66
|
+
Requires-Dist: fastmcp<4,>=2.14; extra == "all"
|
|
67
67
|
Requires-Dist: pip-audit>=2.7.0; extra == "all"
|
|
68
68
|
Requires-Dist: build>=1.3.0; extra == "all"
|
|
69
69
|
Requires-Dist: urllib3>=2.7.0; extra == "all"
|
|
@@ -98,6 +98,7 @@ built in for both.
|
|
|
98
98
|
- [Quick start — JSON Data API](#quick-start--json-data-api)
|
|
99
99
|
- [Auto-download (SSE)](#auto-download-sse)
|
|
100
100
|
- [CLI](#cli)
|
|
101
|
+
- [MCP bridge (`mcp-connect`)](#mcp-bridge-mcp-connect)
|
|
101
102
|
- [Configuration](#configuration)
|
|
102
103
|
- [Logging](#logging)
|
|
103
104
|
- [Error handling](#error-handling)
|
|
@@ -140,6 +141,9 @@ through one `DataQuery` client — pick the methods that match what you need.
|
|
|
140
141
|
- **Retry + circuit breaker** — exponential backoff, configurable failure threshold
|
|
141
142
|
- **Sync and async APIs** — every operation has `_async` and sync variants
|
|
142
143
|
- **CLI** — `dataquery groups | files | availability | download | download-group | auth | config`
|
|
144
|
+
- **MCP bridge** — `dataquery mcp-connect` connects any stdio MCP client
|
|
145
|
+
(Claude Desktop, Claude Code, …) to the remote DataQuery MCP server, minting
|
|
146
|
+
OAuth tokens for it
|
|
143
147
|
|
|
144
148
|
## New here? Three steps to your first download
|
|
145
149
|
|
|
@@ -172,6 +176,9 @@ pip install dataquery-sdk
|
|
|
172
176
|
# With pandas DataFrame conversion
|
|
173
177
|
pip install "dataquery-sdk[pandas]"
|
|
174
178
|
|
|
179
|
+
# With the MCP bridge (dataquery mcp-connect)
|
|
180
|
+
pip install "dataquery-sdk[mcp]"
|
|
181
|
+
|
|
175
182
|
# With dev tooling (ruff, mypy, pytest)
|
|
176
183
|
pip install "dataquery-sdk[dev]"
|
|
177
184
|
```
|
|
@@ -439,8 +446,134 @@ dataquery config template --output .env
|
|
|
439
446
|
dataquery auth test
|
|
440
447
|
```
|
|
441
448
|
|
|
442
|
-
|
|
443
|
-
|
|
449
|
+
`--env-file PATH` (to point at a non-default `.env`) is a top-level flag, so it
|
|
450
|
+
goes *before* the subcommand: `dataquery --env-file .env.prod groups`. Most
|
|
451
|
+
subcommands accept `--json` for machine-readable output.
|
|
452
|
+
|
|
453
|
+
## MCP bridge (`mcp-connect`)
|
|
454
|
+
|
|
455
|
+
`dataquery mcp-connect` connects a desktop MCP client — Claude Desktop, Claude
|
|
456
|
+
Code, or any stdio MCP host — to the remote DataQuery MCP server. It speaks
|
|
457
|
+
stdio to the client and streamable HTTP to the server, stamping every outbound
|
|
458
|
+
request with a fresh OAuth (AuthE) bearer token minted from your `DATAQUERY_*`
|
|
459
|
+
credentials. Tokens are refreshed for the life of the session, and the MCP host
|
|
460
|
+
itself never handles your client secret.
|
|
461
|
+
|
|
462
|
+
It needs the `mcp` extra:
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
pip install "dataquery-sdk[mcp]"
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Wire it into an MCP client
|
|
469
|
+
|
|
470
|
+
Add the server to your client's MCP config (`claude_desktop_config.json`,
|
|
471
|
+
`.mcp.json`, or the equivalent for your host):
|
|
472
|
+
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"mcpServers": {
|
|
476
|
+
"dataquery": {
|
|
477
|
+
"command": "dataquery",
|
|
478
|
+
"args": ["mcp-connect", "--save-credentials"],
|
|
479
|
+
"env": {
|
|
480
|
+
"DATAQUERY_CLIENT_ID": "your_client_id",
|
|
481
|
+
"DATAQUERY_CLIENT_SECRET": "your_client_secret"
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
`--save-credentials` copies the credentials it resolved into
|
|
489
|
+
`~/.dataquery/.env` on the first launch (see [Credentials](#credentials)). From
|
|
490
|
+
then on the bridge — and every other SDK call and CLI run on the machine —
|
|
491
|
+
finds them there, so you can drop the `env` block from the config and keep your
|
|
492
|
+
secret out of a file your MCP client reads on every start:
|
|
493
|
+
|
|
494
|
+
```json
|
|
495
|
+
{
|
|
496
|
+
"mcpServers": {
|
|
497
|
+
"dataquery": {
|
|
498
|
+
"command": "dataquery",
|
|
499
|
+
"args": ["mcp-connect"]
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
To skip installing anything, run it straight from PyPI with `uvx`:
|
|
506
|
+
|
|
507
|
+
```json
|
|
508
|
+
{
|
|
509
|
+
"mcpServers": {
|
|
510
|
+
"dataquery": {
|
|
511
|
+
"command": "uvx",
|
|
512
|
+
"args": ["--from", "dataquery-sdk[mcp]", "dataquery", "mcp-connect", "--save-credentials"],
|
|
513
|
+
"env": {
|
|
514
|
+
"DATAQUERY_CLIENT_ID": "your_client_id",
|
|
515
|
+
"DATAQUERY_CLIENT_SECRET": "your_client_secret"
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Endpoint
|
|
523
|
+
|
|
524
|
+
`--url` is optional. The endpoint resolves as `--url` → `DATAQUERY_MCP_URL` →
|
|
525
|
+
the production server
|
|
526
|
+
`https://api-dataquery.jpmchase.com/research/dataquery-authe/v2/mcp`:
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
# Production (no arguments needed)
|
|
530
|
+
dataquery mcp-connect
|
|
531
|
+
|
|
532
|
+
# Another environment
|
|
533
|
+
dataquery mcp-connect --url https://host/research/dataquery-authe/v2/mcp
|
|
534
|
+
DATAQUERY_MCP_URL=https://host/research/dataquery-authe/v2/mcp dataquery mcp-connect
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### Credentials
|
|
538
|
+
|
|
539
|
+
Credentials resolve exactly as they do everywhere else in the SDK — flags win,
|
|
540
|
+
then the process environment (what your MCP client exports), then a `.env`,
|
|
541
|
+
then the saved user-level file:
|
|
542
|
+
|
|
543
|
+
```bash
|
|
544
|
+
# From the environment (recommended)
|
|
545
|
+
dataquery mcp-connect
|
|
546
|
+
|
|
547
|
+
# From flags — visible in the process list, so avoid on shared machines
|
|
548
|
+
dataquery mcp-connect --client-id ID --client-secret SECRET
|
|
549
|
+
|
|
550
|
+
# From a non-default .env (top-level flag: before the subcommand)
|
|
551
|
+
dataquery --env-file .env.prod mcp-connect
|
|
552
|
+
|
|
553
|
+
# Bearer token instead of OAuth
|
|
554
|
+
dataquery mcp-connect --bearer-token TOKEN
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
Pass `--save-credentials` once and the resolved credentials are written to
|
|
558
|
+
`~/.dataquery/.env` (owner-only `0600` file in a `0700` directory; override the
|
|
559
|
+
directory with `DATAQUERY_CONFIG_DIR`). Every later SDK call and CLI run reads
|
|
560
|
+
that file as a last-resort fallback, so a plain `DataQuery()` in a script
|
|
561
|
+
authenticates with no environment of its own — while shell variables and a
|
|
562
|
+
local `.env` still take precedence over it.
|
|
563
|
+
|
|
564
|
+
### Flags
|
|
565
|
+
|
|
566
|
+
| Flag | Default | Purpose |
|
|
567
|
+
|---|---|---|
|
|
568
|
+
| `--url URL` | `DATAQUERY_MCP_URL`, else the PROD endpoint | Remote MCP endpoint |
|
|
569
|
+
| `--name NAME` | `dataquery-mcp` | Proxy server name reported to the MCP client |
|
|
570
|
+
| `--client-id ID` | _(from env)_ | OAuth client ID; exported as `DATAQUERY_CLIENT_ID` |
|
|
571
|
+
| `--client-secret SECRET` | _(from env)_ | OAuth client secret; exported as `DATAQUERY_CLIENT_SECRET` |
|
|
572
|
+
| `--bearer-token TOKEN` | _(from env)_ | Use a bearer token instead of OAuth |
|
|
573
|
+
| `--save-credentials` | off | Also persist the resolved credentials to `~/.dataquery/.env` |
|
|
574
|
+
|
|
575
|
+
Because stdout carries the JSON-RPC channel, all logging and diagnostics go to
|
|
576
|
+
stderr — look in your MCP client's server log when something fails.
|
|
444
577
|
|
|
445
578
|
## Configuration
|
|
446
579
|
|
|
@@ -457,6 +590,16 @@ All environment variables use the `DATAQUERY_` prefix.
|
|
|
457
590
|
| `DATAQUERY_BEARER_TOKEN` | _(none)_ | Alternative to OAuth |
|
|
458
591
|
| `DATAQUERY_OAUTH_ENABLED` | `true` | Set `false` to use bearer-token mode |
|
|
459
592
|
|
|
593
|
+
**Endpoints**
|
|
594
|
+
|
|
595
|
+
| Variable | Default | Notes |
|
|
596
|
+
|---|---|---|
|
|
597
|
+
| `DATAQUERY_BASE_URL` | `https://api-dataquery.jpmchase.com` | Host for both API surfaces |
|
|
598
|
+
| `DATAQUERY_FILES_BASE_URL` | same as `BASE_URL` | Override only if file endpoints live on another host |
|
|
599
|
+
| `DATAQUERY_OAUTH_TOKEN_URL` | `https://authe.jpmorgan.com/as/token.oauth2` | Token endpoint |
|
|
600
|
+
| `DATAQUERY_OAUTH_AUD` | PROD audience | Set to the value provisioned for your client |
|
|
601
|
+
| `DATAQUERY_MCP_URL` | PROD MCP endpoint | Endpoint used by [`mcp-connect`](#mcp-bridge-mcp-connect); `--url` overrides it |
|
|
602
|
+
|
|
460
603
|
**HTTP / retry / rate limit**
|
|
461
604
|
|
|
462
605
|
| Variable | Default |
|
|
@@ -621,6 +764,17 @@ async with DataQuery() as dq:
|
|
|
621
764
|
`manager.clear_event_id()` (or `dataquery download --watch --reset-event-id`)
|
|
622
765
|
only when you intentionally want a clean slate.
|
|
623
766
|
|
|
767
|
+
**MCP client shows the server as failed**
|
|
768
|
+
|
|
769
|
+
- `The MCP bridge requires the 'mcp' extra` in the server log means `fastmcp`
|
|
770
|
+
is missing — `pip install "dataquery-sdk[mcp]"`, or use the `uvx` form.
|
|
771
|
+
- MCP hosts usually launch the command with a minimal environment, so a
|
|
772
|
+
`.env` in your shell's working directory may not be visible. Put the
|
|
773
|
+
credentials in the server's `env` block, or run `dataquery mcp-connect
|
|
774
|
+
--save-credentials` once from a terminal where they do resolve.
|
|
775
|
+
- Auth failures surface as `Could not obtain an OAuth token`; verify the same
|
|
776
|
+
credentials with `dataquery auth test` before debugging the bridge.
|
|
777
|
+
|
|
624
778
|
## Date formats
|
|
625
779
|
|
|
626
780
|
```python
|
|
@@ -26,6 +26,7 @@ built in for both.
|
|
|
26
26
|
- [Quick start — JSON Data API](#quick-start--json-data-api)
|
|
27
27
|
- [Auto-download (SSE)](#auto-download-sse)
|
|
28
28
|
- [CLI](#cli)
|
|
29
|
+
- [MCP bridge (`mcp-connect`)](#mcp-bridge-mcp-connect)
|
|
29
30
|
- [Configuration](#configuration)
|
|
30
31
|
- [Logging](#logging)
|
|
31
32
|
- [Error handling](#error-handling)
|
|
@@ -68,6 +69,9 @@ through one `DataQuery` client — pick the methods that match what you need.
|
|
|
68
69
|
- **Retry + circuit breaker** — exponential backoff, configurable failure threshold
|
|
69
70
|
- **Sync and async APIs** — every operation has `_async` and sync variants
|
|
70
71
|
- **CLI** — `dataquery groups | files | availability | download | download-group | auth | config`
|
|
72
|
+
- **MCP bridge** — `dataquery mcp-connect` connects any stdio MCP client
|
|
73
|
+
(Claude Desktop, Claude Code, …) to the remote DataQuery MCP server, minting
|
|
74
|
+
OAuth tokens for it
|
|
71
75
|
|
|
72
76
|
## New here? Three steps to your first download
|
|
73
77
|
|
|
@@ -100,6 +104,9 @@ pip install dataquery-sdk
|
|
|
100
104
|
# With pandas DataFrame conversion
|
|
101
105
|
pip install "dataquery-sdk[pandas]"
|
|
102
106
|
|
|
107
|
+
# With the MCP bridge (dataquery mcp-connect)
|
|
108
|
+
pip install "dataquery-sdk[mcp]"
|
|
109
|
+
|
|
103
110
|
# With dev tooling (ruff, mypy, pytest)
|
|
104
111
|
pip install "dataquery-sdk[dev]"
|
|
105
112
|
```
|
|
@@ -367,8 +374,134 @@ dataquery config template --output .env
|
|
|
367
374
|
dataquery auth test
|
|
368
375
|
```
|
|
369
376
|
|
|
370
|
-
|
|
371
|
-
|
|
377
|
+
`--env-file PATH` (to point at a non-default `.env`) is a top-level flag, so it
|
|
378
|
+
goes *before* the subcommand: `dataquery --env-file .env.prod groups`. Most
|
|
379
|
+
subcommands accept `--json` for machine-readable output.
|
|
380
|
+
|
|
381
|
+
## MCP bridge (`mcp-connect`)
|
|
382
|
+
|
|
383
|
+
`dataquery mcp-connect` connects a desktop MCP client — Claude Desktop, Claude
|
|
384
|
+
Code, or any stdio MCP host — to the remote DataQuery MCP server. It speaks
|
|
385
|
+
stdio to the client and streamable HTTP to the server, stamping every outbound
|
|
386
|
+
request with a fresh OAuth (AuthE) bearer token minted from your `DATAQUERY_*`
|
|
387
|
+
credentials. Tokens are refreshed for the life of the session, and the MCP host
|
|
388
|
+
itself never handles your client secret.
|
|
389
|
+
|
|
390
|
+
It needs the `mcp` extra:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
pip install "dataquery-sdk[mcp]"
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Wire it into an MCP client
|
|
397
|
+
|
|
398
|
+
Add the server to your client's MCP config (`claude_desktop_config.json`,
|
|
399
|
+
`.mcp.json`, or the equivalent for your host):
|
|
400
|
+
|
|
401
|
+
```json
|
|
402
|
+
{
|
|
403
|
+
"mcpServers": {
|
|
404
|
+
"dataquery": {
|
|
405
|
+
"command": "dataquery",
|
|
406
|
+
"args": ["mcp-connect", "--save-credentials"],
|
|
407
|
+
"env": {
|
|
408
|
+
"DATAQUERY_CLIENT_ID": "your_client_id",
|
|
409
|
+
"DATAQUERY_CLIENT_SECRET": "your_client_secret"
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
`--save-credentials` copies the credentials it resolved into
|
|
417
|
+
`~/.dataquery/.env` on the first launch (see [Credentials](#credentials)). From
|
|
418
|
+
then on the bridge — and every other SDK call and CLI run on the machine —
|
|
419
|
+
finds them there, so you can drop the `env` block from the config and keep your
|
|
420
|
+
secret out of a file your MCP client reads on every start:
|
|
421
|
+
|
|
422
|
+
```json
|
|
423
|
+
{
|
|
424
|
+
"mcpServers": {
|
|
425
|
+
"dataquery": {
|
|
426
|
+
"command": "dataquery",
|
|
427
|
+
"args": ["mcp-connect"]
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
To skip installing anything, run it straight from PyPI with `uvx`:
|
|
434
|
+
|
|
435
|
+
```json
|
|
436
|
+
{
|
|
437
|
+
"mcpServers": {
|
|
438
|
+
"dataquery": {
|
|
439
|
+
"command": "uvx",
|
|
440
|
+
"args": ["--from", "dataquery-sdk[mcp]", "dataquery", "mcp-connect", "--save-credentials"],
|
|
441
|
+
"env": {
|
|
442
|
+
"DATAQUERY_CLIENT_ID": "your_client_id",
|
|
443
|
+
"DATAQUERY_CLIENT_SECRET": "your_client_secret"
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Endpoint
|
|
451
|
+
|
|
452
|
+
`--url` is optional. The endpoint resolves as `--url` → `DATAQUERY_MCP_URL` →
|
|
453
|
+
the production server
|
|
454
|
+
`https://api-dataquery.jpmchase.com/research/dataquery-authe/v2/mcp`:
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
# Production (no arguments needed)
|
|
458
|
+
dataquery mcp-connect
|
|
459
|
+
|
|
460
|
+
# Another environment
|
|
461
|
+
dataquery mcp-connect --url https://host/research/dataquery-authe/v2/mcp
|
|
462
|
+
DATAQUERY_MCP_URL=https://host/research/dataquery-authe/v2/mcp dataquery mcp-connect
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Credentials
|
|
466
|
+
|
|
467
|
+
Credentials resolve exactly as they do everywhere else in the SDK — flags win,
|
|
468
|
+
then the process environment (what your MCP client exports), then a `.env`,
|
|
469
|
+
then the saved user-level file:
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
# From the environment (recommended)
|
|
473
|
+
dataquery mcp-connect
|
|
474
|
+
|
|
475
|
+
# From flags — visible in the process list, so avoid on shared machines
|
|
476
|
+
dataquery mcp-connect --client-id ID --client-secret SECRET
|
|
477
|
+
|
|
478
|
+
# From a non-default .env (top-level flag: before the subcommand)
|
|
479
|
+
dataquery --env-file .env.prod mcp-connect
|
|
480
|
+
|
|
481
|
+
# Bearer token instead of OAuth
|
|
482
|
+
dataquery mcp-connect --bearer-token TOKEN
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Pass `--save-credentials` once and the resolved credentials are written to
|
|
486
|
+
`~/.dataquery/.env` (owner-only `0600` file in a `0700` directory; override the
|
|
487
|
+
directory with `DATAQUERY_CONFIG_DIR`). Every later SDK call and CLI run reads
|
|
488
|
+
that file as a last-resort fallback, so a plain `DataQuery()` in a script
|
|
489
|
+
authenticates with no environment of its own — while shell variables and a
|
|
490
|
+
local `.env` still take precedence over it.
|
|
491
|
+
|
|
492
|
+
### Flags
|
|
493
|
+
|
|
494
|
+
| Flag | Default | Purpose |
|
|
495
|
+
|---|---|---|
|
|
496
|
+
| `--url URL` | `DATAQUERY_MCP_URL`, else the PROD endpoint | Remote MCP endpoint |
|
|
497
|
+
| `--name NAME` | `dataquery-mcp` | Proxy server name reported to the MCP client |
|
|
498
|
+
| `--client-id ID` | _(from env)_ | OAuth client ID; exported as `DATAQUERY_CLIENT_ID` |
|
|
499
|
+
| `--client-secret SECRET` | _(from env)_ | OAuth client secret; exported as `DATAQUERY_CLIENT_SECRET` |
|
|
500
|
+
| `--bearer-token TOKEN` | _(from env)_ | Use a bearer token instead of OAuth |
|
|
501
|
+
| `--save-credentials` | off | Also persist the resolved credentials to `~/.dataquery/.env` |
|
|
502
|
+
|
|
503
|
+
Because stdout carries the JSON-RPC channel, all logging and diagnostics go to
|
|
504
|
+
stderr — look in your MCP client's server log when something fails.
|
|
372
505
|
|
|
373
506
|
## Configuration
|
|
374
507
|
|
|
@@ -385,6 +518,16 @@ All environment variables use the `DATAQUERY_` prefix.
|
|
|
385
518
|
| `DATAQUERY_BEARER_TOKEN` | _(none)_ | Alternative to OAuth |
|
|
386
519
|
| `DATAQUERY_OAUTH_ENABLED` | `true` | Set `false` to use bearer-token mode |
|
|
387
520
|
|
|
521
|
+
**Endpoints**
|
|
522
|
+
|
|
523
|
+
| Variable | Default | Notes |
|
|
524
|
+
|---|---|---|
|
|
525
|
+
| `DATAQUERY_BASE_URL` | `https://api-dataquery.jpmchase.com` | Host for both API surfaces |
|
|
526
|
+
| `DATAQUERY_FILES_BASE_URL` | same as `BASE_URL` | Override only if file endpoints live on another host |
|
|
527
|
+
| `DATAQUERY_OAUTH_TOKEN_URL` | `https://authe.jpmorgan.com/as/token.oauth2` | Token endpoint |
|
|
528
|
+
| `DATAQUERY_OAUTH_AUD` | PROD audience | Set to the value provisioned for your client |
|
|
529
|
+
| `DATAQUERY_MCP_URL` | PROD MCP endpoint | Endpoint used by [`mcp-connect`](#mcp-bridge-mcp-connect); `--url` overrides it |
|
|
530
|
+
|
|
388
531
|
**HTTP / retry / rate limit**
|
|
389
532
|
|
|
390
533
|
| Variable | Default |
|
|
@@ -549,6 +692,17 @@ async with DataQuery() as dq:
|
|
|
549
692
|
`manager.clear_event_id()` (or `dataquery download --watch --reset-event-id`)
|
|
550
693
|
only when you intentionally want a clean slate.
|
|
551
694
|
|
|
695
|
+
**MCP client shows the server as failed**
|
|
696
|
+
|
|
697
|
+
- `The MCP bridge requires the 'mcp' extra` in the server log means `fastmcp`
|
|
698
|
+
is missing — `pip install "dataquery-sdk[mcp]"`, or use the `uvx` form.
|
|
699
|
+
- MCP hosts usually launch the command with a minimal environment, so a
|
|
700
|
+
`.env` in your shell's working directory may not be visible. Put the
|
|
701
|
+
credentials in the server's `env` block, or run `dataquery mcp-connect
|
|
702
|
+
--save-credentials` once from a terminal where they do resolve.
|
|
703
|
+
- Auth failures surface as `Could not obtain an OAuth token`; verify the same
|
|
704
|
+
credentials with `dataquery auth test` before debugging the bridge.
|
|
705
|
+
|
|
552
706
|
## Date formats
|
|
553
707
|
|
|
554
708
|
```python
|
|
@@ -353,7 +353,10 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
353
353
|
"Bridge a desktop MCP client (stdio) to a remote streamable-HTTP MCP\n"
|
|
354
354
|
"server, authenticating with an OAuth client-credentials (AuthE) token\n"
|
|
355
355
|
"minted from the DATAQUERY_* environment. Point your MCP client's\n"
|
|
356
|
-
"`command` at: dataquery mcp-connect
|
|
356
|
+
"`command` at: dataquery mcp-connect\n"
|
|
357
|
+
"\n"
|
|
358
|
+
"The endpoint defaults to the PROD MCP server; override it with --url\n"
|
|
359
|
+
"or DATAQUERY_MCP_URL to reach a different environment.\n"
|
|
357
360
|
"\n"
|
|
358
361
|
"Credentials passed as flags are exported into the DATAQUERY_*\n"
|
|
359
362
|
"environment of this process; add --save-credentials to also write\n"
|
|
@@ -362,7 +365,11 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
362
365
|
),
|
|
363
366
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
364
367
|
)
|
|
365
|
-
p_connect.add_argument(
|
|
368
|
+
p_connect.add_argument(
|
|
369
|
+
"--url",
|
|
370
|
+
default=None,
|
|
371
|
+
help="Remote MCP endpoint URL (default: DATAQUERY_MCP_URL, else the PROD MCP endpoint)",
|
|
372
|
+
)
|
|
366
373
|
p_connect.add_argument("--name", default="dataquery-mcp", help="Proxy server name (default: dataquery-mcp)")
|
|
367
374
|
p_connect.add_argument("--client-id", default=None, help="OAuth client ID (exported as DATAQUERY_CLIENT_ID)")
|
|
368
375
|
p_connect.add_argument(
|
|
@@ -817,7 +824,7 @@ async def cmd_mcp_connect(args: argparse.Namespace) -> int:
|
|
|
817
824
|
"The MCP bridge requires the 'mcp' extra. Install it with:\n"
|
|
818
825
|
" pip install 'dataquery-sdk[mcp]'\n"
|
|
819
826
|
"or run it directly with:\n"
|
|
820
|
-
" uvx --from 'dataquery-sdk[mcp]' dataquery mcp-connect
|
|
827
|
+
" uvx --from 'dataquery-sdk[mcp]' dataquery mcp-connect",
|
|
821
828
|
file=sys.stderr,
|
|
822
829
|
)
|
|
823
830
|
return 1
|
|
@@ -836,6 +843,15 @@ async def cmd_mcp_connect(args: argparse.Namespace) -> int:
|
|
|
836
843
|
_save_mcp_credentials(savable)
|
|
837
844
|
|
|
838
845
|
config = EnvConfig.create_client_config()
|
|
846
|
+
# --url wins; otherwise DATAQUERY_MCP_URL, and failing that the model
|
|
847
|
+
# default (PROD). Only an explicitly emptied env var leaves it unset.
|
|
848
|
+
url = getattr(args, "url", None) or config.mcp_url
|
|
849
|
+
if not url:
|
|
850
|
+
print(
|
|
851
|
+
"No MCP endpoint configured: pass --url or set DATAQUERY_MCP_URL.",
|
|
852
|
+
file=sys.stderr,
|
|
853
|
+
)
|
|
854
|
+
return 1
|
|
839
855
|
token_manager = TokenManager(config)
|
|
840
856
|
|
|
841
857
|
class _AutheAuth(httpx.Auth):
|
|
@@ -852,7 +868,7 @@ async def cmd_mcp_connect(args: argparse.Namespace) -> int:
|
|
|
852
868
|
request.headers["Authorization"] = header
|
|
853
869
|
yield request
|
|
854
870
|
|
|
855
|
-
transport = StreamableHttpTransport(
|
|
871
|
+
transport = StreamableHttpTransport(url, auth=_AutheAuth())
|
|
856
872
|
proxy = FastMCP.as_proxy(transport, name=args.name)
|
|
857
873
|
await proxy.run_async(transport="stdio", show_banner=False)
|
|
858
874
|
return 0
|
|
@@ -212,10 +212,20 @@ def _emit_stdout(message: Dict[str, Any]) -> None:
|
|
|
212
212
|
sys.stdout.flush()
|
|
213
213
|
|
|
214
214
|
|
|
215
|
-
async def run_mcp_proxy(url: str, env_file: Optional[Path] = None) -> int:
|
|
216
|
-
"""Run the stdio <-> Streamable HTTP proxy until stdin closes.
|
|
215
|
+
async def run_mcp_proxy(url: Optional[str] = None, env_file: Optional[Path] = None) -> int:
|
|
216
|
+
"""Run the stdio <-> Streamable HTTP proxy until stdin closes.
|
|
217
|
+
|
|
218
|
+
``url`` defaults to ``DATAQUERY_MCP_URL``, and failing that to the PROD MCP
|
|
219
|
+
endpoint carried by :class:`ClientConfig`.
|
|
220
|
+
"""
|
|
217
221
|
_configure_stderr_logging()
|
|
218
222
|
try:
|
|
223
|
+
if env_file is not None:
|
|
224
|
+
EnvConfig.load_env_file(env_file)
|
|
225
|
+
EnvConfig.load_user_env_file()
|
|
226
|
+
url = url or EnvConfig.get_env_var("MCP_URL")
|
|
227
|
+
if not url:
|
|
228
|
+
raise ConfigurationError("No MCP endpoint configured: pass a url or set DATAQUERY_MCP_URL")
|
|
219
229
|
oauth = _build_oauth_manager(url, env_file)
|
|
220
230
|
await oauth.authenticate()
|
|
221
231
|
except (ConfigurationError, AuthenticationError) as exc:
|
|
@@ -63,6 +63,10 @@ class ClientConfig(BaseModel):
|
|
|
63
63
|
default="/research/dataquery-authe/api/v2",
|
|
64
64
|
description="Context path for the files host",
|
|
65
65
|
)
|
|
66
|
+
mcp_url: Optional[str] = Field(
|
|
67
|
+
default="https://api-dataquery.jpmchase.com/research/dataquery-authe/v2/mcp",
|
|
68
|
+
description="Remote MCP endpoint bridged by `dataquery mcp-connect`",
|
|
69
|
+
)
|
|
66
70
|
|
|
67
71
|
oauth_enabled: bool = Field(default=True, description="Enable OAuth authentication")
|
|
68
72
|
oauth_token_url: Optional[str] = Field(
|
|
@@ -52,6 +52,10 @@ DATAQUERY_BASE_URL=https://api-dataquery.jpmchase.com
|
|
|
52
52
|
# DATAQUERY_FILES_BASE_URL=https://api-dataquery.jpmchase.com
|
|
53
53
|
# DATAQUERY_FILES_CONTEXT_PATH=/research/dataquery-authe/api/v2
|
|
54
54
|
|
|
55
|
+
# Optional: remote MCP endpoint bridged by `dataquery mcp-connect`
|
|
56
|
+
# Defaults to the PROD endpoint below; override for another environment.
|
|
57
|
+
# DATAQUERY_MCP_URL=https://api-dataquery.jpmchase.com/research/dataquery-authe/v2/mcp
|
|
58
|
+
|
|
55
59
|
# =============================================================================
|
|
56
60
|
# AUTHENTICATION: OAuth 2.0 Configuration (Recommended)
|
|
57
61
|
# =============================================================================
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataquery-sdk
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.6
|
|
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
6
|
Project-URL: Homepage, https://github.com/jpmorganchase/dataquery-sdk
|
|
@@ -50,7 +50,7 @@ Requires-Dist: pymdown-extensions>=11.0.0; extra == "docs"
|
|
|
50
50
|
Provides-Extra: pandas
|
|
51
51
|
Requires-Dist: pandas>=2.0.0; extra == "pandas"
|
|
52
52
|
Provides-Extra: mcp
|
|
53
|
-
Requires-Dist: fastmcp
|
|
53
|
+
Requires-Dist: fastmcp<4,>=2.14; extra == "mcp"
|
|
54
54
|
Provides-Extra: all
|
|
55
55
|
Requires-Dist: pytest>=7.0.0; extra == "all"
|
|
56
56
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "all"
|
|
@@ -63,7 +63,7 @@ Requires-Dist: mkdocs-material>=9.0.0; extra == "all"
|
|
|
63
63
|
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "all"
|
|
64
64
|
Requires-Dist: mike>=1.1.0; extra == "all"
|
|
65
65
|
Requires-Dist: pandas>=2.0.0; extra == "all"
|
|
66
|
-
Requires-Dist: fastmcp
|
|
66
|
+
Requires-Dist: fastmcp<4,>=2.14; extra == "all"
|
|
67
67
|
Requires-Dist: pip-audit>=2.7.0; extra == "all"
|
|
68
68
|
Requires-Dist: build>=1.3.0; extra == "all"
|
|
69
69
|
Requires-Dist: urllib3>=2.7.0; extra == "all"
|
|
@@ -98,6 +98,7 @@ built in for both.
|
|
|
98
98
|
- [Quick start — JSON Data API](#quick-start--json-data-api)
|
|
99
99
|
- [Auto-download (SSE)](#auto-download-sse)
|
|
100
100
|
- [CLI](#cli)
|
|
101
|
+
- [MCP bridge (`mcp-connect`)](#mcp-bridge-mcp-connect)
|
|
101
102
|
- [Configuration](#configuration)
|
|
102
103
|
- [Logging](#logging)
|
|
103
104
|
- [Error handling](#error-handling)
|
|
@@ -140,6 +141,9 @@ through one `DataQuery` client — pick the methods that match what you need.
|
|
|
140
141
|
- **Retry + circuit breaker** — exponential backoff, configurable failure threshold
|
|
141
142
|
- **Sync and async APIs** — every operation has `_async` and sync variants
|
|
142
143
|
- **CLI** — `dataquery groups | files | availability | download | download-group | auth | config`
|
|
144
|
+
- **MCP bridge** — `dataquery mcp-connect` connects any stdio MCP client
|
|
145
|
+
(Claude Desktop, Claude Code, …) to the remote DataQuery MCP server, minting
|
|
146
|
+
OAuth tokens for it
|
|
143
147
|
|
|
144
148
|
## New here? Three steps to your first download
|
|
145
149
|
|
|
@@ -172,6 +176,9 @@ pip install dataquery-sdk
|
|
|
172
176
|
# With pandas DataFrame conversion
|
|
173
177
|
pip install "dataquery-sdk[pandas]"
|
|
174
178
|
|
|
179
|
+
# With the MCP bridge (dataquery mcp-connect)
|
|
180
|
+
pip install "dataquery-sdk[mcp]"
|
|
181
|
+
|
|
175
182
|
# With dev tooling (ruff, mypy, pytest)
|
|
176
183
|
pip install "dataquery-sdk[dev]"
|
|
177
184
|
```
|
|
@@ -439,8 +446,134 @@ dataquery config template --output .env
|
|
|
439
446
|
dataquery auth test
|
|
440
447
|
```
|
|
441
448
|
|
|
442
|
-
|
|
443
|
-
|
|
449
|
+
`--env-file PATH` (to point at a non-default `.env`) is a top-level flag, so it
|
|
450
|
+
goes *before* the subcommand: `dataquery --env-file .env.prod groups`. Most
|
|
451
|
+
subcommands accept `--json` for machine-readable output.
|
|
452
|
+
|
|
453
|
+
## MCP bridge (`mcp-connect`)
|
|
454
|
+
|
|
455
|
+
`dataquery mcp-connect` connects a desktop MCP client — Claude Desktop, Claude
|
|
456
|
+
Code, or any stdio MCP host — to the remote DataQuery MCP server. It speaks
|
|
457
|
+
stdio to the client and streamable HTTP to the server, stamping every outbound
|
|
458
|
+
request with a fresh OAuth (AuthE) bearer token minted from your `DATAQUERY_*`
|
|
459
|
+
credentials. Tokens are refreshed for the life of the session, and the MCP host
|
|
460
|
+
itself never handles your client secret.
|
|
461
|
+
|
|
462
|
+
It needs the `mcp` extra:
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
pip install "dataquery-sdk[mcp]"
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Wire it into an MCP client
|
|
469
|
+
|
|
470
|
+
Add the server to your client's MCP config (`claude_desktop_config.json`,
|
|
471
|
+
`.mcp.json`, or the equivalent for your host):
|
|
472
|
+
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"mcpServers": {
|
|
476
|
+
"dataquery": {
|
|
477
|
+
"command": "dataquery",
|
|
478
|
+
"args": ["mcp-connect", "--save-credentials"],
|
|
479
|
+
"env": {
|
|
480
|
+
"DATAQUERY_CLIENT_ID": "your_client_id",
|
|
481
|
+
"DATAQUERY_CLIENT_SECRET": "your_client_secret"
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
`--save-credentials` copies the credentials it resolved into
|
|
489
|
+
`~/.dataquery/.env` on the first launch (see [Credentials](#credentials)). From
|
|
490
|
+
then on the bridge — and every other SDK call and CLI run on the machine —
|
|
491
|
+
finds them there, so you can drop the `env` block from the config and keep your
|
|
492
|
+
secret out of a file your MCP client reads on every start:
|
|
493
|
+
|
|
494
|
+
```json
|
|
495
|
+
{
|
|
496
|
+
"mcpServers": {
|
|
497
|
+
"dataquery": {
|
|
498
|
+
"command": "dataquery",
|
|
499
|
+
"args": ["mcp-connect"]
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
To skip installing anything, run it straight from PyPI with `uvx`:
|
|
506
|
+
|
|
507
|
+
```json
|
|
508
|
+
{
|
|
509
|
+
"mcpServers": {
|
|
510
|
+
"dataquery": {
|
|
511
|
+
"command": "uvx",
|
|
512
|
+
"args": ["--from", "dataquery-sdk[mcp]", "dataquery", "mcp-connect", "--save-credentials"],
|
|
513
|
+
"env": {
|
|
514
|
+
"DATAQUERY_CLIENT_ID": "your_client_id",
|
|
515
|
+
"DATAQUERY_CLIENT_SECRET": "your_client_secret"
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Endpoint
|
|
523
|
+
|
|
524
|
+
`--url` is optional. The endpoint resolves as `--url` → `DATAQUERY_MCP_URL` →
|
|
525
|
+
the production server
|
|
526
|
+
`https://api-dataquery.jpmchase.com/research/dataquery-authe/v2/mcp`:
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
# Production (no arguments needed)
|
|
530
|
+
dataquery mcp-connect
|
|
531
|
+
|
|
532
|
+
# Another environment
|
|
533
|
+
dataquery mcp-connect --url https://host/research/dataquery-authe/v2/mcp
|
|
534
|
+
DATAQUERY_MCP_URL=https://host/research/dataquery-authe/v2/mcp dataquery mcp-connect
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### Credentials
|
|
538
|
+
|
|
539
|
+
Credentials resolve exactly as they do everywhere else in the SDK — flags win,
|
|
540
|
+
then the process environment (what your MCP client exports), then a `.env`,
|
|
541
|
+
then the saved user-level file:
|
|
542
|
+
|
|
543
|
+
```bash
|
|
544
|
+
# From the environment (recommended)
|
|
545
|
+
dataquery mcp-connect
|
|
546
|
+
|
|
547
|
+
# From flags — visible in the process list, so avoid on shared machines
|
|
548
|
+
dataquery mcp-connect --client-id ID --client-secret SECRET
|
|
549
|
+
|
|
550
|
+
# From a non-default .env (top-level flag: before the subcommand)
|
|
551
|
+
dataquery --env-file .env.prod mcp-connect
|
|
552
|
+
|
|
553
|
+
# Bearer token instead of OAuth
|
|
554
|
+
dataquery mcp-connect --bearer-token TOKEN
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
Pass `--save-credentials` once and the resolved credentials are written to
|
|
558
|
+
`~/.dataquery/.env` (owner-only `0600` file in a `0700` directory; override the
|
|
559
|
+
directory with `DATAQUERY_CONFIG_DIR`). Every later SDK call and CLI run reads
|
|
560
|
+
that file as a last-resort fallback, so a plain `DataQuery()` in a script
|
|
561
|
+
authenticates with no environment of its own — while shell variables and a
|
|
562
|
+
local `.env` still take precedence over it.
|
|
563
|
+
|
|
564
|
+
### Flags
|
|
565
|
+
|
|
566
|
+
| Flag | Default | Purpose |
|
|
567
|
+
|---|---|---|
|
|
568
|
+
| `--url URL` | `DATAQUERY_MCP_URL`, else the PROD endpoint | Remote MCP endpoint |
|
|
569
|
+
| `--name NAME` | `dataquery-mcp` | Proxy server name reported to the MCP client |
|
|
570
|
+
| `--client-id ID` | _(from env)_ | OAuth client ID; exported as `DATAQUERY_CLIENT_ID` |
|
|
571
|
+
| `--client-secret SECRET` | _(from env)_ | OAuth client secret; exported as `DATAQUERY_CLIENT_SECRET` |
|
|
572
|
+
| `--bearer-token TOKEN` | _(from env)_ | Use a bearer token instead of OAuth |
|
|
573
|
+
| `--save-credentials` | off | Also persist the resolved credentials to `~/.dataquery/.env` |
|
|
574
|
+
|
|
575
|
+
Because stdout carries the JSON-RPC channel, all logging and diagnostics go to
|
|
576
|
+
stderr — look in your MCP client's server log when something fails.
|
|
444
577
|
|
|
445
578
|
## Configuration
|
|
446
579
|
|
|
@@ -457,6 +590,16 @@ All environment variables use the `DATAQUERY_` prefix.
|
|
|
457
590
|
| `DATAQUERY_BEARER_TOKEN` | _(none)_ | Alternative to OAuth |
|
|
458
591
|
| `DATAQUERY_OAUTH_ENABLED` | `true` | Set `false` to use bearer-token mode |
|
|
459
592
|
|
|
593
|
+
**Endpoints**
|
|
594
|
+
|
|
595
|
+
| Variable | Default | Notes |
|
|
596
|
+
|---|---|---|
|
|
597
|
+
| `DATAQUERY_BASE_URL` | `https://api-dataquery.jpmchase.com` | Host for both API surfaces |
|
|
598
|
+
| `DATAQUERY_FILES_BASE_URL` | same as `BASE_URL` | Override only if file endpoints live on another host |
|
|
599
|
+
| `DATAQUERY_OAUTH_TOKEN_URL` | `https://authe.jpmorgan.com/as/token.oauth2` | Token endpoint |
|
|
600
|
+
| `DATAQUERY_OAUTH_AUD` | PROD audience | Set to the value provisioned for your client |
|
|
601
|
+
| `DATAQUERY_MCP_URL` | PROD MCP endpoint | Endpoint used by [`mcp-connect`](#mcp-bridge-mcp-connect); `--url` overrides it |
|
|
602
|
+
|
|
460
603
|
**HTTP / retry / rate limit**
|
|
461
604
|
|
|
462
605
|
| Variable | Default |
|
|
@@ -621,6 +764,17 @@ async with DataQuery() as dq:
|
|
|
621
764
|
`manager.clear_event_id()` (or `dataquery download --watch --reset-event-id`)
|
|
622
765
|
only when you intentionally want a clean slate.
|
|
623
766
|
|
|
767
|
+
**MCP client shows the server as failed**
|
|
768
|
+
|
|
769
|
+
- `The MCP bridge requires the 'mcp' extra` in the server log means `fastmcp`
|
|
770
|
+
is missing — `pip install "dataquery-sdk[mcp]"`, or use the `uvx` form.
|
|
771
|
+
- MCP hosts usually launch the command with a minimal environment, so a
|
|
772
|
+
`.env` in your shell's working directory may not be visible. Put the
|
|
773
|
+
credentials in the server's `env` block, or run `dataquery mcp-connect
|
|
774
|
+
--save-credentials` once from a terminal where they do resolve.
|
|
775
|
+
- Auth failures surface as `Could not obtain an OAuth token`; verify the same
|
|
776
|
+
credentials with `dataquery auth test` before debugging the bridge.
|
|
777
|
+
|
|
624
778
|
## Date formats
|
|
625
779
|
|
|
626
780
|
```python
|
|
@@ -16,7 +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
|
|
19
|
+
fastmcp<4,>=2.14
|
|
20
20
|
pip-audit>=2.7.0
|
|
21
21
|
build>=1.3.0
|
|
22
22
|
urllib3>=2.7.0
|
|
@@ -42,7 +42,7 @@ mike>=1.1.0
|
|
|
42
42
|
pymdown-extensions>=11.0.0
|
|
43
43
|
|
|
44
44
|
[mcp]
|
|
45
|
-
fastmcp
|
|
45
|
+
fastmcp<4,>=2.14
|
|
46
46
|
|
|
47
47
|
[pandas]
|
|
48
48
|
pandas>=2.0.0
|
|
@@ -77,7 +77,7 @@ pandas = [
|
|
|
77
77
|
"pandas>=2.0.0",
|
|
78
78
|
]
|
|
79
79
|
mcp = [
|
|
80
|
-
"fastmcp>=2.14",
|
|
80
|
+
"fastmcp>=2.14,<4",
|
|
81
81
|
]
|
|
82
82
|
all = [
|
|
83
83
|
"pytest>=7.0.0",
|
|
@@ -91,7 +91,7 @@ all = [
|
|
|
91
91
|
"mkdocstrings[python]>=0.24.0",
|
|
92
92
|
"mike>=1.1.0",
|
|
93
93
|
"pandas>=2.0.0",
|
|
94
|
-
"fastmcp>=2.14",
|
|
94
|
+
"fastmcp>=2.14,<4",
|
|
95
95
|
"pip-audit>=2.7.0",
|
|
96
96
|
"build>=1.3.0",
|
|
97
97
|
"urllib3>=2.7.0",
|
|
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
|