newsdata-mcp 0.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.
- newsdata_mcp-0.1.0/.dockerignore +41 -0
- newsdata_mcp-0.1.0/.env.example +14 -0
- newsdata_mcp-0.1.0/.github/workflows/ci.yml +33 -0
- newsdata_mcp-0.1.0/.github/workflows/release.yml +85 -0
- newsdata_mcp-0.1.0/.gitignore +26 -0
- newsdata_mcp-0.1.0/.python-version +1 -0
- newsdata_mcp-0.1.0/Dockerfile +57 -0
- newsdata_mcp-0.1.0/LICENSE +21 -0
- newsdata_mcp-0.1.0/PKG-INFO +320 -0
- newsdata_mcp-0.1.0/README.md +270 -0
- newsdata_mcp-0.1.0/pyproject.toml +132 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/__init__.py +10 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/_mcp.py +84 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/formatters.py +256 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/http.py +358 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/params.py +459 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/server.py +41 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/settings.py +54 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/__init__.py +29 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/archive.py +149 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/count.py +144 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/crypto.py +115 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/crypto_count.py +109 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/latest.py +149 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/market.py +146 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/market_count.py +137 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/tools/sources.py +56 -0
- newsdata_mcp-0.1.0/src/newsdata_mcp/validators.py +75 -0
- newsdata_mcp-0.1.0/tests/__init__.py +0 -0
- newsdata_mcp-0.1.0/tests/conftest.py +41 -0
- newsdata_mcp-0.1.0/tests/test_formatters.py +367 -0
- newsdata_mcp-0.1.0/tests/test_http.py +596 -0
- newsdata_mcp-0.1.0/tests/test_integration.py +107 -0
- newsdata_mcp-0.1.0/tests/test_tools.py +688 -0
- newsdata_mcp-0.1.0/tests/test_validators.py +228 -0
- newsdata_mcp-0.1.0/uv.lock +1072 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Build context: the Dockerfile only COPYs pyproject.toml, uv.lock,
|
|
2
|
+
# README.md, src/, and LICENSE. Everything else listed here is
|
|
3
|
+
# excluded from the build context so `docker build` uploads less and
|
|
4
|
+
# layer hashes stay stable when these change.
|
|
5
|
+
|
|
6
|
+
# Python build / runtime artifacts
|
|
7
|
+
__pycache__
|
|
8
|
+
*.pyc
|
|
9
|
+
*.pyo
|
|
10
|
+
*.egg-info/
|
|
11
|
+
.venv/
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
|
|
15
|
+
# Tooling caches
|
|
16
|
+
.mypy_cache/
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.ruff_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
.coverage.*
|
|
21
|
+
htmlcov/
|
|
22
|
+
|
|
23
|
+
# Tests, CI, editor config — not needed inside the image
|
|
24
|
+
tests/
|
|
25
|
+
.github/
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
|
|
29
|
+
# Local scratch / per-machine markers
|
|
30
|
+
.codex
|
|
31
|
+
temp.py
|
|
32
|
+
.claude/
|
|
33
|
+
|
|
34
|
+
# VCS / environment
|
|
35
|
+
.git/
|
|
36
|
+
.gitignore
|
|
37
|
+
.env
|
|
38
|
+
|
|
39
|
+
# Project docs not shipped in the image (README.md is needed by
|
|
40
|
+
# Dockerfile and is NOT listed here).
|
|
41
|
+
CLAUDE.md
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# NewsData.io credentials — copy this file to `.env` and fill in.
|
|
2
|
+
NEWSDATA_API_KEY="your_newsdata_api_key_here"
|
|
3
|
+
|
|
4
|
+
# Optional: request timeout in seconds (default: 30)
|
|
5
|
+
# REQUEST_TIMEOUT=30
|
|
6
|
+
|
|
7
|
+
# Optional: override the API base URL (e.g. for staging or a local mock)
|
|
8
|
+
# NEWSDATA_BASE_URL=https://newsdata.io/api/1
|
|
9
|
+
|
|
10
|
+
# Optional: retry policy for transient failures (network, 5xx, 429).
|
|
11
|
+
# Defaults sleep ~62s total across 5 attempts (2s → 4s → 8s → 16s → 32s, capped at 60s).
|
|
12
|
+
# NEWSDATA_MAX_RETRIES=5
|
|
13
|
+
# NEWSDATA_RETRY_BACKOFF=2.0
|
|
14
|
+
# NEWSDATA_RETRY_BACKOFF_MAX=60.0
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v3
|
|
17
|
+
with:
|
|
18
|
+
enable-cache: true
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
run: uv python install 3.12
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies (runtime + dev)
|
|
24
|
+
run: uv sync --all-groups --frozen
|
|
25
|
+
|
|
26
|
+
- name: Lint (ruff)
|
|
27
|
+
run: uv run ruff check src/ tests/
|
|
28
|
+
|
|
29
|
+
- name: Type-check (mypy)
|
|
30
|
+
run: uv run mypy
|
|
31
|
+
|
|
32
|
+
- name: Test (pytest, unit only by default)
|
|
33
|
+
run: uv run pytest --cov=newsdata_mcp --cov-report=term-missing
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Tag-triggered: build sdist + wheel, publish to PyPI via Trusted
|
|
4
|
+
# Publishing (OIDC, no API token), then create a GitHub Release with
|
|
5
|
+
# auto-generated notes and the same artifacts attached.
|
|
6
|
+
#
|
|
7
|
+
# Requires a one-time PyPI Trusted Publisher config:
|
|
8
|
+
# PyPI project "newsdata-mcp" → Publishing → Add a new pending /
|
|
9
|
+
# trusted publisher with
|
|
10
|
+
# Owner: newsdataapi
|
|
11
|
+
# Repository: newsdata.io-mcp
|
|
12
|
+
# Workflow: release.yml
|
|
13
|
+
# Environment: pypi
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
push:
|
|
17
|
+
tags:
|
|
18
|
+
- "v*"
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build:
|
|
22
|
+
name: Build distribution
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
|
|
27
|
+
- name: Install uv
|
|
28
|
+
uses: astral-sh/setup-uv@v3
|
|
29
|
+
with:
|
|
30
|
+
enable-cache: true
|
|
31
|
+
|
|
32
|
+
- name: Set up Python
|
|
33
|
+
run: uv python install 3.12
|
|
34
|
+
|
|
35
|
+
- name: Build sdist + wheel
|
|
36
|
+
run: uv build
|
|
37
|
+
|
|
38
|
+
- name: Show artifacts
|
|
39
|
+
run: ls -la dist/
|
|
40
|
+
|
|
41
|
+
- name: Upload artifacts
|
|
42
|
+
uses: actions/upload-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: dist
|
|
45
|
+
path: dist/
|
|
46
|
+
|
|
47
|
+
pypi-publish:
|
|
48
|
+
name: Publish to PyPI
|
|
49
|
+
needs: build
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
environment:
|
|
52
|
+
name: pypi
|
|
53
|
+
url: https://pypi.org/p/newsdata-mcp
|
|
54
|
+
permissions:
|
|
55
|
+
id-token: write # required for Trusted Publishing
|
|
56
|
+
steps:
|
|
57
|
+
- name: Download artifacts
|
|
58
|
+
uses: actions/download-artifact@v4
|
|
59
|
+
with:
|
|
60
|
+
name: dist
|
|
61
|
+
path: dist/
|
|
62
|
+
|
|
63
|
+
- name: Publish to PyPI
|
|
64
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
65
|
+
|
|
66
|
+
github-release:
|
|
67
|
+
name: Create GitHub Release
|
|
68
|
+
needs: pypi-publish
|
|
69
|
+
runs-on: ubuntu-latest
|
|
70
|
+
permissions:
|
|
71
|
+
contents: write
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
|
|
75
|
+
- name: Download artifacts
|
|
76
|
+
uses: actions/download-artifact@v4
|
|
77
|
+
with:
|
|
78
|
+
name: dist
|
|
79
|
+
path: dist/
|
|
80
|
+
|
|
81
|
+
- name: Create release
|
|
82
|
+
uses: softprops/action-gh-release@v2
|
|
83
|
+
with:
|
|
84
|
+
generate_release_notes: true
|
|
85
|
+
files: dist/*
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python build artifacts
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
|
|
8
|
+
# Virtual environment
|
|
9
|
+
.venv/
|
|
10
|
+
|
|
11
|
+
# Secrets
|
|
12
|
+
.env
|
|
13
|
+
|
|
14
|
+
# Tooling caches (mypy, pytest, ruff, coverage)
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
.coverage.*
|
|
20
|
+
htmlcov/
|
|
21
|
+
|
|
22
|
+
# Local-only files
|
|
23
|
+
.codex
|
|
24
|
+
temp.py
|
|
25
|
+
CLAUDE.md
|
|
26
|
+
.vscode/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Multistage build: resolve and install with uv against the lockfile in
|
|
2
|
+
# the builder, then copy the resulting venv into a minimal runtime stage.
|
|
3
|
+
|
|
4
|
+
# ---------- Builder ----------
|
|
5
|
+
FROM python:3.12-slim AS builder
|
|
6
|
+
|
|
7
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
8
|
+
UV_COMPILE_BYTECODE=1 \
|
|
9
|
+
UV_LINK_MODE=copy
|
|
10
|
+
|
|
11
|
+
# uv is a small Rust binary; pip-install it once in the builder.
|
|
12
|
+
RUN pip install --no-cache-dir uv
|
|
13
|
+
|
|
14
|
+
WORKDIR /app
|
|
15
|
+
|
|
16
|
+
# Install dependencies first (without the project itself) so this layer
|
|
17
|
+
# stays cached when only application source changes. LICENSE is needed
|
|
18
|
+
# at build time because pyproject.toml declares `license = { file = ... }`.
|
|
19
|
+
COPY pyproject.toml uv.lock README.md LICENSE /app/
|
|
20
|
+
RUN uv sync --frozen --no-install-project --no-dev
|
|
21
|
+
|
|
22
|
+
# Now copy source and install the project itself into the same venv.
|
|
23
|
+
COPY src /app/src
|
|
24
|
+
RUN uv sync --frozen --no-dev
|
|
25
|
+
|
|
26
|
+
# ---------- Runtime ----------
|
|
27
|
+
FROM python:3.12-slim AS runtime
|
|
28
|
+
|
|
29
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
30
|
+
PYTHONUNBUFFERED=1 \
|
|
31
|
+
REQUEST_TIMEOUT=30 \
|
|
32
|
+
PATH="/app/.venv/bin:$PATH"
|
|
33
|
+
|
|
34
|
+
WORKDIR /app
|
|
35
|
+
|
|
36
|
+
# Copy the populated venv + project source from the builder. LICENSE
|
|
37
|
+
# is already inside /app from the builder stage.
|
|
38
|
+
COPY --from=builder /app /app
|
|
39
|
+
|
|
40
|
+
# Run as a non-root user.
|
|
41
|
+
RUN useradd --create-home --uid 1000 app \
|
|
42
|
+
&& chown -R app:app /app
|
|
43
|
+
USER app
|
|
44
|
+
|
|
45
|
+
EXPOSE 8000
|
|
46
|
+
|
|
47
|
+
# TCP-level liveness probe; only meaningful for streamable-http transport.
|
|
48
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
|
|
49
|
+
CMD python -c "import socket; s=socket.socket(); s.settimeout(2); s.connect(('localhost',8000)); s.close()" || exit 1
|
|
50
|
+
|
|
51
|
+
LABEL org.opencontainers.image.title="newsdata-mcp" \
|
|
52
|
+
org.opencontainers.image.description="MCP server for NewsData.io" \
|
|
53
|
+
org.opencontainers.image.licenses="MIT" \
|
|
54
|
+
org.opencontainers.image.source="https://github.com/newsdataapi/newsdata.io-mcp"
|
|
55
|
+
|
|
56
|
+
ENTRYPOINT ["newsdata-mcp"]
|
|
57
|
+
CMD ["--transport", "streamable-http", "--host", "0.0.0.0", "--port", "8000"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NewsData.io
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: newsdata-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for the NewsData.io REST API (latest/archive/crypto/market news, source discovery, aggregate counts).
|
|
5
|
+
Project-URL: Homepage, https://newsdata.io
|
|
6
|
+
Project-URL: Documentation, https://newsdata.io/documentation
|
|
7
|
+
Project-URL: Repository, https://github.com/newsdataapi/newsdata.io-mcp
|
|
8
|
+
Project-URL: Issues, https://github.com/newsdataapi/newsdata.io-mcp/issues
|
|
9
|
+
Author-email: "NewsData.io" <contact@newsdata.io>
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 NewsData.io
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: api,crypto,market,mcp,model-context-protocol,news,newsdata
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Framework :: AsyncIO
|
|
35
|
+
Classifier: Framework :: Pydantic
|
|
36
|
+
Classifier: Intended Audience :: Developers
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Operating System :: OS Independent
|
|
39
|
+
Classifier: Programming Language :: Python :: 3
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
42
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
43
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
44
|
+
Requires-Python: >=3.12
|
|
45
|
+
Requires-Dist: httpx<1,>=0.28.1
|
|
46
|
+
Requires-Dist: mcp[cli]<2,>=1.27.0
|
|
47
|
+
Requires-Dist: pydantic<3,>=2.7.0
|
|
48
|
+
Requires-Dist: python-dotenv<2,>=1.2.2
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
# NewsData MCP Server
|
|
52
|
+
|
|
53
|
+
An MCP server for [NewsData.io](https://newsdata.io/documentation) that exposes real-time, historical, crypto, market, source-discovery, and aggregate-count tools to any MCP-compatible client.
|
|
54
|
+
|
|
55
|
+
## Available Tools
|
|
56
|
+
|
|
57
|
+
| Tool | Endpoint | Description |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `get_latest_news` | `/api/1/latest` | Recent and breaking news (last 48h) |
|
|
60
|
+
| `get_archive_news` | `/api/1/archive` | Historical news, filterable by `from_date` / `to_date` |
|
|
61
|
+
| `get_crypto_news` | `/api/1/crypto` | Crypto and blockchain-focused coverage |
|
|
62
|
+
| `get_market_news` | `/api/1/market` | Stock, financial, and market-related news |
|
|
63
|
+
| `get_news_sources` | `/api/1/sources` | Source discovery by country, category, or language |
|
|
64
|
+
| `get_news_counts` | `/api/1/count` | Aggregate article counts over a date range (`hour` / `day` buckets or single `all` total) |
|
|
65
|
+
| `get_crypto_counts` | `/api/1/crypto/count` | Aggregate crypto article counts over a date range |
|
|
66
|
+
| `get_market_counts` | `/api/1/market/count` | Aggregate market article counts over a date range |
|
|
67
|
+
|
|
68
|
+
All tools are read-only and idempotent; the MCP-protocol annotations let compatible clients (Claude Code, MCP Inspector, etc.) cache and parallelize calls.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
The server is published on PyPI as [`newsdata-mcp`](https://pypi.org/project/newsdata-mcp/). The recommended path is to let your MCP client launch it via [`uvx`](https://docs.astral.sh/uv/guides/tools/) — no clone, no `uv sync`, no virtualenv to manage. The package is downloaded and cached on first launch.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# verify uvx + the server work end-to-end (optional)
|
|
78
|
+
uvx newsdata-mcp --version
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Then add the server to your MCP client (see [Editor & Client Integrations](#editor--client-integrations) below). Every client config uses the same launch command:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
"command": "uvx",
|
|
85
|
+
"args": ["newsdata-mcp"]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
For a local development checkout, see [Development](#development) below.
|
|
89
|
+
|
|
90
|
+
### Configure environment
|
|
91
|
+
|
|
92
|
+
Set `NEWSDATA_API_KEY` in your client config's `env` block (per the per-client examples below). When running the server outside an MCP client (development, Docker, `streamable-http`), use a `.env` file:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
cp .env.example .env
|
|
96
|
+
# then edit .env
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
| Variable | Default | Notes |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `NEWSDATA_API_KEY` | _(required)_ | NewsData.io credential. Missing key returns an error envelope on every call. |
|
|
102
|
+
| `REQUEST_TIMEOUT` | `30` | Per-request timeout in seconds. |
|
|
103
|
+
| `NEWSDATA_BASE_URL` | `https://newsdata.io/api/1` | Override for staging or a local mock. |
|
|
104
|
+
| `NEWSDATA_MAX_RETRIES` | `5` | Maximum attempts for transient failures (network, 5xx, 429). |
|
|
105
|
+
| `NEWSDATA_RETRY_BACKOFF` | `2.0` | Base for exponential backoff (`base * 2^(attempt-1)`). Seconds. |
|
|
106
|
+
| `NEWSDATA_RETRY_BACKOFF_MAX` | `60.0` | Cap on a single retry sleep, seconds. |
|
|
107
|
+
| `NEWSDATA_INTEGRATION_KEY` | _(unset)_ | Used only by `pytest -m integration`. Without it, live-API tests skip. |
|
|
108
|
+
|
|
109
|
+
All values are read at module import time; restart the server after changing them.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Docker
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
docker build -t newsdata-mcp .
|
|
117
|
+
docker run --rm -p 8000:8000 -e NEWSDATA_API_KEY=your_newsdata_api_key newsdata-mcp
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Run in stdio mode:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
docker run --rm -i -e NEWSDATA_API_KEY=your_newsdata_api_key newsdata-mcp --transport stdio
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Pass a `.env` file:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
docker run --rm -p 8000:8000 --env-file .env newsdata-mcp
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The image is a multistage build: dependencies are installed from `uv.lock` in a `python:3.12-slim` builder, then the resulting venv plus `LICENSE` is copied into a fresh `python:3.12-slim` runtime. The container runs as a non-root `app` user.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Editor & Client Integrations
|
|
137
|
+
|
|
138
|
+
The simplest way is to add the server to your MCP client's JSON config. Each client picks up the config on restart. All examples use `uvx`, which downloads + caches the published package — no local clone required.
|
|
139
|
+
|
|
140
|
+
### Claude Code
|
|
141
|
+
|
|
142
|
+
Either edit `~/.claude/mcp.json` (global) or `.claude/mcp.json` (per-project):
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"mcpServers": {
|
|
147
|
+
"newsdata-mcp": {
|
|
148
|
+
"command": "uvx",
|
|
149
|
+
"args": ["newsdata-mcp"],
|
|
150
|
+
"env": {
|
|
151
|
+
"NEWSDATA_API_KEY": "your_newsdata_api_key"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Then restart Claude Code.
|
|
159
|
+
|
|
160
|
+
### Claude Desktop
|
|
161
|
+
|
|
162
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows) — same JSON block as above. Restart Claude Desktop.
|
|
163
|
+
|
|
164
|
+
### Cursor
|
|
165
|
+
|
|
166
|
+
Create or edit `.cursor/mcp.json` in your project root (or `~/.cursor/mcp.json` globally) — same JSON block. Restart Cursor; the server appears under **Cursor Settings → MCP**.
|
|
167
|
+
|
|
168
|
+
### VS Code (GitHub Copilot)
|
|
169
|
+
|
|
170
|
+
Create `.vscode/mcp.json` in your workspace (or add an `mcp` key to user settings):
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"servers": {
|
|
175
|
+
"newsdata-mcp": {
|
|
176
|
+
"type": "stdio",
|
|
177
|
+
"command": "uvx",
|
|
178
|
+
"args": ["newsdata-mcp"],
|
|
179
|
+
"env": {
|
|
180
|
+
"NEWSDATA_API_KEY": "your_newsdata_api_key"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Reload VS Code. Picked up by Copilot Chat in agent mode.
|
|
188
|
+
|
|
189
|
+
### Windsurf
|
|
190
|
+
|
|
191
|
+
Edit `~/.codeium/windsurf/mcp_config.json` — same JSON block as the Claude Code example. Restart Windsurf.
|
|
192
|
+
|
|
193
|
+
### ChatGPT Desktop (OpenAI)
|
|
194
|
+
|
|
195
|
+
Run the server in HTTP mode locally:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
NEWSDATA_API_KEY=your_key uvx newsdata-mcp \
|
|
199
|
+
--transport streamable-http --host 127.0.0.1 --port 8000
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Then in **ChatGPT → Settings → Connectors → Add custom connector**, register `http://127.0.0.1:8000/mcp` as the connector endpoint.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Example Tool Calls
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
get_latest_news(
|
|
210
|
+
q="((pizza OR burger) AND healthy)",
|
|
211
|
+
country=["us", "gb"],
|
|
212
|
+
language="en",
|
|
213
|
+
size=10
|
|
214
|
+
)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
get_archive_news(
|
|
219
|
+
q="ukraine war",
|
|
220
|
+
from_date="2025-01-01",
|
|
221
|
+
to_date="2025-01-31",
|
|
222
|
+
language="en"
|
|
223
|
+
)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
get_crypto_news(
|
|
228
|
+
coin=["btc", "eth"],
|
|
229
|
+
sentiment="positive"
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
```text
|
|
234
|
+
get_market_news(
|
|
235
|
+
symbol=["AAPL", "NVDA"],
|
|
236
|
+
country="us"
|
|
237
|
+
)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
```text
|
|
241
|
+
get_news_sources(
|
|
242
|
+
language="en",
|
|
243
|
+
priority_domain="top"
|
|
244
|
+
)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
get_news_counts(
|
|
249
|
+
from_date="2024-01-01",
|
|
250
|
+
to_date="2024-01-31",
|
|
251
|
+
q="bitcoin",
|
|
252
|
+
interval="day"
|
|
253
|
+
)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```text
|
|
257
|
+
get_market_counts(
|
|
258
|
+
from_date="2024-01-01",
|
|
259
|
+
to_date="2024-03-31",
|
|
260
|
+
symbol=["AAPL", "NVDA"],
|
|
261
|
+
interval="hour"
|
|
262
|
+
)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
```text
|
|
266
|
+
get_latest_news(
|
|
267
|
+
q="elections",
|
|
268
|
+
sentiment="positive",
|
|
269
|
+
sentiment_score=70
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Notes on parameter shapes:
|
|
274
|
+
- CSV-style filters accept either a Python list (preferred) or a comma-separated string.
|
|
275
|
+
- Boolean flags accept `True`/`False` or `1`/`0`.
|
|
276
|
+
- `timeframe` accepts an integer for hours (e.g. `24`) or a string with `m` suffix for minutes (e.g. `90m`).
|
|
277
|
+
- `interval` (count tools only) accepts `hour`, `day`, or `all` (`all` returns a single aggregate count instead of buckets).
|
|
278
|
+
- `sentiment_score` is a 0–100 minimum confidence percentage and requires `sentiment` to also be set — e.g. `sentiment="positive", sentiment_score=70` returns only articles whose positive-sentiment score is at least 70.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Notes
|
|
283
|
+
|
|
284
|
+
- Latest, crypto, and market endpoints return recent coverage — typically up to 48 hours.
|
|
285
|
+
- Free plan results are delayed relative to paid plans.
|
|
286
|
+
- Result `size` is capped by plan tier: commonly 10 results on free, up to 50 on paid plans.
|
|
287
|
+
- The count endpoints return aggregate buckets (one per `interval` slot) rather than article content.
|
|
288
|
+
- Every tool returns plain text (the MCP-protocol return type). Errors come back as `Error (HTTP 4xx): …` with the status code and a friendly message; HTTP 429 errors include a `retry after Ns` hint when the upstream `Retry-After` header was parseable.
|
|
289
|
+
|
|
290
|
+
Full API reference: [https://newsdata.io/documentation](https://newsdata.io/documentation).
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Development
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
git clone https://github.com/newsdataapi/newsdata.io-mcp.git
|
|
298
|
+
cd newsdata.io-mcp
|
|
299
|
+
uv sync --all-groups # install runtime + dev deps
|
|
300
|
+
|
|
301
|
+
uv run pytest # unit tests only (default)
|
|
302
|
+
NEWSDATA_INTEGRATION_KEY=<key> uv run pytest -m integration # live-API tests
|
|
303
|
+
uv run pytest --cov=newsdata_mcp --cov-report=term-missing # with coverage
|
|
304
|
+
uv run ruff check src/ tests/
|
|
305
|
+
uv run mypy
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
CI (`.github/workflows/ci.yml`) runs the same four commands on every push/PR to `main`.
|
|
309
|
+
|
|
310
|
+
### Releasing
|
|
311
|
+
|
|
312
|
+
1. Bump `__version__` in `src/newsdata_mcp/__init__.py`.
|
|
313
|
+
2. Commit and tag: `git tag vX.Y.Z && git push --tags`.
|
|
314
|
+
3. `.github/workflows/release.yml` builds the sdist + wheel, publishes to PyPI via Trusted Publishing (no token), and creates a GitHub Release with auto-generated notes.
|
|
315
|
+
|
|
316
|
+
One-time PyPI setup: configure a Trusted Publisher on the `newsdata-mcp` project pointing at `newsdataapi/newsdata.io-mcp`, workflow `release.yml`, environment `pypi`.
|
|
317
|
+
|
|
318
|
+
## License
|
|
319
|
+
|
|
320
|
+
MIT. See the [LICENSE](LICENSE) file.
|